From 9203d1e69c6d0a466d98cdfff498b6c451cc3fc7 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 27 Jan 2024 06:15:59 +0000 Subject: [PATCH 1/7] Bump vite and @angular-devkit/build-angular Bumps [vite](https://github.com/vitejs/vite/tree/HEAD/packages/vite) to 4.5.2 and updates ancestor dependency [@angular-devkit/build-angular](https://github.com/angular/angular-cli). These dependencies need to be updated together. Updates `vite` from 4.5.1 to 4.5.2 - [Release notes](https://github.com/vitejs/vite/releases) - [Changelog](https://github.com/vitejs/vite/blob/v4.5.2/packages/vite/CHANGELOG.md) - [Commits](https://github.com/vitejs/vite/commits/v4.5.2/packages/vite) Updates `@angular-devkit/build-angular` from 16.2.11 to 16.2.12 - [Release notes](https://github.com/angular/angular-cli/releases) - [Changelog](https://github.com/angular/angular-cli/blob/main/CHANGELOG.md) - [Commits](https://github.com/angular/angular-cli/compare/16.2.11...16.2.12) --- updated-dependencies: - dependency-name: vite dependency-type: indirect - dependency-name: "@angular-devkit/build-angular" dependency-type: direct:development ... Signed-off-by: dependabot[bot] --- package-lock.json | 72 +++++++++++++++++++++++------------------------ package.json | 2 +- 2 files changed, 37 insertions(+), 37 deletions(-) diff --git a/package-lock.json b/package-lock.json index 01540edf9..e7a2dcddf 100644 --- a/package-lock.json +++ b/package-lock.json @@ -25,7 +25,7 @@ "zone.js": "^0.13.1" }, "devDependencies": { - "@angular-devkit/build-angular": "^16.2.6", + "@angular-devkit/build-angular": "^16.2.12", "@angular-eslint/builder": "15.1.0", "@angular-eslint/eslint-plugin": "15.1.0", "@angular-eslint/eslint-plugin-template": "15.1.0", @@ -123,15 +123,15 @@ } }, "node_modules/@angular-devkit/build-angular": { - "version": "16.2.11", - "resolved": "https://registry.npmjs.org/@angular-devkit/build-angular/-/build-angular-16.2.11.tgz", - "integrity": "sha512-yNzUiAeg1WHMsFG9IBg4S/7dsMcEAMYQ1I360ib80c0T/IwRb8pHhOokrl5Mu8zfNqZ/dxH4ItKY1uIMDmuMGQ==", + "version": "16.2.12", + "resolved": "https://registry.npmjs.org/@angular-devkit/build-angular/-/build-angular-16.2.12.tgz", + "integrity": "sha512-VVGKZ0N3gyR0DP7VrcZl4io3ruWYT94mrlyJsJMLlrYy/EX8JCvqrJC9c+dscrtKjhZzjwdyhszkJQY4JfwACA==", "dev": true, "dependencies": { "@ampproject/remapping": "2.2.1", - "@angular-devkit/architect": "0.1602.11", - "@angular-devkit/build-webpack": "0.1602.11", - "@angular-devkit/core": "16.2.11", + "@angular-devkit/architect": "0.1602.12", + "@angular-devkit/build-webpack": "0.1602.12", + "@angular-devkit/core": "16.2.12", "@babel/core": "7.22.9", "@babel/generator": "7.22.9", "@babel/helper-annotate-as-pure": "7.22.5", @@ -143,7 +143,7 @@ "@babel/runtime": "7.22.6", "@babel/template": "7.22.5", "@discoveryjs/json-ext": "0.5.7", - "@ngtools/webpack": "16.2.11", + "@ngtools/webpack": "16.2.12", "@vitejs/plugin-basic-ssl": "1.0.1", "ansi-colors": "4.1.3", "autoprefixer": "10.4.14", @@ -186,7 +186,7 @@ "text-table": "0.2.0", "tree-kill": "1.2.2", "tslib": "2.6.1", - "vite": "4.5.1", + "vite": "4.5.2", "webpack": "5.88.2", "webpack-dev-middleware": "6.1.1", "webpack-dev-server": "4.15.1", @@ -245,12 +245,12 @@ } }, "node_modules/@angular-devkit/build-angular/node_modules/@angular-devkit/architect": { - "version": "0.1602.11", - "resolved": "https://registry.npmjs.org/@angular-devkit/architect/-/architect-0.1602.11.tgz", - "integrity": "sha512-qC1tPL/82gxqCS1z9pTpLn5NQH6uqbV6UNjbkFEQpTwEyWEK6VLChAJsybHHfbpssPS2HWf31VoUzX7RqDjoQQ==", + "version": "0.1602.12", + "resolved": "https://registry.npmjs.org/@angular-devkit/architect/-/architect-0.1602.12.tgz", + "integrity": "sha512-19Fwwfx+KvJ01SyI6cstRgqT9+cwer8Ro1T27t1JqlGyOX8tY3pV78ulwxy2+wCzPjR18V6W7cb7Cv6fyK4xog==", "dev": true, "dependencies": { - "@angular-devkit/core": "16.2.11", + "@angular-devkit/core": "16.2.12", "rxjs": "7.8.1" }, "engines": { @@ -260,9 +260,9 @@ } }, "node_modules/@angular-devkit/build-angular/node_modules/@angular-devkit/core": { - "version": "16.2.11", - "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-16.2.11.tgz", - "integrity": "sha512-u3cEQHqhSMWyAFIaPdRukCJwEUJt7Fy3C02gTlTeCB4F/OnftVFIm2e5vmCqMo9rgbfdvjWj9V+7wWiCpMrzAQ==", + "version": "16.2.12", + "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-16.2.12.tgz", + "integrity": "sha512-o6ziQs+EcEonFezrsA46jbZqkQrs4ckS1bAQj93g5ZjGtieUz8l/U3lclvKpL/iEzWkGVViSYuP2KyW2oqTDiQ==", "dev": true, "dependencies": { "ajv": "8.12.0", @@ -697,12 +697,12 @@ } }, "node_modules/@angular-devkit/build-webpack": { - "version": "0.1602.11", - "resolved": "https://registry.npmjs.org/@angular-devkit/build-webpack/-/build-webpack-0.1602.11.tgz", - "integrity": "sha512-2Au6xRMxNugFkXP0LS1TwNE5gAfGW4g6yxC9P5j5p3kdGDnAVaZRTOKB9dg73i3uXtJHUMciYOThV0b78XRxwA==", + "version": "0.1602.12", + "resolved": "https://registry.npmjs.org/@angular-devkit/build-webpack/-/build-webpack-0.1602.12.tgz", + "integrity": "sha512-1lmR4jCkxPJuAFXReesEY3CB+/5jSebGE5ry6qJJvNm6kuSc9bzfTytrcwosVY+Q7kAA2ij7kAYw0loGbTjLWA==", "dev": true, "dependencies": { - "@angular-devkit/architect": "0.1602.11", + "@angular-devkit/architect": "0.1602.12", "rxjs": "7.8.1" }, "engines": { @@ -716,12 +716,12 @@ } }, "node_modules/@angular-devkit/build-webpack/node_modules/@angular-devkit/architect": { - "version": "0.1602.11", - "resolved": "https://registry.npmjs.org/@angular-devkit/architect/-/architect-0.1602.11.tgz", - "integrity": "sha512-qC1tPL/82gxqCS1z9pTpLn5NQH6uqbV6UNjbkFEQpTwEyWEK6VLChAJsybHHfbpssPS2HWf31VoUzX7RqDjoQQ==", + "version": "0.1602.12", + "resolved": "https://registry.npmjs.org/@angular-devkit/architect/-/architect-0.1602.12.tgz", + "integrity": "sha512-19Fwwfx+KvJ01SyI6cstRgqT9+cwer8Ro1T27t1JqlGyOX8tY3pV78ulwxy2+wCzPjR18V6W7cb7Cv6fyK4xog==", "dev": true, "dependencies": { - "@angular-devkit/core": "16.2.11", + "@angular-devkit/core": "16.2.12", "rxjs": "7.8.1" }, "engines": { @@ -731,9 +731,9 @@ } }, "node_modules/@angular-devkit/build-webpack/node_modules/@angular-devkit/core": { - "version": "16.2.11", - "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-16.2.11.tgz", - "integrity": "sha512-u3cEQHqhSMWyAFIaPdRukCJwEUJt7Fy3C02gTlTeCB4F/OnftVFIm2e5vmCqMo9rgbfdvjWj9V+7wWiCpMrzAQ==", + "version": "16.2.12", + "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-16.2.12.tgz", + "integrity": "sha512-o6ziQs+EcEonFezrsA46jbZqkQrs4ckS1bAQj93g5ZjGtieUz8l/U3lclvKpL/iEzWkGVViSYuP2KyW2oqTDiQ==", "dev": true, "dependencies": { "ajv": "8.12.0", @@ -5275,9 +5275,9 @@ } }, "node_modules/@ngtools/webpack": { - "version": "16.2.11", - "resolved": "https://registry.npmjs.org/@ngtools/webpack/-/webpack-16.2.11.tgz", - "integrity": "sha512-4ndXJ4s94ZsryVGSDk/waIDrUqXqdGWftoOEn81Zu+nkL9ncI/G1fNUlSJ5OqeKmMLxMFouoy+BuJfvT+gEgnQ==", + "version": "16.2.12", + "resolved": "https://registry.npmjs.org/@ngtools/webpack/-/webpack-16.2.12.tgz", + "integrity": "sha512-f9R9Qsk8v+ffDxryl6PQ7Wnf2JCNd4dDXOH+d/AuF06VFiwcwGDRDZpmqkAXbFxQfcWTbT1FFvfoJ+SFcJgXLA==", "dev": true, "engines": { "node": "^16.14.0 || >=18.10.0", @@ -13192,9 +13192,9 @@ } }, "node_modules/bonjour-service": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/bonjour-service/-/bonjour-service-1.2.0.tgz", - "integrity": "sha512-xdzMA6JGckxyJzZByjEWRcfKmDxXaGXZWVftah3FkCqdlePNS9DjHSUN5zkP4oEfz/t0EXXlro88EIhzwMB4zA==", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/bonjour-service/-/bonjour-service-1.2.1.tgz", + "integrity": "sha512-oSzCS2zV14bh2kji6vNe7vrpJYCHGvcZnlffFQ1MEoX/WOeQ/teD8SYWKR942OI3INjq8OMNJlbPK5LLLUxFDw==", "dev": true, "dependencies": { "fast-deep-equal": "^3.1.3", @@ -30273,9 +30273,9 @@ } }, "node_modules/vite": { - "version": "4.5.1", - "resolved": "https://registry.npmjs.org/vite/-/vite-4.5.1.tgz", - "integrity": "sha512-AXXFaAJ8yebyqzoNB9fu2pHoo/nWX+xZlaRwoeYUxEqBO+Zj4msE5G+BhGBll9lYEKv9Hfks52PAF2X7qDYXQA==", + "version": "4.5.2", + "resolved": "https://registry.npmjs.org/vite/-/vite-4.5.2.tgz", + "integrity": "sha512-tBCZBNSBbHQkaGyhGCDUGqeo2ph8Fstyp6FMSvTtsXeZSPpSMGlviAOav2hxVTqFcx8Hj/twtWKsMJXNY0xI8w==", "dev": true, "dependencies": { "esbuild": "^0.18.10", diff --git a/package.json b/package.json index 1b7763b22..e3c52a4f8 100644 --- a/package.json +++ b/package.json @@ -42,7 +42,7 @@ "zone.js": "^0.13.1" }, "devDependencies": { - "@angular-devkit/build-angular": "^16.2.6", + "@angular-devkit/build-angular": "^16.2.12", "@angular-eslint/builder": "15.1.0", "@angular-eslint/eslint-plugin": "15.1.0", "@angular-eslint/eslint-plugin-template": "15.1.0", From a3dfd66254a16c29ea663a0eb3cbac2b62446ab4 Mon Sep 17 00:00:00 2001 From: manav sethi <133642302+manav-sethi-oncehub@users.noreply.github.com> Date: Thu, 1 Feb 2024 12:10:52 +0000 Subject: [PATCH 2/7] upgrade version and update changelog --- CHANGELOG.md | 8 ++++++-- package-lock.json | 4 ++-- package.json | 2 +- ui/package-lock.json | 4 ++-- ui/package.json | 2 +- 5 files changed, 12 insertions(+), 8 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 18f691f16..42c0c8870 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,11 +5,15 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). -## [8.0.6] - 2023-01-29 +## [8.0.7] - 2024-02-01 + +- [ONCEHUB-77380](https://scheduleonce.atlassian.net/browse/ONCEHUB-77380) fixed vulnerability found in package vite + +## [8.0.6] - 2024-01-29 - [ONCEHUB-60767](https://scheduleonce.atlassian.net/browse/ONCEHUB-60767) Fixed an padding issue in label in oui-tab -## [8.0.5] - 2023-01-14 +## [8.0.5] - 2024-01-14 - [ONCEHUB-60767](https://scheduleonce.atlassian.net/browse/ONCEHUB-60767) Fixed an issue related to the spacing in oui-tab diff --git a/package-lock.json b/package-lock.json index e7a2dcddf..403c4f71a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "oncehub-ui", - "version": "8.0.6", + "version": "8.0.7", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "oncehub-ui", - "version": "8.0.6", + "version": "8.0.7", "dependencies": { "@angular-devkit/architect": "0.1601.6", "@angular-devkit/core": "16.1.6", diff --git a/package.json b/package.json index e3c52a4f8..d08da823f 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "oncehub-ui", - "version": "8.0.6", + "version": "8.0.7", "scripts": { "ng": "ng", "build": "ng build ui", diff --git a/ui/package-lock.json b/ui/package-lock.json index 4eb47cd20..d47f97a92 100644 --- a/ui/package-lock.json +++ b/ui/package-lock.json @@ -1,12 +1,12 @@ { "name": "@oncehub/ui", - "version": "8.0.6", + "version": "8.0.7", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "@oncehub/ui", - "version": "8.0.6", + "version": "8.0.7", "dependencies": { "tslib": "^2.4.0" } diff --git a/ui/package.json b/ui/package.json index 072081539..68220577a 100644 --- a/ui/package.json +++ b/ui/package.json @@ -1,6 +1,6 @@ { "name": "@oncehub/ui", - "version": "8.0.6", + "version": "8.0.7", "description": "Oncehub UI", "peerDependencies": {}, "repository": { From 0f71b67ce66749b57e9d049ef340b65e7932da8b Mon Sep 17 00:00:00 2001 From: manav sethi <133642302+manav-sethi-oncehub@users.noreply.github.com> Date: Thu, 1 Feb 2024 12:17:41 +0000 Subject: [PATCH 3/7] ran prettier --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 42c0c8870..ea5c03a5e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,7 +7,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [8.0.7] - 2024-02-01 -- [ONCEHUB-77380](https://scheduleonce.atlassian.net/browse/ONCEHUB-77380) fixed vulnerability found in package vite +- [ONCEHUB-77380](https://scheduleonce.atlassian.net/browse/ONCEHUB-77380) fixed vulnerability found in package vite ## [8.0.6] - 2024-01-29 From ac5b4200c0acadb35c21ad63c03dd93c770333a1 Mon Sep 17 00:00:00 2001 From: siddharth Date: Thu, 1 Feb 2024 13:59:46 +0530 Subject: [PATCH 4/7] Add accessibility on oui-panel-icon --- CHANGELOG.md | 4 + documentation.json | 4622 +++++++++++++++++------------- package-lock.json | 4 +- package.json | 2 +- ui/package-lock.json | 4 +- ui/package.json | 2 +- ui/src/components/panel/panel.ts | 3 +- 7 files changed, 2689 insertions(+), 1952 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 18f691f16..2f74d4bf2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,10 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [8.0.8] - 2023-02-02 + +- [ONCEHUB-60767](https://scheduleonce.atlassian.net/browse/ONCEHUB-77583) Add accessibility on oui-panel-icon + ## [8.0.6] - 2023-01-29 - [ONCEHUB-60767](https://scheduleonce.atlassian.net/browse/ONCEHUB-60767) Fixed an padding issue in label in oui-tab diff --git a/documentation.json b/documentation.json index 1db52d05d..f7c3c61e4 100644 --- a/documentation.json +++ b/documentation.json @@ -70,6 +70,7 @@ ] } ], + "standalone": false, "ngname": "filterOptions", "sourceCode": "import { Pipe, PipeTransform } from '@angular/core';\n@Pipe({\n name: 'filterOptions',\n})\nexport class FilterPipe implements PipeTransform {\n transform(items: any[], searchText: string, field: string): any[] {\n if (!items) {\n return [];\n }\n\n if (!searchText) {\n return items;\n }\n\n return items.filter((it) => {\n let results;\n // Support both array and the json object\n if (it[field]) {\n results = it[field].toLowerCase().includes(searchText.toLowerCase());\n } else {\n results = it.toLowerCase().includes(searchText.toLowerCase());\n }\n return results;\n });\n }\n}\n" } @@ -77,15 +78,15 @@ "interfaces": [ { "name": "_OuiInkBarPositioner", - "id": "interface-_OuiInkBarPositioner-135c8ccdab508fcf19b684306b7b52fe3cacc460ac2081644d8b0d211b3fb9a93c581e6b1e98ed9fdc3965312903a402f79f7ef73e228a1ef8f3bd236d89976f", + "id": "interface-_OuiInkBarPositioner-50fe2f1bca65db33aac094b14b277a02924ff4199f4bfe029de4c7e70c55f0d0b3d8f03cc04d8961159c28f0d20d52a85a2edbaf9f6b9506a466792860b45ccf", "file": "ui/src/components/tabs/ink-bar.ts", "deprecated": false, "deprecationMessage": "", "type": "interface", - "sourceCode": "import { BooleanInput, coerceBooleanProperty } from '@angular/cdk/coercion';\nimport {\n ElementRef,\n InjectionToken,\n OnDestroy,\n OnInit,\n QueryList,\n} from '@angular/core';\nimport { isDevMode } from '@angular/core';\n\n/**\n * Item inside a tab header relative to which the ink bar can be aligned.\n * @docs-private\n */\nexport interface MatInkBarItem extends OnInit, OnDestroy {\n elementRef: ElementRef;\n activateInkBar(previousIndicatorClientRect?: ClientRect): void;\n deactivateInkBar(): void;\n fitInkBarToContent: boolean;\n}\n\n/** Class that is applied when a tab indicator is active. */\nconst ACTIVE_CLASS = 'mdc-tab-indicator--active';\n\n/** Class that is applied when the tab indicator should not transition. */\nconst NO_TRANSITION_CLASS = 'mdc-tab-indicator--no-transition';\n\n/**\n * Abstraction around the MDC tab indicator that acts as the tab header's ink bar.\n * @docs-private\n */\nexport class OuiInkBar {\n /** Item to which the ink bar is aligned currently. */\n private _currentItem: MatInkBarItem | undefined;\n\n constructor(private _items: QueryList) {}\n\n /** Hides the ink bar. */\n hide() {\n this._items.forEach((item) => item.deactivateInkBar());\n }\n\n /** Aligns the ink bar to a DOM node. */\n alignToElement(element: HTMLElement) {\n const correspondingItem = this._items.find(\n (item) => item.elementRef.nativeElement === element\n );\n const currentItem = this._currentItem;\n\n if (correspondingItem === currentItem) {\n return;\n }\n\n currentItem?.deactivateInkBar();\n\n if (correspondingItem) {\n const clientRect =\n currentItem?.elementRef.nativeElement.getBoundingClientRect?.();\n\n // The ink bar won't animate unless we give it the `ClientRect` of the previous item.\n correspondingItem.activateInkBar(clientRect);\n this._currentItem = correspondingItem;\n }\n }\n}\n\n/**\n * Mixin that can be used to apply the `MatInkBarItem` behavior to a class.\n * Base on MDC's `MDCSlidingTabIndicatorFoundation`:\n * https://github.com/material-components/material-components-web/blob/c0a11ef0d000a098fd0c372be8f12d6a99302855/packages/mdc-tab-indicator/sliding-foundation.ts\n * @docs-private\n */\nexport function mixinInkBarItem<\n T extends new (...args: any[]) => { elementRef: ElementRef }\n>(base: T): T & (new (...args: any[]) => MatInkBarItem) {\n return class extends base {\n constructor(...args: any[]) {\n // eslint-disable-next-line @typescript-eslint/no-unsafe-argument\n super(...args);\n }\n\n private _inkBarElement: HTMLElement | null;\n private _inkBarContentElement: HTMLElement | null;\n private _fitToContent = false;\n\n /** Whether the ink bar should fit to the entire tab or just its content. */\n get fitInkBarToContent(): boolean {\n return this._fitToContent;\n }\n set fitInkBarToContent(v: BooleanInput) {\n const newValue = coerceBooleanProperty(v);\n\n if (this._fitToContent !== newValue) {\n this._fitToContent = newValue;\n\n if (this._inkBarElement) {\n this._appendInkBarElement();\n }\n }\n }\n\n /** Aligns the ink bar to the current item. */\n activateInkBar(previousIndicatorClientRect?: ClientRect) {\n const element = this.elementRef.nativeElement;\n\n // Early exit if no indicator is present to handle cases where an indicator\n // may be activated without a prior indicator state\n if (\n !previousIndicatorClientRect ||\n !element.getBoundingClientRect ||\n !this._inkBarContentElement\n ) {\n element.classList.add(ACTIVE_CLASS);\n return;\n }\n\n // This animation uses the FLIP approach. You can read more about it at the link below:\n // https://aerotwist.com/blog/flip-your-animations/\n\n // Calculate the dimensions based on the dimensions of the previous indicator\n const currentClientRect = element.getBoundingClientRect();\n const widthDelta =\n previousIndicatorClientRect.width / currentClientRect.width;\n const xPosition =\n previousIndicatorClientRect.left - currentClientRect.left;\n element.classList.add(NO_TRANSITION_CLASS);\n this._inkBarContentElement.style.setProperty(\n 'transform',\n `translateX(${xPosition}px) scaleX(${widthDelta})`\n );\n\n // Force repaint before updating classes and transform to ensure the transform properly takes effect\n element.getBoundingClientRect();\n\n element.classList.remove(NO_TRANSITION_CLASS);\n element.classList.add(ACTIVE_CLASS);\n this._inkBarContentElement.style.setProperty('transform', '');\n }\n\n /** Removes the ink bar from the current item. */\n deactivateInkBar() {\n this.elementRef.nativeElement.classList.remove(ACTIVE_CLASS);\n }\n\n /** Initializes the foundation. */\n ngOnInit() {\n this._createInkBarElement();\n }\n\n /** Destroys the foundation. */\n ngOnDestroy() {\n this._inkBarElement?.remove();\n this._inkBarElement = this._inkBarContentElement = null!;\n }\n\n /** Creates and appends the ink bar element. */\n private _createInkBarElement() {\n const documentNode =\n this.elementRef.nativeElement.ownerDocument || document;\n this._inkBarElement = documentNode.createElement('span');\n this._inkBarContentElement = documentNode.createElement('span');\n\n this._inkBarElement.className = 'mdc-tab-indicator';\n this._inkBarContentElement.className =\n 'mdc-tab-indicator__content mdc-tab-indicator__content--underline';\n\n this._inkBarElement.appendChild(this._inkBarContentElement);\n this._appendInkBarElement();\n }\n\n /**\n * Appends the ink bar to the tab host element or content, depending on whether\n * the ink bar should fit to content.\n */\n private _appendInkBarElement() {\n if (\n !this._inkBarElement &&\n (typeof isDevMode === 'undefined' || isDevMode)\n ) {\n throw Error(\n 'Ink bar element has not been created and cannot be appended'\n );\n }\n\n const parentElement = this._fitToContent\n ? this.elementRef.nativeElement.querySelector('.mdc-tab__content')\n : this.elementRef.nativeElement;\n\n if (!parentElement && (typeof isDevMode === 'undefined' || isDevMode)) {\n throw Error('Missing element to host the ink bar');\n }\n\n parentElement!.appendChild(this._inkBarElement!);\n }\n };\n}\n\n/**\n * Interface for a OuiInkBar positioner method, defining the positioning and width of the ink\n * bar in a set of tabs.\n */\nexport interface _OuiInkBarPositioner {\n (element: HTMLElement): { left: string; width: string };\n}\n\n/**\n * The default positioner function for the OuiInkBar.\n * @docs-private\n */\nexport function _OUI_INK_BAR_POSITIONER_FACTORY(): _OuiInkBarPositioner {\n const method = (element: HTMLElement) => ({\n // eslint-disable-next-line @typescript-eslint/restrict-plus-operands\n left: element ? (element.offsetLeft || 0) + 'px' : '0',\n // eslint-disable-next-line @typescript-eslint/restrict-plus-operands\n width: element ? (element.offsetWidth || 0) + 'px' : '0',\n });\n\n return method;\n}\n\n/** Injection token for the OuiInkBar's Positioner. */\nexport const _OUI_INK_BAR_POSITIONER = new InjectionToken<_OuiInkBarPositioner>(\n 'MatInkBarPositioner',\n {\n providedIn: 'root',\n factory: _OUI_INK_BAR_POSITIONER_FACTORY,\n }\n);\n", + "sourceCode": "import { BooleanInput, coerceBooleanProperty } from '@angular/cdk/coercion';\r\nimport {\r\n ElementRef,\r\n InjectionToken,\r\n OnDestroy,\r\n OnInit,\r\n QueryList,\r\n} from '@angular/core';\r\nimport { isDevMode } from '@angular/core';\r\n\r\n/**\r\n * Item inside a tab header relative to which the ink bar can be aligned.\r\n * @docs-private\r\n */\r\nexport interface MatInkBarItem extends OnInit, OnDestroy {\r\n elementRef: ElementRef;\r\n activateInkBar(previousIndicatorClientRect?: ClientRect): void;\r\n deactivateInkBar(): void;\r\n fitInkBarToContent: boolean;\r\n}\r\n\r\n/** Class that is applied when a tab indicator is active. */\r\nconst ACTIVE_CLASS = 'mdc-tab-indicator--active';\r\n\r\n/** Class that is applied when the tab indicator should not transition. */\r\nconst NO_TRANSITION_CLASS = 'mdc-tab-indicator--no-transition';\r\n\r\n/**\r\n * Abstraction around the MDC tab indicator that acts as the tab header's ink bar.\r\n * @docs-private\r\n */\r\nexport class OuiInkBar {\r\n /** Item to which the ink bar is aligned currently. */\r\n private _currentItem: MatInkBarItem | undefined;\r\n\r\n constructor(private _items: QueryList) {}\r\n\r\n /** Hides the ink bar. */\r\n hide() {\r\n this._items.forEach((item) => item.deactivateInkBar());\r\n }\r\n\r\n /** Aligns the ink bar to a DOM node. */\r\n alignToElement(element: HTMLElement) {\r\n const correspondingItem = this._items.find(\r\n (item) => item.elementRef.nativeElement === element\r\n );\r\n const currentItem = this._currentItem;\r\n\r\n if (correspondingItem === currentItem) {\r\n return;\r\n }\r\n\r\n currentItem?.deactivateInkBar();\r\n\r\n if (correspondingItem) {\r\n const clientRect =\r\n currentItem?.elementRef.nativeElement.getBoundingClientRect?.();\r\n\r\n // The ink bar won't animate unless we give it the `ClientRect` of the previous item.\r\n correspondingItem.activateInkBar(clientRect);\r\n this._currentItem = correspondingItem;\r\n }\r\n }\r\n}\r\n\r\n/**\r\n * Mixin that can be used to apply the `MatInkBarItem` behavior to a class.\r\n * Base on MDC's `MDCSlidingTabIndicatorFoundation`:\r\n * https://github.com/material-components/material-components-web/blob/c0a11ef0d000a098fd0c372be8f12d6a99302855/packages/mdc-tab-indicator/sliding-foundation.ts\r\n * @docs-private\r\n */\r\nexport function mixinInkBarItem<\r\n T extends new (...args: any[]) => { elementRef: ElementRef }\r\n>(base: T): T & (new (...args: any[]) => MatInkBarItem) {\r\n return class extends base {\r\n constructor(...args: any[]) {\r\n // eslint-disable-next-line @typescript-eslint/no-unsafe-argument\r\n super(...args);\r\n }\r\n\r\n private _inkBarElement: HTMLElement | null;\r\n private _inkBarContentElement: HTMLElement | null;\r\n private _fitToContent = false;\r\n\r\n /** Whether the ink bar should fit to the entire tab or just its content. */\r\n get fitInkBarToContent(): boolean {\r\n return this._fitToContent;\r\n }\r\n set fitInkBarToContent(v: BooleanInput) {\r\n const newValue = coerceBooleanProperty(v);\r\n\r\n if (this._fitToContent !== newValue) {\r\n this._fitToContent = newValue;\r\n\r\n if (this._inkBarElement) {\r\n this._appendInkBarElement();\r\n }\r\n }\r\n }\r\n\r\n /** Aligns the ink bar to the current item. */\r\n activateInkBar(previousIndicatorClientRect?: ClientRect) {\r\n const element = this.elementRef.nativeElement;\r\n\r\n // Early exit if no indicator is present to handle cases where an indicator\r\n // may be activated without a prior indicator state\r\n if (\r\n !previousIndicatorClientRect ||\r\n !element.getBoundingClientRect ||\r\n !this._inkBarContentElement\r\n ) {\r\n element.classList.add(ACTIVE_CLASS);\r\n return;\r\n }\r\n\r\n // This animation uses the FLIP approach. You can read more about it at the link below:\r\n // https://aerotwist.com/blog/flip-your-animations/\r\n\r\n // Calculate the dimensions based on the dimensions of the previous indicator\r\n const currentClientRect = element.getBoundingClientRect();\r\n const widthDelta =\r\n previousIndicatorClientRect.width / currentClientRect.width;\r\n const xPosition =\r\n previousIndicatorClientRect.left - currentClientRect.left;\r\n element.classList.add(NO_TRANSITION_CLASS);\r\n this._inkBarContentElement.style.setProperty(\r\n 'transform',\r\n `translateX(${xPosition}px) scaleX(${widthDelta})`\r\n );\r\n\r\n // Force repaint before updating classes and transform to ensure the transform properly takes effect\r\n element.getBoundingClientRect();\r\n\r\n element.classList.remove(NO_TRANSITION_CLASS);\r\n element.classList.add(ACTIVE_CLASS);\r\n this._inkBarContentElement.style.setProperty('transform', '');\r\n }\r\n\r\n /** Removes the ink bar from the current item. */\r\n deactivateInkBar() {\r\n this.elementRef.nativeElement.classList.remove(ACTIVE_CLASS);\r\n }\r\n\r\n /** Initializes the foundation. */\r\n ngOnInit() {\r\n this._createInkBarElement();\r\n }\r\n\r\n /** Destroys the foundation. */\r\n ngOnDestroy() {\r\n this._inkBarElement?.remove();\r\n this._inkBarElement = this._inkBarContentElement = null!;\r\n }\r\n\r\n /** Creates and appends the ink bar element. */\r\n private _createInkBarElement() {\r\n const documentNode =\r\n this.elementRef.nativeElement.ownerDocument || document;\r\n this._inkBarElement = documentNode.createElement('span');\r\n this._inkBarContentElement = documentNode.createElement('span');\r\n\r\n this._inkBarElement.className = 'mdc-tab-indicator';\r\n this._inkBarContentElement.className =\r\n 'mdc-tab-indicator__content mdc-tab-indicator__content--underline';\r\n\r\n this._inkBarElement.appendChild(this._inkBarContentElement);\r\n this._appendInkBarElement();\r\n }\r\n\r\n /**\r\n * Appends the ink bar to the tab host element or content, depending on whether\r\n * the ink bar should fit to content.\r\n */\r\n private _appendInkBarElement() {\r\n if (\r\n !this._inkBarElement &&\r\n (typeof isDevMode === 'undefined' || isDevMode)\r\n ) {\r\n throw Error(\r\n 'Ink bar element has not been created and cannot be appended'\r\n );\r\n }\r\n\r\n const parentElement = this._fitToContent\r\n ? this.elementRef.nativeElement.querySelector('.mdc-tab__content')\r\n : this.elementRef.nativeElement;\r\n\r\n if (!parentElement && (typeof isDevMode === 'undefined' || isDevMode)) {\r\n throw Error('Missing element to host the ink bar');\r\n }\r\n\r\n parentElement!.appendChild(this._inkBarElement!);\r\n }\r\n };\r\n}\r\n\r\n/**\r\n * Interface for a OuiInkBar positioner method, defining the positioning and width of the ink\r\n * bar in a set of tabs.\r\n */\r\nexport interface _OuiInkBarPositioner {\r\n (element: HTMLElement): { left: string; width: string };\r\n}\r\n\r\n/**\r\n * The default positioner function for the OuiInkBar.\r\n * @docs-private\r\n */\r\nexport function _OUI_INK_BAR_POSITIONER_FACTORY(): _OuiInkBarPositioner {\r\n const method = (element: HTMLElement) => ({\r\n // eslint-disable-next-line @typescript-eslint/restrict-plus-operands\r\n left: element ? (element.offsetLeft || 0) + 'px' : '0',\r\n // eslint-disable-next-line @typescript-eslint/restrict-plus-operands\r\n width: element ? (element.offsetWidth || 0) + 'px' : '0',\r\n });\r\n\r\n return method;\r\n}\r\n\r\n/** Injection token for the OuiInkBar's Positioner. */\r\nexport const _OUI_INK_BAR_POSITIONER = new InjectionToken<_OuiInkBarPositioner>(\r\n 'MatInkBarPositioner',\r\n {\r\n providedIn: 'root',\r\n factory: _OUI_INK_BAR_POSITIONER_FACTORY,\r\n }\r\n);\r\n", "properties": [ { - "id": "call-declaration-135c8ccdab508fcf19b684306b7b52fe3cacc460ac2081644d8b0d211b3fb9a93c581e6b1e98ed9fdc3965312903a402f79f7ef73e228a1ef8f3bd236d89976f", + "id": "call-declaration-50fe2f1bca65db33aac094b14b277a02924ff4199f4bfe029de4c7e70c55f0d0b3d8f03cc04d8961159c28f0d20d52a85a2edbaf9f6b9506a466792860b45ccf", "args": [ { "name": "element", @@ -101,10 +102,11 @@ } ], "indexSignatures": [], - "kind": 173, + "kind": 179, "description": "

Interface for a OuiInkBar positioner method, defining the positioning and width of the ink\nbar in a set of tabs.

\n", "rawdescription": "\n\nInterface for a OuiInkBar positioner method, defining the positioning and width of the ink\nbar in a set of tabs.\n", - "methods": [] + "methods": [], + "extends": [] }, { "name": "ArrowViewStateTransition", @@ -135,10 +137,11 @@ } ], "indexSignatures": [], - "kind": 165, + "kind": 171, "description": "

States describing the arrow's animated position (animating fromState to toState).\nIf the fromState is not defined, there will be no animated transition to the toState.

\n", "rawdescription": "\n\nStates describing the arrow's animated position (animating fromState to toState).\nIf the fromState is not defined, there will be no animated transition to the toState.\n\n", - "methods": [] + "methods": [], + "extends": [] }, { "name": "CanColor", @@ -161,8 +164,9 @@ } ], "indexSignatures": [], - "kind": 165, - "methods": [] + "kind": 171, + "methods": [], + "extends": [] }, { "name": "CanDisable", @@ -185,17 +189,18 @@ } ], "indexSignatures": [], - "kind": 165, - "methods": [] + "kind": 171, + "methods": [], + "extends": [] }, { "name": "CanDisableRipple", - "id": "interface-CanDisableRipple-09c7af012755e2cbe32c19e029d36088c90b250a4a667073130015ffd19d8d3b13350c592c41d4d81cc528545a59eb2df34767f91c164fde8100e98da5e860f0", + "id": "interface-CanDisableRipple-4575677a5dcc30231c9f3c6f7e2854d9f2bed7be7afffb3454364604455730a63f3881b4e45660ecb4dedf4f516c0848b7bf3a3e6da229868ea8266a54940502", "file": "ui/src/components/core/common-behaviors/disable-ripple.ts", "deprecated": false, "deprecationMessage": "", "type": "interface", - "sourceCode": "import { coerceBooleanProperty } from '@angular/cdk/coercion';\nimport { AbstractConstructor, Constructor } from './constructor';\n\n/** @docs-private */\nexport interface CanDisableRipple {\n /** Whether ripples are disabled. */\n disableRipple: boolean;\n}\n\ntype CanDisableRippleCtor = Constructor &\n AbstractConstructor;\n\n/** Mixin to augment a directive with a `disableRipple` property. */\nexport function mixinDisableRipple>(\n base: T\n): CanDisableRippleCtor & T;\nexport function mixinDisableRipple>(\n base: T\n): CanDisableRippleCtor & T {\n return class extends base {\n private _disableRipple = false;\n\n /** Whether the ripple effect is disabled or not. */\n get disableRipple(): boolean {\n return this._disableRipple;\n }\n set disableRipple(value: any) {\n this._disableRipple = coerceBooleanProperty(value);\n }\n\n constructor(...args: any[]) {\n // eslint-disable-next-line @typescript-eslint/no-unsafe-argument\n super(...args);\n }\n };\n}\n", + "sourceCode": "import { coerceBooleanProperty } from '@angular/cdk/coercion';\r\nimport { AbstractConstructor, Constructor } from './constructor';\r\n\r\n/** @docs-private */\r\nexport interface CanDisableRipple {\r\n /** Whether ripples are disabled. */\r\n disableRipple: boolean;\r\n}\r\n\r\ntype CanDisableRippleCtor = Constructor &\r\n AbstractConstructor;\r\n\r\n/** Mixin to augment a directive with a `disableRipple` property. */\r\nexport function mixinDisableRipple>(\r\n base: T\r\n): CanDisableRippleCtor & T;\r\nexport function mixinDisableRipple>(\r\n base: T\r\n): CanDisableRippleCtor & T {\r\n return class extends base {\r\n private _disableRipple = false;\r\n\r\n /** Whether the ripple effect is disabled or not. */\r\n get disableRipple(): boolean {\r\n return this._disableRipple;\r\n }\r\n set disableRipple(value: any) {\r\n this._disableRipple = coerceBooleanProperty(value);\r\n }\r\n\r\n constructor(...args: any[]) {\r\n // eslint-disable-next-line @typescript-eslint/no-unsafe-argument\r\n super(...args);\r\n }\r\n };\r\n}\r\n", "properties": [ { "name": "disableRipple", @@ -209,8 +214,9 @@ } ], "indexSignatures": [], - "kind": 165, - "methods": [] + "kind": 171, + "methods": [], + "extends": [] }, { "name": "CanProgress", @@ -260,8 +266,9 @@ } ], "indexSignatures": [], - "kind": 165, - "methods": [] + "kind": 171, + "methods": [], + "extends": [] }, { "name": "CanUpdateErrorState", @@ -299,12 +306,12 @@ "description": "", "line": 13, "modifierKind": [ - 144 + 148 ] } ], "indexSignatures": [], - "kind": 167, + "kind": 173, "methods": [ { "name": "updateErrorState", @@ -316,7 +323,8 @@ "deprecated": false, "deprecationMessage": "" } - ] + ], + "extends": [] }, { "name": "DialogPosition", @@ -369,19 +377,20 @@ } ], "indexSignatures": [], - "kind": 165, + "kind": 171, "description": "

Possible overrides for a dialog's position.

\n", "rawdescription": "\nPossible overrides for a dialog's position.", - "methods": [] + "methods": [], + "extends": [] }, { "name": "GranularSanityChecks", - "id": "interface-GranularSanityChecks-faf3c2d5fa6ebca28372c7cb5b8112d9d13108d2e2811f5e27b343cdad3e494640760104bebf9faa35deae7c62ab89021cce2b1ce16b785f1cd5bd3271ba0044", + "id": "interface-GranularSanityChecks-ef22db41367b2c08b13c523be66ebd594c90c986a94f6990f23d6414cbbfc4a9e9dfe943acf905441d9051e0e19202026192cb30f79f93da1f2c6830ab030985", "file": "ui/src/components/core/common-behaviors/common-module.ts", "deprecated": false, "deprecationMessage": "", "type": "interface", - "sourceCode": "import { HighContrastModeDetector } from '@angular/cdk/a11y';\nimport { BidiModule } from '@angular/cdk/bidi';\nimport {\n inject,\n Inject,\n InjectionToken,\n NgModule,\n Optional,\n} from '@angular/core';\nimport { VERSION as CDK_VERSION } from '@angular/cdk';\nimport { DOCUMENT } from '@angular/common';\nimport { Platform, _isTestEnvironment } from '@angular/cdk/platform';\nimport { VERSION } from '../version';\nimport { isDevMode } from '@angular/core';\n\n/** @docs-private */\nexport function MATERIAL_SANITY_CHECKS_FACTORY(): SanityChecks {\n return true;\n}\n\n/** Injection token that configures whether the Material sanity checks are enabled. */\nexport const MATERIAL_SANITY_CHECKS = new InjectionToken(\n 'mat-sanity-checks',\n {\n providedIn: 'root',\n factory: MATERIAL_SANITY_CHECKS_FACTORY,\n }\n);\n\n/**\n * Possible sanity checks that can be enabled. If set to\n * true/false, all checks will be enabled/disabled.\n */\nexport type SanityChecks = boolean | GranularSanityChecks;\n\n/** Object that can be used to configure the sanity checks granularly. */\nexport interface GranularSanityChecks {\n doctype: boolean;\n theme: boolean;\n version: boolean;\n}\n\n/**\n * Module that captures anything that should be loaded and/or run for *all* Angular Material\n * components. This includes Bidi, etc.\n *\n * This module should be imported to each top-level component module (e.g., OuiTabsModule).\n */\n@NgModule({\n imports: [BidiModule],\n exports: [BidiModule],\n})\nexport class OuiCommonModule {\n /** Whether we've done the global sanity checks (e.g. a theme is loaded, there is a doctype). */\n private _hasDoneGlobalChecks = false;\n\n constructor(\n highContrastModeDetector: HighContrastModeDetector,\n @Optional()\n @Inject(MATERIAL_SANITY_CHECKS)\n private _sanityChecks: SanityChecks,\n @Inject(DOCUMENT) private _document: Document\n ) {\n // While A11yModule also does this, we repeat it here to avoid importing A11yModule\n // in OuiCommonModule.\n highContrastModeDetector._applyBodyHighContrastModeCssClasses();\n\n if (!this._hasDoneGlobalChecks) {\n this._hasDoneGlobalChecks = true;\n\n if (typeof isDevMode === 'undefined' || isDevMode) {\n // Inject in here so the reference to `Platform` can be removed in production mode.\n const platform = inject(Platform, { optional: true });\n\n if (this._checkIsEnabled('doctype')) {\n _checkDoctypeIsDefined(this._document);\n }\n\n if (this._checkIsEnabled('theme')) {\n _checkThemeIsPresent(this._document, !!platform?.isBrowser);\n }\n\n if (this._checkIsEnabled('version')) {\n _checkCdkVersionMatch();\n }\n }\n }\n }\n\n /** Gets whether a specific sanity check is enabled. */\n private _checkIsEnabled(name: keyof GranularSanityChecks): boolean {\n if (_isTestEnvironment()) {\n return false;\n }\n\n if (typeof this._sanityChecks === 'boolean') {\n return this._sanityChecks;\n }\n\n return !!this._sanityChecks[name];\n }\n}\n\n/** Checks that the page has a doctype. */\nfunction _checkDoctypeIsDefined(doc: Document): void {\n if (!doc.doctype) {\n console.warn(\n 'Current document does not have a doctype. This may cause ' +\n 'some Angular Material components not to behave as expected.'\n );\n }\n}\n\n/** Checks that a theme has been included. */\nfunction _checkThemeIsPresent(doc: Document, isBrowser: boolean): void {\n // We need to assert that the `body` is defined, because these checks run very early\n // and the `body` won't be defined if the consumer put their scripts in the `head`.\n if (!doc.body || !isBrowser) {\n return;\n }\n\n const testElement = doc.createElement('div');\n testElement.classList.add('mat-theme-loaded-marker');\n doc.body.appendChild(testElement);\n\n const computedStyle = getComputedStyle(testElement);\n\n // In some situations the computed style of the test element can be null. For example in\n // Firefox, the computed style is null if an application is running inside of a hidden iframe.\n // See: https://bugzilla.mozilla.org/show_bug.cgi?id=548397\n if (computedStyle && computedStyle.display !== 'none') {\n console.warn(\n 'Could not find Angular Material core theme. Most Material ' +\n 'components may not work as expected. For more info refer ' +\n 'to the theming guide: https://material.angular.io/guide/theming'\n );\n }\n\n testElement.remove();\n}\n\n/** Checks whether the Material version matches the CDK version. */\nfunction _checkCdkVersionMatch(): void {\n if (VERSION.full !== CDK_VERSION.full) {\n console.warn(\n 'The Angular Material version (' +\n VERSION.full +\n ') does not match ' +\n 'the Angular CDK version (' +\n CDK_VERSION.full +\n ').\\n' +\n 'Please ensure the versions of these two packages exactly match.'\n );\n }\n}\n", + "sourceCode": "import { HighContrastModeDetector } from '@angular/cdk/a11y';\r\nimport { BidiModule } from '@angular/cdk/bidi';\r\nimport {\r\n inject,\r\n Inject,\r\n InjectionToken,\r\n NgModule,\r\n Optional,\r\n} from '@angular/core';\r\nimport { VERSION as CDK_VERSION } from '@angular/cdk';\r\nimport { DOCUMENT } from '@angular/common';\r\nimport { Platform, _isTestEnvironment } from '@angular/cdk/platform';\r\nimport { VERSION } from '../version';\r\nimport { isDevMode } from '@angular/core';\r\n\r\n/** @docs-private */\r\nexport function MATERIAL_SANITY_CHECKS_FACTORY(): SanityChecks {\r\n return true;\r\n}\r\n\r\n/** Injection token that configures whether the Material sanity checks are enabled. */\r\nexport const MATERIAL_SANITY_CHECKS = new InjectionToken(\r\n 'mat-sanity-checks',\r\n {\r\n providedIn: 'root',\r\n factory: MATERIAL_SANITY_CHECKS_FACTORY,\r\n }\r\n);\r\n\r\n/**\r\n * Possible sanity checks that can be enabled. If set to\r\n * true/false, all checks will be enabled/disabled.\r\n */\r\nexport type SanityChecks = boolean | GranularSanityChecks;\r\n\r\n/** Object that can be used to configure the sanity checks granularly. */\r\nexport interface GranularSanityChecks {\r\n doctype: boolean;\r\n theme: boolean;\r\n version: boolean;\r\n}\r\n\r\n/**\r\n * Module that captures anything that should be loaded and/or run for *all* Angular Material\r\n * components. This includes Bidi, etc.\r\n *\r\n * This module should be imported to each top-level component module (e.g., OuiTabsModule).\r\n */\r\n@NgModule({\r\n imports: [BidiModule],\r\n exports: [BidiModule],\r\n})\r\nexport class OuiCommonModule {\r\n /** Whether we've done the global sanity checks (e.g. a theme is loaded, there is a doctype). */\r\n private _hasDoneGlobalChecks = false;\r\n\r\n constructor(\r\n highContrastModeDetector: HighContrastModeDetector,\r\n @Optional()\r\n @Inject(MATERIAL_SANITY_CHECKS)\r\n private _sanityChecks: SanityChecks,\r\n @Inject(DOCUMENT) private _document: Document\r\n ) {\r\n // While A11yModule also does this, we repeat it here to avoid importing A11yModule\r\n // in OuiCommonModule.\r\n highContrastModeDetector._applyBodyHighContrastModeCssClasses();\r\n\r\n if (!this._hasDoneGlobalChecks) {\r\n this._hasDoneGlobalChecks = true;\r\n\r\n if (typeof isDevMode === 'undefined' || isDevMode) {\r\n // Inject in here so the reference to `Platform` can be removed in production mode.\r\n const platform = inject(Platform, { optional: true });\r\n\r\n if (this._checkIsEnabled('doctype')) {\r\n _checkDoctypeIsDefined(this._document);\r\n }\r\n\r\n if (this._checkIsEnabled('theme')) {\r\n _checkThemeIsPresent(this._document, !!platform?.isBrowser);\r\n }\r\n\r\n if (this._checkIsEnabled('version')) {\r\n _checkCdkVersionMatch();\r\n }\r\n }\r\n }\r\n }\r\n\r\n /** Gets whether a specific sanity check is enabled. */\r\n private _checkIsEnabled(name: keyof GranularSanityChecks): boolean {\r\n if (_isTestEnvironment()) {\r\n return false;\r\n }\r\n\r\n if (typeof this._sanityChecks === 'boolean') {\r\n return this._sanityChecks;\r\n }\r\n\r\n return !!this._sanityChecks[name];\r\n }\r\n}\r\n\r\n/** Checks that the page has a doctype. */\r\nfunction _checkDoctypeIsDefined(doc: Document): void {\r\n if (!doc.doctype) {\r\n console.warn(\r\n 'Current document does not have a doctype. This may cause ' +\r\n 'some Angular Material components not to behave as expected.'\r\n );\r\n }\r\n}\r\n\r\n/** Checks that a theme has been included. */\r\nfunction _checkThemeIsPresent(doc: Document, isBrowser: boolean): void {\r\n // We need to assert that the `body` is defined, because these checks run very early\r\n // and the `body` won't be defined if the consumer put their scripts in the `head`.\r\n if (!doc.body || !isBrowser) {\r\n return;\r\n }\r\n\r\n const testElement = doc.createElement('div');\r\n testElement.classList.add('mat-theme-loaded-marker');\r\n doc.body.appendChild(testElement);\r\n\r\n const computedStyle = getComputedStyle(testElement);\r\n\r\n // In some situations the computed style of the test element can be null. For example in\r\n // Firefox, the computed style is null if an application is running inside of a hidden iframe.\r\n // See: https://bugzilla.mozilla.org/show_bug.cgi?id=548397\r\n if (computedStyle && computedStyle.display !== 'none') {\r\n console.warn(\r\n 'Could not find Angular Material core theme. Most Material ' +\r\n 'components may not work as expected. For more info refer ' +\r\n 'to the theming guide: https://material.angular.io/guide/theming'\r\n );\r\n }\r\n\r\n testElement.remove();\r\n}\r\n\r\n/** Checks whether the Material version matches the CDK version. */\r\nfunction _checkCdkVersionMatch(): void {\r\n if (VERSION.full !== CDK_VERSION.full) {\r\n console.warn(\r\n 'The Angular Material version (' +\r\n VERSION.full +\r\n ') does not match ' +\r\n 'the Angular CDK version (' +\r\n CDK_VERSION.full +\r\n ').\\n' +\r\n 'Please ensure the versions of these two packages exactly match.'\r\n );\r\n }\r\n}\r\n", "properties": [ { "name": "doctype", @@ -412,10 +421,11 @@ } ], "indexSignatures": [], - "kind": 165, + "kind": 171, "description": "

Object that can be used to configure the sanity checks granularly.

\n", "rawdescription": "\nObject that can be used to configure the sanity checks granularly.", - "methods": [] + "methods": [], + "extends": [] }, { "name": "HasElementRef", @@ -437,8 +447,9 @@ } ], "indexSignatures": [], - "kind": 165, - "methods": [] + "kind": 171, + "methods": [], + "extends": [] }, { "name": "HasElementRef", @@ -460,8 +471,9 @@ } ], "indexSignatures": [], - "kind": 165, + "kind": 171, "methods": [], + "extends": [], "isDuplicate": true, "duplicateId": 1, "duplicateName": "HasElementRef-1" @@ -513,8 +525,9 @@ } ], "indexSignatures": [], - "kind": 165, - "methods": [] + "kind": 171, + "methods": [], + "extends": [] }, { "name": "HasInitialized", @@ -538,17 +551,17 @@ { "pos": 738, "end": 755, - "flags": 4194304, + "flags": 16777216, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 325, + "kind": 334, "tagName": { "pos": 739, "end": 751, - "flags": 4194304, + "flags": 16777216, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "docs-private" }, "comment": "" @@ -567,10 +580,11 @@ } ], "indexSignatures": [], - "kind": 165, + "kind": 171, "description": "

Mixin that adds an initialized property to a directive which, when subscribed to, will emit a\nvalue once markInitialized has been called, which should be done during the ngOnInit function.\nIf the subscription is made after it has already been marked as initialized, then it will trigger\nan emit immediately.

\n", "rawdescription": "\n\nMixin that adds an initialized property to a directive which, when subscribed to, will emit a\nvalue once markInitialized has been called, which should be done during the ngOnInit function.\nIf the subscription is made after it has already been marked as initialized, then it will trigger\nan emit immediately.\n\n", - "methods": [] + "methods": [], + "extends": [] }, { "name": "HasTabIndex", @@ -593,17 +607,18 @@ } ], "indexSignatures": [], - "kind": 165, - "methods": [] + "kind": 171, + "methods": [], + "extends": [] }, { "name": "MatInkBarItem", - "id": "interface-MatInkBarItem-135c8ccdab508fcf19b684306b7b52fe3cacc460ac2081644d8b0d211b3fb9a93c581e6b1e98ed9fdc3965312903a402f79f7ef73e228a1ef8f3bd236d89976f", + "id": "interface-MatInkBarItem-50fe2f1bca65db33aac094b14b277a02924ff4199f4bfe029de4c7e70c55f0d0b3d8f03cc04d8961159c28f0d20d52a85a2edbaf9f6b9506a466792860b45ccf", "file": "ui/src/components/tabs/ink-bar.ts", "deprecated": false, "deprecationMessage": "", "type": "interface", - "sourceCode": "import { BooleanInput, coerceBooleanProperty } from '@angular/cdk/coercion';\nimport {\n ElementRef,\n InjectionToken,\n OnDestroy,\n OnInit,\n QueryList,\n} from '@angular/core';\nimport { isDevMode } from '@angular/core';\n\n/**\n * Item inside a tab header relative to which the ink bar can be aligned.\n * @docs-private\n */\nexport interface MatInkBarItem extends OnInit, OnDestroy {\n elementRef: ElementRef;\n activateInkBar(previousIndicatorClientRect?: ClientRect): void;\n deactivateInkBar(): void;\n fitInkBarToContent: boolean;\n}\n\n/** Class that is applied when a tab indicator is active. */\nconst ACTIVE_CLASS = 'mdc-tab-indicator--active';\n\n/** Class that is applied when the tab indicator should not transition. */\nconst NO_TRANSITION_CLASS = 'mdc-tab-indicator--no-transition';\n\n/**\n * Abstraction around the MDC tab indicator that acts as the tab header's ink bar.\n * @docs-private\n */\nexport class OuiInkBar {\n /** Item to which the ink bar is aligned currently. */\n private _currentItem: MatInkBarItem | undefined;\n\n constructor(private _items: QueryList) {}\n\n /** Hides the ink bar. */\n hide() {\n this._items.forEach((item) => item.deactivateInkBar());\n }\n\n /** Aligns the ink bar to a DOM node. */\n alignToElement(element: HTMLElement) {\n const correspondingItem = this._items.find(\n (item) => item.elementRef.nativeElement === element\n );\n const currentItem = this._currentItem;\n\n if (correspondingItem === currentItem) {\n return;\n }\n\n currentItem?.deactivateInkBar();\n\n if (correspondingItem) {\n const clientRect =\n currentItem?.elementRef.nativeElement.getBoundingClientRect?.();\n\n // The ink bar won't animate unless we give it the `ClientRect` of the previous item.\n correspondingItem.activateInkBar(clientRect);\n this._currentItem = correspondingItem;\n }\n }\n}\n\n/**\n * Mixin that can be used to apply the `MatInkBarItem` behavior to a class.\n * Base on MDC's `MDCSlidingTabIndicatorFoundation`:\n * https://github.com/material-components/material-components-web/blob/c0a11ef0d000a098fd0c372be8f12d6a99302855/packages/mdc-tab-indicator/sliding-foundation.ts\n * @docs-private\n */\nexport function mixinInkBarItem<\n T extends new (...args: any[]) => { elementRef: ElementRef }\n>(base: T): T & (new (...args: any[]) => MatInkBarItem) {\n return class extends base {\n constructor(...args: any[]) {\n // eslint-disable-next-line @typescript-eslint/no-unsafe-argument\n super(...args);\n }\n\n private _inkBarElement: HTMLElement | null;\n private _inkBarContentElement: HTMLElement | null;\n private _fitToContent = false;\n\n /** Whether the ink bar should fit to the entire tab or just its content. */\n get fitInkBarToContent(): boolean {\n return this._fitToContent;\n }\n set fitInkBarToContent(v: BooleanInput) {\n const newValue = coerceBooleanProperty(v);\n\n if (this._fitToContent !== newValue) {\n this._fitToContent = newValue;\n\n if (this._inkBarElement) {\n this._appendInkBarElement();\n }\n }\n }\n\n /** Aligns the ink bar to the current item. */\n activateInkBar(previousIndicatorClientRect?: ClientRect) {\n const element = this.elementRef.nativeElement;\n\n // Early exit if no indicator is present to handle cases where an indicator\n // may be activated without a prior indicator state\n if (\n !previousIndicatorClientRect ||\n !element.getBoundingClientRect ||\n !this._inkBarContentElement\n ) {\n element.classList.add(ACTIVE_CLASS);\n return;\n }\n\n // This animation uses the FLIP approach. You can read more about it at the link below:\n // https://aerotwist.com/blog/flip-your-animations/\n\n // Calculate the dimensions based on the dimensions of the previous indicator\n const currentClientRect = element.getBoundingClientRect();\n const widthDelta =\n previousIndicatorClientRect.width / currentClientRect.width;\n const xPosition =\n previousIndicatorClientRect.left - currentClientRect.left;\n element.classList.add(NO_TRANSITION_CLASS);\n this._inkBarContentElement.style.setProperty(\n 'transform',\n `translateX(${xPosition}px) scaleX(${widthDelta})`\n );\n\n // Force repaint before updating classes and transform to ensure the transform properly takes effect\n element.getBoundingClientRect();\n\n element.classList.remove(NO_TRANSITION_CLASS);\n element.classList.add(ACTIVE_CLASS);\n this._inkBarContentElement.style.setProperty('transform', '');\n }\n\n /** Removes the ink bar from the current item. */\n deactivateInkBar() {\n this.elementRef.nativeElement.classList.remove(ACTIVE_CLASS);\n }\n\n /** Initializes the foundation. */\n ngOnInit() {\n this._createInkBarElement();\n }\n\n /** Destroys the foundation. */\n ngOnDestroy() {\n this._inkBarElement?.remove();\n this._inkBarElement = this._inkBarContentElement = null!;\n }\n\n /** Creates and appends the ink bar element. */\n private _createInkBarElement() {\n const documentNode =\n this.elementRef.nativeElement.ownerDocument || document;\n this._inkBarElement = documentNode.createElement('span');\n this._inkBarContentElement = documentNode.createElement('span');\n\n this._inkBarElement.className = 'mdc-tab-indicator';\n this._inkBarContentElement.className =\n 'mdc-tab-indicator__content mdc-tab-indicator__content--underline';\n\n this._inkBarElement.appendChild(this._inkBarContentElement);\n this._appendInkBarElement();\n }\n\n /**\n * Appends the ink bar to the tab host element or content, depending on whether\n * the ink bar should fit to content.\n */\n private _appendInkBarElement() {\n if (\n !this._inkBarElement &&\n (typeof isDevMode === 'undefined' || isDevMode)\n ) {\n throw Error(\n 'Ink bar element has not been created and cannot be appended'\n );\n }\n\n const parentElement = this._fitToContent\n ? this.elementRef.nativeElement.querySelector('.mdc-tab__content')\n : this.elementRef.nativeElement;\n\n if (!parentElement && (typeof isDevMode === 'undefined' || isDevMode)) {\n throw Error('Missing element to host the ink bar');\n }\n\n parentElement!.appendChild(this._inkBarElement!);\n }\n };\n}\n\n/**\n * Interface for a OuiInkBar positioner method, defining the positioning and width of the ink\n * bar in a set of tabs.\n */\nexport interface _OuiInkBarPositioner {\n (element: HTMLElement): { left: string; width: string };\n}\n\n/**\n * The default positioner function for the OuiInkBar.\n * @docs-private\n */\nexport function _OUI_INK_BAR_POSITIONER_FACTORY(): _OuiInkBarPositioner {\n const method = (element: HTMLElement) => ({\n // eslint-disable-next-line @typescript-eslint/restrict-plus-operands\n left: element ? (element.offsetLeft || 0) + 'px' : '0',\n // eslint-disable-next-line @typescript-eslint/restrict-plus-operands\n width: element ? (element.offsetWidth || 0) + 'px' : '0',\n });\n\n return method;\n}\n\n/** Injection token for the OuiInkBar's Positioner. */\nexport const _OUI_INK_BAR_POSITIONER = new InjectionToken<_OuiInkBarPositioner>(\n 'MatInkBarPositioner',\n {\n providedIn: 'root',\n factory: _OUI_INK_BAR_POSITIONER_FACTORY,\n }\n);\n", + "sourceCode": "import { BooleanInput, coerceBooleanProperty } from '@angular/cdk/coercion';\r\nimport {\r\n ElementRef,\r\n InjectionToken,\r\n OnDestroy,\r\n OnInit,\r\n QueryList,\r\n} from '@angular/core';\r\nimport { isDevMode } from '@angular/core';\r\n\r\n/**\r\n * Item inside a tab header relative to which the ink bar can be aligned.\r\n * @docs-private\r\n */\r\nexport interface MatInkBarItem extends OnInit, OnDestroy {\r\n elementRef: ElementRef;\r\n activateInkBar(previousIndicatorClientRect?: ClientRect): void;\r\n deactivateInkBar(): void;\r\n fitInkBarToContent: boolean;\r\n}\r\n\r\n/** Class that is applied when a tab indicator is active. */\r\nconst ACTIVE_CLASS = 'mdc-tab-indicator--active';\r\n\r\n/** Class that is applied when the tab indicator should not transition. */\r\nconst NO_TRANSITION_CLASS = 'mdc-tab-indicator--no-transition';\r\n\r\n/**\r\n * Abstraction around the MDC tab indicator that acts as the tab header's ink bar.\r\n * @docs-private\r\n */\r\nexport class OuiInkBar {\r\n /** Item to which the ink bar is aligned currently. */\r\n private _currentItem: MatInkBarItem | undefined;\r\n\r\n constructor(private _items: QueryList) {}\r\n\r\n /** Hides the ink bar. */\r\n hide() {\r\n this._items.forEach((item) => item.deactivateInkBar());\r\n }\r\n\r\n /** Aligns the ink bar to a DOM node. */\r\n alignToElement(element: HTMLElement) {\r\n const correspondingItem = this._items.find(\r\n (item) => item.elementRef.nativeElement === element\r\n );\r\n const currentItem = this._currentItem;\r\n\r\n if (correspondingItem === currentItem) {\r\n return;\r\n }\r\n\r\n currentItem?.deactivateInkBar();\r\n\r\n if (correspondingItem) {\r\n const clientRect =\r\n currentItem?.elementRef.nativeElement.getBoundingClientRect?.();\r\n\r\n // The ink bar won't animate unless we give it the `ClientRect` of the previous item.\r\n correspondingItem.activateInkBar(clientRect);\r\n this._currentItem = correspondingItem;\r\n }\r\n }\r\n}\r\n\r\n/**\r\n * Mixin that can be used to apply the `MatInkBarItem` behavior to a class.\r\n * Base on MDC's `MDCSlidingTabIndicatorFoundation`:\r\n * https://github.com/material-components/material-components-web/blob/c0a11ef0d000a098fd0c372be8f12d6a99302855/packages/mdc-tab-indicator/sliding-foundation.ts\r\n * @docs-private\r\n */\r\nexport function mixinInkBarItem<\r\n T extends new (...args: any[]) => { elementRef: ElementRef }\r\n>(base: T): T & (new (...args: any[]) => MatInkBarItem) {\r\n return class extends base {\r\n constructor(...args: any[]) {\r\n // eslint-disable-next-line @typescript-eslint/no-unsafe-argument\r\n super(...args);\r\n }\r\n\r\n private _inkBarElement: HTMLElement | null;\r\n private _inkBarContentElement: HTMLElement | null;\r\n private _fitToContent = false;\r\n\r\n /** Whether the ink bar should fit to the entire tab or just its content. */\r\n get fitInkBarToContent(): boolean {\r\n return this._fitToContent;\r\n }\r\n set fitInkBarToContent(v: BooleanInput) {\r\n const newValue = coerceBooleanProperty(v);\r\n\r\n if (this._fitToContent !== newValue) {\r\n this._fitToContent = newValue;\r\n\r\n if (this._inkBarElement) {\r\n this._appendInkBarElement();\r\n }\r\n }\r\n }\r\n\r\n /** Aligns the ink bar to the current item. */\r\n activateInkBar(previousIndicatorClientRect?: ClientRect) {\r\n const element = this.elementRef.nativeElement;\r\n\r\n // Early exit if no indicator is present to handle cases where an indicator\r\n // may be activated without a prior indicator state\r\n if (\r\n !previousIndicatorClientRect ||\r\n !element.getBoundingClientRect ||\r\n !this._inkBarContentElement\r\n ) {\r\n element.classList.add(ACTIVE_CLASS);\r\n return;\r\n }\r\n\r\n // This animation uses the FLIP approach. You can read more about it at the link below:\r\n // https://aerotwist.com/blog/flip-your-animations/\r\n\r\n // Calculate the dimensions based on the dimensions of the previous indicator\r\n const currentClientRect = element.getBoundingClientRect();\r\n const widthDelta =\r\n previousIndicatorClientRect.width / currentClientRect.width;\r\n const xPosition =\r\n previousIndicatorClientRect.left - currentClientRect.left;\r\n element.classList.add(NO_TRANSITION_CLASS);\r\n this._inkBarContentElement.style.setProperty(\r\n 'transform',\r\n `translateX(${xPosition}px) scaleX(${widthDelta})`\r\n );\r\n\r\n // Force repaint before updating classes and transform to ensure the transform properly takes effect\r\n element.getBoundingClientRect();\r\n\r\n element.classList.remove(NO_TRANSITION_CLASS);\r\n element.classList.add(ACTIVE_CLASS);\r\n this._inkBarContentElement.style.setProperty('transform', '');\r\n }\r\n\r\n /** Removes the ink bar from the current item. */\r\n deactivateInkBar() {\r\n this.elementRef.nativeElement.classList.remove(ACTIVE_CLASS);\r\n }\r\n\r\n /** Initializes the foundation. */\r\n ngOnInit() {\r\n this._createInkBarElement();\r\n }\r\n\r\n /** Destroys the foundation. */\r\n ngOnDestroy() {\r\n this._inkBarElement?.remove();\r\n this._inkBarElement = this._inkBarContentElement = null!;\r\n }\r\n\r\n /** Creates and appends the ink bar element. */\r\n private _createInkBarElement() {\r\n const documentNode =\r\n this.elementRef.nativeElement.ownerDocument || document;\r\n this._inkBarElement = documentNode.createElement('span');\r\n this._inkBarContentElement = documentNode.createElement('span');\r\n\r\n this._inkBarElement.className = 'mdc-tab-indicator';\r\n this._inkBarContentElement.className =\r\n 'mdc-tab-indicator__content mdc-tab-indicator__content--underline';\r\n\r\n this._inkBarElement.appendChild(this._inkBarContentElement);\r\n this._appendInkBarElement();\r\n }\r\n\r\n /**\r\n * Appends the ink bar to the tab host element or content, depending on whether\r\n * the ink bar should fit to content.\r\n */\r\n private _appendInkBarElement() {\r\n if (\r\n !this._inkBarElement &&\r\n (typeof isDevMode === 'undefined' || isDevMode)\r\n ) {\r\n throw Error(\r\n 'Ink bar element has not been created and cannot be appended'\r\n );\r\n }\r\n\r\n const parentElement = this._fitToContent\r\n ? this.elementRef.nativeElement.querySelector('.mdc-tab__content')\r\n : this.elementRef.nativeElement;\r\n\r\n if (!parentElement && (typeof isDevMode === 'undefined' || isDevMode)) {\r\n throw Error('Missing element to host the ink bar');\r\n }\r\n\r\n parentElement!.appendChild(this._inkBarElement!);\r\n }\r\n };\r\n}\r\n\r\n/**\r\n * Interface for a OuiInkBar positioner method, defining the positioning and width of the ink\r\n * bar in a set of tabs.\r\n */\r\nexport interface _OuiInkBarPositioner {\r\n (element: HTMLElement): { left: string; width: string };\r\n}\r\n\r\n/**\r\n * The default positioner function for the OuiInkBar.\r\n * @docs-private\r\n */\r\nexport function _OUI_INK_BAR_POSITIONER_FACTORY(): _OuiInkBarPositioner {\r\n const method = (element: HTMLElement) => ({\r\n // eslint-disable-next-line @typescript-eslint/restrict-plus-operands\r\n left: element ? (element.offsetLeft || 0) + 'px' : '0',\r\n // eslint-disable-next-line @typescript-eslint/restrict-plus-operands\r\n width: element ? (element.offsetWidth || 0) + 'px' : '0',\r\n });\r\n\r\n return method;\r\n}\r\n\r\n/** Injection token for the OuiInkBar's Positioner. */\r\nexport const _OUI_INK_BAR_POSITIONER = new InjectionToken<_OuiInkBarPositioner>(\r\n 'MatInkBarPositioner',\r\n {\r\n providedIn: 'root',\r\n factory: _OUI_INK_BAR_POSITIONER_FACTORY,\r\n }\r\n);\r\n", "properties": [ { "name": "elementRef", @@ -625,7 +640,7 @@ } ], "indexSignatures": [], - "kind": 165, + "kind": 171, "description": "

Item inside a tab header relative to which the ink bar can be aligned.

\n", "rawdescription": "\n\nItem inside a tab header relative to which the ink bar can be aligned.\n", "methods": [ @@ -670,7 +685,10 @@ "deprecationMessage": "" } ], - "extends": "OnInit" + "extends": [ + "OnInit", + "OnDestroy" + ] }, { "name": "NewCSSStyleDeclaration", @@ -692,9 +710,11 @@ } ], "indexSignatures": [], - "kind": 165, + "kind": 171, "methods": [], - "extends": "CSSStyleDeclaration" + "extends": [ + "CSSStyleDeclaration" + ] }, { "name": "OuiAutocompleteDefaultOptions", @@ -717,10 +737,11 @@ } ], "indexSignatures": [], - "kind": 165, + "kind": 171, "description": "

Default oui-autocomplete options that can be overridden.

\n", "rawdescription": "\nDefault `oui-autocomplete` options that can be overridden.", - "methods": [] + "methods": [], + "extends": [] }, { "name": "OuiFormFieldDefaultOptions", @@ -742,10 +763,11 @@ } ], "indexSignatures": [], - "kind": 165, + "kind": 171, "description": "

Represents the default options form the form field that can be configured\nusing the OUI_FORM_FIELD_DEFAULT_OPTIONS injection token.

\n", "rawdescription": "\n\nRepresents the default options form the form field that can be configured\nusing the `OUI_FORM_FIELD_DEFAULT_OPTIONS` injection token.\n", - "methods": [] + "methods": [], + "extends": [] }, { "name": "OuiIconLocation", @@ -767,10 +789,11 @@ } ], "indexSignatures": [], - "kind": 165, + "kind": 171, "description": "

Stubbed out location for OuiIcon.

\n", "rawdescription": "\n\nStubbed out location for `OuiIcon`.\n\n", - "methods": [] + "methods": [], + "extends": [] }, { "name": "OuiMenuDefaultOptions", @@ -833,10 +856,11 @@ } ], "indexSignatures": [], - "kind": 165, + "kind": 171, "description": "

Default oui-menu options that can be overridden.

\n", "rawdescription": "\nDefault `oui-menu` options that can be overridden.", - "methods": [] + "methods": [], + "extends": [] }, { "name": "OuiMenuPanel", @@ -975,10 +999,11 @@ } ], "indexSignatures": [], - "kind": 165, + "kind": 171, "description": "

Interface for a custom menu panel that can be used with ouiMenuTriggerFor.

\n", "rawdescription": "\n\nInterface for a custom menu panel that can be used with `ouiMenuTriggerFor`.\n\n", - "methods": [] + "methods": [], + "extends": [] }, { "name": "OuiOptionParentComponent", @@ -1000,19 +1025,20 @@ } ], "indexSignatures": [], - "kind": 165, + "kind": 171, "description": "

Describes a parent component that manages a list of options.\nContains properties that the options can inherit.

\n", "rawdescription": "\n\nDescribes a parent component that manages a list of options.\nContains properties that the options can inherit.\n\n", - "methods": [] + "methods": [], + "extends": [] }, { "name": "OuiPanelDefaultOptions", - "id": "interface-OuiPanelDefaultOptions-75834551469a77f2f75f2c9c42d0de964ac0ed9710e9d05128f9c9784e8e494b743a4a79301ee2a9f23c2c02744b30e7f33d4244928766088870a565b9863ed3", + "id": "interface-OuiPanelDefaultOptions-065bb74cd1fa7f57341de83af5abd480b4a05e128e287e5f54c73e268d54b3b383070ce1cfa253877356eca1debdca5c7fc6658f6f2f2690c8fd1b55a9d5486e", "file": "ui/src/components/panel/panel.ts", "deprecated": false, "deprecationMessage": "", "type": "interface", - "sourceCode": "import {\n ChangeDetectionStrategy,\n ViewEncapsulation,\n Component,\n InjectionToken,\n Inject,\n Input,\n ViewChild,\n TemplateRef,\n OnInit,\n ContentChild,\n Output,\n EventEmitter,\n Attribute,\n NgZone,\n ElementRef,\n OnDestroy,\n} from '@angular/core';\nimport { PanelPositionX, PanelPositionY } from './panel-positions';\nimport {\n throwOuiPanelInvalidPositionX,\n throwOuiPanelInvalidPositionY,\n} from './panel-errors';\nimport { OuiPanelOverlay } from './panel-overlay';\nimport { OuiPanelContent } from './panel-content';\nimport { Subject, Observable, Subscription } from 'rxjs';\nimport { OuiIconRegistry } from '../icon/icon-registery';\nimport { DomSanitizer } from '@angular/platform-browser';\nimport { ICONS } from '../core/shared/icons';\nimport { FocusMonitor } from '@angular/cdk/a11y';\n\n/** Default `oui-panel` options that can be overridden. */\nexport interface OuiPanelDefaultOptions {\n /** The x-axis position of the menu. */\n xPosition: PanelPositionX;\n\n /** The y-axis position of the menu. */\n yPosition: PanelPositionY;\n}\n\n/** Injection token to be used to override the default options for `oui-menu`. */\nexport const OUI_PANEL_DEFAULT_OPTIONS =\n new InjectionToken('oui-panel-default-options', {\n providedIn: 'root',\n factory: OUI_PANEL_DEFAULT_OPTIONS_FACTORY,\n });\n\n/** @docs-private */\nexport function OUI_PANEL_DEFAULT_OPTIONS_FACTORY(): OuiPanelDefaultOptions {\n return {\n xPosition: 'after',\n yPosition: 'below',\n };\n}\n\n@Component({\n selector: 'oui-panel',\n templateUrl: 'panel.html',\n styleUrls: ['panel.scss'],\n changeDetection: ChangeDetectionStrategy.OnPush,\n encapsulation: ViewEncapsulation.None,\n exportAs: 'ouiPanel',\n})\nexport class OuiPanel implements OnInit, OuiPanelOverlay {\n private _xPosition: PanelPositionX = this._defaultOptions.xPosition;\n private _yPosition: PanelPositionY = this._defaultOptions.yPosition;\n private readonly _mouseLeave: Subject = new Subject();\n public mouseLeave: Observable;\n private readonly _mouseEnter: Subject = new Subject();\n public mouseEnter: Observable;\n public escapeEvent: Subject = new Subject();\n\n @Input() width?: number;\n\n /** Config object to be passed into the menu's ngClass */\n _classList: { [key: string]: boolean } = {};\n\n @ViewChild(TemplateRef)\n templateRef: TemplateRef;\n\n /**\n * Panel content that will be rendered lazily.\n *\n * @docs-private\n */\n @ContentChild(OuiPanelContent)\n lazyContent: OuiPanelContent;\n\n /** Event emitted when the menu is closed. */\n @Output()\n readonly closed: EventEmitter = new EventEmitter();\n\n /** Position of the menu in the X axis. */\n @Input()\n get xPosition(): PanelPositionX {\n return this._xPosition;\n }\n set xPosition(value: PanelPositionX) {\n if (value !== 'before' && value !== 'after') {\n throwOuiPanelInvalidPositionX();\n }\n this._xPosition = value;\n this.setPositionClasses();\n }\n\n /** Position of the menu in the Y axis. */\n @Input()\n get yPosition(): PanelPositionY {\n return this._yPosition;\n }\n set yPosition(value: PanelPositionY) {\n if (value !== 'above' && value !== 'below') {\n throwOuiPanelInvalidPositionY();\n }\n this._yPosition = value;\n this.setPositionClasses();\n }\n constructor(\n @Inject(OUI_PANEL_DEFAULT_OPTIONS)\n private _defaultOptions: OuiPanelDefaultOptions\n ) {\n this.mouseLeave = this._mouseLeave.asObservable();\n this.mouseEnter = this._mouseEnter.asObservable();\n }\n\n ngOnInit() {\n this.setPositionClasses();\n }\n\n /**\n * Adds classes to the panel-overlay based on its position. Can be used by\n * consumers to add specific styling based on the position.\n *\n * @param posX Position of the panel along the x axis.\n * @param posY Position of the panel along the y axis.\n * @docs-private\n */\n setPositionClasses(\n posX: PanelPositionX = this.xPosition,\n posY: PanelPositionY = this.yPosition\n ) {\n const classes = this._classList;\n classes['oui-panel-before'] = posX === 'before';\n classes['oui-panel-after'] = posX === 'after';\n classes['oui-panel-above'] = posY === 'above';\n classes['oui-panel-below'] = posY === 'below';\n }\n\n public _handleMouseLeave(event: MouseEvent) {\n this._mouseLeave.next(event);\n }\n\n public _handleMouseEnter(event: MouseEvent) {\n this._mouseEnter.next(event);\n }\n\n public _handleCloseIcon() {\n this.escapeEvent.next();\n }\n}\n\n@Component({\n selector: 'oui-panel-icon',\n template:\n '',\n styleUrls: ['panel.scss'],\n changeDetection: ChangeDetectionStrategy.OnPush,\n encapsulation: ViewEncapsulation.None,\n exportAs: 'ouiPanelIcon',\n})\nexport class OuiPanelIcon implements OnDestroy {\n private _monitorSubscription: Subscription = Subscription.EMPTY;\n tabIndex: any;\n constructor(\n private _elementRef: ElementRef,\n private ouiIconRegistry: OuiIconRegistry,\n private domSanitizer: DomSanitizer,\n private _focusMonitor: FocusMonitor,\n private _ngZone: NgZone,\n @Attribute('tabindex') tabIndex: string\n ) {\n this.tabIndex = parseInt(tabIndex, 10) || 0;\n this._monitorSubscription = this._focusMonitor\n .monitor(this._elementRef, true)\n .subscribe(() => this._ngZone.run(() => {}));\n\n this.ouiIconRegistry.addSvgIconLiteral(\n `panel-icon`,\n this.domSanitizer.bypassSecurityTrustHtml(ICONS.PANEL_ICON)\n );\n this.ouiIconRegistry.addSvgIconLiteral(\n `close-icon_8X8`,\n this.domSanitizer.bypassSecurityTrustHtml(ICONS.CLOSE_ICON_8X8)\n );\n }\n\n ngOnDestroy() {\n this._focusMonitor.stopMonitoring(this._elementRef.nativeElement);\n this._monitorSubscription.unsubscribe();\n }\n}\n", + "sourceCode": "import {\n ChangeDetectionStrategy,\n ViewEncapsulation,\n Component,\n InjectionToken,\n Inject,\n Input,\n ViewChild,\n TemplateRef,\n OnInit,\n ContentChild,\n Output,\n EventEmitter,\n Attribute,\n NgZone,\n ElementRef,\n OnDestroy,\n} from '@angular/core';\nimport { PanelPositionX, PanelPositionY } from './panel-positions';\nimport {\n throwOuiPanelInvalidPositionX,\n throwOuiPanelInvalidPositionY,\n} from './panel-errors';\nimport { OuiPanelOverlay } from './panel-overlay';\nimport { OuiPanelContent } from './panel-content';\nimport { Subject, Observable, Subscription } from 'rxjs';\nimport { OuiIconRegistry } from '../icon/icon-registery';\nimport { DomSanitizer } from '@angular/platform-browser';\nimport { ICONS } from '../core/shared/icons';\nimport { FocusMonitor } from '@angular/cdk/a11y';\n\n/** Default `oui-panel` options that can be overridden. */\nexport interface OuiPanelDefaultOptions {\n /** The x-axis position of the menu. */\n xPosition: PanelPositionX;\n\n /** The y-axis position of the menu. */\n yPosition: PanelPositionY;\n}\n\n/** Injection token to be used to override the default options for `oui-menu`. */\nexport const OUI_PANEL_DEFAULT_OPTIONS =\n new InjectionToken('oui-panel-default-options', {\n providedIn: 'root',\n factory: OUI_PANEL_DEFAULT_OPTIONS_FACTORY,\n });\n\n/** @docs-private */\nexport function OUI_PANEL_DEFAULT_OPTIONS_FACTORY(): OuiPanelDefaultOptions {\n return {\n xPosition: 'after',\n yPosition: 'below',\n };\n}\n\n@Component({\n selector: 'oui-panel',\n templateUrl: 'panel.html',\n styleUrls: ['panel.scss'],\n changeDetection: ChangeDetectionStrategy.OnPush,\n encapsulation: ViewEncapsulation.None,\n exportAs: 'ouiPanel',\n})\nexport class OuiPanel implements OnInit, OuiPanelOverlay {\n private _xPosition: PanelPositionX = this._defaultOptions.xPosition;\n private _yPosition: PanelPositionY = this._defaultOptions.yPosition;\n private readonly _mouseLeave: Subject = new Subject();\n public mouseLeave: Observable;\n private readonly _mouseEnter: Subject = new Subject();\n public mouseEnter: Observable;\n public escapeEvent: Subject = new Subject();\n\n @Input() width?: number;\n\n /** Config object to be passed into the menu's ngClass */\n _classList: { [key: string]: boolean } = {};\n\n @ViewChild(TemplateRef)\n templateRef: TemplateRef;\n\n /**\n * Panel content that will be rendered lazily.\n *\n * @docs-private\n */\n @ContentChild(OuiPanelContent)\n lazyContent: OuiPanelContent;\n\n /** Event emitted when the menu is closed. */\n @Output()\n readonly closed: EventEmitter = new EventEmitter();\n\n /** Position of the menu in the X axis. */\n @Input()\n get xPosition(): PanelPositionX {\n return this._xPosition;\n }\n set xPosition(value: PanelPositionX) {\n if (value !== 'before' && value !== 'after') {\n throwOuiPanelInvalidPositionX();\n }\n this._xPosition = value;\n this.setPositionClasses();\n }\n\n /** Position of the menu in the Y axis. */\n @Input()\n get yPosition(): PanelPositionY {\n return this._yPosition;\n }\n set yPosition(value: PanelPositionY) {\n if (value !== 'above' && value !== 'below') {\n throwOuiPanelInvalidPositionY();\n }\n this._yPosition = value;\n this.setPositionClasses();\n }\n constructor(\n @Inject(OUI_PANEL_DEFAULT_OPTIONS)\n private _defaultOptions: OuiPanelDefaultOptions\n ) {\n this.mouseLeave = this._mouseLeave.asObservable();\n this.mouseEnter = this._mouseEnter.asObservable();\n }\n\n ngOnInit() {\n this.setPositionClasses();\n }\n\n /**\n * Adds classes to the panel-overlay based on its position. Can be used by\n * consumers to add specific styling based on the position.\n *\n * @param posX Position of the panel along the x axis.\n * @param posY Position of the panel along the y axis.\n * @docs-private\n */\n setPositionClasses(\n posX: PanelPositionX = this.xPosition,\n posY: PanelPositionY = this.yPosition\n ) {\n const classes = this._classList;\n classes['oui-panel-before'] = posX === 'before';\n classes['oui-panel-after'] = posX === 'after';\n classes['oui-panel-above'] = posY === 'above';\n classes['oui-panel-below'] = posY === 'below';\n }\n\n public _handleMouseLeave(event: MouseEvent) {\n this._mouseLeave.next(event);\n }\n\n public _handleMouseEnter(event: MouseEvent) {\n this._mouseEnter.next(event);\n }\n\n public _handleCloseIcon() {\n this.escapeEvent.next();\n }\n}\n\n@Component({\n selector: 'oui-panel-icon',\n template:\n '',\n styleUrls: ['panel.scss'],\n changeDetection: ChangeDetectionStrategy.OnPush,\n encapsulation: ViewEncapsulation.None,\n exportAs: 'ouiPanelIcon',\n})\nexport class OuiPanelIcon implements OnDestroy {\n private _monitorSubscription: Subscription = Subscription.EMPTY;\n tabIndex: any;\n constructor(\n private _elementRef: ElementRef,\n private ouiIconRegistry: OuiIconRegistry,\n private domSanitizer: DomSanitizer,\n private _focusMonitor: FocusMonitor,\n private _ngZone: NgZone,\n @Attribute('tabindex') tabIndex: string\n ) {\n this.tabIndex = parseInt(tabIndex, 10) || 0;\n this._monitorSubscription = this._focusMonitor\n .monitor(this._elementRef, true)\n .subscribe(() => this._ngZone.run(() => {}));\n\n this.ouiIconRegistry.addSvgIconLiteral(\n `panel-icon`,\n this.domSanitizer.bypassSecurityTrustHtml(ICONS.PANEL_ICON)\n );\n this.ouiIconRegistry.addSvgIconLiteral(\n `close-icon_8X8`,\n this.domSanitizer.bypassSecurityTrustHtml(ICONS.CLOSE_ICON_8X8)\n );\n }\n\n ngOnDestroy() {\n this._focusMonitor.stopMonitoring(this._elementRef.nativeElement);\n this._monitorSubscription.unsubscribe();\n }\n}\n", "properties": [ { "name": "xPosition", @@ -1036,10 +1062,11 @@ } ], "indexSignatures": [], - "kind": 165, + "kind": 171, "description": "

Default oui-panel options that can be overridden.

\n", "rawdescription": "\nDefault `oui-panel` options that can be overridden.", - "methods": [] + "methods": [], + "extends": [] }, { "name": "OuiPanelOverlay", @@ -1133,10 +1160,11 @@ } ], "indexSignatures": [], - "kind": 165, + "kind": 171, "description": "

Interface for a custom menu panel that can be used with ouiMenuTriggerFor.

\n", "rawdescription": "\n\nInterface for a custom menu panel that can be used with `ouiMenuTriggerFor`.\n\n", - "methods": [] + "methods": [], + "extends": [] }, { "name": "OuiSortable", @@ -1179,10 +1207,11 @@ } ], "indexSignatures": [], - "kind": 165, + "kind": 171, "description": "

Interface for a directive that holds sorting state consumed by OuiSortHeader.

\n", "rawdescription": "\nInterface for a directive that holds sorting state consumed by `OuiSortHeader`.", - "methods": [] + "methods": [], + "extends": [] }, { "name": "OuiSortHeaderColumnDef", @@ -1204,19 +1233,20 @@ } ], "indexSignatures": [], - "kind": 165, + "kind": 171, "description": "

Column definition associated with a OuiSortHeader.

\n", "rawdescription": "\nColumn definition associated with a `OuiSortHeader`.", - "methods": [] + "methods": [], + "extends": [] }, { "name": "OuiTabGroupBaseHeader", - "id": "interface-OuiTabGroupBaseHeader-4d0b5030ca195d184c74343feab780aa235b8d985fd04212cdaaa64ed005edd09a6056c8ba4c4954752c47f07323482c45b313640a731c2d5d0547df5865b67d", + "id": "interface-OuiTabGroupBaseHeader-589c514ba2f48297f4aa02fd4ced821bdcbc822779026ff6c817d949a12f81fcb79562a1d57b8975a29ae4b3cacdebafe77cf4a4035a5d582aa823ca4fafe395", "file": "ui/src/components/tabs/tab-group.ts", "deprecated": false, "deprecationMessage": "", "type": "interface", - "sourceCode": "import {\n AfterContentChecked,\n AfterContentInit,\n ChangeDetectionStrategy,\n ChangeDetectorRef,\n Component,\n ContentChildren,\n ElementRef,\n EventEmitter,\n Inject,\n Input,\n OnDestroy,\n Optional,\n Output,\n QueryList,\n ViewChild,\n ViewEncapsulation,\n} from '@angular/core';\nimport { ANIMATION_MODULE_TYPE } from '@angular/platform-browser/animations';\nimport { OUI_TAB_GROUP, OuiTab } from './tab';\nimport { OuiTabHeader } from './tab-header';\nimport {\n BooleanInput,\n coerceBooleanProperty,\n coerceNumberProperty,\n NumberInput,\n} from '@angular/cdk/coercion';\nimport {\n CanColor,\n CanDisableRipple,\n mixinColor,\n mixinDisableRipple,\n ThemePalette,\n} from '../core';\nimport { merge, Subscription } from 'rxjs';\nimport { OUI_TABS_CONFIG, OuiTabsConfig } from './tab-config';\nimport { startWith } from 'rxjs/operators';\nimport { FocusOrigin } from '@angular/cdk/a11y';\n\n/** Used to generate unique ID's for each tab component */\nlet nextId = 0;\n\n// Boilerplate for applying mixins to ouiTabGroup.\n/** @docs-private */\nconst _OuiTabGroupMixinBase = mixinColor(\n mixinDisableRipple(\n class {\n constructor(public _elementRef: ElementRef) {}\n }\n ),\n 'primary'\n);\n\n/** @docs-private */\nexport interface OuiTabGroupBaseHeader {\n _alignInkBarToSelectedTab(): void;\n updatePagination(): void;\n focusIndex: number;\n}\n\n/** Possible positions for the tab header. */\nexport type OuiTabHeaderPosition = 'above' | 'below';\n\n/**\n * Material design tab-group component. Supports basic tab pairs (label + content) and includes\n * animated ink-bar, keyboard navigation, and screen reader.\n * See: https://material.io/design/components/tabs.html\n */\n@Component({\n selector: 'oui-tab-group',\n exportAs: 'ouiTabGroup',\n templateUrl: 'tab-group.html',\n styleUrls: ['tab-group.scss'],\n encapsulation: ViewEncapsulation.None,\n // tslint:disable-next-line:validate-decorators\n changeDetection: ChangeDetectionStrategy.Default,\n // eslint-disable-next-line\n inputs: ['color', 'disableRipple'],\n providers: [\n {\n provide: OUI_TAB_GROUP,\n useExisting: ouiTabGroup,\n },\n ],\n // eslint-disable-next-line\n host: {\n ngSkipHydration: '',\n class: 'oui-mdc-tab-group oui-tab',\n '[class.oui-mdc-tab-group-dynamic-height]': 'dynamicHeight',\n '[class.oui-mdc-tab-group-inverted-header]': 'headerPosition === \"below\"',\n '[class.oui-mdc-tab-group-stretch-tabs]': 'stretchTabs',\n '[style.--oui-tab-animation-duration]': 'animationDuration',\n },\n})\nexport class ouiTabGroup\n extends _OuiTabGroupMixinBase\n implements\n AfterContentInit,\n AfterContentChecked,\n OnDestroy,\n CanColor,\n CanDisableRipple\n{\n /**\n * All tabs inside the tab group. This includes tabs that belong to groups that are nested\n * inside the current one. We filter out only the tabs that belong to this group in `_tabs`.\n */\n @ContentChildren(OuiTab, { descendants: true }) _allTabs: QueryList;\n @ViewChild('tabBodyWrapper') _tabBodyWrapper: ElementRef;\n @ViewChild('tabHeader') _tabHeader: OuiTabHeader;\n\n /** All of the tabs that belong to the group. */\n _tabs: QueryList = new QueryList();\n\n /** The tab index that should be selected after the content has been checked. */\n private _indexToSelect: number | null = 0;\n\n /** Index of the tab that was focused last. */\n private _lastFocusedTabIndex: number | null = null;\n\n /** Snapshot of the height of the tab body wrapper before another tab is activated. */\n private _tabBodyWrapperHeight = 0;\n\n /** Subscription to tabs being added/removed. */\n private _tabsSubscription = Subscription.EMPTY;\n\n /** Subscription to changes in the tab labels. */\n private _tabLabelSubscription = Subscription.EMPTY;\n\n /** Whether the ink bar should fit its width to the size of the tab label content. */\n @Input()\n get fitInkBarToContent(): boolean {\n return this._fitInkBarToContent;\n }\n set fitInkBarToContent(v: BooleanInput) {\n this._fitInkBarToContent = coerceBooleanProperty(v);\n this._changeDetectorRef.markForCheck();\n }\n private _fitInkBarToContent = false;\n\n /** Whether tabs should be stretched to fill the header. */\n @Input('oui-stretch-tabs')\n get stretchTabs(): boolean {\n return this._stretchTabs;\n }\n set stretchTabs(v: BooleanInput) {\n this._stretchTabs = coerceBooleanProperty(v);\n }\n private _stretchTabs = true;\n\n /** Whether the tab group should grow to the size of the active tab. */\n @Input()\n get dynamicHeight(): boolean {\n return this._dynamicHeight;\n }\n\n set dynamicHeight(value: BooleanInput) {\n this._dynamicHeight = coerceBooleanProperty(value);\n }\n\n private _dynamicHeight = false;\n\n /** The index of the active tab. */\n @Input()\n get selectedIndex(): number | null {\n return this._selectedIndex;\n }\n\n set selectedIndex(value: NumberInput) {\n this._indexToSelect = coerceNumberProperty(value, null);\n }\n\n private _selectedIndex: number | null = null;\n\n /** Position of the tab header. */\n @Input() headerPosition: OuiTabHeaderPosition = 'above';\n\n /** Duration for the tab animation. Will be normalized to milliseconds if no units are set. */\n @Input()\n get animationDuration(): string {\n return this._animationDuration;\n }\n\n set animationDuration(value: NumberInput) {\n // eslint-disable-next-line @typescript-eslint/restrict-plus-operands\n this._animationDuration = /^\\d+$/.test(value + '') // eslint-disable-next-line @typescript-eslint/restrict-plus-operands\n ? value + 'ms'\n : (value as string);\n }\n\n private _animationDuration: string;\n\n /**\n * `tabindex` to be set on the inner element that wraps the tab content. Can be used for improved\n * accessibility when the tab does not have focusable elements or if it has scrollable content.\n * The `tabindex` will be removed automatically for inactive tabs.\n * Read more at https://www.w3.org/TR/wai-aria-practices/examples/tabs/tabs-2/tabs.html\n */\n @Input()\n get contentTabIndex(): number | null {\n return this._contentTabIndex;\n }\n\n set contentTabIndex(value: NumberInput) {\n this._contentTabIndex = coerceNumberProperty(value, null);\n }\n\n private _contentTabIndex: number | null;\n\n /**\n * Whether pagination should be disabled. This can be used to avoid unnecessary\n * layout recalculations if it's known that pagination won't be required.\n */\n @Input()\n get disablePagination(): boolean {\n return this._disablePagination;\n }\n\n set disablePagination(value: BooleanInput) {\n this._disablePagination = coerceBooleanProperty(value);\n }\n\n private _disablePagination = false;\n\n /**\n * By default tabs remove their content from the DOM while it's off-screen.\n * Setting this to `true` will keep it in the DOM which will prevent elements\n * like iframes and videos from reloading next time it comes back into the view.\n */\n @Input()\n get preserveContent(): boolean {\n return this._preserveContent;\n }\n\n set preserveContent(value: BooleanInput) {\n this._preserveContent = coerceBooleanProperty(value);\n }\n\n private _preserveContent = false;\n\n /** Background color of the tab group. */\n @Input()\n get backgroundColor(): ThemePalette {\n return this._backgroundColor;\n }\n\n set backgroundColor(value: ThemePalette) {\n const classList: DOMTokenList = this._elementRef.nativeElement.classList;\n\n classList.remove(\n 'oui-tabs-with-background',\n `oui-background-${this.backgroundColor}`\n );\n\n if (value) {\n classList.add('oui-tabs-with-background', `oui-background-${value}`);\n }\n\n this._backgroundColor = value;\n }\n\n private _backgroundColor: ThemePalette;\n\n /** Output to enable support for two-way binding on `[(selectedIndex)]` */\n @Output() readonly selectedIndexChange: EventEmitter =\n new EventEmitter();\n\n /** Event emitted when focus has changed within a tab group. */\n @Output() readonly focusChange: EventEmitter =\n new EventEmitter();\n\n /** Event emitted when the body animation has completed */\n @Output() readonly animationDone: EventEmitter =\n new EventEmitter();\n\n /** Event emitted when the tab selection has changed. */\n @Output() readonly selectedTabChange: EventEmitter =\n new EventEmitter(true);\n\n private _groupId: number;\n getHTMLText: any;\n updatedTabHTML: any;\n\n constructor(\n elementRef: ElementRef,\n private _changeDetectorRef: ChangeDetectorRef,\n @Inject(OUI_TABS_CONFIG) @Optional() defaultConfig?: OuiTabsConfig,\n @Optional() @Inject(ANIMATION_MODULE_TYPE) public _animationMode?: string\n ) {\n super(elementRef);\n this._groupId = nextId++;\n this.animationDuration =\n defaultConfig && defaultConfig.animationDuration\n ? defaultConfig.animationDuration\n : '500ms';\n this.disablePagination =\n defaultConfig && defaultConfig.disablePagination != null\n ? defaultConfig.disablePagination\n : false;\n this.dynamicHeight =\n defaultConfig && defaultConfig.dynamicHeight != null\n ? defaultConfig.dynamicHeight\n : false;\n this.contentTabIndex = defaultConfig?.contentTabIndex ?? null;\n this.preserveContent = !!defaultConfig?.preserveContent;\n this.fitInkBarToContent =\n defaultConfig && defaultConfig.fitInkBarToContent != null\n ? defaultConfig.fitInkBarToContent\n : false;\n this.stretchTabs =\n defaultConfig && defaultConfig.stretchTabs != null\n ? defaultConfig.stretchTabs\n : true;\n }\n\n /**\n * After the content is checked, this component knows what tabs have been defined\n * and what the selected index should be. This is where we can know exactly what position\n * each tab should be in according to the new selected index, and additionally we know how\n * a new selected tab should transition in (from the left or right).\n */\n ngAfterContentChecked() {\n // Don't clamp the `indexToSelect` immediately in the setter because it can happen that\n // the amount of tabs changes before the actual change detection runs.\n const indexToSelect = (this._indexToSelect = this._clampTabIndex(\n this._indexToSelect\n ));\n\n // If there is a change in selected index, emit a change event. Should not trigger if\n // the selected index has not yet been initialized.\n if (this._selectedIndex != indexToSelect) {\n const isFirstRun = this._selectedIndex == null;\n\n if (!isFirstRun) {\n this.selectedTabChange.emit(this._createChangeEvent(indexToSelect));\n // Preserve the height so page doesn't scroll up during tab change.\n // Fixes https://stackblitz.com/edit/mat-tabs-scroll-page-top-on-tab-change\n const wrapper = this._tabBodyWrapper.nativeElement;\n // eslint-disable-next-line @typescript-eslint/restrict-plus-operands\n wrapper.style.minHeight = wrapper.clientHeight + 'px';\n }\n\n // Changing these values after change detection has run\n // since the checked content may contain references to them.\n Promise.resolve().then(() => {\n this._tabs.forEach(\n (tab, index) => (tab.isActive = index === indexToSelect)\n );\n\n if (!isFirstRun) {\n this.selectedIndexChange.emit(indexToSelect);\n // Clear the min-height, this was needed during tab change to avoid\n // unnecessary scrolling.\n this._tabBodyWrapper.nativeElement.style.minHeight = '';\n }\n });\n }\n\n // Setup the position for each tab and optionally setup an origin on the next selected tab.\n this._tabs.forEach((tab: OuiTab, index: number) => {\n tab.position = index - indexToSelect;\n\n // If there is already a selected tab, then set up an origin for the next selected tab\n // if it doesn't have one already.\n if (this._selectedIndex != null && tab.position == 0 && !tab.origin) {\n tab.origin = indexToSelect - this._selectedIndex;\n }\n });\n\n if (this._selectedIndex !== indexToSelect) {\n this._selectedIndex = indexToSelect;\n this._lastFocusedTabIndex = null;\n this._changeDetectorRef.markForCheck();\n }\n }\n\n ngAfterContentInit() {\n this._subscribeToAllTabChanges();\n this._subscribeToTabLabels();\n // Subscribe to changes in the amount of tabs, in order to be\n // able to re-render the content as new tabs are added or removed.\n this._tabsSubscription = this._tabs.changes.subscribe(() => {\n const indexToSelect = this._clampTabIndex(this._indexToSelect);\n\n // Maintain the previously-selected tab if a new tab is added or removed and there is no\n // explicit change that selects a different tab.\n if (indexToSelect === this._selectedIndex) {\n const tabs = this._tabs.toArray();\n let selectedTab: OuiTab | undefined;\n\n for (let i = 0; i < tabs.length; i++) {\n if (tabs[i].isActive) {\n // Assign both to the `_indexToSelect` and `_selectedIndex` so we don't fire a changed\n // event, otherwise the consumer may end up in an infinite loop in some edge cases like\n // adding a tab within the `selectedIndexChange` event.\n this._indexToSelect = this._selectedIndex = i;\n this._lastFocusedTabIndex = null;\n selectedTab = tabs[i];\n break;\n }\n }\n\n // If we haven't found an active tab and a tab exists at the selected index, it means\n // that the active tab was swapped out. Since this won't be picked up by the rendering\n // loop in `ngAfterContentChecked`, we need to sync it up manually.\n if (!selectedTab && tabs[indexToSelect]) {\n Promise.resolve().then(() => {\n tabs[indexToSelect].isActive = true;\n this.selectedTabChange.emit(this._createChangeEvent(indexToSelect));\n });\n }\n }\n\n this._changeDetectorRef.markForCheck();\n });\n }\n\n /** Listens to changes in all of the tabs. */\n private _subscribeToAllTabChanges() {\n // Since we use a query with `descendants: true` to pick up the tabs, we may end up catching\n // some that are inside of nested tab groups. We filter them out manually by checking that\n // the closest group to the tab is the current one.\n this.getHTMLText = this._allTabs['_results'][0].givenText;\n this.updatedTabHTML = this.getHTMLText;\n this._allTabs.changes\n .pipe(startWith(this._allTabs))\n .subscribe((tabs: QueryList) => {\n this._tabs.reset(\n tabs.filter((tab) => {\n return tab._closestTabGroup === this || !tab._closestTabGroup;\n })\n );\n this._tabs.notifyOnChanges();\n });\n }\n\n ngOnDestroy() {\n this._tabs.destroy();\n this._tabsSubscription.unsubscribe();\n this._tabLabelSubscription.unsubscribe();\n }\n\n /** Re-aligns the ink bar to the selected tab element. */\n realignInkBar() {\n if (this._tabHeader) {\n this._tabHeader._alignInkBarToSelectedTab();\n }\n }\n\n /**\n * Recalculates the tab group's pagination dimensions.\n *\n * WARNING: Calling this method can be very costly in terms of performance. It should be called\n * as infrequently as possible from outside of the Tabs component as it causes a reflow of the\n * page.\n */\n updatePagination() {\n if (this._tabHeader) {\n this._tabHeader.updatePagination();\n }\n }\n\n /**\n * Sets focus to a particular tab.\n * @param index Index of the tab to be focused.\n */\n focusTab(index: number) {\n const header = this._tabHeader;\n\n if (header) {\n header.focusIndex = index;\n }\n }\n\n _focusChanged(index: number) {\n this._lastFocusedTabIndex = index;\n this.focusChange.emit(this._createChangeEvent(index));\n }\n\n private _createChangeEvent(index: number): OuiTabChangeEvent {\n const event = new OuiTabChangeEvent();\n event.index = index;\n if (this._tabs && this._tabs.length) {\n event.tab = this._tabs.toArray()[index];\n this.updatedTabHTML = event.tab.givenText;\n }\n return event;\n }\n\n _handleEnter() {\n this.getHTMLText = this.updatedTabHTML;\n }\n\n /**\n * Subscribes to changes in the tab labels. This is needed, because the @Input for the label is\n * on the OuiTab component, whereas the data binding is inside the ouiTabGroup. In order for the\n * binding to be updated, we need to subscribe to changes in it and trigger change detection\n * manually.\n */\n private _subscribeToTabLabels() {\n if (this._tabLabelSubscription) {\n this._tabLabelSubscription.unsubscribe();\n }\n\n this._tabLabelSubscription = merge(\n ...this._tabs.map((tab) => tab._stateChanges)\n ).subscribe(() => this._changeDetectorRef.markForCheck());\n }\n\n /** Clamps the given index to the bounds of 0 and the tabs length. */\n private _clampTabIndex(index: number | null): number {\n // Note the `|| 0`, which ensures that values like NaN can't get through\n // and which would otherwise throw the component into an infinite loop\n // (since Math.max(NaN, 0) === NaN).\n return Math.min(this._tabs.length - 1, Math.max(index || 0, 0));\n }\n\n /** Returns a unique id for each tab label element */\n _getTabLabelId(i: number): string {\n return `oui-tab-label-${this._groupId}-${i}`;\n }\n\n /** Returns a unique id for each tab content element */\n _getTabContentId(i: number): string {\n return `oui-tab-content-${this._groupId}-${i}`;\n }\n\n /**\n * Sets the height of the body wrapper to the height of the activating tab if dynamic\n * height property is true.\n */\n _setTabBodyWrapperHeight(tabHeight: number): void {\n if (!this._dynamicHeight || !this._tabBodyWrapperHeight) {\n return;\n }\n\n const wrapper: HTMLElement = this._tabBodyWrapper.nativeElement;\n // eslint-disable-next-line @typescript-eslint/restrict-plus-operands\n wrapper.style.height = this._tabBodyWrapperHeight + 'px';\n\n // This conditional forces the browser to paint the height so that\n // the animation to the new height can have an origin.\n if (this._tabBodyWrapper.nativeElement.offsetHeight) {\n // eslint-disable-next-line @typescript-eslint/restrict-plus-operands\n wrapper.style.height = tabHeight + 'px';\n }\n }\n\n /** Removes the height of the tab body wrapper. */\n _removeTabBodyWrapperHeight(): void {\n const wrapper = this._tabBodyWrapper.nativeElement;\n this._tabBodyWrapperHeight = wrapper.clientHeight;\n wrapper.style.height = '';\n this.animationDone.emit();\n }\n\n /** Handle click events, setting new selected index if appropriate. */\n _handleClick(tab: OuiTab, tabHeader: OuiTabGroupBaseHeader, index: number) {\n tabHeader.focusIndex = index;\n this.getHTMLText = this.updatedTabHTML;\n\n if (!tab.disabled) {\n this.selectedIndex = index;\n }\n }\n\n /** Retrieves the tabindex for the tab. */\n _getTabIndex(index: number): number {\n const targetIndex = this._lastFocusedTabIndex ?? this.selectedIndex;\n return index === targetIndex ? 0 : -1;\n }\n\n /** Callback for when the focused state of a tab has changed. */\n _tabFocusChanged(focusOrigin: FocusOrigin, index: number) {\n // Mouse/touch focus happens during the `mousedown`/`touchstart` phase which\n // can cause the tab to be moved out from under the pointer, interrupting the\n // click sequence (see #21898). We don't need to scroll the tab into view for\n // such cases anyway, because it will be done when the tab becomes selected.\n if (focusOrigin && focusOrigin !== 'mouse' && focusOrigin !== 'touch') {\n this._tabHeader.focusIndex = index;\n }\n }\n}\n\n/** A simple change event emitted on focus or selection changes. */\nexport class OuiTabChangeEvent {\n /** Index of the currently-selected tab. */\n index: number;\n /** Reference to the currently-selected tab. */\n tab: OuiTab;\n event: Event;\n}\n", + "sourceCode": "import {\r\n AfterContentChecked,\r\n AfterContentInit,\r\n ChangeDetectionStrategy,\r\n ChangeDetectorRef,\r\n Component,\r\n ContentChildren,\r\n ElementRef,\r\n EventEmitter,\r\n Inject,\r\n Input,\r\n OnDestroy,\r\n Optional,\r\n Output,\r\n QueryList,\r\n ViewChild,\r\n ViewEncapsulation,\r\n} from '@angular/core';\r\nimport { ANIMATION_MODULE_TYPE } from '@angular/platform-browser/animations';\r\nimport { OUI_TAB_GROUP, OuiTab } from './tab';\r\nimport { OuiTabHeader } from './tab-header';\r\nimport {\r\n BooleanInput,\r\n coerceBooleanProperty,\r\n coerceNumberProperty,\r\n NumberInput,\r\n} from '@angular/cdk/coercion';\r\nimport {\r\n CanColor,\r\n CanDisableRipple,\r\n mixinColor,\r\n mixinDisableRipple,\r\n ThemePalette,\r\n} from '../core';\r\nimport { merge, Subscription } from 'rxjs';\r\nimport { OUI_TABS_CONFIG, OuiTabsConfig } from './tab-config';\r\nimport { startWith } from 'rxjs/operators';\r\nimport { FocusOrigin } from '@angular/cdk/a11y';\r\n\r\n/** Used to generate unique ID's for each tab component */\r\nlet nextId = 0;\r\n\r\n// Boilerplate for applying mixins to ouiTabGroup.\r\n/** @docs-private */\r\nconst _OuiTabGroupMixinBase = mixinColor(\r\n mixinDisableRipple(\r\n class {\r\n constructor(public _elementRef: ElementRef) {}\r\n }\r\n ),\r\n 'primary'\r\n);\r\n\r\n/** @docs-private */\r\nexport interface OuiTabGroupBaseHeader {\r\n _alignInkBarToSelectedTab(): void;\r\n updatePagination(): void;\r\n focusIndex: number;\r\n}\r\n\r\n/** Possible positions for the tab header. */\r\nexport type OuiTabHeaderPosition = 'above' | 'below';\r\n\r\n/**\r\n * Material design tab-group component. Supports basic tab pairs (label + content) and includes\r\n * animated ink-bar, keyboard navigation, and screen reader.\r\n * See: https://material.io/design/components/tabs.html\r\n */\r\n@Component({\r\n selector: 'oui-tab-group',\r\n exportAs: 'ouiTabGroup',\r\n templateUrl: 'tab-group.html',\r\n styleUrls: ['tab-group.scss'],\r\n encapsulation: ViewEncapsulation.None,\r\n // tslint:disable-next-line:validate-decorators\r\n changeDetection: ChangeDetectionStrategy.Default,\r\n // eslint-disable-next-line\r\n inputs: ['color', 'disableRipple'],\r\n providers: [\r\n {\r\n provide: OUI_TAB_GROUP,\r\n useExisting: ouiTabGroup,\r\n },\r\n ],\r\n // eslint-disable-next-line\r\n host: {\r\n ngSkipHydration: '',\r\n class: 'oui-mdc-tab-group oui-tab',\r\n '[class.oui-mdc-tab-group-dynamic-height]': 'dynamicHeight',\r\n '[class.oui-mdc-tab-group-inverted-header]': 'headerPosition === \"below\"',\r\n '[class.oui-mdc-tab-group-stretch-tabs]': 'stretchTabs',\r\n '[style.--oui-tab-animation-duration]': 'animationDuration',\r\n },\r\n})\r\nexport class ouiTabGroup\r\n extends _OuiTabGroupMixinBase\r\n implements\r\n AfterContentInit,\r\n AfterContentChecked,\r\n OnDestroy,\r\n CanColor,\r\n CanDisableRipple\r\n{\r\n /**\r\n * All tabs inside the tab group. This includes tabs that belong to groups that are nested\r\n * inside the current one. We filter out only the tabs that belong to this group in `_tabs`.\r\n */\r\n @ContentChildren(OuiTab, { descendants: true }) _allTabs: QueryList;\r\n @ViewChild('tabBodyWrapper') _tabBodyWrapper: ElementRef;\r\n @ViewChild('tabHeader') _tabHeader: OuiTabHeader;\r\n\r\n /** All of the tabs that belong to the group. */\r\n _tabs: QueryList = new QueryList();\r\n\r\n /** The tab index that should be selected after the content has been checked. */\r\n private _indexToSelect: number | null = 0;\r\n\r\n /** Index of the tab that was focused last. */\r\n private _lastFocusedTabIndex: number | null = null;\r\n\r\n /** Snapshot of the height of the tab body wrapper before another tab is activated. */\r\n private _tabBodyWrapperHeight = 0;\r\n\r\n /** Subscription to tabs being added/removed. */\r\n private _tabsSubscription = Subscription.EMPTY;\r\n\r\n /** Subscription to changes in the tab labels. */\r\n private _tabLabelSubscription = Subscription.EMPTY;\r\n\r\n /** Whether the ink bar should fit its width to the size of the tab label content. */\r\n @Input()\r\n get fitInkBarToContent(): boolean {\r\n return this._fitInkBarToContent;\r\n }\r\n set fitInkBarToContent(v: BooleanInput) {\r\n this._fitInkBarToContent = coerceBooleanProperty(v);\r\n this._changeDetectorRef.markForCheck();\r\n }\r\n private _fitInkBarToContent = false;\r\n\r\n /** Whether tabs should be stretched to fill the header. */\r\n @Input('oui-stretch-tabs')\r\n get stretchTabs(): boolean {\r\n return this._stretchTabs;\r\n }\r\n set stretchTabs(v: BooleanInput) {\r\n this._stretchTabs = coerceBooleanProperty(v);\r\n }\r\n private _stretchTabs = true;\r\n\r\n /** Whether the tab group should grow to the size of the active tab. */\r\n @Input()\r\n get dynamicHeight(): boolean {\r\n return this._dynamicHeight;\r\n }\r\n\r\n set dynamicHeight(value: BooleanInput) {\r\n this._dynamicHeight = coerceBooleanProperty(value);\r\n }\r\n\r\n private _dynamicHeight = false;\r\n\r\n /** The index of the active tab. */\r\n @Input()\r\n get selectedIndex(): number | null {\r\n return this._selectedIndex;\r\n }\r\n\r\n set selectedIndex(value: NumberInput) {\r\n this._indexToSelect = coerceNumberProperty(value, null);\r\n }\r\n\r\n private _selectedIndex: number | null = null;\r\n\r\n /** Position of the tab header. */\r\n @Input() headerPosition: OuiTabHeaderPosition = 'above';\r\n\r\n /** Duration for the tab animation. Will be normalized to milliseconds if no units are set. */\r\n @Input()\r\n get animationDuration(): string {\r\n return this._animationDuration;\r\n }\r\n\r\n set animationDuration(value: NumberInput) {\r\n // eslint-disable-next-line @typescript-eslint/restrict-plus-operands\r\n this._animationDuration = /^\\d+$/.test(value + '') // eslint-disable-next-line @typescript-eslint/restrict-plus-operands\r\n ? value + 'ms'\r\n : (value as string);\r\n }\r\n\r\n private _animationDuration: string;\r\n\r\n /**\r\n * `tabindex` to be set on the inner element that wraps the tab content. Can be used for improved\r\n * accessibility when the tab does not have focusable elements or if it has scrollable content.\r\n * The `tabindex` will be removed automatically for inactive tabs.\r\n * Read more at https://www.w3.org/TR/wai-aria-practices/examples/tabs/tabs-2/tabs.html\r\n */\r\n @Input()\r\n get contentTabIndex(): number | null {\r\n return this._contentTabIndex;\r\n }\r\n\r\n set contentTabIndex(value: NumberInput) {\r\n this._contentTabIndex = coerceNumberProperty(value, null);\r\n }\r\n\r\n private _contentTabIndex: number | null;\r\n\r\n /**\r\n * Whether pagination should be disabled. This can be used to avoid unnecessary\r\n * layout recalculations if it's known that pagination won't be required.\r\n */\r\n @Input()\r\n get disablePagination(): boolean {\r\n return this._disablePagination;\r\n }\r\n\r\n set disablePagination(value: BooleanInput) {\r\n this._disablePagination = coerceBooleanProperty(value);\r\n }\r\n\r\n private _disablePagination = false;\r\n\r\n /**\r\n * By default tabs remove their content from the DOM while it's off-screen.\r\n * Setting this to `true` will keep it in the DOM which will prevent elements\r\n * like iframes and videos from reloading next time it comes back into the view.\r\n */\r\n @Input()\r\n get preserveContent(): boolean {\r\n return this._preserveContent;\r\n }\r\n\r\n set preserveContent(value: BooleanInput) {\r\n this._preserveContent = coerceBooleanProperty(value);\r\n }\r\n\r\n private _preserveContent = false;\r\n\r\n /** Background color of the tab group. */\r\n @Input()\r\n get backgroundColor(): ThemePalette {\r\n return this._backgroundColor;\r\n }\r\n\r\n set backgroundColor(value: ThemePalette) {\r\n const classList: DOMTokenList = this._elementRef.nativeElement.classList;\r\n\r\n classList.remove(\r\n 'oui-tabs-with-background',\r\n `oui-background-${this.backgroundColor}`\r\n );\r\n\r\n if (value) {\r\n classList.add('oui-tabs-with-background', `oui-background-${value}`);\r\n }\r\n\r\n this._backgroundColor = value;\r\n }\r\n\r\n private _backgroundColor: ThemePalette;\r\n\r\n /** Output to enable support for two-way binding on `[(selectedIndex)]` */\r\n @Output() readonly selectedIndexChange: EventEmitter =\r\n new EventEmitter();\r\n\r\n /** Event emitted when focus has changed within a tab group. */\r\n @Output() readonly focusChange: EventEmitter =\r\n new EventEmitter();\r\n\r\n /** Event emitted when the body animation has completed */\r\n @Output() readonly animationDone: EventEmitter =\r\n new EventEmitter();\r\n\r\n /** Event emitted when the tab selection has changed. */\r\n @Output() readonly selectedTabChange: EventEmitter =\r\n new EventEmitter(true);\r\n\r\n private _groupId: number;\r\n getHTMLText: any;\r\n updatedTabHTML: any;\r\n\r\n constructor(\r\n elementRef: ElementRef,\r\n private _changeDetectorRef: ChangeDetectorRef,\r\n @Inject(OUI_TABS_CONFIG) @Optional() defaultConfig?: OuiTabsConfig,\r\n @Optional() @Inject(ANIMATION_MODULE_TYPE) public _animationMode?: string\r\n ) {\r\n super(elementRef);\r\n this._groupId = nextId++;\r\n this.animationDuration =\r\n defaultConfig && defaultConfig.animationDuration\r\n ? defaultConfig.animationDuration\r\n : '500ms';\r\n this.disablePagination =\r\n defaultConfig && defaultConfig.disablePagination != null\r\n ? defaultConfig.disablePagination\r\n : false;\r\n this.dynamicHeight =\r\n defaultConfig && defaultConfig.dynamicHeight != null\r\n ? defaultConfig.dynamicHeight\r\n : false;\r\n this.contentTabIndex = defaultConfig?.contentTabIndex ?? null;\r\n this.preserveContent = !!defaultConfig?.preserveContent;\r\n this.fitInkBarToContent =\r\n defaultConfig && defaultConfig.fitInkBarToContent != null\r\n ? defaultConfig.fitInkBarToContent\r\n : false;\r\n this.stretchTabs =\r\n defaultConfig && defaultConfig.stretchTabs != null\r\n ? defaultConfig.stretchTabs\r\n : true;\r\n }\r\n\r\n /**\r\n * After the content is checked, this component knows what tabs have been defined\r\n * and what the selected index should be. This is where we can know exactly what position\r\n * each tab should be in according to the new selected index, and additionally we know how\r\n * a new selected tab should transition in (from the left or right).\r\n */\r\n ngAfterContentChecked() {\r\n // Don't clamp the `indexToSelect` immediately in the setter because it can happen that\r\n // the amount of tabs changes before the actual change detection runs.\r\n const indexToSelect = (this._indexToSelect = this._clampTabIndex(\r\n this._indexToSelect\r\n ));\r\n\r\n // If there is a change in selected index, emit a change event. Should not trigger if\r\n // the selected index has not yet been initialized.\r\n if (this._selectedIndex != indexToSelect) {\r\n const isFirstRun = this._selectedIndex == null;\r\n\r\n if (!isFirstRun) {\r\n this.selectedTabChange.emit(this._createChangeEvent(indexToSelect));\r\n // Preserve the height so page doesn't scroll up during tab change.\r\n // Fixes https://stackblitz.com/edit/mat-tabs-scroll-page-top-on-tab-change\r\n const wrapper = this._tabBodyWrapper.nativeElement;\r\n // eslint-disable-next-line @typescript-eslint/restrict-plus-operands\r\n wrapper.style.minHeight = wrapper.clientHeight + 'px';\r\n }\r\n\r\n // Changing these values after change detection has run\r\n // since the checked content may contain references to them.\r\n Promise.resolve().then(() => {\r\n this._tabs.forEach(\r\n (tab, index) => (tab.isActive = index === indexToSelect)\r\n );\r\n\r\n if (!isFirstRun) {\r\n this.selectedIndexChange.emit(indexToSelect);\r\n // Clear the min-height, this was needed during tab change to avoid\r\n // unnecessary scrolling.\r\n this._tabBodyWrapper.nativeElement.style.minHeight = '';\r\n }\r\n });\r\n }\r\n\r\n // Setup the position for each tab and optionally setup an origin on the next selected tab.\r\n this._tabs.forEach((tab: OuiTab, index: number) => {\r\n tab.position = index - indexToSelect;\r\n\r\n // If there is already a selected tab, then set up an origin for the next selected tab\r\n // if it doesn't have one already.\r\n if (this._selectedIndex != null && tab.position == 0 && !tab.origin) {\r\n tab.origin = indexToSelect - this._selectedIndex;\r\n }\r\n });\r\n\r\n if (this._selectedIndex !== indexToSelect) {\r\n this._selectedIndex = indexToSelect;\r\n this._lastFocusedTabIndex = null;\r\n this._changeDetectorRef.markForCheck();\r\n }\r\n }\r\n\r\n ngAfterContentInit() {\r\n this._subscribeToAllTabChanges();\r\n this._subscribeToTabLabels();\r\n // Subscribe to changes in the amount of tabs, in order to be\r\n // able to re-render the content as new tabs are added or removed.\r\n this._tabsSubscription = this._tabs.changes.subscribe(() => {\r\n const indexToSelect = this._clampTabIndex(this._indexToSelect);\r\n\r\n // Maintain the previously-selected tab if a new tab is added or removed and there is no\r\n // explicit change that selects a different tab.\r\n if (indexToSelect === this._selectedIndex) {\r\n const tabs = this._tabs.toArray();\r\n let selectedTab: OuiTab | undefined;\r\n\r\n for (let i = 0; i < tabs.length; i++) {\r\n if (tabs[i].isActive) {\r\n // Assign both to the `_indexToSelect` and `_selectedIndex` so we don't fire a changed\r\n // event, otherwise the consumer may end up in an infinite loop in some edge cases like\r\n // adding a tab within the `selectedIndexChange` event.\r\n this._indexToSelect = this._selectedIndex = i;\r\n this._lastFocusedTabIndex = null;\r\n selectedTab = tabs[i];\r\n break;\r\n }\r\n }\r\n\r\n // If we haven't found an active tab and a tab exists at the selected index, it means\r\n // that the active tab was swapped out. Since this won't be picked up by the rendering\r\n // loop in `ngAfterContentChecked`, we need to sync it up manually.\r\n if (!selectedTab && tabs[indexToSelect]) {\r\n Promise.resolve().then(() => {\r\n tabs[indexToSelect].isActive = true;\r\n this.selectedTabChange.emit(this._createChangeEvent(indexToSelect));\r\n });\r\n }\r\n }\r\n\r\n this._changeDetectorRef.markForCheck();\r\n });\r\n }\r\n\r\n /** Listens to changes in all of the tabs. */\r\n private _subscribeToAllTabChanges() {\r\n // Since we use a query with `descendants: true` to pick up the tabs, we may end up catching\r\n // some that are inside of nested tab groups. We filter them out manually by checking that\r\n // the closest group to the tab is the current one.\r\n this.getHTMLText = this._allTabs['_results'][0].givenText;\r\n this.updatedTabHTML = this.getHTMLText;\r\n this._allTabs.changes\r\n .pipe(startWith(this._allTabs))\r\n .subscribe((tabs: QueryList) => {\r\n this._tabs.reset(\r\n tabs.filter((tab) => {\r\n return tab._closestTabGroup === this || !tab._closestTabGroup;\r\n })\r\n );\r\n this._tabs.notifyOnChanges();\r\n });\r\n }\r\n\r\n ngOnDestroy() {\r\n this._tabs.destroy();\r\n this._tabsSubscription.unsubscribe();\r\n this._tabLabelSubscription.unsubscribe();\r\n }\r\n\r\n /** Re-aligns the ink bar to the selected tab element. */\r\n realignInkBar() {\r\n if (this._tabHeader) {\r\n this._tabHeader._alignInkBarToSelectedTab();\r\n }\r\n }\r\n\r\n /**\r\n * Recalculates the tab group's pagination dimensions.\r\n *\r\n * WARNING: Calling this method can be very costly in terms of performance. It should be called\r\n * as infrequently as possible from outside of the Tabs component as it causes a reflow of the\r\n * page.\r\n */\r\n updatePagination() {\r\n if (this._tabHeader) {\r\n this._tabHeader.updatePagination();\r\n }\r\n }\r\n\r\n /**\r\n * Sets focus to a particular tab.\r\n * @param index Index of the tab to be focused.\r\n */\r\n focusTab(index: number) {\r\n const header = this._tabHeader;\r\n\r\n if (header) {\r\n header.focusIndex = index;\r\n }\r\n }\r\n\r\n _focusChanged(index: number) {\r\n this._lastFocusedTabIndex = index;\r\n this.focusChange.emit(this._createChangeEvent(index));\r\n }\r\n\r\n private _createChangeEvent(index: number): OuiTabChangeEvent {\r\n const event = new OuiTabChangeEvent();\r\n event.index = index;\r\n if (this._tabs && this._tabs.length) {\r\n event.tab = this._tabs.toArray()[index];\r\n this.updatedTabHTML = event.tab.givenText;\r\n }\r\n return event;\r\n }\r\n\r\n _handleEnter() {\r\n this.getHTMLText = this.updatedTabHTML;\r\n }\r\n\r\n /**\r\n * Subscribes to changes in the tab labels. This is needed, because the @Input for the label is\r\n * on the OuiTab component, whereas the data binding is inside the ouiTabGroup. In order for the\r\n * binding to be updated, we need to subscribe to changes in it and trigger change detection\r\n * manually.\r\n */\r\n private _subscribeToTabLabels() {\r\n if (this._tabLabelSubscription) {\r\n this._tabLabelSubscription.unsubscribe();\r\n }\r\n\r\n this._tabLabelSubscription = merge(\r\n ...this._tabs.map((tab) => tab._stateChanges)\r\n ).subscribe(() => this._changeDetectorRef.markForCheck());\r\n }\r\n\r\n /** Clamps the given index to the bounds of 0 and the tabs length. */\r\n private _clampTabIndex(index: number | null): number {\r\n // Note the `|| 0`, which ensures that values like NaN can't get through\r\n // and which would otherwise throw the component into an infinite loop\r\n // (since Math.max(NaN, 0) === NaN).\r\n return Math.min(this._tabs.length - 1, Math.max(index || 0, 0));\r\n }\r\n\r\n /** Returns a unique id for each tab label element */\r\n _getTabLabelId(i: number): string {\r\n return `oui-tab-label-${this._groupId}-${i}`;\r\n }\r\n\r\n /** Returns a unique id for each tab content element */\r\n _getTabContentId(i: number): string {\r\n return `oui-tab-content-${this._groupId}-${i}`;\r\n }\r\n\r\n /**\r\n * Sets the height of the body wrapper to the height of the activating tab if dynamic\r\n * height property is true.\r\n */\r\n _setTabBodyWrapperHeight(tabHeight: number): void {\r\n if (!this._dynamicHeight || !this._tabBodyWrapperHeight) {\r\n return;\r\n }\r\n\r\n const wrapper: HTMLElement = this._tabBodyWrapper.nativeElement;\r\n // eslint-disable-next-line @typescript-eslint/restrict-plus-operands\r\n wrapper.style.height = this._tabBodyWrapperHeight + 'px';\r\n\r\n // This conditional forces the browser to paint the height so that\r\n // the animation to the new height can have an origin.\r\n if (this._tabBodyWrapper.nativeElement.offsetHeight) {\r\n // eslint-disable-next-line @typescript-eslint/restrict-plus-operands\r\n wrapper.style.height = tabHeight + 'px';\r\n }\r\n }\r\n\r\n /** Removes the height of the tab body wrapper. */\r\n _removeTabBodyWrapperHeight(): void {\r\n const wrapper = this._tabBodyWrapper.nativeElement;\r\n this._tabBodyWrapperHeight = wrapper.clientHeight;\r\n wrapper.style.height = '';\r\n this.animationDone.emit();\r\n }\r\n\r\n /** Handle click events, setting new selected index if appropriate. */\r\n _handleClick(tab: OuiTab, tabHeader: OuiTabGroupBaseHeader, index: number) {\r\n tabHeader.focusIndex = index;\r\n this.getHTMLText = this.updatedTabHTML;\r\n\r\n if (!tab.disabled) {\r\n this.selectedIndex = index;\r\n }\r\n }\r\n\r\n /** Retrieves the tabindex for the tab. */\r\n _getTabIndex(index: number): number {\r\n const targetIndex = this._lastFocusedTabIndex ?? this.selectedIndex;\r\n return index === targetIndex ? 0 : -1;\r\n }\r\n\r\n /** Callback for when the focused state of a tab has changed. */\r\n _tabFocusChanged(focusOrigin: FocusOrigin, index: number) {\r\n // Mouse/touch focus happens during the `mousedown`/`touchstart` phase which\r\n // can cause the tab to be moved out from under the pointer, interrupting the\r\n // click sequence (see #21898). We don't need to scroll the tab into view for\r\n // such cases anyway, because it will be done when the tab becomes selected.\r\n if (focusOrigin && focusOrigin !== 'mouse' && focusOrigin !== 'touch') {\r\n this._tabHeader.focusIndex = index;\r\n }\r\n }\r\n}\r\n\r\n/** A simple change event emitted on focus or selection changes. */\r\nexport class OuiTabChangeEvent {\r\n /** Index of the currently-selected tab. */\r\n index: number;\r\n /** Reference to the currently-selected tab. */\r\n tab: OuiTab;\r\n event: Event;\r\n}\r\n", "properties": [ { "name": "focusIndex", @@ -1229,7 +1259,7 @@ } ], "indexSignatures": [], - "kind": 165, + "kind": 171, "methods": [ { "name": "_alignInkBarToSelectedTab", @@ -1251,16 +1281,17 @@ "deprecated": false, "deprecationMessage": "" } - ] + ], + "extends": [] }, { "name": "OuiTabsConfig", - "id": "interface-OuiTabsConfig-f604a8c3593a063b6569f66f20b2b3176e2f23afae566c345f7e8f3ca2728c3fe1c28789c99d7098ef6117c43342b8894b83f884792b093087089b4827a6d873", + "id": "interface-OuiTabsConfig-f642516cfe541099ce468c723e7253bf64ae27ad564c1b234bd2bb912f828f7048176d06b12025c737f694ec052fb389bc5eec150cbaa37e4adec41af6b167a9", "file": "ui/src/components/tabs/tab-config.ts", "deprecated": false, "deprecationMessage": "", "type": "interface", - "sourceCode": "import { InjectionToken } from '@angular/core';\n\n/** Object that can be used to configure the default options for the tabs module. */\nexport interface OuiTabsConfig {\n /** Duration for the tab animation. Must be a valid CSS value (e.g. 600ms). */\n animationDuration?: string;\n\n /**\n * Whether pagination should be disabled. This can be used to avoid unnecessary\n * layout recalculations if it's known that pagination won't be required.\n */\n disablePagination?: boolean;\n\n /**\n * Whether the ink bar should fit its width to the size of the tab label content.\n * This only applies to the MDC-based tabs.\n */\n fitInkBarToContent?: boolean;\n\n /** Whether the tab group should grow to the size of the active tab. */\n dynamicHeight?: boolean;\n\n /** `tabindex` to be set on the inner element that wraps the tab content. */\n contentTabIndex?: number;\n\n /**\n * By default tabs remove their content from the DOM while it's off-screen.\n * Setting this to `true` will keep it in the DOM which will prevent elements\n * like iframes and videos from reloading next time it comes back into the view.\n */\n preserveContent?: boolean;\n\n /** Whether tabs should be stretched to fill the header. */\n stretchTabs?: boolean;\n}\n\n/** Injection token that can be used to provide the default options the tabs module. */\nexport const OUI_TABS_CONFIG = new InjectionToken(\n 'OUI_TABS_CONFIG'\n);\n", + "sourceCode": "import { InjectionToken } from '@angular/core';\r\n\r\n/** Object that can be used to configure the default options for the tabs module. */\r\nexport interface OuiTabsConfig {\r\n /** Duration for the tab animation. Must be a valid CSS value (e.g. 600ms). */\r\n animationDuration?: string;\r\n\r\n /**\r\n * Whether pagination should be disabled. This can be used to avoid unnecessary\r\n * layout recalculations if it's known that pagination won't be required.\r\n */\r\n disablePagination?: boolean;\r\n\r\n /**\r\n * Whether the ink bar should fit its width to the size of the tab label content.\r\n * This only applies to the MDC-based tabs.\r\n */\r\n fitInkBarToContent?: boolean;\r\n\r\n /** Whether the tab group should grow to the size of the active tab. */\r\n dynamicHeight?: boolean;\r\n\r\n /** `tabindex` to be set on the inner element that wraps the tab content. */\r\n contentTabIndex?: number;\r\n\r\n /**\r\n * By default tabs remove their content from the DOM while it's off-screen.\r\n * Setting this to `true` will keep it in the DOM which will prevent elements\r\n * like iframes and videos from reloading next time it comes back into the view.\r\n */\r\n preserveContent?: boolean;\r\n\r\n /** Whether tabs should be stretched to fill the header. */\r\n stretchTabs?: boolean;\r\n}\r\n\r\n/** Injection token that can be used to provide the default options the tabs module. */\r\nexport const OUI_TABS_CONFIG = new InjectionToken(\r\n 'OUI_TABS_CONFIG'\r\n);\r\n", "properties": [ { "name": "animationDuration", @@ -1334,10 +1365,11 @@ } ], "indexSignatures": [], - "kind": 165, + "kind": 171, "description": "

Object that can be used to configure the default options for the tabs module.

\n", "rawdescription": "\nObject that can be used to configure the default options for the tabs module.", - "methods": [] + "methods": [], + "extends": [] }, { "name": "OuiTooltipDefaultOptions", @@ -1377,10 +1409,11 @@ } ], "indexSignatures": [], - "kind": 165, + "kind": 171, "description": "

Default ouiTooltip options that can be overridden.

\n", "rawdescription": "\nDefault `ouiTooltip` options that can be overridden.", - "methods": [] + "methods": [], + "extends": [] }, { "name": "Sort", @@ -1413,19 +1446,20 @@ } ], "indexSignatures": [], - "kind": 165, + "kind": 171, "description": "

The current sort state.

\n", "rawdescription": "\nThe current sort state.", - "methods": [] + "methods": [], + "extends": [] }, { "name": "StateGroup", - "id": "interface-StateGroup-a05c014d2972db1c12417e8b91b83e9c05e198f5aefa128642f94d6c8f39f1743944bff24abcb101f17049bff0df923723ca6efcd8edcabf932a36d0e252b563", + "id": "interface-StateGroup-a7c3a42dc260f97f48099129f3271decd60a827448988b8e399989f849989a0745c120e669504c278a5df2bf0c7aa7d074d5b69fefc6e004ad3a5a3600023dd0", "file": "ui/src/stories/autocomplete/autocomplete.component.ts", "deprecated": false, "deprecationMessage": "", "type": "interface", - "sourceCode": "import { Input, Component, OnInit } from '@angular/core';\nimport { Observable } from 'rxjs';\nimport {\n UntypedFormControl,\n UntypedFormBuilder,\n UntypedFormGroup,\n} from '@angular/forms';\nimport { startWith, map } from 'rxjs/operators';\n\nexport interface StateGroup {\n letter: string;\n names: string[];\n}\nexport const _filter = (opt: string[], value: string): string[] => {\n const filterValue = value.toLowerCase();\n\n return opt.filter((item) => item.toLowerCase().indexOf(filterValue) === 0);\n};\n\n@Component({\n selector: 'oui-autocomplete-storybook',\n template: `\n \n \n \n \n \n {{ option }}\n \n \n `,\n})\nexport class OuiAutocompleteStorybook implements OnInit {\n filteredOptions: Observable;\n myControl = new UntypedFormControl();\n @Input() options: any[];\n @Input()\n set disabled(value: boolean) {\n if (value) {\n this.myControl.disable();\n } else {\n this.myControl.enable();\n }\n }\n ngOnInit() {\n this.filteredOptions = this.myControl.valueChanges.pipe(\n startWith(''),\n map((value) => (typeof value === 'string' ? value : value)),\n map((option) => (option ? this._filter(option) : this.options.slice()))\n );\n }\n private _filter(option): string[] {\n const filterValue = option.toLowerCase();\n\n return this.options.filter(\n // eslint-disable-next-line no-shadow\n (option) => option.toLowerCase().indexOf(filterValue) === 0\n );\n }\n}\n\n@Component({\n selector: 'oui-autocomplete-group-storybook',\n template: `\n \n \n \n \n \n {{ name }}\n \n \n \n \n `,\n})\nexport class OuiAutocompleteGroupStorybook implements OnInit {\n @Input() stateGroups: StateGroup[];\n @Input()\n set disabled(value: boolean) {\n if (value) {\n this.stateForm.get('stateGroup')!.disable();\n } else {\n this.stateForm.get('stateGroup')!.enable();\n }\n }\n stateForm: UntypedFormGroup = this.fb.group({\n stateGroup: '',\n });\n stateGroupOptions: Observable;\n\n constructor(private fb: UntypedFormBuilder) {}\n ngOnInit() {\n this.stateGroupOptions = this.stateForm\n .get('stateGroup')!\n .valueChanges.pipe(\n startWith(''),\n map((value: string) => this._filterGroup(value))\n );\n }\n\n private _filterGroup(value: string): StateGroup[] {\n if (value) {\n return this.stateGroups\n .map((group) => ({\n letter: group.letter,\n names: _filter(group.names, value),\n }))\n .filter((group) => group.names.length > 0);\n }\n\n return this.stateGroups;\n }\n}\n", + "sourceCode": "import { Input, Component, OnInit } from '@angular/core';\r\nimport { Observable } from 'rxjs';\r\nimport {\r\n UntypedFormControl,\r\n UntypedFormBuilder,\r\n UntypedFormGroup,\r\n} from '@angular/forms';\r\nimport { startWith, map } from 'rxjs/operators';\r\n\r\nexport interface StateGroup {\r\n letter: string;\r\n names: string[];\r\n}\r\nexport const _filter = (opt: string[], value: string): string[] => {\r\n const filterValue = value.toLowerCase();\r\n\r\n return opt.filter((item) => item.toLowerCase().indexOf(filterValue) === 0);\r\n};\r\n\r\n@Component({\r\n selector: 'oui-autocomplete-storybook',\r\n template: `\r\n \r\n \r\n \r\n \r\n \r\n {{ option }}\r\n \r\n \r\n `,\r\n})\r\nexport class OuiAutocompleteStorybook implements OnInit {\r\n filteredOptions: Observable;\r\n myControl = new UntypedFormControl();\r\n @Input() options: any[];\r\n @Input()\r\n set disabled(value: boolean) {\r\n if (value) {\r\n this.myControl.disable();\r\n } else {\r\n this.myControl.enable();\r\n }\r\n }\r\n ngOnInit() {\r\n this.filteredOptions = this.myControl.valueChanges.pipe(\r\n startWith(''),\r\n map((value) => (typeof value === 'string' ? value : value)),\r\n map((option) => (option ? this._filter(option) : this.options.slice()))\r\n );\r\n }\r\n private _filter(option): string[] {\r\n const filterValue = option.toLowerCase();\r\n\r\n return this.options.filter(\r\n // eslint-disable-next-line no-shadow\r\n (option) => option.toLowerCase().indexOf(filterValue) === 0\r\n );\r\n }\r\n}\r\n\r\n@Component({\r\n selector: 'oui-autocomplete-group-storybook',\r\n template: `\r\n \r\n \r\n \r\n \r\n \r\n {{ name }}\r\n \r\n \r\n \r\n \r\n `,\r\n})\r\nexport class OuiAutocompleteGroupStorybook implements OnInit {\r\n @Input() stateGroups: StateGroup[];\r\n @Input()\r\n set disabled(value: boolean) {\r\n if (value) {\r\n this.stateForm.get('stateGroup')!.disable();\r\n } else {\r\n this.stateForm.get('stateGroup')!.enable();\r\n }\r\n }\r\n stateForm: UntypedFormGroup = this.fb.group({\r\n stateGroup: '',\r\n });\r\n stateGroupOptions: Observable;\r\n\r\n constructor(private fb: UntypedFormBuilder) {}\r\n ngOnInit() {\r\n this.stateGroupOptions = this.stateForm\r\n .get('stateGroup')!\r\n .valueChanges.pipe(\r\n startWith(''),\r\n map((value: string) => this._filterGroup(value))\r\n );\r\n }\r\n\r\n private _filterGroup(value: string): StateGroup[] {\r\n if (value) {\r\n return this.stateGroups\r\n .map((group) => ({\r\n letter: group.letter,\r\n names: _filter(group.names, value),\r\n }))\r\n .filter((group) => group.names.length > 0);\r\n }\r\n\r\n return this.stateGroups;\r\n }\r\n}\r\n", "properties": [ { "name": "letter", @@ -1447,8 +1481,9 @@ } ], "indexSignatures": [], - "kind": 165, - "methods": [] + "kind": 171, + "methods": [], + "extends": [] } ], "injectables": [ @@ -1467,7 +1502,7 @@ "description": "", "line": 36, "modifierKind": [ - 122 + 124 ] }, { @@ -1480,7 +1515,7 @@ "line": 30, "rawdescription": "\nThe locale to use for all dates.", "modifierKind": [ - 122 + 124 ] } ], @@ -1510,17 +1545,17 @@ "rawdescription": "\n\nAdds the given number of days to the date. Days are counted as if moving one cell on the\ncalendar for each day.\n\n", "description": "

Adds the given number of days to the date. Days are counted as if moving one cell on the\ncalendar for each day.

\n", "modifierKind": [ - 126 + 128 ], "jsdoctags": [ { "name": { "pos": 6091, "end": 6095, - "flags": 4227072, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "date" }, "type": "D", @@ -1529,10 +1564,10 @@ "tagName": { "pos": 6085, "end": 6090, - "flags": 4227072, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "param" }, "comment": "

The date to add days to.

\n" @@ -1541,10 +1576,10 @@ "name": { "pos": 6133, "end": 6137, - "flags": 4227072, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "days" }, "type": "number", @@ -1553,10 +1588,10 @@ "tagName": { "pos": 6127, "end": 6132, - "flags": 4227072, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "param" }, "comment": "

The number of days to add (may be negative).

\n" @@ -1565,10 +1600,10 @@ "tagName": { "pos": 6189, "end": 6196, - "flags": 4227072, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "returns" }, "comment": "

A new date equal to the given one with the specified number of days added.

\n" @@ -1600,17 +1635,17 @@ "rawdescription": "\n\nAdds the given number of months to the date. Months are counted as if flipping a page on the\ncalendar for each month and then finding the closest date in the new month. For example when\nadding 1 month to Jan 31, 2017, the resulting date will be Feb 28, 2017.\n\n", "description": "

Adds the given number of months to the date. Months are counted as if flipping a page on the\ncalendar for each month and then finding the closest date in the new month. For example when\nadding 1 month to Jan 31, 2017, the resulting date will be Feb 28, 2017.

\n", "modifierKind": [ - 126 + 128 ], "jsdoctags": [ { "name": { "pos": 5692, "end": 5696, - "flags": 4227072, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "date" }, "type": "D", @@ -1619,10 +1654,10 @@ "tagName": { "pos": 5686, "end": 5691, - "flags": 4227072, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "param" }, "comment": "

The date to add months to.

\n" @@ -1631,10 +1666,10 @@ "name": { "pos": 5736, "end": 5742, - "flags": 4227072, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "months" }, "type": "number", @@ -1643,10 +1678,10 @@ "tagName": { "pos": 5730, "end": 5735, - "flags": 4227072, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "param" }, "comment": "

The number of months to add (may be negative).

\n" @@ -1655,10 +1690,10 @@ "tagName": { "pos": 5796, "end": 5803, - "flags": 4227072, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "returns" }, "comment": "

A new date equal to the given one with the specified number of months added.

\n" @@ -1690,17 +1725,17 @@ "rawdescription": "\n\nAdds the given number of years to the date. Years are counted as if flipping 12 pages on the\ncalendar for each year and then finding the closest date in the new month. For example when\nadding 1 year to Feb 29, 2016, the resulting date will be Feb 28, 2017.\n\n", "description": "

Adds the given number of years to the date. Years are counted as if flipping 12 pages on the\ncalendar for each year and then finding the closest date in the new month. For example when\nadding 1 year to Feb 29, 2016, the resulting date will be Feb 28, 2017.

\n", "modifierKind": [ - 126 + 128 ], "jsdoctags": [ { "name": { "pos": 5147, "end": 5151, - "flags": 4227072, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "date" }, "type": "D", @@ -1709,10 +1744,10 @@ "tagName": { "pos": 5141, "end": 5146, - "flags": 4227072, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "param" }, "comment": "

The date to add years to.

\n" @@ -1721,10 +1756,10 @@ "name": { "pos": 5190, "end": 5195, - "flags": 4227072, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "years" }, "type": "number", @@ -1733,10 +1768,10 @@ "tagName": { "pos": 5184, "end": 5189, - "flags": 4227072, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "param" }, "comment": "

The number of years to add (may be negative).

\n" @@ -1745,10 +1780,10 @@ "tagName": { "pos": 5248, "end": 5255, - "flags": 4227072, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "returns" }, "comment": "

A new date equal to the given one with the specified number of years added.

\n" @@ -1786,16 +1821,16 @@ "deprecated": false, "deprecationMessage": "", "rawdescription": "\n\nClamp the given date between min and max dates.\n\n otherwise `date`.\n", - "description": "

Clamp the given date between min and max dates.

\n
otherwise `date`.
", + "description": "

Clamp the given date between min and max dates.

\nExample :
otherwise `date`.
", "jsdoctags": [ { "name": { "pos": 9774, "end": 9778, - "flags": 4227072, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "date" }, "type": "D", @@ -1804,10 +1839,10 @@ "tagName": { "pos": 9768, "end": 9773, - "flags": 4227072, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "param" }, "comment": "

The date to clamp.

\n" @@ -1816,10 +1851,10 @@ "name": { "pos": 9810, "end": 9813, - "flags": 4227072, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "min" }, "type": "D | null", @@ -1829,10 +1864,10 @@ "tagName": { "pos": 9804, "end": 9809, - "flags": 4227072, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "param" }, "comment": "

The minimum value to allow. If null or omitted no min is enforced.

\n" @@ -1841,10 +1876,10 @@ "name": { "pos": 9893, "end": 9896, - "flags": 4227072, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "max" }, "type": "D | null", @@ -1854,10 +1889,10 @@ "tagName": { "pos": 9887, "end": 9892, - "flags": 4227072, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "param" }, "comment": "

The maximum value to allow. If null or omitted no max is enforced.

\n" @@ -1866,10 +1901,10 @@ "tagName": { "pos": 9970, "end": 9977, - "flags": 4227072, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "returns" }, "comment": "

min if date is less than min, max if date is greater than max,\notherwise date.

\n" @@ -1895,17 +1930,17 @@ "rawdescription": "\n\nClones the given date.\n\n", "description": "

Clones the given date.

\n", "modifierKind": [ - 126 + 128 ], "jsdoctags": [ { "name": { "pos": 3514, "end": 3518, - "flags": 4227072, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "date" }, "type": "D", @@ -1914,10 +1949,10 @@ "tagName": { "pos": 3508, "end": 3513, - "flags": 4227072, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "param" }, "comment": "

The date to clone

\n" @@ -1926,10 +1961,10 @@ "tagName": { "pos": 3543, "end": 3550, - "flags": 4227072, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "returns" }, "comment": "

A new date equal to the given date.

\n" @@ -1959,16 +1994,16 @@ "deprecated": false, "deprecationMessage": "", "rawdescription": "\n\nCompares two dates.\n\n a number greater than 0 if the first date is later.\n", - "description": "

Compares two dates.

\n
a number greater than 0 if the first date is later.
", + "description": "

Compares two dates.

\nExample :
a number greater than 0 if the first date is later.
", "jsdoctags": [ { "name": { "pos": 8630, "end": 8635, - "flags": 4227072, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "first" }, "type": "D", @@ -1977,10 +2012,10 @@ "tagName": { "pos": 8624, "end": 8629, - "flags": 4227072, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "param" }, "comment": "

The first date to compare.

\n" @@ -1989,10 +2024,10 @@ "name": { "pos": 8675, "end": 8681, - "flags": 4227072, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "second" }, "type": "D", @@ -2001,10 +2036,10 @@ "tagName": { "pos": 8669, "end": 8674, - "flags": 4227072, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "param" }, "comment": "

The second date to compare.

\n" @@ -2013,10 +2048,10 @@ "tagName": { "pos": 8716, "end": 8723, - "flags": 4227072, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "returns" }, "comment": "

0 if the dates are equal, a number less than 0 if the first date is earlier,\na number greater than 0 if the first date is later.

\n" @@ -2054,17 +2089,17 @@ "rawdescription": "\n\nCreates a date with the given year, month, and date. Does not allow over/under-flow of the\nmonth and date.\n\n", "description": "

Creates a date with the given year, month, and date. Does not allow over/under-flow of the\nmonth and date.

\n", "modifierKind": [ - 126 + 128 ], "jsdoctags": [ { "name": { "pos": 3764, "end": 3768, - "flags": 4227072, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "year" }, "type": "number", @@ -2073,10 +2108,10 @@ "tagName": { "pos": 3758, "end": 3763, - "flags": 4227072, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "param" }, "comment": "

The full year of the date. (e.g. 89 means the year 89, not the year 1989).

\n" @@ -2085,10 +2120,10 @@ "name": { "pos": 3856, "end": 3861, - "flags": 4227072, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "month" }, "type": "number", @@ -2097,10 +2132,10 @@ "tagName": { "pos": 3850, "end": 3855, - "flags": 4227072, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "param" }, "comment": "

The month of the date (0-indexed, 0 = January). Must be an integer 0 - 11.

\n" @@ -2109,10 +2144,10 @@ "name": { "pos": 3949, "end": 3953, - "flags": 4227072, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "date" }, "type": "number", @@ -2121,10 +2156,10 @@ "tagName": { "pos": 3943, "end": 3948, - "flags": 4227072, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "param" }, "comment": "

The date of month of the date. Must be an integer 1 - length of the given month.

\n" @@ -2133,10 +2168,10 @@ "tagName": { "pos": 4041, "end": 4048, - "flags": 4227072, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "returns" }, "comment": "

The new date, or null if invalid.

\n" @@ -2160,16 +2195,16 @@ "deprecated": false, "deprecationMessage": "", "rawdescription": "\n\nAttempts to deserialize a value to a valid date object. This is different from parsing in that\ndeserialize should only accept non-ambiguous, locale-independent formats (e.g. a ISO 8601\nstring). The default implementation does not allow any deserialization, it simply checks that\nthe given value is already a valid date object or null. The `` will call this\nmethod on all of it's `@Input()` properties that accept dates. It is therefore possible to\nsupport passing values from your backend directly to these properties by overriding this method\nto also deserialize the format used by your backend.\n\n deserialized into a null date (e.g. the empty string), or an invalid date.\n", - "description": "

Attempts to deserialize a value to a valid date object. This is different from parsing in that\ndeserialize should only accept non-ambiguous, locale-independent formats (e.g. a ISO 8601\nstring). The default implementation does not allow any deserialization, it simply checks that\nthe given value is already a valid date object or null. The <oui-datepicker> will call this\nmethod on all of it's @Input() properties that accept dates. It is therefore possible to\nsupport passing values from your backend directly to these properties by overriding this method\nto also deserialize the format used by your backend.

\n
deserialized into a null date (e.g. the empty string), or an invalid date.
", + "description": "

Attempts to deserialize a value to a valid date object. This is different from parsing in that\ndeserialize should only accept non-ambiguous, locale-independent formats (e.g. a ISO 8601\nstring). The default implementation does not allow any deserialization, it simply checks that\nthe given value is already a valid date object or null. The <oui-datepicker> will call this\nmethod on all of it's @Input() properties that accept dates. It is therefore possible to\nsupport passing values from your backend directly to these properties by overriding this method\nto also deserialize the format used by your backend.

\nExample :
deserialized into a null date (e.g. the empty string), or an invalid date.
", "jsdoctags": [ { "name": { "pos": 7958, "end": 7963, - "flags": 4227072, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "value" }, "type": "any", @@ -2178,10 +2213,10 @@ "tagName": { "pos": 7952, "end": 7957, - "flags": 4227072, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "param" }, "comment": "

The value to be deserialized into a date object.

\n" @@ -2190,10 +2225,10 @@ "tagName": { "pos": 8019, "end": 8026, - "flags": 4227072, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "returns" }, "comment": "

The deserialized date object, either a valid date, null if the value can be\ndeserialized into a null date (e.g. the empty string), or an invalid date.

\n" @@ -2225,17 +2260,17 @@ "rawdescription": "\n\nFormats a date as a string according to the given format.\n\n", "description": "

Formats a date as a string according to the given format.

\n", "modifierKind": [ - 126 + 128 ], "jsdoctags": [ { "name": { "pos": 4645, "end": 4649, - "flags": 4227072, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "date" }, "type": "D", @@ -2244,10 +2279,10 @@ "tagName": { "pos": 4639, "end": 4644, - "flags": 4227072, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "param" }, "comment": "

The value to format.

\n" @@ -2256,10 +2291,10 @@ "name": { "pos": 4683, "end": 4696, - "flags": 4227072, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "displayFormat" }, "type": "any", @@ -2268,10 +2303,10 @@ "tagName": { "pos": 4677, "end": 4682, - "flags": 4227072, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "param" }, "comment": "

The format to use to display the date as a string.

\n" @@ -2280,10 +2315,10 @@ "tagName": { "pos": 4754, "end": 4761, - "flags": 4227072, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "returns" }, "comment": "

The formatted date string.

\n" @@ -2309,17 +2344,17 @@ "rawdescription": "\n\nGets the date of the month component of the given date.\n\n", "description": "

Gets the date of the month component of the given date.

\n", "modifierKind": [ - 126 + 128 ], "jsdoctags": [ { "name": { "pos": 1640, "end": 1644, - "flags": 4227072, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "date" }, "type": "D", @@ -2328,10 +2363,10 @@ "tagName": { "pos": 1634, "end": 1639, - "flags": 4227072, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "param" }, "comment": "

The date to extract the date of the month from.

\n" @@ -2340,10 +2375,10 @@ "tagName": { "pos": 1699, "end": 1706, - "flags": 4227072, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "returns" }, "comment": "

The month component (1-indexed, 1 = first of month).

\n" @@ -2362,17 +2397,17 @@ "rawdescription": "\n\nGets a list of names for the dates of the month.\n\n", "description": "

Gets a list of names for the dates of the month.

\n", "modifierKind": [ - 126 + 128 ], "jsdoctags": [ { "tagName": { "pos": 2410, "end": 2417, - "flags": 4227072, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "returns" }, "comment": "

An ordered list of all date of the month names, starting with '1'.

\n" @@ -2398,17 +2433,17 @@ "rawdescription": "\n\nGets the day of the week component of the given date.\n\n", "description": "

Gets the day of the week component of the given date.

\n", "modifierKind": [ - 126 + 128 ], "jsdoctags": [ { "name": { "pos": 1886, "end": 1890, - "flags": 4227072, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "date" }, "type": "D", @@ -2417,10 +2452,10 @@ "tagName": { "pos": 1880, "end": 1885, - "flags": 4227072, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "param" }, "comment": "

The date to extract the day of the week from.

\n" @@ -2429,10 +2464,10 @@ "tagName": { "pos": 1943, "end": 1950, - "flags": 4227072, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "returns" }, "comment": "

The month component (0-indexed, 0 = Sunday).

\n" @@ -2458,17 +2493,17 @@ "rawdescription": "\n\nGets a list of names for the days of the week.\n\n", "description": "

Gets a list of names for the days of the week.

\n", "modifierKind": [ - 126 + 128 ], "jsdoctags": [ { "name": { "pos": 2604, "end": 2609, - "flags": 4227072, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "style" }, "type": "\"long\" | \"short\" | \"narrow\"", @@ -2477,10 +2512,10 @@ "tagName": { "pos": 2598, "end": 2603, - "flags": 4227072, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "param" }, "comment": "

The naming style (e.g. long = 'Sunday', short = 'Sun', narrow = 'S').

\n" @@ -2489,10 +2524,10 @@ "tagName": { "pos": 2686, "end": 2693, - "flags": 4227072, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "returns" }, "comment": "

An ordered list of all weekday names, starting with Sunday.

\n" @@ -2511,17 +2546,17 @@ "rawdescription": "\n\nGets the first day of the week.\n\n", "description": "

Gets the first day of the week.

\n", "modifierKind": [ - 126 + 128 ], "jsdoctags": [ { "tagName": { "pos": 3109, "end": 3116, - "flags": 4227072, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "returns" }, "comment": "

The first day of the week (0-indexed, 0 = Sunday).

\n" @@ -2547,17 +2582,17 @@ "rawdescription": "\n\nGets the month component of the given date.\n\n", "description": "

Gets the month component of the given date.

\n", "modifierKind": [ - 126 + 128 ], "jsdoctags": [ { "name": { "pos": 1410, "end": 1414, - "flags": 4227072, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "date" }, "type": "D", @@ -2566,10 +2601,10 @@ "tagName": { "pos": 1404, "end": 1409, - "flags": 4227072, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "param" }, "comment": "

The date to extract the month from.

\n" @@ -2578,10 +2613,10 @@ "tagName": { "pos": 1457, "end": 1464, - "flags": 4227072, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "returns" }, "comment": "

The month component (0-indexed, 0 = January).

\n" @@ -2607,17 +2642,17 @@ "rawdescription": "\n\nGets a list of names for the months.\n\n", "description": "

Gets a list of names for the months.

\n", "modifierKind": [ - 126 + 128 ], "jsdoctags": [ { "name": { "pos": 2110, "end": 2115, - "flags": 4227072, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "style" }, "type": "\"long\" | \"short\" | \"narrow\"", @@ -2626,10 +2661,10 @@ "tagName": { "pos": 2104, "end": 2109, - "flags": 4227072, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "param" }, "comment": "

The naming style (e.g. long = 'January', short = 'Jan', narrow = 'J').

\n" @@ -2638,10 +2673,10 @@ "tagName": { "pos": 2193, "end": 2200, - "flags": 4227072, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "returns" }, "comment": "

An ordered list of all month names, starting with January.

\n" @@ -2667,17 +2702,17 @@ "rawdescription": "\n\nGets the number of days in the month of the given date.\n\n", "description": "

Gets the number of days in the month of the given date.

\n", "modifierKind": [ - 126 + 128 ], "jsdoctags": [ { "name": { "pos": 3299, "end": 3303, - "flags": 4227072, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "date" }, "type": "D", @@ -2686,10 +2721,10 @@ "tagName": { "pos": 3293, "end": 3298, - "flags": 4227072, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "param" }, "comment": "

The date whose month should be checked.

\n" @@ -2698,10 +2733,10 @@ "tagName": { "pos": 3350, "end": 3357, - "flags": 4227072, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "returns" }, "comment": "

The number of days in the month of the given date.

\n" @@ -2727,17 +2762,17 @@ "rawdescription": "\n\nGets the year component of the given date.\n\n", "description": "

Gets the year component of the given date.

\n", "modifierKind": [ - 126 + 128 ], "jsdoctags": [ { "name": { "pos": 1220, "end": 1224, - "flags": 4227072, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "date" }, "type": "D", @@ -2746,10 +2781,10 @@ "tagName": { "pos": 1214, "end": 1219, - "flags": 4227072, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "param" }, "comment": "

The date to extract the year from.

\n" @@ -2758,10 +2793,10 @@ "tagName": { "pos": 1266, "end": 1273, - "flags": 4227072, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "returns" }, "comment": "

The year component.

\n" @@ -2787,17 +2822,17 @@ "rawdescription": "\n\nGets the name for the year of the given date.\n\n", "description": "

Gets the name for the year of the given date.

\n", "modifierKind": [ - 126 + 128 ], "jsdoctags": [ { "name": { "pos": 2911, "end": 2915, - "flags": 4227072, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "date" }, "type": "D", @@ -2806,10 +2841,10 @@ "tagName": { "pos": 2905, "end": 2910, - "flags": 4227072, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "param" }, "comment": "

The date to get the year name for.

\n" @@ -2818,10 +2853,10 @@ "tagName": { "pos": 2957, "end": 2964, - "flags": 4227072, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "returns" }, "comment": "

The name of the given year (e.g. '2017').

\n" @@ -2840,17 +2875,17 @@ "rawdescription": "\n\nGets date instance that is not valid.\n\n", "description": "

Gets date instance that is not valid.

\n", "modifierKind": [ - 126 + 128 ], "jsdoctags": [ { "tagName": { "pos": 7230, "end": 7237, - "flags": 4227072, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "returns" }, "comment": "

An invalid date.

\n" @@ -2876,17 +2911,17 @@ "rawdescription": "\n\nChecks whether the given object is considered a date instance by this DateAdapter.\n\n", "description": "

Checks whether the given object is considered a date instance by this DateAdapter.

\n", "modifierKind": [ - 126 + 128 ], "jsdoctags": [ { "name": { "pos": 6862, "end": 6865, - "flags": 4227072, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "obj" }, "type": "any", @@ -2895,10 +2930,10 @@ "tagName": { "pos": 6856, "end": 6861, - "flags": 4227072, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "param" }, "comment": "

The object to check

\n" @@ -2907,10 +2942,10 @@ "tagName": { "pos": 6892, "end": 6899, - "flags": 4227072, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "returns" }, "comment": "

Whether the object is a date instance.

\n" @@ -2936,17 +2971,17 @@ "rawdescription": "\n\nChecks whether the given date is valid.\n\n", "description": "

Checks whether the given date is valid.

\n", "modifierKind": [ - 126 + 128 ], "jsdoctags": [ { "name": { "pos": 7060, "end": 7064, - "flags": 4227072, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "date" }, "type": "D", @@ -2955,10 +2990,10 @@ "tagName": { "pos": 7054, "end": 7059, - "flags": 4227072, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "param" }, "comment": "

The date to check.

\n" @@ -2967,10 +3002,10 @@ "tagName": { "pos": 7090, "end": 7097, - "flags": 4227072, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "returns" }, "comment": "

Whether the date is valid.

\n" @@ -3000,19 +3035,19 @@ "deprecated": false, "deprecationMessage": "", "rawdescription": "\n\nParses a date from a user-provided value.\n\n (type is implementation-dependent).\n", - "description": "

Parses a date from a user-provided value.

\n
(type is implementation-dependent).
", + "description": "

Parses a date from a user-provided value.

\nExample :
(type is implementation-dependent).
", "modifierKind": [ - 126 + 128 ], "jsdoctags": [ { "name": { "pos": 4322, "end": 4327, - "flags": 4227072, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "value" }, "type": "any", @@ -3021,10 +3056,10 @@ "tagName": { "pos": 4316, "end": 4321, - "flags": 4227072, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "param" }, "comment": "

The value to parse.

\n" @@ -3033,10 +3068,10 @@ "name": { "pos": 4360, "end": 4371, - "flags": 4227072, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "parseFormat" }, "type": "any", @@ -3045,10 +3080,10 @@ "tagName": { "pos": 4354, "end": 4359, - "flags": 4227072, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "param" }, "comment": "

The expected format of the value being parsed\n(type is implementation-dependent).

\n" @@ -3057,10 +3092,10 @@ "tagName": { "pos": 4469, "end": 4476, - "flags": 4227072, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "returns" }, "comment": "

The parsed date.

\n" @@ -3090,16 +3125,16 @@ "deprecated": false, "deprecationMessage": "", "rawdescription": "\n\nChecks if two dates are equal.\n\n Null dates are considered equal to other null dates.\n", - "description": "

Checks if two dates are equal.

\n
Null dates are considered equal to other null dates.
", + "description": "

Checks if two dates are equal.

\nExample :
Null dates are considered equal to other null dates.
", "jsdoctags": [ { "name": { "pos": 9152, "end": 9157, - "flags": 4227072, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "first" }, "type": "D | null", @@ -3108,10 +3143,10 @@ "tagName": { "pos": 9146, "end": 9151, - "flags": 4227072, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "param" }, "comment": "

The first date to check.

\n" @@ -3120,10 +3155,10 @@ "name": { "pos": 9195, "end": 9201, - "flags": 4227072, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "second" }, "type": "D | null", @@ -3132,10 +3167,10 @@ "tagName": { "pos": 9189, "end": 9194, - "flags": 4227072, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "param" }, "comment": "

The second date to check.

\n" @@ -3144,10 +3179,10 @@ "tagName": { "pos": 9234, "end": 9241, - "flags": 4227072, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "returns" }, "comment": "

Whether the two dates are equal.\nNull dates are considered equal to other null dates.

\n" @@ -3177,10 +3212,10 @@ "name": { "pos": 8463, "end": 8469, - "flags": 4227072, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "locale" }, "type": "any", @@ -3189,10 +3224,10 @@ "tagName": { "pos": 8457, "end": 8462, - "flags": 4227072, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "param" }, "comment": "

The new locale.

\n" @@ -3211,17 +3246,17 @@ "rawdescription": "\n\nGets today's date.\n\n", "description": "

Gets today's date.

\n", "modifierKind": [ - 126 + 128 ], "jsdoctags": [ { "tagName": { "pos": 4200, "end": 4207, - "flags": 4227072, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "returns" }, "comment": "

Today's date.

\n" @@ -3247,17 +3282,17 @@ "rawdescription": "\n\nGets the RFC 3339 compatible string (https://tools.ietf.org/html/rfc3339) for the given date.\nThis method is used to generate date strings that are compatible with native HTML attributes\nsuch as the `min` or `max` attribute of an ``.\n\n", "description": "

Gets the RFC 3339 compatible string (https://tools.ietf.org/html/rfc3339) for the given date.\nThis method is used to generate date strings that are compatible with native HTML attributes\nsuch as the min or max attribute of an <input>.

\n", "modifierKind": [ - 126 + 128 ], "jsdoctags": [ { "name": { "pos": 6612, "end": 6616, - "flags": 4227072, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "date" }, "type": "D", @@ -3266,10 +3301,10 @@ "tagName": { "pos": 6606, "end": 6611, - "flags": 4227072, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "param" }, "comment": "

The date to get the ISO date string for.

\n" @@ -3278,10 +3313,10 @@ "tagName": { "pos": 6664, "end": 6671, - "flags": 4227072, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "returns" }, "comment": "

The ISO date string date string.

\n" @@ -3307,6 +3342,7 @@ } } }, + "extends": [], "type": "injectable" }, { @@ -3323,7 +3359,7 @@ "description": "", "line": 12, "modifierKind": [ - 121 + 123 ] }, { @@ -3335,7 +3371,7 @@ "description": "", "line": 13, "modifierKind": [ - 121 + 123 ] }, { @@ -3347,7 +3383,7 @@ "description": "", "line": 14, "modifierKind": [ - 121 + 123 ] } ], @@ -3362,7 +3398,7 @@ "deprecated": false, "deprecationMessage": "", "modifierKind": [ - 121 + 123 ] }, { @@ -3431,12 +3467,13 @@ "args": [], "line": 14 }, + "extends": [], "type": "injectable" }, { "name": "ErrorStateMatcher", "id": "injectable-ErrorStateMatcher-2a790495b111018f3cbba0de2309c414412a62be2f0fb8cffdc004f5dc3b3f11c8e19fc024a0ae5e7487dfe35577ec4246ce26c8c46297b9d2651b92f301d6e5", - "file": "ui/src/components/core/error/error-options.ts", + "file": "ui/src/components/core/common-behaviors/error-options.ts", "properties": [], "methods": [ { @@ -3488,12 +3525,13 @@ "description": "

Provider that defines how form controls behave with regards to displaying error messages.

\n", "rawdescription": "\nProvider that defines how form controls behave with regards to displaying error messages.", "sourceCode": "import { Injectable } from '@angular/core';\nimport { FormGroupDirective, NgForm, UntypedFormControl } from '@angular/forms';\n\n/** Provider that defines how form controls behave with regards to displaying error messages. */\n@Injectable({ providedIn: 'root' })\nexport class ErrorStateMatcher {\n isErrorState(\n control: UntypedFormControl | null,\n form: FormGroupDirective | NgForm | null\n ): boolean {\n return !!(\n control &&\n control.invalid &&\n (control.touched || (form && form.submitted))\n );\n }\n}\n\n/** Error state matcher that matches when a control is invalid and dirty. */\n@Injectable()\nexport class ShowOnDirtyErrorStateMatcher implements ErrorStateMatcher {\n isErrorState(\n control: UntypedFormControl | null,\n form: FormGroupDirective | NgForm | null\n ): boolean {\n return !!(\n control &&\n control.invalid &&\n (control.dirty || (form && form.submitted))\n );\n }\n}\n", + "extends": [], "type": "injectable" }, { "name": "ErrorStateMatcher", "id": "injectable-ErrorStateMatcher-2a790495b111018f3cbba0de2309c414412a62be2f0fb8cffdc004f5dc3b3f11c8e19fc024a0ae5e7487dfe35577ec4246ce26c8c46297b9d2651b92f301d6e5-1", - "file": "ui/src/components/core/common-behaviors/error-options.ts", + "file": "ui/src/components/core/error/error-options.ts", "properties": [], "methods": [ { @@ -3545,6 +3583,7 @@ "description": "

Provider that defines how form controls behave with regards to displaying error messages.

\n", "rawdescription": "\nProvider that defines how form controls behave with regards to displaying error messages.", "sourceCode": "import { Injectable } from '@angular/core';\nimport { FormGroupDirective, NgForm, UntypedFormControl } from '@angular/forms';\n\n/** Provider that defines how form controls behave with regards to displaying error messages. */\n@Injectable({ providedIn: 'root' })\nexport class ErrorStateMatcher {\n isErrorState(\n control: UntypedFormControl | null,\n form: FormGroupDirective | NgForm | null\n ): boolean {\n return !!(\n control &&\n control.invalid &&\n (control.touched || (form && form.submitted))\n );\n }\n}\n\n/** Error state matcher that matches when a control is invalid and dirty. */\n@Injectable()\nexport class ShowOnDirtyErrorStateMatcher implements ErrorStateMatcher {\n isErrorState(\n control: UntypedFormControl | null,\n form: FormGroupDirective | NgForm | null\n ): boolean {\n return !!(\n control &&\n control.invalid &&\n (control.dirty || (form && form.submitted))\n );\n }\n}\n", + "extends": [], "type": "injectable", "isDuplicate": true, "duplicateId": 1, @@ -3566,7 +3605,7 @@ "deprecated": false, "deprecationMessage": "", "modifierKind": [ - 121 + 123 ] }, { @@ -3615,6 +3654,7 @@ "description": "

A null icon registry that must be imported to allow disabling of custom icons

\n", "rawdescription": "\n\nA null icon registry that must be imported to allow disabling of custom icons\n", "sourceCode": "import { Injectable, NgModule } from '@angular/core';\nimport { OuiIconRegistry } from '../icon-registery';\nimport { Observable, of as observableOf } from 'rxjs';\n\n/* eslint-disable @typescript-eslint/no-explicit-any */\ntype PublicApi = {\n [K in keyof T]: T[K] extends (...x: any[]) => T\n ? (...x: any[]) => PublicApi\n : T[K];\n};\n/* eslint-enable @typescript-eslint/no-explicit-any */\n\n/**\n * A null icon registry that must be imported to allow disabling of custom icons\n */\n@Injectable()\nexport class FakeOuiIconRegistry implements PublicApi {\n addSvgIcon(): this {\n return this;\n }\n\n addSvgIconLiteral(): this {\n return this;\n }\n\n addSvgIconSet(): this {\n return this;\n }\n\n getNamedSvgIcon(): Observable {\n return observableOf(this._generateEmptySvg());\n }\n\n private _generateEmptySvg(): SVGElement {\n const emptySvg = document.createElementNS(\n 'http://www.w3.org/2000/svg',\n 'svg'\n );\n emptySvg.classList.add('fake-testing-svg');\n // Emulate real icon characteristics from `OuiIconRegistry` so size remains consistent in tests.\n emptySvg.setAttribute('fit', '');\n emptySvg.setAttribute('height', '100%');\n emptySvg.setAttribute('width', '100%');\n emptySvg.setAttribute('preserveAspectRatio', 'xMidYMid meet');\n emptySvg.setAttribute('focusable', 'false');\n return emptySvg;\n }\n}\n\n/** Use this module to install the null icon registry. */\n@NgModule({\n providers: [{ provide: OuiIconRegistry, useClass: FakeOuiIconRegistry }],\n})\nexport class OuiIconTestingModule {}\n", + "extends": [], "type": "injectable" }, { @@ -3714,7 +3754,9 @@ "args": [], "line": 13 }, - "extends": "NgZone", + "extends": [ + "NgZone" + ], "type": "injectable" }, { @@ -3732,8 +3774,8 @@ "line": 81, "rawdescription": "\nWhether to clamp the date between 1 and 9999 to avoid IE and Edge errors.", "modifierKind": [ - 121, - 144 + 123, + 148 ] }, { @@ -3757,7 +3799,7 @@ "description": "", "line": 36, "modifierKind": [ - 122 + 124 ], "inheritance": { "file": "DateAdapter" @@ -3773,7 +3815,7 @@ "line": 30, "rawdescription": "\nThe locale to use for all dates.", "modifierKind": [ - 122 + 124 ], "inheritance": { "file": "DateAdapter" @@ -3800,17 +3842,17 @@ "rawdescription": "\n\nPads a number to make it two digits.\n\n", "description": "

Pads a number to make it two digits.

\n", "modifierKind": [ - 121 + 123 ], "jsdoctags": [ { "name": { "pos": 9091, "end": 9092, - "flags": 4227072, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "n" }, "type": "number", @@ -3819,10 +3861,10 @@ "tagName": { "pos": 9085, "end": 9090, - "flags": 4227072, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "param" }, "comment": "

The number to pad.

\n" @@ -3831,10 +3873,10 @@ "tagName": { "pos": 9118, "end": 9125, - "flags": 4227072, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "returns" }, "comment": "

The padded number.

\n" @@ -3872,7 +3914,7 @@ "rawdescription": "\nCreates a date but allows the month and date to overflow.", "description": "

Creates a date but allows the month and date to overflow.

\n", "modifierKind": [ - 121 + 123 ], "jsdoctags": [ { @@ -3929,17 +3971,17 @@ "rawdescription": "\n\nWhen converting Date object to string, javascript built-in functions may return wrong\nresults because it applies its internal DST rules. The DST rules around the world change\nvery frequently, and the current valid rule is not always valid in previous years though.\nWe work around this problem building a new Date object which has its internal UTC\nrepresentation with the local date and time.\n\n timeZone set to 'utc' to work fine.\n", "description": "

When converting Date object to string, javascript built-in functions may return wrong\nresults because it applies its internal DST rules. The DST rules around the world change\nvery frequently, and the current valid rule is not always valid in previous years though.\nWe work around this problem building a new Date object which has its internal UTC\nrepresentation with the local date and time.

\n

timeZone set to 'utc' to work fine.

\n", "modifierKind": [ - 121 + 123 ], "jsdoctags": [ { "name": { "pos": 10100, "end": 10103, - "flags": 4227072, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "dtf" }, "type": "Intl.DateTimeFormat", @@ -3948,10 +3990,10 @@ "tagName": { "pos": 10094, "end": 10099, - "flags": 4227072, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "param" }, "comment": "

Intl.DateTimeFormat object, containg the desired string format. It must have\ntimeZone set to 'utc' to work fine.

\n" @@ -3960,10 +4002,10 @@ "name": { "pos": 10237, "end": 10241, - "flags": 4227072, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "date" }, "type": "Date", @@ -3972,10 +4014,10 @@ "tagName": { "pos": 10231, "end": 10236, - "flags": 4227072, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "param" }, "comment": "

Date from which we want to get the string representation according to dtf

\n" @@ -3984,10 +4026,10 @@ "tagName": { "pos": 10322, "end": 10329, - "flags": 4227072, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "returns" }, "comment": "

A Date object with its UTC representation based on the passed in date info

\n" @@ -4013,17 +4055,17 @@ "rawdescription": "\n\nStrip out unicode LTR and RTL characters. Edge and IE insert these into formatted dates while\nother browsers do not. We remove them to make output consistent and because they interfere with\ndate parsing.\n\n", "description": "

Strip out unicode LTR and RTL characters. Edge and IE insert these into formatted dates while\nother browsers do not. We remove them to make output consistent and because they interfere with\ndate parsing.

\n", "modifierKind": [ - 121 + 123 ], "jsdoctags": [ { "name": { "pos": 9460, "end": 9463, - "flags": 4227072, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "str" }, "type": "string", @@ -4032,10 +4074,10 @@ "tagName": { "pos": 9454, "end": 9459, - "flags": 4227072, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "param" }, "comment": "

The string to strip direction characters from.

\n" @@ -4044,10 +4086,10 @@ "tagName": { "pos": 9517, "end": 9524, - "flags": 4227072, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "returns" }, "comment": "

The stripped string.

\n" @@ -4818,16 +4860,16 @@ "deprecated": false, "deprecationMessage": "", "rawdescription": "\n\nClamp the given date between min and max dates.\n\n otherwise `date`.\n", - "description": "

Clamp the given date between min and max dates.

\n
otherwise `date`.
", + "description": "

Clamp the given date between min and max dates.

\nExample :
otherwise `date`.
", "jsdoctags": [ { "name": { "pos": 9774, "end": 9778, - "flags": 4227072, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "date" }, "type": "D", @@ -4836,10 +4878,10 @@ "tagName": { "pos": 9768, "end": 9773, - "flags": 4227072, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "param" }, "comment": "

The date to clamp.

\n" @@ -4848,10 +4890,10 @@ "name": { "pos": 9810, "end": 9813, - "flags": 4227072, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "min" }, "type": "D | null", @@ -4861,10 +4903,10 @@ "tagName": { "pos": 9804, "end": 9809, - "flags": 4227072, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "param" }, "comment": "

The minimum value to allow. If null or omitted no min is enforced.

\n" @@ -4873,10 +4915,10 @@ "name": { "pos": 9893, "end": 9896, - "flags": 4227072, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "max" }, "type": "D | null", @@ -4886,10 +4928,10 @@ "tagName": { "pos": 9887, "end": 9892, - "flags": 4227072, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "param" }, "comment": "

The maximum value to allow. If null or omitted no max is enforced.

\n" @@ -4898,10 +4940,10 @@ "tagName": { "pos": 9970, "end": 9977, - "flags": 4227072, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "returns" }, "comment": "

min if date is less than min, max if date is greater than max,\notherwise date.

\n" @@ -4934,16 +4976,16 @@ "deprecated": false, "deprecationMessage": "", "rawdescription": "\n\nCompares two dates.\n\n a number greater than 0 if the first date is later.\n", - "description": "

Compares two dates.

\n
a number greater than 0 if the first date is later.
", + "description": "

Compares two dates.

\nExample :
a number greater than 0 if the first date is later.
", "jsdoctags": [ { "name": { "pos": 8630, "end": 8635, - "flags": 4227072, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "first" }, "type": "D", @@ -4952,10 +4994,10 @@ "tagName": { "pos": 8624, "end": 8629, - "flags": 4227072, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "param" }, "comment": "

The first date to compare.

\n" @@ -4964,10 +5006,10 @@ "name": { "pos": 8675, "end": 8681, - "flags": 4227072, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "second" }, "type": "D", @@ -4976,10 +5018,10 @@ "tagName": { "pos": 8669, "end": 8674, - "flags": 4227072, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "param" }, "comment": "

The second date to compare.

\n" @@ -4988,10 +5030,10 @@ "tagName": { "pos": 8716, "end": 8723, - "flags": 4227072, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "returns" }, "comment": "

0 if the dates are equal, a number less than 0 if the first date is earlier,\na number greater than 0 if the first date is later.

\n" @@ -5024,16 +5066,16 @@ "deprecated": false, "deprecationMessage": "", "rawdescription": "\n\nChecks if two dates are equal.\n\n Null dates are considered equal to other null dates.\n", - "description": "

Checks if two dates are equal.

\n
Null dates are considered equal to other null dates.
", + "description": "

Checks if two dates are equal.

\nExample :
Null dates are considered equal to other null dates.
", "jsdoctags": [ { "name": { "pos": 9152, "end": 9157, - "flags": 4227072, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "first" }, "type": "D | null", @@ -5042,10 +5084,10 @@ "tagName": { "pos": 9146, "end": 9151, - "flags": 4227072, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "param" }, "comment": "

The first date to check.

\n" @@ -5054,10 +5096,10 @@ "name": { "pos": 9195, "end": 9201, - "flags": 4227072, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "second" }, "type": "D | null", @@ -5066,10 +5108,10 @@ "tagName": { "pos": 9189, "end": 9194, - "flags": 4227072, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "param" }, "comment": "

The second date to check.

\n" @@ -5078,10 +5120,10 @@ "tagName": { "pos": 9234, "end": 9241, - "flags": 4227072, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "returns" }, "comment": "

Whether the two dates are equal.\nNull dates are considered equal to other null dates.

\n" @@ -5114,10 +5156,10 @@ "name": { "pos": 8463, "end": 8469, - "flags": 4227072, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "locale" }, "type": "any", @@ -5126,10 +5168,10 @@ "tagName": { "pos": 8457, "end": 8462, - "flags": 4227072, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "param" }, "comment": "

The new locale.

\n" @@ -5186,7 +5228,9 @@ } ] }, - "extends": "DateAdapter", + "extends": [ + "DateAdapter" + ], "type": "injectable" }, { @@ -5216,7 +5260,7 @@ "line": 11, "rawdescription": "\n\nStream that emits whenever the labels here are changed. Use this to notify\ncomponents if the labels have changed after initialization.\n", "modifierKind": [ - 144 + 148 ] }, { @@ -5325,6 +5369,7 @@ "description": "

Datepicker data that requires internationalization.

\n", "rawdescription": "\nDatepicker data that requires internationalization.", "sourceCode": "import { Injectable } from '@angular/core';\nimport { Subject } from 'rxjs';\n\n/** Datepicker data that requires internationalization. */\n@Injectable({ providedIn: 'root' })\nexport class OuiDatepickerIntl {\n /**\n * Stream that emits whenever the labels here are changed. Use this to notify\n * components if the labels have changed after initialization.\n */\n readonly changes: Subject = new Subject();\n\n /** A label for the calendar popup (used by screen readers). */\n calendarLabel = 'Calendar';\n\n /** A label for the button used to open the calendar popup (used by screen readers). */\n openCalendarLabel = 'Open calendar';\n\n /** A label for the previous month button (used by screen readers). */\n prevMonthLabel = 'Previous month';\n\n /** A label for the next month button (used by screen readers). */\n nextMonthLabel = 'Next month';\n\n /** A label for the previous year button (used by screen readers). */\n prevYearLabel = 'Previous year';\n\n /** A label for the next year button (used by screen readers). */\n nextYearLabel = 'Next year';\n\n /** A label for the previous multi-year button (used by screen readers). */\n prevMultiYearLabel = 'Previous 20 years';\n\n /** A label for the next multi-year button (used by screen readers). */\n nextMultiYearLabel = 'Next 20 years';\n\n /** A label for the 'switch to month view' button (used by screen readers). */\n switchToMonthViewLabel = 'Choose date';\n\n /** A label for the 'switch to year view' button (used by screen readers). */\n switchToMultiYearViewLabel = 'Choose month and year';\n}\n", + "extends": [], "type": "injectable" }, { @@ -5342,8 +5387,8 @@ "description": "", "line": 78, "modifierKind": [ - 121, - 144 + 123, + 148 ] }, { @@ -5356,8 +5401,8 @@ "description": "", "line": 79, "modifierKind": [ - 121, - 144 + 123, + 148 ] }, { @@ -5370,7 +5415,7 @@ "description": "", "line": 80, "modifierKind": [ - 121 + 123 ] }, { @@ -5383,7 +5428,7 @@ "description": "", "line": 81, "modifierKind": [ - 121 + 123 ] }, { @@ -5396,7 +5441,7 @@ "description": "", "line": 77, "modifierKind": [ - 121 + 123 ] }, { @@ -5410,7 +5455,7 @@ "line": 106, "rawdescription": "\n\nStream that emits when all open dialog have finished closing.\nWill emit on subscribe if there are no open dialogs to begin with.\n", "modifierKind": [ - 144 + 148 ] } ], @@ -5440,17 +5485,17 @@ "rawdescription": "\n\nAttaches an OuiDialogContainer to a dialog's already-created overlay.\n\n", "description": "

Attaches an OuiDialogContainer to a dialog's already-created overlay.

\n", "modifierKind": [ - 121 + 123 ], "jsdoctags": [ { "name": { "pos": 7117, "end": 7124, - "flags": 4227072, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "overlay" }, "type": "OverlayRef", @@ -5459,10 +5504,10 @@ "tagName": { "pos": 7111, "end": 7116, - "flags": 4227072, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "param" }, "comment": "

Reference to the dialog's underlying overlay.

\n" @@ -5471,10 +5516,10 @@ "name": { "pos": 7183, "end": 7189, - "flags": 4227072, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "config" }, "type": "OuiDialogConfig", @@ -5483,10 +5528,10 @@ "tagName": { "pos": 7177, "end": 7182, - "flags": 4227072, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "param" }, "comment": "

The dialog configuration.

\n" @@ -5495,10 +5540,10 @@ "tagName": { "pos": 7222, "end": 7229, - "flags": 4227072, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "returns" }, "comment": "

A promise resolving to a ComponentRef for the attached container.

\n" @@ -5543,19 +5588,19 @@ "deprecated": false, "deprecationMessage": "", "rawdescription": "\n\nAttaches the user-provided component to the already-created OuiDialogContainer.\n\n or a TemplateRef to instantiate as the content.\n", - "description": "

Attaches the user-provided component to the already-created OuiDialogContainer.

\n
or a TemplateRef to instantiate as the content.
", + "description": "

Attaches the user-provided component to the already-created OuiDialogContainer.

\nExample :
or a TemplateRef to instantiate as the content.
", "modifierKind": [ - 121 + 123 ], "jsdoctags": [ { "name": { "pos": 8004, "end": 8026, - "flags": 4227072, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "componentOrTemplateRef" }, "type": "ComponentType | TemplateRef", @@ -5564,10 +5609,10 @@ "tagName": { "pos": 7998, "end": 8003, - "flags": 4227072, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "param" }, "comment": "

The type of component being loaded into the dialog,\nor a TemplateRef to instantiate as the content.

\n" @@ -5576,10 +5621,10 @@ "name": { "pos": 8148, "end": 8163, - "flags": 4227072, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "dialogContainer" }, "type": "OuiDialogContainer", @@ -5588,10 +5633,10 @@ "tagName": { "pos": 8142, "end": 8147, - "flags": 4227072, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "param" }, "comment": "

Reference to the wrapping OuiDialogContainer.

\n" @@ -5600,10 +5645,10 @@ "name": { "pos": 8222, "end": 8232, - "flags": 4227072, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "overlayRef" }, "type": "OverlayRef", @@ -5612,10 +5657,10 @@ "tagName": { "pos": 8216, "end": 8221, - "flags": 4227072, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "param" }, "comment": "

Reference to the overlay in which the dialog resides.

\n" @@ -5624,10 +5669,10 @@ "name": { "pos": 8299, "end": 8305, - "flags": 4227072, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "config" }, "type": "OuiDialogConfig", @@ -5636,10 +5681,10 @@ "tagName": { "pos": 8293, "end": 8298, - "flags": 4227072, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "param" }, "comment": "

The dialog configuration.

\n" @@ -5648,10 +5693,10 @@ "tagName": { "pos": 8338, "end": 8345, - "flags": 4227072, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "returns" }, "comment": "

A promise resolving to the OuiDialogRef that should be returned to the user.

\n" @@ -5677,7 +5722,7 @@ "rawdescription": "\nCloses all of the dialogs in an array.", "description": "

Closes all of the dialogs in an array.

\n", "modifierKind": [ - 121 + 123 ], "jsdoctags": [ { @@ -5724,17 +5769,17 @@ "rawdescription": "\n\nCreates a custom injector to be used inside the dialog. This allows a component loaded inside\nof a dialog to close itself and, optionally, to return a value.\n\n", "description": "

Creates a custom injector to be used inside the dialog. This allows a component loaded inside\nof a dialog to close itself and, optionally, to return a value.

\n", "modifierKind": [ - 121 + 123 ], "jsdoctags": [ { "name": { "pos": 10145, "end": 10151, - "flags": 4227072, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "config" }, "type": "OuiDialogConfig", @@ -5743,10 +5788,10 @@ "tagName": { "pos": 10139, "end": 10144, - "flags": 4227072, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "param" }, "comment": "

Config object that is used to construct the dialog.

\n" @@ -5755,10 +5800,10 @@ "name": { "pos": 10216, "end": 10225, - "flags": 4227072, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "dialogRef" }, "type": "OuiDialogRef", @@ -5767,10 +5812,10 @@ "tagName": { "pos": 10210, "end": 10215, - "flags": 4227072, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "param" }, "comment": "

Reference to the dialog.

\n" @@ -5788,10 +5833,10 @@ "tagName": { "pos": 10336, "end": 10343, - "flags": 4227072, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "returns" }, "comment": "

The custom injector that can be used inside the dialog.

\n" @@ -5817,17 +5862,17 @@ "rawdescription": "\n\nCreates the overlay into which the dialog will be loaded.\n\n", "description": "

Creates the overlay into which the dialog will be loaded.

\n", "modifierKind": [ - 121 + 123 ], "jsdoctags": [ { "name": { "pos": 5857, "end": 5863, - "flags": 4227072, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "config" }, "type": "OuiDialogConfig", @@ -5836,10 +5881,10 @@ "tagName": { "pos": 5851, "end": 5856, - "flags": 4227072, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "param" }, "comment": "

The dialog configuration.

\n" @@ -5848,10 +5893,10 @@ "tagName": { "pos": 5896, "end": 5903, - "flags": 4227072, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "returns" }, "comment": "

A promise resolving to the OverlayRef for the created overlay.

\n" @@ -5877,17 +5922,17 @@ "rawdescription": "\n\nCreates an overlay config from a dialog config.\n\n", "description": "

Creates an overlay config from a dialog config.

\n", "modifierKind": [ - 121 + 123 ], "jsdoctags": [ { "name": { "pos": 6224, "end": 6236, - "flags": 4227072, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "dialogConfig" }, "type": "OuiDialogConfig", @@ -5896,10 +5941,10 @@ "tagName": { "pos": 6218, "end": 6223, - "flags": 4227072, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "param" }, "comment": "

The dialog configuration.

\n" @@ -5908,10 +5953,10 @@ "tagName": { "pos": 6269, "end": 6276, - "flags": 4227072, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "returns" }, "comment": "

The overlay configuration.

\n" @@ -5930,7 +5975,7 @@ "rawdescription": "\n\nHides all of the content that isn't an overlay from assistive technology.\n", "description": "

Hides all of the content that isn't an overlay from assistive technology.

\n", "modifierKind": [ - 121 + 123 ] }, { @@ -5952,17 +5997,17 @@ "rawdescription": "\n\nRemoves a dialog from the array of open dialogs.\n\n", "description": "

Removes a dialog from the array of open dialogs.

\n", "modifierKind": [ - 121 + 123 ], "jsdoctags": [ { "name": { "pos": 11597, "end": 11606, - "flags": 4227072, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "dialogRef" }, "type": "OuiDialogRef", @@ -5971,10 +6016,10 @@ "tagName": { "pos": 11591, "end": 11596, - "flags": 4227072, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "param" }, "comment": "

Dialog to be removed.

\n" @@ -6016,10 +6061,10 @@ "name": { "pos": 5311, "end": 5313, - "flags": 4227072, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "id" }, "type": "string", @@ -6028,10 +6073,10 @@ "tagName": { "pos": 5305, "end": 5310, - "flags": 4227072, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "param" }, "comment": "

ID to use when looking up the dialog.

\n" @@ -6076,16 +6121,16 @@ "deprecated": false, "deprecationMessage": "", "rawdescription": "\n\nOpens a modal dialog containing the given component.\n\n or a TemplateRef to instantiate as the dialog content.\n", - "description": "

Opens a modal dialog containing the given component.

\n
or a TemplateRef to instantiate as the dialog content.
", + "description": "

Opens a modal dialog containing the given component.

\nExample :
or a TemplateRef to instantiate as the dialog content.
", "jsdoctags": [ { "name": { "pos": 3654, "end": 3676, - "flags": 4227072, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "componentOrTemplateRef" }, "type": "ComponentType | TemplateRef", @@ -6094,10 +6139,10 @@ "tagName": { "pos": 3648, "end": 3653, - "flags": 4227072, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "param" }, "comment": "

Type of the component to load into the dialog,\nor a TemplateRef to instantiate as the dialog content.

\n" @@ -6106,10 +6151,10 @@ "name": { "pos": 3800, "end": 3806, - "flags": 4227072, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "config" }, "type": "OuiDialogConfig", @@ -6119,10 +6164,10 @@ "tagName": { "pos": 3794, "end": 3799, - "flags": 4227072, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "param" }, "comment": "

Extra configuration options.

\n" @@ -6131,10 +6176,10 @@ "tagName": { "pos": 3842, "end": 3849, - "flags": 4227072, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "returns" }, "comment": "

Reference to the newly-opened dialog.

\n" @@ -6266,6 +6311,7 @@ } } }, + "extends": [], "type": "injectable" }, { @@ -6282,7 +6328,7 @@ "description": "", "line": 97, "modifierKind": [ - 121 + 123 ] }, { @@ -6296,7 +6342,7 @@ "line": 108, "rawdescription": "\n\nSvgIconConfig objects and cached SVG elements for icon sets, keyed by namespace.\nMultiple icon sets can be registered under the same namespace.\n", "modifierKind": [ - 121 + 123 ] }, { @@ -6310,7 +6356,7 @@ "line": 111, "rawdescription": "\nIn-progress icon fetches. Used to coalesce multiple requests to the same URL.", "modifierKind": [ - 121 + 123 ] }, { @@ -6324,7 +6370,7 @@ "line": 102, "rawdescription": "\n\nURLs and cached SVG elements for individual icons. Keys are of the format\n", "modifierKind": [ - 121 + 123 ] } ], @@ -6348,7 +6394,7 @@ "rawdescription": "\n\nCreates a DOM element from the given SVG string, and adds default attributes.\n", "description": "

Creates a DOM element from the given SVG string, and adds default attributes.

\n", "modifierKind": [ - 121 + 123 ], "jsdoctags": [ { @@ -6387,7 +6433,7 @@ "rawdescription": "\n\nSearches the cached SVG elements for the given icon sets for a nested icon element whose \"id\"\ntag matches the specified name. If found, copies the nested element to a new SVG element and\nreturns it. Returns null if no matching element is found.\n", "description": "

Searches the cached SVG elements for the given icon sets for a nested icon element whose "id"\ntag matches the specified name. If found, copies the nested element to a new SVG element and\nreturns it. Returns null if no matching element is found.

\n", "modifierKind": [ - 121 + 123 ], "jsdoctags": [ { @@ -6435,7 +6481,7 @@ "rawdescription": "\n\nSearches the cached element of the given SvgIconConfig for a nested icon element whose \"id\"\ntag matches the specified name. If found, copies the nested element to a new SVG element and\nreturns it. Returns null if no matching element is found.\n", "description": "

Searches the cached element of the given SvgIconConfig for a nested icon element whose "id"\ntag matches the specified name. If found, copies the nested element to a new SVG element and\nreturns it. Returns null if no matching element is found.

\n", "modifierKind": [ - 121 + 123 ], "jsdoctags": [ { @@ -6477,7 +6523,7 @@ "rawdescription": "\n\nReturns an Observable which produces the string contents of the given URL. Results may be\ncached, so future calls with the same URL may not cause another HTTP request.\n", "description": "

Returns an Observable which produces the string contents of the given URL. Results may be\ncached, so future calls with the same URL may not cause another HTTP request.

\n", "modifierKind": [ - 121 + 123 ], "jsdoctags": [ { @@ -6510,7 +6556,7 @@ "rawdescription": "\n\nReturns the cached icon for a SvgIconConfig if available, or fetches it from its URL if not.\n", "description": "

Returns the cached icon for a SvgIconConfig if available, or fetches it from its URL if not.

\n", "modifierKind": [ - 121 + 123 ], "jsdoctags": [ { @@ -6549,7 +6595,7 @@ "rawdescription": "\n\nAttempts to find an icon with the specified name in any of the SVG icon sets.\nFirst searches the available cached icons for a nested element with a matching name, and\nif found copies the element to a new `` element. If not found, fetches all icon sets\nthat have not been cached, and searches again after all fetches are completed.\nThe returned Observable produces the SVG element if possible, and throws\nan error if no icon with the specified name can be found.\n", "description": "

Attempts to find an icon with the specified name in any of the SVG icon sets.\nFirst searches the available cached icons for a nested element with a matching name, and\nif found copies the element to a new <svg> element. If not found, fetches all icon sets\nthat have not been cached, and searches again after all fetches are completed.\nThe returned Observable produces the SVG element if possible, and throws\nan error if no icon with the specified name can be found.

\n", "modifierKind": [ - 121 + 123 ], "jsdoctags": [ { @@ -6591,7 +6637,7 @@ "rawdescription": "\n\nLoads the content of the icon URL specified in the SvgIconConfig and creates an SVG element\nfrom it.\n", "description": "

Loads the content of the icon URL specified in the SvgIconConfig and creates an SVG element\nfrom it.

\n", "modifierKind": [ - 121 + 123 ], "jsdoctags": [ { @@ -6624,7 +6670,7 @@ "rawdescription": "\n\nLoads the content of the icon set URL specified in the SvgIconConfig and creates an SVG element\nfrom it.\n", "description": "

Loads the content of the icon set URL specified in the SvgIconConfig and creates an SVG element\nfrom it.

\n", "modifierKind": [ - 121 + 123 ], "jsdoctags": [ { @@ -6657,7 +6703,7 @@ "rawdescription": "\n\nSets the default attributes for an SVG element to be used as an icon.\n", "description": "

Sets the default attributes for an SVG element to be used as an icon.

\n", "modifierKind": [ - 121 + 123 ], "jsdoctags": [ { @@ -6690,7 +6736,7 @@ "rawdescription": "\n\nCreates a DOM element from the given SVG string.\n", "description": "

Creates a DOM element from the given SVG string.

\n", "modifierKind": [ - 121 + 123 ], "jsdoctags": [ { @@ -6723,7 +6769,7 @@ "rawdescription": "\n\nConverts an element into an SVG node by cloning all of its children.\n", "description": "

Converts an element into an SVG node by cloning all of its children.

\n", "modifierKind": [ - 121 + 123 ], "jsdoctags": [ { @@ -6766,10 +6812,10 @@ "name": { "pos": 3627, "end": 3635, - "flags": 4227072, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "iconName" }, "type": "string", @@ -6778,10 +6824,10 @@ "tagName": { "pos": 3621, "end": 3626, - "flags": 4227072, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "param" }, "comment": "

Name under which the icon should be registered.

\n" @@ -6790,10 +6836,10 @@ "name": { "pos": 3696, "end": 3699, - "flags": 4227072, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "url" }, "type": "SafeResourceUrl", @@ -6802,10 +6848,10 @@ "tagName": { "pos": 3690, "end": 3695, - "flags": 4227072, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "param" }, "comment": "" @@ -6841,10 +6887,10 @@ "name": { "pos": 3959, "end": 3967, - "flags": 4227072, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "iconName" }, "type": "string", @@ -6853,10 +6899,10 @@ "tagName": { "pos": 3953, "end": 3958, - "flags": 4227072, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "param" }, "comment": "

Name under which the icon should be registered.

\n" @@ -6865,10 +6911,10 @@ "name": { "pos": 4028, "end": 4035, - "flags": 4227072, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "literal" }, "type": "SafeHtml", @@ -6877,10 +6923,10 @@ "tagName": { "pos": 4022, "end": 4027, - "flags": 4227072, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "param" }, "comment": "

SVG source of the icon.

\n" @@ -6910,10 +6956,10 @@ "name": { "pos": 4619, "end": 4622, - "flags": 4227072, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "url" }, "type": "SafeResourceUrl", @@ -6922,10 +6968,10 @@ "tagName": { "pos": 4613, "end": 4618, - "flags": 4227072, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "param" }, "comment": "" @@ -6962,10 +7008,10 @@ "name": { "pos": 5192, "end": 5196, - "flags": 4227072, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "name" }, "type": "string", @@ -6974,10 +7020,10 @@ "tagName": { "pos": 5186, "end": 5191, - "flags": 4227072, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "param" }, "comment": "" @@ -6986,11 +7032,10 @@ "name": { "pos": 5209, "end": 5218, - "flags": 4227072, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, - "originalKeywordKind": 142, + "kind": 80, "escapedText": "namespace" }, "type": "string", @@ -7000,10 +7045,10 @@ "tagName": { "pos": 5203, "end": 5208, - "flags": 4227072, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "param" }, "comment": "" @@ -7072,6 +7117,7 @@ } ] }, + "extends": [], "type": "injectable" }, { @@ -7090,7 +7136,7 @@ "line": 14, "rawdescription": "\n\nStream to emit from when labels are changed. Use this to notify components when the labels have\nchanged after initialization.\n", "modifierKind": [ - 144 + 148 ] }, { @@ -7144,6 +7190,7 @@ "description": "

To modify the labels and text displayed, create a new instance of OuiPaginatorIntl and\ninclude it in a custom provider

\n", "rawdescription": "\n\nTo modify the labels and text displayed, create a new instance of OuiPaginatorIntl and\ninclude it in a custom provider\n", "sourceCode": "import { Injectable, Optional, SkipSelf } from '@angular/core';\nimport { Subject } from 'rxjs';\n\n/**\n * To modify the labels and text displayed, create a new instance of OuiPaginatorIntl and\n * include it in a custom provider\n */\n@Injectable({ providedIn: 'root' })\nexport class OuiPaginatorIntl {\n /**\n * Stream to emit from when labels are changed. Use this to notify components when the labels have\n * changed after initialization.\n */\n readonly changes: Subject = new Subject();\n\n /** A label for the button that increments the current page. */\n nextPageLabel = 'Next page';\n\n /** A label for the button that decrements the current page. */\n previousPageLabel = 'Previous page';\n\n /** A label for the button that moves to the first page. */\n firstPageLabel = 'First page';\n\n /** A label for the button that moves to the last page. */\n lastPageLabel = 'Last page';\n}\n\n/** @docs-private */\nexport function OUI_PAGINATOR_INTL_PROVIDER_FACTORY(\n parentIntl: OuiPaginatorIntl\n) {\n return parentIntl || new OuiPaginatorIntl();\n}\n\n/** @docs-private */\nexport const OUI_PAGINATOR_INTL_PROVIDER = {\n // If there is already an OuiPaginatorIntl available, use that. Otherwise, provide a new one.\n provide: OuiPaginatorIntl,\n deps: [[new Optional(), new SkipSelf(), OuiPaginatorIntl]],\n useFactory: OUI_PAGINATOR_INTL_PROVIDER_FACTORY,\n};\n", + "extends": [], "type": "injectable" }, { @@ -7162,7 +7209,7 @@ "line": 14, "rawdescription": "\n\nStream that emits whenever the labels here are changed. Use this to notify\ncomponents if the labels have changed after initialization.\n", "modifierKind": [ - 144 + 148 ] }, { @@ -7183,12 +7230,13 @@ "description": "

To modify the labels and text displayed, create a new instance of OuiSortHeaderIntl and\ninclude it in a custom provider.

\n", "rawdescription": "\n\nTo modify the labels and text displayed, create a new instance of OuiSortHeaderIntl and\ninclude it in a custom provider.\n", "sourceCode": "import { Injectable, SkipSelf, Optional } from '@angular/core';\nimport { Subject } from 'rxjs';\n\n/**\n * To modify the labels and text displayed, create a new instance of OuiSortHeaderIntl and\n * include it in a custom provider.\n */\n@Injectable({ providedIn: 'root' })\nexport class OuiSortHeaderIntl {\n /**\n * Stream that emits whenever the labels here are changed. Use this to notify\n * components if the labels have changed after initialization.\n */\n readonly changes: Subject = new Subject();\n\n /** ARIA label for the sorting button. */\n sortButtonLabel = (id: string) => `${id}`;\n}\n/** @docs-private */\nexport function OUI_SORT_HEADER_INTL_PROVIDER_FACTORY(\n parentIntl: OuiSortHeaderIntl\n) {\n return parentIntl || new OuiSortHeaderIntl();\n}\n\n/** @docs-private */\nexport const OUI_SORT_HEADER_INTL_PROVIDER = {\n // If there is already an OuiSortHeaderIntl available, use that. Otherwise, provide a new one.\n provide: OuiSortHeaderIntl,\n deps: [[new Optional(), new SkipSelf(), OuiSortHeaderIntl]],\n useFactory: OUI_SORT_HEADER_INTL_PROVIDER_FACTORY,\n};\n", + "extends": [], "type": "injectable" }, { "name": "ShowOnDirtyErrorStateMatcher", "id": "injectable-ShowOnDirtyErrorStateMatcher-2a790495b111018f3cbba0de2309c414412a62be2f0fb8cffdc004f5dc3b3f11c8e19fc024a0ae5e7487dfe35577ec4246ce26c8c46297b9d2651b92f301d6e5", - "file": "ui/src/components/core/error/error-options.ts", + "file": "ui/src/components/core/common-behaviors/error-options.ts", "properties": [], "methods": [ { @@ -7240,12 +7288,13 @@ "description": "

Error state matcher that matches when a control is invalid and dirty.

\n", "rawdescription": "\nError state matcher that matches when a control is invalid and dirty.", "sourceCode": "import { Injectable } from '@angular/core';\nimport { FormGroupDirective, NgForm, UntypedFormControl } from '@angular/forms';\n\n/** Provider that defines how form controls behave with regards to displaying error messages. */\n@Injectable({ providedIn: 'root' })\nexport class ErrorStateMatcher {\n isErrorState(\n control: UntypedFormControl | null,\n form: FormGroupDirective | NgForm | null\n ): boolean {\n return !!(\n control &&\n control.invalid &&\n (control.touched || (form && form.submitted))\n );\n }\n}\n\n/** Error state matcher that matches when a control is invalid and dirty. */\n@Injectable()\nexport class ShowOnDirtyErrorStateMatcher implements ErrorStateMatcher {\n isErrorState(\n control: UntypedFormControl | null,\n form: FormGroupDirective | NgForm | null\n ): boolean {\n return !!(\n control &&\n control.invalid &&\n (control.dirty || (form && form.submitted))\n );\n }\n}\n", + "extends": [], "type": "injectable" }, { "name": "ShowOnDirtyErrorStateMatcher", "id": "injectable-ShowOnDirtyErrorStateMatcher-2a790495b111018f3cbba0de2309c414412a62be2f0fb8cffdc004f5dc3b3f11c8e19fc024a0ae5e7487dfe35577ec4246ce26c8c46297b9d2651b92f301d6e5-1", - "file": "ui/src/components/core/common-behaviors/error-options.ts", + "file": "ui/src/components/core/error/error-options.ts", "properties": [], "methods": [ { @@ -7297,6 +7346,7 @@ "description": "

Error state matcher that matches when a control is invalid and dirty.

\n", "rawdescription": "\nError state matcher that matches when a control is invalid and dirty.", "sourceCode": "import { Injectable } from '@angular/core';\nimport { FormGroupDirective, NgForm, UntypedFormControl } from '@angular/forms';\n\n/** Provider that defines how form controls behave with regards to displaying error messages. */\n@Injectable({ providedIn: 'root' })\nexport class ErrorStateMatcher {\n isErrorState(\n control: UntypedFormControl | null,\n form: FormGroupDirective | NgForm | null\n ): boolean {\n return !!(\n control &&\n control.invalid &&\n (control.touched || (form && form.submitted))\n );\n }\n}\n\n/** Error state matcher that matches when a control is invalid and dirty. */\n@Injectable()\nexport class ShowOnDirtyErrorStateMatcher implements ErrorStateMatcher {\n isErrorState(\n control: UntypedFormControl | null,\n form: FormGroupDirective | NgForm | null\n ): boolean {\n return !!(\n control &&\n control.invalid &&\n (control.dirty || (form && form.submitted))\n );\n }\n}\n", + "extends": [], "type": "injectable", "isDuplicate": true, "duplicateId": 1, @@ -7325,7 +7375,7 @@ "description": "", "line": 5, "modifierKind": [ - 124 + 126 ] }, { @@ -7338,7 +7388,7 @@ "description": "", "line": 4, "modifierKind": [ - 124 + 126 ] }, { @@ -7351,7 +7401,7 @@ "description": "", "line": 6, "modifierKind": [ - 124 + 126 ] }, { @@ -7364,12 +7414,13 @@ "description": "", "line": 3, "modifierKind": [ - 124 + 126 ] } ], "methods": [], "indexSignatures": [], + "extends": [], "inputsClass": [], "outputsClass": [], "hostBindings": [], @@ -7394,7 +7445,7 @@ "description": "", "line": 11, "modifierKind": [ - 124 + 126 ] }, { @@ -7407,7 +7458,7 @@ "description": "", "line": 12, "modifierKind": [ - 124 + 126 ] }, { @@ -7420,12 +7471,13 @@ "description": "", "line": 13, "modifierKind": [ - 124 + 126 ] } ], "methods": [], "indexSignatures": [], + "extends": [], "inputsClass": [], "outputsClass": [], "hostBindings": [], @@ -7491,7 +7543,7 @@ "line": 36, "rawdescription": "\nOption that was selected.", "modifierKind": [ - 123 + 125 ] }, { @@ -7504,7 +7556,7 @@ "line": 34, "rawdescription": "\nReference to the autocomplete panel that emitted the event.", "modifierKind": [ - 123 + 125 ] } ], @@ -7512,6 +7564,7 @@ "rawdescription": "\nEvent object that is emitted when an autocomplete option is selected.", "methods": [], "indexSignatures": [], + "extends": [], "inputsClass": [], "outputsClass": [], "hostBindings": [], @@ -7576,7 +7629,7 @@ "description": "", "line": 41, "modifierKind": [ - 123 + 125 ] }, { @@ -7588,12 +7641,13 @@ "description": "", "line": 41, "modifierKind": [ - 123 + 125 ] } ], "methods": [], "indexSignatures": [], + "extends": [], "inputsClass": [], "outputsClass": [], "hostBindings": [], @@ -7705,7 +7759,7 @@ "description": "", "line": 31, "modifierKind": [ - 123 + 125 ] }, { @@ -7717,7 +7771,7 @@ "description": "", "line": 33, "modifierKind": [ - 123 + 125 ] }, { @@ -7729,7 +7783,7 @@ "description": "", "line": 30, "modifierKind": [ - 123 + 125 ] }, { @@ -7741,7 +7795,7 @@ "description": "", "line": 32, "modifierKind": [ - 123 + 125 ] }, { @@ -7753,7 +7807,7 @@ "description": "", "line": 29, "modifierKind": [ - 123 + 125 ] } ], @@ -7761,6 +7815,7 @@ "rawdescription": "\n\nAn internal class that represents the data corresponding to a single calendar cell.\n", "methods": [], "indexSignatures": [], + "extends": [], "inputsClass": [], "outputsClass": [], "hostBindings": [], @@ -7810,12 +7865,13 @@ "description": "", "line": 34, "modifierKind": [ - 123 + 125 ] } ], "methods": [], "indexSignatures": [], + "extends": [], "inputsClass": [], "outputsClass": [], "hostBindings": [], @@ -7855,6 +7911,7 @@ "rawdescription": "\nChange event object emitted by MatCheckbox.", "methods": [], "indexSignatures": [], + "extends": [], "inputsClass": [], "outputsClass": [], "hostBindings": [], @@ -7904,12 +7961,13 @@ "description": "", "line": 65, "modifierKind": [ - 123 + 125 ] } ], "methods": [], "indexSignatures": [], + "extends": [], "inputsClass": [], "outputsClass": [], "hostBindings": [], @@ -7975,7 +8033,7 @@ "line": 57, "rawdescription": "\nReference to the datepicker input component that emitted the event.", "modifierKind": [ - 123 + 125 ] }, { @@ -7988,7 +8046,7 @@ "line": 59, "rawdescription": "\nReference to the native input element associated with the datepicker input.", "modifierKind": [ - 123 + 125 ] }, { @@ -8006,6 +8064,7 @@ "rawdescription": "\n\nAn event used for datepicker input and change events. We don't always have access to a native\ninput or change event because the event may have been triggered by the user clicking on the\ncalendar popup. For consistency, we always use OuiDatepickerInputEvent instead.\n", "methods": [], "indexSignatures": [], + "extends": [], "inputsClass": [], "outputsClass": [], "hostBindings": [], @@ -8249,6 +8308,7 @@ "rawdescription": "\n\nConfiguration for opening a modal dialog with the OuiDialog service.\n", "methods": [], "indexSignatures": [], + "extends": [], "inputsClass": [], "outputsClass": [], "hostBindings": [], @@ -8332,8 +8392,8 @@ "line": 27, "rawdescription": "\nSubject for notifying the user that the dialog has finished closing.", "modifierKind": [ - 121, - 144 + 123, + 148 ] }, { @@ -8347,8 +8407,8 @@ "line": 24, "rawdescription": "\nSubject for notifying the user that the dialog has finished opening.", "modifierKind": [ - 121, - 144 + 123, + 148 ] }, { @@ -8362,8 +8422,8 @@ "line": 30, "rawdescription": "\nSubject for notifying the user that the dialog has started closing.", "modifierKind": [ - 121, - 144 + 123, + 148 ] }, { @@ -8375,7 +8435,7 @@ "description": "", "line": 47, "modifierKind": [ - 123 + 125 ] }, { @@ -8387,7 +8447,7 @@ "description": "", "line": 35, "modifierKind": [ - 121 + 123 ] }, { @@ -8400,7 +8460,7 @@ "line": 33, "rawdescription": "\nResult to be passed to afterClosed.", "modifierKind": [ - 121 + 123 ] }, { @@ -8440,7 +8500,7 @@ "rawdescription": "\nFetches the position strategy object from the overlay ref.", "description": "

Fetches the position strategy object from the overlay ref.

\n", "modifierKind": [ - 121 + 123 ] }, { @@ -8515,10 +8575,10 @@ "name": { "pos": 2222, "end": 2234, - "flags": 4227072, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "dialogResult" }, "type": "R", @@ -8528,10 +8588,10 @@ "tagName": { "pos": 2216, "end": 2221, - "flags": 4227072, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "param" }, "comment": "

Optional result to return to the dialog opener.

\n" @@ -8574,10 +8634,10 @@ "name": { "pos": 3497, "end": 3505, - "flags": 4227072, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "position" }, "type": "DialogPosition", @@ -8587,10 +8647,10 @@ "tagName": { "pos": 3491, "end": 3496, - "flags": 4227072, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "param" }, "comment": "

New dialog position.

\n" @@ -8628,10 +8688,10 @@ "name": { "pos": 4192, "end": 4197, - "flags": 4227072, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "width" }, "type": "string", @@ -8641,10 +8701,10 @@ "tagName": { "pos": 4186, "end": 4191, - "flags": 4227072, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "param" }, "comment": "

New width of the dialog.

\n" @@ -8653,10 +8713,10 @@ "name": { "pos": 4235, "end": 4241, - "flags": 4227072, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "height" }, "type": "string", @@ -8666,10 +8726,10 @@ "tagName": { "pos": 4229, "end": 4234, - "flags": 4227072, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "param" }, "comment": "

New height of the dialog.

\n" @@ -8678,6 +8738,7 @@ } ], "indexSignatures": [], + "extends": [], "accessors": { "dialogConfig": { "name": "dialogConfig", @@ -8765,7 +8826,7 @@ "description": "", "line": 29, "modifierKind": [ - 123 + 125 ] } ], @@ -8773,6 +8834,7 @@ "rawdescription": "\n\nBoilerplate for applying mixins to OuiFormField.\n\n", "methods": [], "indexSignatures": [], + "extends": [], "inputsClass": [], "outputsClass": [], "hostBindings": [], @@ -8797,7 +8859,7 @@ "line": 53, "rawdescription": "\n\nWhether the input is currently in an autofilled state. If property is not present on the\ncontrol it is assumed to be false.\n", "modifierKind": [ - 144 + 148 ] }, { @@ -8810,7 +8872,7 @@ "line": 47, "rawdescription": "\n\nAn optional name for the control type that can be used to distinguish `oui-form-field` elements\nbased on their control type. The form field will add a class,\n`oui-form-field-type-{{controlType}}` to its root element.\n", "modifierKind": [ - 144 + 148 ] }, { @@ -8823,7 +8885,7 @@ "line": 37, "rawdescription": "\nWhether the control is disabled.", "modifierKind": [ - 144 + 148 ] }, { @@ -8836,7 +8898,7 @@ "line": 28, "rawdescription": "\nWhether the control is empty.", "modifierKind": [ - 144 + 148 ] }, { @@ -8849,7 +8911,7 @@ "line": 40, "rawdescription": "\nWhether the control is in an error state.", "modifierKind": [ - 144 + 148 ] }, { @@ -8862,7 +8924,7 @@ "line": 25, "rawdescription": "\nWhether the control is focused.", "modifierKind": [ - 144 + 148 ] }, { @@ -8875,7 +8937,7 @@ "line": 16, "rawdescription": "\nThe element ID for this control.", "modifierKind": [ - 144 + 148 ] }, { @@ -8888,7 +8950,7 @@ "line": 22, "rawdescription": "\nGets the NgControl for this control.", "modifierKind": [ - 144 + 148 ] }, { @@ -8901,7 +8963,7 @@ "line": 19, "rawdescription": "\nThe placeholder for this control.", "modifierKind": [ - 144 + 148 ] }, { @@ -8914,7 +8976,7 @@ "line": 34, "rawdescription": "\nWhether the control is required.", "modifierKind": [ - 144 + 148 ] }, { @@ -8927,7 +8989,7 @@ "line": 31, "rawdescription": "\nWhether the `OuiFormField` label should try to float.", "modifierKind": [ - 144 + 148 ] }, { @@ -8940,7 +9002,7 @@ "line": 13, "rawdescription": "\n\nStream that emits whenever the state of the control changes such that the parent `OuiFormField`\nneeds to run change detection.\n", "modifierKind": [ - 144 + 148 ] }, { @@ -8976,7 +9038,7 @@ "rawdescription": "\nHandles a click on the control's container.", "description": "

Handles a click on the control's container.

\n", "modifierKind": [ - 126 + 128 ], "jsdoctags": [ { @@ -9009,7 +9071,7 @@ "rawdescription": "\nSets the list of element IDs that currently describe this control.", "description": "

Sets the list of element IDs that currently describe this control.

\n", "modifierKind": [ - 126 + 128 ], "jsdoctags": [ { @@ -9025,6 +9087,7 @@ } ], "indexSignatures": [], + "extends": [], "inputsClass": [], "outputsClass": [], "hostBindings": [], @@ -9074,12 +9137,13 @@ "description": "", "line": 22, "modifierKind": [ - 123 + 125 ] } ], "methods": [], "indexSignatures": [], + "extends": [], "inputsClass": [], "outputsClass": [], "hostBindings": [], @@ -9087,12 +9151,12 @@ }, { "name": "OuiInkBar", - "id": "class-OuiInkBar-135c8ccdab508fcf19b684306b7b52fe3cacc460ac2081644d8b0d211b3fb9a93c581e6b1e98ed9fdc3965312903a402f79f7ef73e228a1ef8f3bd236d89976f", + "id": "class-OuiInkBar-50fe2f1bca65db33aac094b14b277a02924ff4199f4bfe029de4c7e70c55f0d0b3d8f03cc04d8961159c28f0d20d52a85a2edbaf9f6b9506a466792860b45ccf", "file": "ui/src/components/tabs/ink-bar.ts", "deprecated": false, "deprecationMessage": "", "type": "class", - "sourceCode": "import { BooleanInput, coerceBooleanProperty } from '@angular/cdk/coercion';\nimport {\n ElementRef,\n InjectionToken,\n OnDestroy,\n OnInit,\n QueryList,\n} from '@angular/core';\nimport { isDevMode } from '@angular/core';\n\n/**\n * Item inside a tab header relative to which the ink bar can be aligned.\n * @docs-private\n */\nexport interface MatInkBarItem extends OnInit, OnDestroy {\n elementRef: ElementRef;\n activateInkBar(previousIndicatorClientRect?: ClientRect): void;\n deactivateInkBar(): void;\n fitInkBarToContent: boolean;\n}\n\n/** Class that is applied when a tab indicator is active. */\nconst ACTIVE_CLASS = 'mdc-tab-indicator--active';\n\n/** Class that is applied when the tab indicator should not transition. */\nconst NO_TRANSITION_CLASS = 'mdc-tab-indicator--no-transition';\n\n/**\n * Abstraction around the MDC tab indicator that acts as the tab header's ink bar.\n * @docs-private\n */\nexport class OuiInkBar {\n /** Item to which the ink bar is aligned currently. */\n private _currentItem: MatInkBarItem | undefined;\n\n constructor(private _items: QueryList) {}\n\n /** Hides the ink bar. */\n hide() {\n this._items.forEach((item) => item.deactivateInkBar());\n }\n\n /** Aligns the ink bar to a DOM node. */\n alignToElement(element: HTMLElement) {\n const correspondingItem = this._items.find(\n (item) => item.elementRef.nativeElement === element\n );\n const currentItem = this._currentItem;\n\n if (correspondingItem === currentItem) {\n return;\n }\n\n currentItem?.deactivateInkBar();\n\n if (correspondingItem) {\n const clientRect =\n currentItem?.elementRef.nativeElement.getBoundingClientRect?.();\n\n // The ink bar won't animate unless we give it the `ClientRect` of the previous item.\n correspondingItem.activateInkBar(clientRect);\n this._currentItem = correspondingItem;\n }\n }\n}\n\n/**\n * Mixin that can be used to apply the `MatInkBarItem` behavior to a class.\n * Base on MDC's `MDCSlidingTabIndicatorFoundation`:\n * https://github.com/material-components/material-components-web/blob/c0a11ef0d000a098fd0c372be8f12d6a99302855/packages/mdc-tab-indicator/sliding-foundation.ts\n * @docs-private\n */\nexport function mixinInkBarItem<\n T extends new (...args: any[]) => { elementRef: ElementRef }\n>(base: T): T & (new (...args: any[]) => MatInkBarItem) {\n return class extends base {\n constructor(...args: any[]) {\n // eslint-disable-next-line @typescript-eslint/no-unsafe-argument\n super(...args);\n }\n\n private _inkBarElement: HTMLElement | null;\n private _inkBarContentElement: HTMLElement | null;\n private _fitToContent = false;\n\n /** Whether the ink bar should fit to the entire tab or just its content. */\n get fitInkBarToContent(): boolean {\n return this._fitToContent;\n }\n set fitInkBarToContent(v: BooleanInput) {\n const newValue = coerceBooleanProperty(v);\n\n if (this._fitToContent !== newValue) {\n this._fitToContent = newValue;\n\n if (this._inkBarElement) {\n this._appendInkBarElement();\n }\n }\n }\n\n /** Aligns the ink bar to the current item. */\n activateInkBar(previousIndicatorClientRect?: ClientRect) {\n const element = this.elementRef.nativeElement;\n\n // Early exit if no indicator is present to handle cases where an indicator\n // may be activated without a prior indicator state\n if (\n !previousIndicatorClientRect ||\n !element.getBoundingClientRect ||\n !this._inkBarContentElement\n ) {\n element.classList.add(ACTIVE_CLASS);\n return;\n }\n\n // This animation uses the FLIP approach. You can read more about it at the link below:\n // https://aerotwist.com/blog/flip-your-animations/\n\n // Calculate the dimensions based on the dimensions of the previous indicator\n const currentClientRect = element.getBoundingClientRect();\n const widthDelta =\n previousIndicatorClientRect.width / currentClientRect.width;\n const xPosition =\n previousIndicatorClientRect.left - currentClientRect.left;\n element.classList.add(NO_TRANSITION_CLASS);\n this._inkBarContentElement.style.setProperty(\n 'transform',\n `translateX(${xPosition}px) scaleX(${widthDelta})`\n );\n\n // Force repaint before updating classes and transform to ensure the transform properly takes effect\n element.getBoundingClientRect();\n\n element.classList.remove(NO_TRANSITION_CLASS);\n element.classList.add(ACTIVE_CLASS);\n this._inkBarContentElement.style.setProperty('transform', '');\n }\n\n /** Removes the ink bar from the current item. */\n deactivateInkBar() {\n this.elementRef.nativeElement.classList.remove(ACTIVE_CLASS);\n }\n\n /** Initializes the foundation. */\n ngOnInit() {\n this._createInkBarElement();\n }\n\n /** Destroys the foundation. */\n ngOnDestroy() {\n this._inkBarElement?.remove();\n this._inkBarElement = this._inkBarContentElement = null!;\n }\n\n /** Creates and appends the ink bar element. */\n private _createInkBarElement() {\n const documentNode =\n this.elementRef.nativeElement.ownerDocument || document;\n this._inkBarElement = documentNode.createElement('span');\n this._inkBarContentElement = documentNode.createElement('span');\n\n this._inkBarElement.className = 'mdc-tab-indicator';\n this._inkBarContentElement.className =\n 'mdc-tab-indicator__content mdc-tab-indicator__content--underline';\n\n this._inkBarElement.appendChild(this._inkBarContentElement);\n this._appendInkBarElement();\n }\n\n /**\n * Appends the ink bar to the tab host element or content, depending on whether\n * the ink bar should fit to content.\n */\n private _appendInkBarElement() {\n if (\n !this._inkBarElement &&\n (typeof isDevMode === 'undefined' || isDevMode)\n ) {\n throw Error(\n 'Ink bar element has not been created and cannot be appended'\n );\n }\n\n const parentElement = this._fitToContent\n ? this.elementRef.nativeElement.querySelector('.mdc-tab__content')\n : this.elementRef.nativeElement;\n\n if (!parentElement && (typeof isDevMode === 'undefined' || isDevMode)) {\n throw Error('Missing element to host the ink bar');\n }\n\n parentElement!.appendChild(this._inkBarElement!);\n }\n };\n}\n\n/**\n * Interface for a OuiInkBar positioner method, defining the positioning and width of the ink\n * bar in a set of tabs.\n */\nexport interface _OuiInkBarPositioner {\n (element: HTMLElement): { left: string; width: string };\n}\n\n/**\n * The default positioner function for the OuiInkBar.\n * @docs-private\n */\nexport function _OUI_INK_BAR_POSITIONER_FACTORY(): _OuiInkBarPositioner {\n const method = (element: HTMLElement) => ({\n // eslint-disable-next-line @typescript-eslint/restrict-plus-operands\n left: element ? (element.offsetLeft || 0) + 'px' : '0',\n // eslint-disable-next-line @typescript-eslint/restrict-plus-operands\n width: element ? (element.offsetWidth || 0) + 'px' : '0',\n });\n\n return method;\n}\n\n/** Injection token for the OuiInkBar's Positioner. */\nexport const _OUI_INK_BAR_POSITIONER = new InjectionToken<_OuiInkBarPositioner>(\n 'MatInkBarPositioner',\n {\n providedIn: 'root',\n factory: _OUI_INK_BAR_POSITIONER_FACTORY,\n }\n);\n", + "sourceCode": "import { BooleanInput, coerceBooleanProperty } from '@angular/cdk/coercion';\r\nimport {\r\n ElementRef,\r\n InjectionToken,\r\n OnDestroy,\r\n OnInit,\r\n QueryList,\r\n} from '@angular/core';\r\nimport { isDevMode } from '@angular/core';\r\n\r\n/**\r\n * Item inside a tab header relative to which the ink bar can be aligned.\r\n * @docs-private\r\n */\r\nexport interface MatInkBarItem extends OnInit, OnDestroy {\r\n elementRef: ElementRef;\r\n activateInkBar(previousIndicatorClientRect?: ClientRect): void;\r\n deactivateInkBar(): void;\r\n fitInkBarToContent: boolean;\r\n}\r\n\r\n/** Class that is applied when a tab indicator is active. */\r\nconst ACTIVE_CLASS = 'mdc-tab-indicator--active';\r\n\r\n/** Class that is applied when the tab indicator should not transition. */\r\nconst NO_TRANSITION_CLASS = 'mdc-tab-indicator--no-transition';\r\n\r\n/**\r\n * Abstraction around the MDC tab indicator that acts as the tab header's ink bar.\r\n * @docs-private\r\n */\r\nexport class OuiInkBar {\r\n /** Item to which the ink bar is aligned currently. */\r\n private _currentItem: MatInkBarItem | undefined;\r\n\r\n constructor(private _items: QueryList) {}\r\n\r\n /** Hides the ink bar. */\r\n hide() {\r\n this._items.forEach((item) => item.deactivateInkBar());\r\n }\r\n\r\n /** Aligns the ink bar to a DOM node. */\r\n alignToElement(element: HTMLElement) {\r\n const correspondingItem = this._items.find(\r\n (item) => item.elementRef.nativeElement === element\r\n );\r\n const currentItem = this._currentItem;\r\n\r\n if (correspondingItem === currentItem) {\r\n return;\r\n }\r\n\r\n currentItem?.deactivateInkBar();\r\n\r\n if (correspondingItem) {\r\n const clientRect =\r\n currentItem?.elementRef.nativeElement.getBoundingClientRect?.();\r\n\r\n // The ink bar won't animate unless we give it the `ClientRect` of the previous item.\r\n correspondingItem.activateInkBar(clientRect);\r\n this._currentItem = correspondingItem;\r\n }\r\n }\r\n}\r\n\r\n/**\r\n * Mixin that can be used to apply the `MatInkBarItem` behavior to a class.\r\n * Base on MDC's `MDCSlidingTabIndicatorFoundation`:\r\n * https://github.com/material-components/material-components-web/blob/c0a11ef0d000a098fd0c372be8f12d6a99302855/packages/mdc-tab-indicator/sliding-foundation.ts\r\n * @docs-private\r\n */\r\nexport function mixinInkBarItem<\r\n T extends new (...args: any[]) => { elementRef: ElementRef }\r\n>(base: T): T & (new (...args: any[]) => MatInkBarItem) {\r\n return class extends base {\r\n constructor(...args: any[]) {\r\n // eslint-disable-next-line @typescript-eslint/no-unsafe-argument\r\n super(...args);\r\n }\r\n\r\n private _inkBarElement: HTMLElement | null;\r\n private _inkBarContentElement: HTMLElement | null;\r\n private _fitToContent = false;\r\n\r\n /** Whether the ink bar should fit to the entire tab or just its content. */\r\n get fitInkBarToContent(): boolean {\r\n return this._fitToContent;\r\n }\r\n set fitInkBarToContent(v: BooleanInput) {\r\n const newValue = coerceBooleanProperty(v);\r\n\r\n if (this._fitToContent !== newValue) {\r\n this._fitToContent = newValue;\r\n\r\n if (this._inkBarElement) {\r\n this._appendInkBarElement();\r\n }\r\n }\r\n }\r\n\r\n /** Aligns the ink bar to the current item. */\r\n activateInkBar(previousIndicatorClientRect?: ClientRect) {\r\n const element = this.elementRef.nativeElement;\r\n\r\n // Early exit if no indicator is present to handle cases where an indicator\r\n // may be activated without a prior indicator state\r\n if (\r\n !previousIndicatorClientRect ||\r\n !element.getBoundingClientRect ||\r\n !this._inkBarContentElement\r\n ) {\r\n element.classList.add(ACTIVE_CLASS);\r\n return;\r\n }\r\n\r\n // This animation uses the FLIP approach. You can read more about it at the link below:\r\n // https://aerotwist.com/blog/flip-your-animations/\r\n\r\n // Calculate the dimensions based on the dimensions of the previous indicator\r\n const currentClientRect = element.getBoundingClientRect();\r\n const widthDelta =\r\n previousIndicatorClientRect.width / currentClientRect.width;\r\n const xPosition =\r\n previousIndicatorClientRect.left - currentClientRect.left;\r\n element.classList.add(NO_TRANSITION_CLASS);\r\n this._inkBarContentElement.style.setProperty(\r\n 'transform',\r\n `translateX(${xPosition}px) scaleX(${widthDelta})`\r\n );\r\n\r\n // Force repaint before updating classes and transform to ensure the transform properly takes effect\r\n element.getBoundingClientRect();\r\n\r\n element.classList.remove(NO_TRANSITION_CLASS);\r\n element.classList.add(ACTIVE_CLASS);\r\n this._inkBarContentElement.style.setProperty('transform', '');\r\n }\r\n\r\n /** Removes the ink bar from the current item. */\r\n deactivateInkBar() {\r\n this.elementRef.nativeElement.classList.remove(ACTIVE_CLASS);\r\n }\r\n\r\n /** Initializes the foundation. */\r\n ngOnInit() {\r\n this._createInkBarElement();\r\n }\r\n\r\n /** Destroys the foundation. */\r\n ngOnDestroy() {\r\n this._inkBarElement?.remove();\r\n this._inkBarElement = this._inkBarContentElement = null!;\r\n }\r\n\r\n /** Creates and appends the ink bar element. */\r\n private _createInkBarElement() {\r\n const documentNode =\r\n this.elementRef.nativeElement.ownerDocument || document;\r\n this._inkBarElement = documentNode.createElement('span');\r\n this._inkBarContentElement = documentNode.createElement('span');\r\n\r\n this._inkBarElement.className = 'mdc-tab-indicator';\r\n this._inkBarContentElement.className =\r\n 'mdc-tab-indicator__content mdc-tab-indicator__content--underline';\r\n\r\n this._inkBarElement.appendChild(this._inkBarContentElement);\r\n this._appendInkBarElement();\r\n }\r\n\r\n /**\r\n * Appends the ink bar to the tab host element or content, depending on whether\r\n * the ink bar should fit to content.\r\n */\r\n private _appendInkBarElement() {\r\n if (\r\n !this._inkBarElement &&\r\n (typeof isDevMode === 'undefined' || isDevMode)\r\n ) {\r\n throw Error(\r\n 'Ink bar element has not been created and cannot be appended'\r\n );\r\n }\r\n\r\n const parentElement = this._fitToContent\r\n ? this.elementRef.nativeElement.querySelector('.mdc-tab__content')\r\n : this.elementRef.nativeElement;\r\n\r\n if (!parentElement && (typeof isDevMode === 'undefined' || isDevMode)) {\r\n throw Error('Missing element to host the ink bar');\r\n }\r\n\r\n parentElement!.appendChild(this._inkBarElement!);\r\n }\r\n };\r\n}\r\n\r\n/**\r\n * Interface for a OuiInkBar positioner method, defining the positioning and width of the ink\r\n * bar in a set of tabs.\r\n */\r\nexport interface _OuiInkBarPositioner {\r\n (element: HTMLElement): { left: string; width: string };\r\n}\r\n\r\n/**\r\n * The default positioner function for the OuiInkBar.\r\n * @docs-private\r\n */\r\nexport function _OUI_INK_BAR_POSITIONER_FACTORY(): _OuiInkBarPositioner {\r\n const method = (element: HTMLElement) => ({\r\n // eslint-disable-next-line @typescript-eslint/restrict-plus-operands\r\n left: element ? (element.offsetLeft || 0) + 'px' : '0',\r\n // eslint-disable-next-line @typescript-eslint/restrict-plus-operands\r\n width: element ? (element.offsetWidth || 0) + 'px' : '0',\r\n });\r\n\r\n return method;\r\n}\r\n\r\n/** Injection token for the OuiInkBar's Positioner. */\r\nexport const _OUI_INK_BAR_POSITIONER = new InjectionToken<_OuiInkBarPositioner>(\r\n 'MatInkBarPositioner',\r\n {\r\n providedIn: 'root',\r\n factory: _OUI_INK_BAR_POSITIONER_FACTORY,\r\n }\r\n);\r\n", "constructorObj": { "name": "constructor", "description": "", @@ -9130,7 +9194,7 @@ "line": 42, "rawdescription": "\nItem to which the ink bar is aligned currently.", "modifierKind": [ - 121 + 123 ] } ], @@ -9181,6 +9245,7 @@ } ], "indexSignatures": [], + "extends": [], "inputsClass": [], "outputsClass": [], "hostBindings": [], @@ -9290,7 +9355,7 @@ "description": "", "line": 69, "modifierKind": [ - 123 + 125 ] }, { @@ -9302,7 +9367,7 @@ "description": "", "line": 68, "modifierKind": [ - 123 + 125 ] }, { @@ -9314,7 +9379,7 @@ "description": "", "line": 70, "modifierKind": [ - 123 + 125 ] }, { @@ -9326,7 +9391,7 @@ "description": "", "line": 71, "modifierKind": [ - 123 + 125 ] }, { @@ -9339,23 +9404,23 @@ "line": 73, "rawdescription": "", "modifierKind": [ - 123 + 125 ], "jsdoctags": [ { "pos": 2060, "end": 2074, - "flags": 4194304, + "flags": 16777216, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 325, + "kind": 334, "tagName": { "pos": 2061, "end": 2073, - "flags": 4194304, + "flags": 16777216, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "docs-private" }, "comment": "" @@ -9365,7 +9430,9 @@ ], "methods": [], "indexSignatures": [], - "extends": "_OuiInputErrorMixinBase", + "extends": [ + "_OuiInputErrorMixinBase" + ], "inputsClass": [], "outputsClass": [], "hostBindings": [], @@ -9460,7 +9527,7 @@ "description": "", "line": 56, "modifierKind": [ - 123 + 125 ] }, { @@ -9472,7 +9539,7 @@ "description": "", "line": 57, "modifierKind": [ - 123 + 125 ] }, { @@ -9484,7 +9551,7 @@ "description": "", "line": 58, "modifierKind": [ - 123 + 125 ] }, { @@ -9497,23 +9564,23 @@ "line": 60, "rawdescription": "", "modifierKind": [ - 123 + 125 ], "jsdoctags": [ { "pos": 1615, "end": 1629, - "flags": 4194304, + "flags": 16777216, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 325, + "kind": 334, "tagName": { "pos": 1616, "end": 1628, - "flags": 4194304, + "flags": 16777216, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "docs-private" }, "comment": "" @@ -9523,6 +9590,7 @@ ], "methods": [], "indexSignatures": [], + "extends": [], "inputsClass": [], "outputsClass": [], "hostBindings": [], @@ -9539,6 +9607,7 @@ "properties": [], "methods": [], "indexSignatures": [], + "extends": [], "inputsClass": [], "outputsClass": [], "hostBindings": [], @@ -9555,6 +9624,7 @@ "properties": [], "methods": [], "indexSignatures": [], + "extends": [], "inputsClass": [], "outputsClass": [], "hostBindings": [], @@ -9623,7 +9693,7 @@ "line": 36, "rawdescription": "\nWhether the change in the option's value was a result of a user action.", "modifierKind": [ - 123 + 125 ] }, { @@ -9636,7 +9706,7 @@ "line": 34, "rawdescription": "\nReference to the option that emitted the event.", "modifierKind": [ - 123 + 125 ] } ], @@ -9644,6 +9714,7 @@ "rawdescription": "\nEvent object emitted by OuiOption when selected or deselected.", "methods": [], "indexSignatures": [], + "extends": [], "inputsClass": [], "outputsClass": [], "hostBindings": [], @@ -9660,6 +9731,7 @@ "properties": [], "methods": [], "indexSignatures": [], + "extends": [], "inputsClass": [], "outputsClass": [], "hostBindings": [], @@ -9709,12 +9781,13 @@ "description": "", "line": 12, "modifierKind": [ - 123 + 125 ] } ], "methods": [], "indexSignatures": [], + "extends": [], "inputsClass": [], "outputsClass": [], "hostBindings": [], @@ -9764,12 +9837,13 @@ "description": "", "line": 15, "modifierKind": [ - 123 + 125 ] } ], "methods": [], "indexSignatures": [], + "extends": [], "inputsClass": [], "outputsClass": [], "hostBindings": [], @@ -9819,12 +9893,13 @@ "description": "", "line": 306, "modifierKind": [ - 123 + 125 ] } ], "methods": [], "indexSignatures": [], + "extends": [], "inputsClass": [], "outputsClass": [], "hostBindings": [], @@ -9890,7 +9965,7 @@ "line": 48, "rawdescription": "\nThe OuiRadioButton that emits the change event.", "modifierKind": [ - 123 + 125 ] }, { @@ -9903,7 +9978,7 @@ "line": 50, "rawdescription": "\nThe value of the OuiRadioButton.", "modifierKind": [ - 123 + 125 ] } ], @@ -9911,6 +9986,7 @@ "rawdescription": "\nChange event object emitted by OuiRadio and OuiRadioGroup.", "methods": [], "indexSignatures": [], + "extends": [], "inputsClass": [], "outputsClass": [], "hostBindings": [], @@ -9927,6 +10003,7 @@ "properties": [], "methods": [], "indexSignatures": [], + "extends": [], "inputsClass": [], "outputsClass": [], "hostBindings": [], @@ -9934,12 +10011,12 @@ }, { "name": "OuiSelectBase", - "id": "class-OuiSelectBase-d85db46eab36d315c1fdcd891bdac570b57a0ccdc711e79255f204f23073d94dc6b0707254460df0585b83b8338fb5a5a8a9bcb9d49bc6bf529c53c663cbdac2", + "id": "class-OuiSelectBase-69627b742fec8101b0c412f353bb903b4d499f0f8291080ef1d6ac0c418484f2235fec3981e84104b948fe2f242b0a29fea2c39687b9ed9b01e6aa4fcda7ba37", "file": "ui/src/components/select/select.component.ts", "deprecated": false, "deprecationMessage": "", "type": "class", - "sourceCode": "import { ActiveDescendantKeyManager, FocusMonitor } from '@angular/cdk/a11y';\nimport { Directionality } from '@angular/cdk/bidi';\nimport { coerceBooleanProperty } from '@angular/cdk/coercion';\nimport { SelectionModel } from '@angular/cdk/collections';\nimport {\n A,\n DOWN_ARROW,\n END,\n ENTER,\n HOME,\n LEFT_ARROW,\n RIGHT_ARROW,\n SPACE,\n UP_ARROW,\n hasModifierKey,\n TAB,\n} from '@angular/cdk/keycodes';\nimport { CdkConnectedOverlay } from '@angular/cdk/overlay';\nimport {\n AfterContentInit,\n Attribute,\n ChangeDetectionStrategy,\n ChangeDetectorRef,\n Component,\n ContentChild,\n ContentChildren,\n Directive,\n DoCheck,\n ElementRef,\n EventEmitter,\n Input,\n isDevMode,\n NgZone,\n OnChanges,\n OnDestroy,\n OnInit,\n Optional,\n Output,\n QueryList,\n Self,\n SimpleChanges,\n ViewChild,\n ViewEncapsulation,\n Inject,\n} from '@angular/core';\nimport {\n ControlValueAccessor,\n FormGroupDirective,\n NgControl,\n NgForm,\n} from '@angular/forms';\nimport {\n _countGroupLabelsBeforeOption,\n _getOptionScrollPosition,\n CanDisable,\n CanDisableCtor,\n CanUpdateErrorState,\n CanUpdateErrorStateCtor,\n HasTabIndex,\n HasTabIndexCtor,\n OuiOptionSelectionChange,\n mixinErrorState,\n mixinTabIndex,\n mixinDisabled,\n} from '../core';\nimport { OuiFormField, OuiFormFieldControl } from '../form-field/public-api';\nimport { DOCUMENT } from '@angular/common';\nimport { OUI_OPTION_PARENT_COMPONENT, OuiOption } from '../core/option/option';\nimport { OuiOptgroup } from '../core/option/optgroup';\nimport { ErrorStateMatcher } from '../core/error/error-options';\nimport { defer, merge, Observable, Subject } from 'rxjs';\nimport {\n distinctUntilChanged,\n filter,\n map,\n startWith,\n switchMap,\n take,\n takeUntil,\n} from 'rxjs/operators';\nimport {\n getOuiSelectDynamicMultipleError,\n getOuiSelectNonArrayValueError,\n getOuiSelectNonFunctionValueError,\n} from './select-errors';\nimport { OuiIconRegistry } from '../icon/icon-registery';\nimport { DomSanitizer } from '@angular/platform-browser';\nimport { ICONS } from '../core/shared/icons';\n\nlet nextUniqueId = 0;\n\n/**\n * The following style constants are necessary to save here in order\n * to properly calculate the alignment of the selected option over\n * the trigger element.\n */\n\n/** The height of each select option. */\nexport const SELECT_OPTION_HEIGHT = 40;\n\n/** The panel's padding on the x-axis */\nexport const SELECT_PANEL_PADDING_X = 16;\n\n/** The panel's x axis padding if it is indented (e.g. there is an option group). */\nexport const SELECT_PANEL_INDENT_PADDING_X = SELECT_PANEL_PADDING_X * 2;\n\n/** The height of the select items in `em` units. */\nexport const SELECT_ITEM_HEIGHT_EM = 3;\n\n/** The total height of the select panel. */\nexport const SELECT_PANEL_HEIGHT = 200;\n\n// TODO(josephperrott): Revert to a constant after 2018 spec updates are fully merged.\n/**\n * Distance between the panel edge and the option text in\n * multi-selection mode.\n *\n * Calculated as:\n * (SELECT_PANEL_PADDING_X * 1.5) + 20 = 44\n * The padding is multiplied by 1.5 because the checkbox's margin is half the padding.\n * The checkbox width is 16px.\n */\nexport let SELECT_MULTIPLE_PANEL_PADDING_X = 0;\n\n/**\n * The select panel will only \"fit\" inside the viewport if it is positioned at\n * this value or more away from the viewport boundary.\n */\nexport const SELECT_PANEL_VIEWPORT_PADDING = 8;\n\n/** Change event object that is emitted when the select value has changed. */\nexport class OuiSelectChange {\n constructor(\n /** Reference to the select that emitted the change event. */\n public source: OuiSelect,\n /** Current value of the select that emitted the event. */\n public value: any\n ) {}\n}\n\n// Boilerplate for applying mixins to OuiSelect.\n/** @docs-private */\nexport class OuiSelectBase {\n constructor(\n public _elementRef: ElementRef,\n public _defaultErrorStateMatcher: ErrorStateMatcher,\n public _parentForm: NgForm,\n public _parentFormGroup: FormGroupDirective,\n public ngControl: NgControl\n ) {}\n}\n\nexport const _OuiSelectMixinBase: CanDisableCtor &\n HasTabIndexCtor &\n CanUpdateErrorStateCtor &\n typeof OuiSelectBase = mixinTabIndex(\n mixinDisabled(mixinErrorState(OuiSelectBase))\n);\n\n/**\n * Allows the user to customize the trigger that is displayed when the select has a value.\n */\n@Directive({\n // eslint-disable-next-line @angular-eslint/directive-selector\n selector: 'oui-select-trigger',\n})\nexport class OuiSelectTrigger {}\n\n@Component({\n selector: 'oui-select',\n exportAs: 'ouiSelect',\n templateUrl: 'select.html',\n styleUrls: ['select.scss'],\n // eslint-disable-next-line @angular-eslint/no-inputs-metadata-property\n inputs: ['disabled', 'tabIndex'],\n encapsulation: ViewEncapsulation.None,\n changeDetection: ChangeDetectionStrategy.OnPush,\n // eslint-disable-next-line @angular-eslint/no-host-metadata-property\n host: {\n role: 'listbox',\n '[attr.id]': 'id',\n '[attr.tabindex]': 'tabIndex',\n '[attr.aria-label]': '_getAriaLabel()',\n '[attr.aria-labelledby]': '_getAriaLabelledby()',\n '[attr.aria-required]': 'required.toString()',\n '[attr.aria-disabled]': 'disabled.toString()',\n '[attr.aria-invalid]': 'errorState',\n '[attr.aria-owns]': 'panelOpen ? _optionIds : null',\n '[attr.aria-multiselectable]': 'multiple',\n '[attr.aria-describedby]': '_ariaDescribedby || null',\n '[attr.aria-activedescendant]': '_getAriaActiveDescendant()',\n '[class.oui-select-disabled]': 'disabled',\n '[class.oui-select-invalid]': 'errorState',\n '[class.oui-select-required]': 'required',\n '[class.oui-select-empty]': 'empty',\n class: 'oui-select oui-input',\n '(keydown)': '_handleKeydown($event)',\n '(focus)': '_onFocus()',\n '(blur)': '_onBlur()',\n },\n providers: [\n { provide: OuiFormFieldControl, useExisting: OuiSelect },\n { provide: OUI_OPTION_PARENT_COMPONENT, useExisting: OuiSelect },\n ],\n})\nexport class OuiSelect\n extends _OuiSelectMixinBase\n implements\n AfterContentInit,\n OnChanges,\n OnDestroy,\n OnInit,\n DoCheck,\n ControlValueAccessor,\n CanDisable,\n HasTabIndex,\n OuiFormFieldControl,\n CanUpdateErrorState\n{\n /**Holds selected values after done */\n @Input() savedValues = [];\n /**Done button disabled until dropdown is dirty */\n disableDoneButton = true;\n /** Whether or not the overlay panel is open. */\n private _panelOpen = false;\n\n /** Whether filling out the select is required in the form. */\n private _required = false;\n\n /** Whether filling out the select is required in the form. */\n private _actionItems = false;\n\n /** The scroll position of the overlay panel, calculated to center the selected option. */\n private _scrollTop = 0;\n\n /** The placeholder displayed in the trigger of the select. */\n private _placeholder: string;\n\n /** Whether the component is in multiple selection mode. */\n private _multiple = false;\n\n /** Search input field **/\n isSearchFieldPresent: boolean;\n\n /** Unique id for this input. */\n private _uid = `oui-select-${nextUniqueId++}`;\n\n /** The last measured value for the trigger's client bounding rect. */\n _triggerRect: ClientRect;\n\n /** The aria-describedby attribute on the select for improved a11y. */\n _ariaDescribedby: string;\n\n /** The cached font-size of the trigger element. */\n _triggerFontSize = 0;\n\n /** Deals with the selection logic. */\n _selectionModel: SelectionModel;\n\n /** Manages keyboard events for options in the panel. */\n _keyManager: ActiveDescendantKeyManager;\n\n /** The IDs of child options to be passed to the aria-owns attribute. */\n _optionIds = '';\n\n /** The value of the select panel's transform-origin property. */\n _transformOrigin = 'top';\n\n /** If there is search input field a class is added dynamically to the perfect scrollbar **/\n ouiSelectInputOuterClassName: string;\n\n /** Adding top class to overlay panel */\n cdkConnectionOverlayPanel = '';\n\n /**\n * The y-offset of the overlay panel in relation to the trigger's top start corner.\n * This must be adjusted to align the selected option text over the trigger text.\n * when the panel opens. Will change based on the y-position of the selected option.\n */\n _offsetY = 0;\n\n /**\n * This position config ensures that the top \"start\" corner of the overlay\n * is aligned with with the top \"start\" of the origin by default (overlapping\n * the trigger completely). If the panel cannot fit below the trigger, it\n * will fall back to a position above the trigger.\n */\n _positions = [\n {\n originX: 'start',\n originY: 'top',\n overlayX: 'start',\n overlayY: 'top',\n },\n {\n originX: 'start',\n originY: 'bottom',\n overlayX: 'start',\n overlayY: 'bottom',\n },\n ];\n /** Emits whenever the component is destroyed. */\n private readonly _destroy = new Subject();\n\n /** Whether the component is disabling centering of the active option over the trigger. */\n private _disableOptionCentering = false;\n\n private _focused = false;\n\n /** A name for this control that can be used by `oui-form-field`. */\n controlType = 'oui-select';\n\n /** Trigger that opens the select. */\n @ViewChild('trigger') trigger: ElementRef;\n\n /** Trigger that opens the select. */\n @ViewChild('ddCancelButton', { read: ElementRef }) ddCancelButton: ElementRef;\n\n /** Trigger that opens the select. */\n @ViewChild('ddDoneButton', { read: ElementRef }) ddDoneButton: ElementRef;\n\n /** Panel containing the select options. */\n @ViewChild('panel', { read: ElementRef }) panel: ElementRef;\n\n private _value: any;\n\n /**\n * Function used to sort the values in a select in multiple mode.\n * Follows the same logic as `Array.prototype.sort`.\n */\n @Input() sortComparator: (\n a: OuiOption,\n b: OuiOption,\n options: OuiOption[]\n ) => number;\n\n /** Aria label of the select. If not specified, the placeholder will be used as label. */\n @Input('aria-label') ariaLabel = '';\n\n /** Input that can be used to specify the `aria-labelledby` attribute. */\n @Input('aria-labelledby') ariaLabelledby: string;\n private _large = false;\n _monitorSubscription: any;\n\n /** Whether the oui-select is of large size. */\n @Input()\n get large(): boolean {\n return this._large;\n }\n set large(value) {\n this._large = coerceBooleanProperty(value);\n this._changeDetectorRef.markForCheck();\n }\n\n private _id: string;\n\n /** Event emitted when the select panel has been toggled. */\n @Output()\n readonly openedChange: EventEmitter = new EventEmitter();\n\n /** Combined stream of all of the child options' change events. */\n readonly optionSelectionChanges: Observable = defer(\n (): Observable => {\n if (this.options) {\n return merge(...this.options.map((option) => option.onSelectionChange));\n }\n\n return this._ngZone.onStable.asObservable().pipe(\n take(1),\n switchMap(() => this.optionSelectionChanges)\n );\n }\n );\n\n /**\n * Event that emits whenever the raw value of the select changes. This is here primarily\n * to facilitate the two-way binding for the `value` input.\n *\n * @docs-private\n */\n @Output() readonly valueChange: EventEmitter = new EventEmitter();\n\n /** Object used to control when error messages are shown. */\n @Input() errorStateMatcher: ErrorStateMatcher;\n\n /** All of the defined select options. */\n @ContentChildren(OuiOption, { descendants: true })\n options: QueryList;\n\n /** Event emitted when the select has been opened. */\n // eslint-disable-next-line @angular-eslint/no-output-rename\n @Output('opened')\n readonly _openedStream: Observable = this.openedChange.pipe(\n filter((o) => o),\n map(() => {})\n );\n\n /** Event emitted when the select has been closed. */\n // eslint-disable-next-line @angular-eslint/no-output-rename\n @Output('closed')\n readonly _closedStream: Observable = this.openedChange.pipe(\n filter((o) => !o),\n map(() => {\n this.isSearchFieldPresent = false;\n })\n );\n\n /** Event emitted when the selected value has been changed by the user. */\n @Output()\n readonly selectionChange: EventEmitter =\n new EventEmitter();\n\n /** Event emitted when the selected value has been changed and saved by the user. */\n @Output()\n readonly saveSelectionChange: EventEmitter =\n new EventEmitter();\n\n /** All of the defined groups of options. */\n @ContentChildren(OuiOptgroup) optionGroups: QueryList;\n\n /** User-supplied override of the trigger element. */\n @ContentChild(OuiSelectTrigger)\n customTrigger: OuiSelectTrigger;\n\n /** Classes to be passed to the select panel. Supports the same syntax as `ngClass`. */\n @Input() panelClass: string | string[] | Set | { [key: string]: any };\n\n /** Overlay pane containing the options. */\n @ViewChild(CdkConnectedOverlay)\n overlayDir: CdkConnectedOverlay;\n\n /** Emits when the panel element is finished transforming in. */\n _panelDoneAnimatingStream = new Subject();\n\n /** Comparison function to specify which option is displayed. Defaults to object equality. */\n private _compareWith = (o1: any, o2: any) => o1 === o2;\n\n /** Whether the select is focused. */\n get focused(): boolean {\n return this._focused || this._panelOpen;\n }\n /**\n * @deprecated Setter to be removed as this property is intended to be readonly.\n */\n set focused(value: boolean) {\n this._focused = value;\n }\n /** `View -> model callback called when value changes` */\n _onChange: (value: any) => void = () => {};\n\n /** `View -> model callback called when select has been touched` */\n _onTouched = () => {};\n\n /** Placeholder to be shown if no value has been selected. */\n @Input()\n get placeholder(): string {\n return this._placeholder;\n }\n set placeholder(value: string) {\n this._placeholder = value;\n this.stateChanges.next();\n }\n\n /** Whether the component is required. */\n @Input()\n get required(): boolean {\n return this._required;\n }\n set required(value: boolean) {\n this._required = coerceBooleanProperty(value);\n this.stateChanges.next();\n }\n\n /** Whether the user should be allowed to select multiple options. */\n @Input()\n get multiple(): boolean {\n return this._multiple;\n }\n set multiple(value: boolean) {\n if (this._selectionModel) {\n throw getOuiSelectDynamicMultipleError();\n }\n\n this._multiple = coerceBooleanProperty(value);\n }\n\n /** Whether the action items are required and use saveSelectionChange instead of selectionChange. */\n @Input()\n get actionItems(): boolean {\n return this._actionItems;\n }\n set actionItems(value: boolean) {\n if (this._multiple) {\n this._actionItems = coerceBooleanProperty(value);\n this.stateChanges.next();\n }\n }\n\n /** Whether to center the active option over the trigger. */\n @Input()\n get disableOptionCentering(): boolean {\n return this._disableOptionCentering;\n }\n set disableOptionCentering(value: boolean) {\n this._disableOptionCentering = coerceBooleanProperty(value);\n }\n\n /**\n * Function to compare the option values with the selected values. The first argument\n * is a value from an option. The second is a value from the selection. A boolean\n * should be returned.\n */\n @Input()\n get compareWith() {\n return this._compareWith;\n }\n set compareWith(fn: (o1: any, o2: any) => boolean) {\n if (typeof fn !== 'function') {\n throw getOuiSelectNonFunctionValueError();\n }\n this._compareWith = fn;\n if (this._selectionModel) {\n // A different comparator means the selection could change.\n this._initializeSelection();\n }\n }\n\n /** Value of the select control. */\n @Input()\n get value(): any {\n return this._value;\n }\n set value(newValue: any) {\n if (newValue !== this._value) {\n this.writeValue(newValue);\n this._value = newValue;\n }\n }\n\n /** Unique id of the element. */\n @Input()\n get id(): string {\n return this._id;\n }\n set id(value: string) {\n this._id = value || this._uid;\n this.stateChanges.next();\n }\n\n constructor(\n private _changeDetectorRef: ChangeDetectorRef,\n private _ngZone: NgZone,\n _defaultErrorStateMatcher: ErrorStateMatcher,\n elementRef: ElementRef,\n private _focusMonitor: FocusMonitor,\n @Optional() private _dir: Directionality,\n @Optional() _parentForm: NgForm,\n @Optional() _parentFormGroup: FormGroupDirective,\n @Optional() private _parentFormField: OuiFormField,\n @Self() @Optional() public ngControl: NgControl,\n @Attribute('tabindex') tabIndex: string,\n @Optional() @Inject(DOCUMENT) private _document: any,\n public _elementRef: ElementRef,\n public _ouiIconRegistry: OuiIconRegistry,\n private _domSanitizer: DomSanitizer\n ) {\n super(\n elementRef,\n _defaultErrorStateMatcher,\n _parentForm,\n _parentFormGroup,\n ngControl\n );\n this._monitorSubscription = this._focusMonitor\n .monitor(this._elementRef, true)\n .subscribe(() => this._ngZone.run(() => {}));\n this._ouiIconRegistry.addSvgIconLiteral(\n `select-arrow-icon`,\n this._domSanitizer.bypassSecurityTrustHtml(ICONS.SELECT_ARROW_ICON)\n );\n\n if (this.ngControl) {\n // Note: we provide the value accessor through here, instead of\n // the `providers` to avoid running into a circular import.\n this.ngControl.valueAccessor = this;\n }\n\n this.tabIndex = parseInt(tabIndex, 10) || 0;\n\n // Force setter to be called in case id was not specified.\n this.id = this.id;\n }\n\n ngOnInit() {\n this._selectionModel = new SelectionModel(this.multiple);\n this.stateChanges.next();\n\n // We need `distinctUntilChanged` here, because some browsers will\n // fire the animation end event twice for the same animation. See:\n // https://github.com/angular/angular/issues/24084\n this._panelDoneAnimatingStream\n .pipe(distinctUntilChanged(), takeUntil(this._destroy))\n .subscribe(() => {\n if (this.panelOpen) {\n this._scrollTop = 0;\n this.openedChange.emit(true);\n } else {\n this.openedChange.emit(false);\n this.overlayDir.offsetX = 0;\n this._changeDetectorRef.markForCheck();\n }\n });\n }\n\n ngAfterContentInit() {\n this._initKeyManager();\n\n this._selectionModel.changed\n .pipe(takeUntil(this._destroy))\n .subscribe((event) => {\n event.added.forEach((option) => option.select());\n event.removed.forEach((option) => option.deselect());\n });\n\n this.options.changes\n .pipe(startWith(null), takeUntil(this._destroy))\n .subscribe(() => {\n this._resetOptions();\n this._initializeSelection();\n });\n }\n\n ngDoCheck() {\n if (this.ngControl) {\n this.updateErrorState();\n }\n }\n\n ngOnChanges(changes: SimpleChanges) {\n // Updating the disabled state is handled by `mixinDisabled`, but we need to additionally let\n // the parent form field know to run change detection when the disabled state changes.\n if (changes.disabled) {\n this.stateChanges.next();\n }\n }\n\n ngOnDestroy() {\n this._monitorSubscription.unsubscribe();\n this._focusMonitor.stopMonitoring(this._elementRef);\n this._destroy.next();\n this._destroy.complete();\n this.stateChanges.complete();\n }\n\n /** Toggles the overlay panel open or closed. */\n toggle(): void {\n this.panelOpen ? this.close() : this.open();\n }\n\n /** Opens the overlay panel. */\n open(): void {\n if (\n this.disabled ||\n !this.options ||\n !this.options.length ||\n this._panelOpen\n ) {\n return;\n }\n\n this._triggerRect = this.trigger.nativeElement.getBoundingClientRect();\n\n this._panelOpen = true;\n this._keyManager.withHorizontalOrientation(null);\n\n this._highlightCorrectOption();\n this._changeDetectorRef.markForCheck();\n this.openedChange.emit(true);\n this._elementRef.nativeElement.classList.add(\n 'oui-select-list-options-opened'\n );\n }\n\n /** Closes the overlay panel and focuses the host element. */\n close(): void {\n if (this._panelOpen) {\n this._panelOpen = false;\n this._keyManager.withHorizontalOrientation(this._isRtl() ? 'rtl' : 'ltr');\n this._changeDetectorRef.markForCheck();\n this._onTouched();\n this.openedChange.emit(false);\n this._elementRef.nativeElement.classList.remove(\n 'oui-select-list-options-opened'\n );\n setTimeout((_) => this._document.activeElement.blur());\n }\n }\n\n /**\n * Sets the select's value. Part of the ControlValueAccessor interface\n * required to integrate with Angular's core forms API.\n *\n * @param value New value to be written to the model.\n */\n writeValue(value: any): void {\n if (this.options) {\n this._setSelectionByValue(value);\n }\n }\n\n /**\n * Saves a callback function to be invoked when the select's value\n * changes from user input. Part of the ControlValueAccessor interface\n * required to integrate with Angular's core forms API.\n *\n * @param fn Callback to be triggered when the value changes.\n */\n registerOnChange(fn: (value: any) => void): void {\n this._onChange = fn;\n }\n\n /**\n * Saves a callback function to be invoked when the select is blurred\n * by the user. Part of the ControlValueAccessor interface required\n * to integrate with Angular's core forms API.\n *\n * @param fn Callback to be triggered when the component has been touched.\n */\n registerOnTouched(fn: () => {}): void {\n this._onTouched = fn;\n }\n\n /**\n * Disables the select. Part of the ControlValueAccessor interface required\n * to integrate with Angular's core forms API.\n *\n * @param isDisabled Sets whether the component is disabled.\n */\n setDisabledState(isDisabled: boolean): void {\n this.disabled = isDisabled;\n this._changeDetectorRef.markForCheck();\n this.stateChanges.next();\n }\n\n /** Whether or not the overlay panel is open. */\n get panelOpen(): boolean {\n return this._panelOpen;\n }\n\n /** The currently selected option. */\n get selected(): OuiOption | OuiOption[] {\n return this.multiple\n ? this._selectionModel.selected\n : this._selectionModel.selected[0];\n }\n\n /** The value displayed in the trigger. */\n get triggerValue(): string {\n if (this.empty) {\n return '';\n }\n if (this._multiple) {\n const selectedOptions = this._selectionModel.selected.map(\n (option) => option.viewValueForSelect\n );\n\n if (this._isRtl()) {\n selectedOptions.reverse();\n }\n return selectedOptions.join(', ');\n }\n return this._selectionModel.selected[0].viewValueForSelect;\n }\n\n /** Whether the element is in RTL mode. */\n _isRtl(): boolean {\n return this._dir ? this._dir.value === 'rtl' : false;\n }\n\n /** Handles all keydown events on the select. */\n _handleKeydown(event: KeyboardEvent): void {\n if (!this.disabled) {\n this.panelOpen\n ? this._handleOpenKeydown(event)\n : this._handleClosedKeydown(event);\n }\n }\n\n /** Handles keyboard events while the select is closed. */\n private _handleClosedKeydown(event: KeyboardEvent): void {\n const keyCode = event.keyCode;\n const isArrowKey =\n keyCode === DOWN_ARROW ||\n keyCode === UP_ARROW ||\n keyCode === LEFT_ARROW ||\n keyCode === RIGHT_ARROW;\n const isOpenKey = keyCode === ENTER || keyCode === SPACE;\n const manager = this._keyManager;\n\n // Open the select on ALT + arrow key to match the native \n event.preventDefault();\n this.close();\n } else if (\n (keyCode === ENTER || keyCode === SPACE) &&\n manager.activeItem &&\n !hasModifierKey(event)\n ) {\n event.preventDefault();\n manager.activeItem._selectViaInteraction();\n } else if (this._multiple && keyCode === A && event.ctrlKey) {\n event.preventDefault();\n this.handleCtrlKey();\n } else if (normalNavigationCheck) {\n // Check for non multiple select dropdown that the key pressed is not Tab, Space, Enter\n if (!this.isSearchFieldPresent) this.focus();\n this.handleScrolling(manager, event, isArrowKey, keyCode);\n }\n }\n\n /**\n * Handle ctrl key\n */\n private handleCtrlKey() {\n const hasDeselectedOptions = this.options.some(\n (opt) => !opt.disabled && !opt.selected\n );\n\n this.options.forEach((option) => {\n if (!option.disabled) {\n hasDeselectedOptions ? option.select() : option.deselect();\n }\n });\n }\n\n /**\n * @param manager\n * @param event\n * @param isArrowKey\n * @param keyCode\n */\n private handleScrolling(\n manager: ActiveDescendantKeyManager,\n event: KeyboardEvent,\n isArrowKey: boolean,\n keyCode: number\n ) {\n const previouslyFocusedIndex = manager.activeItemIndex;\n\n manager.onKeydown(event);\n\n if (\n this._multiple &&\n isArrowKey &&\n event.shiftKey &&\n manager.activeItem &&\n manager.activeItemIndex !== previouslyFocusedIndex\n ) {\n manager.activeItem._selectViaInteraction();\n }\n if (isArrowKey && manager.activeItemIndex !== previouslyFocusedIndex) {\n this._scrollToOption();\n } else {\n // First or last\n if (keyCode === DOWN_ARROW) {\n manager.setFirstItemActive();\n this._setScrollTop(0);\n }\n if (keyCode === UP_ARROW) {\n manager.setLastItemActive();\n this._scrollToOption();\n }\n }\n }\n\n _onFocus() {\n if (!this.disabled) {\n this._focused = true;\n this.stateChanges.next();\n }\n }\n\n /**\n * Calls the touched callback only if the panel is closed. Otherwise, the trigger will\n * \"blur\" to the panel when it opens, causing a false positive.\n */\n _onBlur() {\n this._focused = false;\n // this.isSearchFieldPresent = false;\n\n if (!this.disabled && !this.panelOpen) {\n this._onTouched();\n this._changeDetectorRef.markForCheck();\n this.stateChanges.next();\n }\n }\n\n /**\n * Callback that is invoked when the overlay panel has been attached.\n */\n _onAttached(): void {\n this.overlayDir.positionChange.pipe(take(1)).subscribe(() => {\n this._setPseudoCheckboxPaddingSize();\n this._changeDetectorRef.detectChanges();\n this.panel.nativeElement.scrollTop = this._scrollTop;\n });\n }\n\n /** Returns the theme to be used on the panel. */\n _getPanelTheme(): string {\n return this._parentFormField ? `oui-${this._parentFormField.color}` : '';\n }\n\n // TODO(josephperrott): Remove after 2018 spec updates are fully merged.\n /** Sets the pseudo checkbox padding size based on the width of the pseudo checkbox. */\n private _setPseudoCheckboxPaddingSize() {\n if (!SELECT_MULTIPLE_PANEL_PADDING_X && this.multiple) {\n const pseudoCheckbox = this.panel.nativeElement.querySelector(\n '.oui-pseudo-checkbox'\n );\n if (pseudoCheckbox) {\n SELECT_MULTIPLE_PANEL_PADDING_X =\n SELECT_PANEL_PADDING_X * 1.5 + pseudoCheckbox.offsetWidth;\n }\n }\n }\n\n /** Whether the select has a value. */\n get empty(): boolean {\n return !this._selectionModel || this._selectionModel.isEmpty();\n }\n\n private _initializeSelection(): void {\n // Defer setting the value in order to avoid the \"Expression\n // has changed after it was checked\" errors from Angular.\n Promise.resolve().then(() => {\n this._setSelectionByValue(\n this.ngControl ? this.ngControl.value : this._value\n );\n this.savedValues = this.ngControl ? this.ngControl.value : this._value;\n if (this.multiple) {\n this._highlightFirstFilteredOption();\n }\n });\n }\n\n /**\n * Sets the selected option based on a value. If no option can be\n * found with the designated value, the select trigger is cleared.\n */\n private _setSelectionByValue(value: any | any[]): void {\n if (this.multiple && value) {\n if (!Array.isArray(value)) {\n throw getOuiSelectNonArrayValueError();\n }\n\n this._selectionModel.clear();\n value.forEach((currentValue: any) => this._selectValue(currentValue));\n this._sortValues();\n } else {\n this._selectionModel.clear();\n const correspondingOption = this._selectValue(value);\n // Shift focus to the active item. Note that we shouldn't do this in multiple\n // mode, because we don't know what option the user interacted with last.\n if (correspondingOption) {\n this._keyManager.setActiveItem(correspondingOption);\n }\n }\n this._changeDetectorRef.markForCheck();\n }\n\n /**\n * Finds and selects and option based on its value.\n *\n * @returns Option that has the corresponding value.\n */\n private _selectValue(value: any): OuiOption | undefined {\n const correspondingOption = this.options.find((option: OuiOption) => {\n try {\n // Treat null as a special reset value.\n return option.value != null && this._compareWith(option.value, value);\n } catch (error) {\n if (isDevMode()) {\n // Notify developers of errors in their comparator.\n console.warn(error);\n }\n return false;\n }\n });\n\n if (correspondingOption) {\n this._selectionModel.select(correspondingOption);\n }\n\n return correspondingOption;\n }\n\n /** Sets up a key manager to listen to keyboard events on the overlay panel. */\n private _initKeyManager() {\n this._keyManager = new ActiveDescendantKeyManager(this.options)\n .withTypeAhead()\n .withVerticalOrientation()\n .withHorizontalOrientation(this._isRtl() ? 'rtl' : 'ltr')\n .withAllowedModifierKeys(['shiftKey']);\n\n this._keyManager.tabOut.pipe(takeUntil(this._destroy)).subscribe(() => {\n // Restore focus to the trigger before closing. Ensures that the focus\n // position won't be lost if the user got focus into the overlay.\n this.focus();\n this.close();\n });\n\n this._keyManager.change.pipe(takeUntil(this._destroy)).subscribe(() => {\n if (this._panelOpen && this.panel) {\n // Panel is opened\n // Need not to scroll\n } else if (\n !this._panelOpen &&\n !this.multiple &&\n this._keyManager.activeItem\n ) {\n this._keyManager.activeItem._selectViaInteraction();\n }\n });\n }\n\n /** Drops current option subscriptions and IDs and resets from scratch. */\n private _resetOptions(): void {\n const changedOrDestroyed = merge(this.options.changes, this._destroy);\n\n this.optionSelectionChanges\n .pipe(takeUntil(changedOrDestroyed))\n .subscribe((event) => {\n this._onSelect(event.source, event.isUserInput);\n\n if (event.isUserInput && !this.multiple && this._panelOpen) {\n this.close();\n this.focus();\n }\n });\n\n // Listen to changes in the internal state of the options and react accordingly.\n // Handles cases like the labels of the selected options changing.\n merge(...this.options.map((option) => option._stateChanges))\n .pipe(takeUntil(changedOrDestroyed))\n .subscribe(() => {\n this._changeDetectorRef.markForCheck();\n this.stateChanges.next();\n });\n\n this._setOptionIds();\n }\n\n /** Invoked when an option is clicked. */\n private _onSelect(option: OuiOption, isUserInput: boolean): void {\n const wasSelected = this._selectionModel.isSelected(option);\n\n if (option.value == null && !this._multiple) {\n option.deselect();\n this._selectionModel.clear();\n this._propagateChanges(option.value);\n } else {\n option.selected\n ? this._selectionModel.select(option)\n : this._selectionModel.deselect(option);\n\n if (isUserInput) {\n this._keyManager.setActiveItem(option);\n }\n\n if (this.multiple) {\n this._sortValues();\n\n if (isUserInput) {\n // In case the user selected the option with their mouse, we\n // want to restore focus back to the trigger, in order to\n // prevent the select keyboard controls from clashing with\n // the ones from `oui-option`.\n this.focus();\n }\n }\n }\n\n if (wasSelected !== this._selectionModel.isSelected(option)) {\n this._propagateChanges();\n }\n this.disableDoneButton = false;\n this.stateChanges.next();\n }\n discardRecentChanges() {\n this.value = this.savedValues;\n this._setSelectionByValue(this.value);\n this.disableDoneButton = true;\n this.close();\n }\n doneRecentChanges() {\n this.savedValues = this.value;\n this.disableDoneButton = true;\n this.saveSelectionChange.emit(new OuiSelectChange(this, this.value));\n this.close();\n }\n /** Sorts the selected values in the selected based on their order in the panel. */\n private _sortValues() {\n if (this.multiple) {\n const options = this.options.toArray();\n\n this._selectionModel.sort((a, b) =>\n this.sortComparator\n ? this.sortComparator(a, b, options)\n : options.indexOf(a) - options.indexOf(b)\n );\n this.stateChanges.next();\n }\n }\n\n /** Emits change event to set the model value. */\n private _propagateChanges(fallbackValue?: any): void {\n let valueToEmit: any = null;\n\n if (this.multiple) {\n valueToEmit = (this.selected as OuiOption[]).map(\n (option) => option.value\n );\n } else {\n valueToEmit = this.selected\n ? (this.selected as OuiOption).value\n : fallbackValue;\n }\n\n this._value = valueToEmit;\n this.valueChange.emit(valueToEmit);\n this._onChange(valueToEmit);\n this.selectionChange.emit(new OuiSelectChange(this, valueToEmit));\n this._changeDetectorRef.markForCheck();\n }\n\n /** Records option IDs to pass to the aria-owns property. */\n private _setOptionIds() {\n this._optionIds = this.options.map((option) => option.id).join(' ');\n }\n\n /**\n * Highlights the selected item. If no option is selected, it will highlight\n * the first item instead.\n */\n private _highlightCorrectOption(): void {\n if (this.multiple) {\n this._highlightFirstFilteredOption();\n } else if (this._keyManager) {\n if (this.empty) {\n this._keyManager.setFirstItemActive();\n } else {\n this._keyManager.setActiveItem(this._selectionModel.selected[0]);\n }\n }\n }\n\n /**\n * Highlights the first of the filtered options if no element is currently highlighted\n */\n private _highlightFirstFilteredOption(): void {\n if (this._keyManager) {\n const activeElement = this._keyManager.activeItem?._getHostElement();\n // activeElement is not part of DOM if there is no parent element\n if (!activeElement || !activeElement.parentElement) {\n // highlight first element if there is no active element or active element is not part of DOM\n this._keyManager.setFirstItemActive();\n }\n }\n }\n\n /** Focuses the select element. */\n focus(): void {\n this._elementRef.nativeElement.focus();\n }\n\n /** Returns the aria-label of the select component. */\n _getAriaLabel(): string | null {\n // If an ariaLabelledby value has been set by the consumer, the select should not overwrite the\n // `aria-labelledby` value by setting the ariaLabel to the placeholder.\n return this.ariaLabelledby ? null : this.ariaLabel || this.placeholder;\n }\n\n /** Returns the aria-labelledby of the select component. */\n _getAriaLabelledby(): string | null {\n if (this.ariaLabelledby) {\n return this.ariaLabelledby;\n }\n\n return null;\n }\n\n /** Determines the `aria-activedescendant` to be set on the host. */\n _getAriaActiveDescendant(): string | null {\n if (this.panelOpen && this._keyManager && this._keyManager.activeItem) {\n return this._keyManager.activeItem.id;\n }\n\n return null;\n }\n\n /**\n * Implemented as part of OuiFormFieldControl.\n *\n * @docs-private\n */\n setDescribedByIds(ids: string[]) {\n this._ariaDescribedby = ids.join(' ');\n }\n\n /**\n * Implemented as part of OuiFormFieldControl.\n *\n * @docs-private\n */\n onContainerClick() {\n this.focus();\n this.open();\n }\n\n /**\n * Implemented as part of OuiFormFieldControl.\n *\n * @docs-private\n */\n get shouldLabelFloat(): boolean {\n return this._panelOpen || !this.empty;\n }\n\n /**\n * Add outer class to perfect scrollbar\n * This is added only when there is a search field\n */\n ouiSelectInputOuter() {\n this.ouiSelectInputOuterClassName = 'oui-select-input-outer';\n }\n\n /**\n * Custom overlay class for cdk overlay container\n */\n openCdk() {\n this.overlayDir.positionChange.pipe(take(1)).subscribe((e) => {\n this.cdkConnectionOverlayPanel = '';\n if (e.connectionPair.originY === 'top') {\n this.cdkConnectionOverlayPanel = 'select-overlay-top';\n }\n this._changeDetectorRef.detectChanges();\n setTimeout((_) => this._scrollToOption());\n });\n\n const cdkOverLayContainer = this._document.querySelector(\n '.cdk-overlay-container'\n );\n const ouiSelectPanel = this._document.querySelector('.oui-select-panel');\n cdkOverLayContainer.classList.add('oui-select-overlay-container');\n const containerWidth = this._elementRef.nativeElement.offsetWidth;\n ouiSelectPanel.style.width = `${containerWidth}px`;\n const searchQueryString = '.oui-select-search-inner';\n if (this._document.querySelector(searchQueryString)) {\n this.scrollCalc(searchQueryString);\n this.isSearchFieldPresent = true;\n }\n }\n scrollCalc(selectQueryString: string) {\n const searchInput = this._document.querySelector(selectQueryString);\n const outter = this._document.querySelector('.oui-select-panel');\n let inner = this._document.querySelector('.oui-option');\n if (inner === null) {\n inner = 0;\n }\n const scrollbarWidth = outter.offsetWidth - inner.offsetWidth;\n if (scrollbarWidth > 5) {\n searchInput.style.width = `${inner.offsetWidth}px`;\n } else {\n searchInput.style.width = `calc(100% + 8px)`;\n }\n }\n\n /**\n * Given that we are not actually focusing active options, we must manually adjust scroll\n * to reveal options below the fold. First, we find the offset of the option from the top\n * of the panel. If that offset is below the fold, the new scrollTop will be the offset -\n * the panel height + the option height, so the active option will be just visible at the\n * bottom of the panel. If that offset is above the top of the visible panel, the new scrollTop\n * will become the offset. If that offset is visible within the panel already, the scrollTop is\n * not adjusted.\n */\n private _scrollToOption(): void {\n const manager = this._keyManager;\n const index = manager.activeItemIndex || 0;\n const labelCount = _countGroupLabelsBeforeOption(\n index,\n this.options,\n this.optionGroups\n );\n const scrollTop = this._getScrollTop();\n const newScrollPosition = _getOptionScrollPosition(\n index + labelCount,\n SELECT_OPTION_HEIGHT,\n scrollTop,\n this.actionItems && this.isSearchFieldPresent && labelCount\n ? SELECT_PANEL_HEIGHT - (50 + labelCount * 19)\n : (this.actionItems && this.isSearchFieldPresent && !labelCount) ||\n (this.actionItems && !this.isSearchFieldPresent && labelCount) ||\n (!this.actionItems && this.isSearchFieldPresent && labelCount)\n ? SELECT_PANEL_HEIGHT - 50\n : SELECT_PANEL_HEIGHT\n );\n this._setScrollTop(newScrollPosition);\n }\n\n /**\n * Sets the panel scrollTop. This allows us to manually scroll to display options\n * above or below the fold, as they are not actually being focused when active.\n */\n _setScrollTop(scrollTop: number): void {\n if (this.panel) {\n this.panel.nativeElement.querySelector('.oui-select-options').scrollTop =\n scrollTop;\n }\n }\n\n /** Returns the panel's scrollTop. */\n _getScrollTop(): number {\n return this.panel ? this.panel.nativeElement.scrollTop : 0;\n }\n}\n", + "sourceCode": "import { ActiveDescendantKeyManager, FocusMonitor } from '@angular/cdk/a11y';\r\nimport { Directionality } from '@angular/cdk/bidi';\r\nimport { coerceBooleanProperty } from '@angular/cdk/coercion';\r\nimport { SelectionModel } from '@angular/cdk/collections';\r\nimport {\r\n A,\r\n DOWN_ARROW,\r\n END,\r\n ENTER,\r\n HOME,\r\n LEFT_ARROW,\r\n RIGHT_ARROW,\r\n SPACE,\r\n UP_ARROW,\r\n hasModifierKey,\r\n TAB,\r\n} from '@angular/cdk/keycodes';\r\nimport { CdkConnectedOverlay } from '@angular/cdk/overlay';\r\nimport {\r\n AfterContentInit,\r\n Attribute,\r\n ChangeDetectionStrategy,\r\n ChangeDetectorRef,\r\n Component,\r\n ContentChild,\r\n ContentChildren,\r\n Directive,\r\n DoCheck,\r\n ElementRef,\r\n EventEmitter,\r\n Input,\r\n isDevMode,\r\n NgZone,\r\n OnChanges,\r\n OnDestroy,\r\n OnInit,\r\n Optional,\r\n Output,\r\n QueryList,\r\n Self,\r\n SimpleChanges,\r\n ViewChild,\r\n ViewEncapsulation,\r\n Inject,\r\n} from '@angular/core';\r\nimport {\r\n ControlValueAccessor,\r\n FormGroupDirective,\r\n NgControl,\r\n NgForm,\r\n} from '@angular/forms';\r\nimport {\r\n _countGroupLabelsBeforeOption,\r\n _getOptionScrollPosition,\r\n CanDisable,\r\n CanDisableCtor,\r\n CanUpdateErrorState,\r\n CanUpdateErrorStateCtor,\r\n HasTabIndex,\r\n HasTabIndexCtor,\r\n OuiOptionSelectionChange,\r\n mixinErrorState,\r\n mixinTabIndex,\r\n mixinDisabled,\r\n} from '../core';\r\nimport { OuiFormField, OuiFormFieldControl } from '../form-field/public-api';\r\nimport { DOCUMENT } from '@angular/common';\r\nimport { OUI_OPTION_PARENT_COMPONENT, OuiOption } from '../core/option/option';\r\nimport { OuiOptgroup } from '../core/option/optgroup';\r\nimport { ErrorStateMatcher } from '../core/error/error-options';\r\nimport { defer, merge, Observable, Subject } from 'rxjs';\r\nimport {\r\n distinctUntilChanged,\r\n filter,\r\n map,\r\n startWith,\r\n switchMap,\r\n take,\r\n takeUntil,\r\n} from 'rxjs/operators';\r\nimport {\r\n getOuiSelectDynamicMultipleError,\r\n getOuiSelectNonArrayValueError,\r\n getOuiSelectNonFunctionValueError,\r\n} from './select-errors';\r\nimport { OuiIconRegistry } from '../icon/icon-registery';\r\nimport { DomSanitizer } from '@angular/platform-browser';\r\nimport { ICONS } from '../core/shared/icons';\r\n\r\nlet nextUniqueId = 0;\r\n\r\n/**\r\n * The following style constants are necessary to save here in order\r\n * to properly calculate the alignment of the selected option over\r\n * the trigger element.\r\n */\r\n\r\n/** The height of each select option. */\r\nexport const SELECT_OPTION_HEIGHT = 40;\r\n\r\n/** The panel's padding on the x-axis */\r\nexport const SELECT_PANEL_PADDING_X = 16;\r\n\r\n/** The panel's x axis padding if it is indented (e.g. there is an option group). */\r\nexport const SELECT_PANEL_INDENT_PADDING_X = SELECT_PANEL_PADDING_X * 2;\r\n\r\n/** The height of the select items in `em` units. */\r\nexport const SELECT_ITEM_HEIGHT_EM = 3;\r\n\r\n/** The total height of the select panel. */\r\nexport const SELECT_PANEL_HEIGHT = 200;\r\n\r\n// TODO(josephperrott): Revert to a constant after 2018 spec updates are fully merged.\r\n/**\r\n * Distance between the panel edge and the option text in\r\n * multi-selection mode.\r\n *\r\n * Calculated as:\r\n * (SELECT_PANEL_PADDING_X * 1.5) + 20 = 44\r\n * The padding is multiplied by 1.5 because the checkbox's margin is half the padding.\r\n * The checkbox width is 16px.\r\n */\r\nexport let SELECT_MULTIPLE_PANEL_PADDING_X = 0;\r\n\r\n/**\r\n * The select panel will only \"fit\" inside the viewport if it is positioned at\r\n * this value or more away from the viewport boundary.\r\n */\r\nexport const SELECT_PANEL_VIEWPORT_PADDING = 8;\r\n\r\n/** Change event object that is emitted when the select value has changed. */\r\nexport class OuiSelectChange {\r\n constructor(\r\n /** Reference to the select that emitted the change event. */\r\n public source: OuiSelect,\r\n /** Current value of the select that emitted the event. */\r\n public value: any\r\n ) {}\r\n}\r\n\r\n// Boilerplate for applying mixins to OuiSelect.\r\n/** @docs-private */\r\nexport class OuiSelectBase {\r\n constructor(\r\n public _elementRef: ElementRef,\r\n public _defaultErrorStateMatcher: ErrorStateMatcher,\r\n public _parentForm: NgForm,\r\n public _parentFormGroup: FormGroupDirective,\r\n public ngControl: NgControl\r\n ) {}\r\n}\r\n\r\nexport const _OuiSelectMixinBase: CanDisableCtor &\r\n HasTabIndexCtor &\r\n CanUpdateErrorStateCtor &\r\n typeof OuiSelectBase = mixinTabIndex(\r\n mixinDisabled(mixinErrorState(OuiSelectBase))\r\n);\r\n\r\n/**\r\n * Allows the user to customize the trigger that is displayed when the select has a value.\r\n */\r\n@Directive({\r\n // eslint-disable-next-line @angular-eslint/directive-selector\r\n selector: 'oui-select-trigger',\r\n})\r\nexport class OuiSelectTrigger {}\r\n\r\n@Component({\r\n selector: 'oui-select',\r\n exportAs: 'ouiSelect',\r\n templateUrl: 'select.html',\r\n styleUrls: ['select.scss'],\r\n // eslint-disable-next-line @angular-eslint/no-inputs-metadata-property\r\n inputs: ['disabled', 'tabIndex'],\r\n encapsulation: ViewEncapsulation.None,\r\n changeDetection: ChangeDetectionStrategy.OnPush,\r\n // eslint-disable-next-line @angular-eslint/no-host-metadata-property\r\n host: {\r\n role: 'listbox',\r\n '[attr.id]': 'id',\r\n '[attr.tabindex]': 'tabIndex',\r\n '[attr.aria-label]': '_getAriaLabel()',\r\n '[attr.aria-labelledby]': '_getAriaLabelledby()',\r\n '[attr.aria-required]': 'required.toString()',\r\n '[attr.aria-disabled]': 'disabled.toString()',\r\n '[attr.aria-invalid]': 'errorState',\r\n '[attr.aria-owns]': 'panelOpen ? _optionIds : null',\r\n '[attr.aria-multiselectable]': 'multiple',\r\n '[attr.aria-describedby]': '_ariaDescribedby || null',\r\n '[attr.aria-activedescendant]': '_getAriaActiveDescendant()',\r\n '[class.oui-select-disabled]': 'disabled',\r\n '[class.oui-select-invalid]': 'errorState',\r\n '[class.oui-select-required]': 'required',\r\n '[class.oui-select-empty]': 'empty',\r\n class: 'oui-select oui-input',\r\n '(keydown)': '_handleKeydown($event)',\r\n '(focus)': '_onFocus()',\r\n '(blur)': '_onBlur()',\r\n },\r\n providers: [\r\n { provide: OuiFormFieldControl, useExisting: OuiSelect },\r\n { provide: OUI_OPTION_PARENT_COMPONENT, useExisting: OuiSelect },\r\n ],\r\n})\r\nexport class OuiSelect\r\n extends _OuiSelectMixinBase\r\n implements\r\n AfterContentInit,\r\n OnChanges,\r\n OnDestroy,\r\n OnInit,\r\n DoCheck,\r\n ControlValueAccessor,\r\n CanDisable,\r\n HasTabIndex,\r\n OuiFormFieldControl,\r\n CanUpdateErrorState\r\n{\r\n /**Holds selected values after done */\r\n @Input() savedValues = [];\r\n /**Done button disabled until dropdown is dirty */\r\n disableDoneButton = true;\r\n /** Whether or not the overlay panel is open. */\r\n private _panelOpen = false;\r\n\r\n /** Whether filling out the select is required in the form. */\r\n private _required = false;\r\n\r\n /** Whether filling out the select is required in the form. */\r\n private _actionItems = false;\r\n\r\n /** The scroll position of the overlay panel, calculated to center the selected option. */\r\n private _scrollTop = 0;\r\n\r\n /** The placeholder displayed in the trigger of the select. */\r\n private _placeholder: string;\r\n\r\n /** Whether the component is in multiple selection mode. */\r\n private _multiple = false;\r\n\r\n /** Search input field **/\r\n isSearchFieldPresent: boolean;\r\n\r\n /** Unique id for this input. */\r\n private _uid = `oui-select-${nextUniqueId++}`;\r\n\r\n /** The last measured value for the trigger's client bounding rect. */\r\n _triggerRect: ClientRect;\r\n\r\n /** The aria-describedby attribute on the select for improved a11y. */\r\n _ariaDescribedby: string;\r\n\r\n /** The cached font-size of the trigger element. */\r\n _triggerFontSize = 0;\r\n\r\n /** Deals with the selection logic. */\r\n _selectionModel: SelectionModel;\r\n\r\n /** Manages keyboard events for options in the panel. */\r\n _keyManager: ActiveDescendantKeyManager;\r\n\r\n /** The IDs of child options to be passed to the aria-owns attribute. */\r\n _optionIds = '';\r\n\r\n /** The value of the select panel's transform-origin property. */\r\n _transformOrigin = 'top';\r\n\r\n /** If there is search input field a class is added dynamically to the perfect scrollbar **/\r\n ouiSelectInputOuterClassName: string;\r\n\r\n /** Adding top class to overlay panel */\r\n cdkConnectionOverlayPanel = '';\r\n\r\n /**\r\n * The y-offset of the overlay panel in relation to the trigger's top start corner.\r\n * This must be adjusted to align the selected option text over the trigger text.\r\n * when the panel opens. Will change based on the y-position of the selected option.\r\n */\r\n _offsetY = 0;\r\n\r\n /**\r\n * This position config ensures that the top \"start\" corner of the overlay\r\n * is aligned with with the top \"start\" of the origin by default (overlapping\r\n * the trigger completely). If the panel cannot fit below the trigger, it\r\n * will fall back to a position above the trigger.\r\n */\r\n _positions = [\r\n {\r\n originX: 'start',\r\n originY: 'top',\r\n overlayX: 'start',\r\n overlayY: 'top',\r\n },\r\n {\r\n originX: 'start',\r\n originY: 'bottom',\r\n overlayX: 'start',\r\n overlayY: 'bottom',\r\n },\r\n ];\r\n /** Emits whenever the component is destroyed. */\r\n private readonly _destroy = new Subject();\r\n\r\n /** Whether the component is disabling centering of the active option over the trigger. */\r\n private _disableOptionCentering = false;\r\n\r\n private _focused = false;\r\n\r\n /** A name for this control that can be used by `oui-form-field`. */\r\n controlType = 'oui-select';\r\n\r\n /** Trigger that opens the select. */\r\n @ViewChild('trigger') trigger: ElementRef;\r\n\r\n /** Trigger that opens the select. */\r\n @ViewChild('ddCancelButton', { read: ElementRef }) ddCancelButton: ElementRef;\r\n\r\n /** Trigger that opens the select. */\r\n @ViewChild('ddDoneButton', { read: ElementRef }) ddDoneButton: ElementRef;\r\n\r\n /** Panel containing the select options. */\r\n @ViewChild('panel', { read: ElementRef }) panel: ElementRef;\r\n\r\n private _value: any;\r\n\r\n /**\r\n * Function used to sort the values in a select in multiple mode.\r\n * Follows the same logic as `Array.prototype.sort`.\r\n */\r\n @Input() sortComparator: (\r\n a: OuiOption,\r\n b: OuiOption,\r\n options: OuiOption[]\r\n ) => number;\r\n\r\n /** Aria label of the select. If not specified, the placeholder will be used as label. */\r\n @Input('aria-label') ariaLabel = '';\r\n\r\n /** Input that can be used to specify the `aria-labelledby` attribute. */\r\n @Input('aria-labelledby') ariaLabelledby: string;\r\n private _large = false;\r\n _monitorSubscription: any;\r\n\r\n /** Whether the oui-select is of large size. */\r\n @Input()\r\n get large(): boolean {\r\n return this._large;\r\n }\r\n set large(value) {\r\n this._large = coerceBooleanProperty(value);\r\n this._changeDetectorRef.markForCheck();\r\n }\r\n\r\n private _id: string;\r\n\r\n /** Event emitted when the select panel has been toggled. */\r\n @Output()\r\n readonly openedChange: EventEmitter = new EventEmitter();\r\n\r\n /** Combined stream of all of the child options' change events. */\r\n readonly optionSelectionChanges: Observable = defer(\r\n (): Observable => {\r\n if (this.options) {\r\n return merge(...this.options.map((option) => option.onSelectionChange));\r\n }\r\n\r\n return this._ngZone.onStable.asObservable().pipe(\r\n take(1),\r\n switchMap(() => this.optionSelectionChanges)\r\n );\r\n }\r\n );\r\n\r\n /**\r\n * Event that emits whenever the raw value of the select changes. This is here primarily\r\n * to facilitate the two-way binding for the `value` input.\r\n *\r\n * @docs-private\r\n */\r\n @Output() readonly valueChange: EventEmitter = new EventEmitter();\r\n\r\n /** Object used to control when error messages are shown. */\r\n @Input() errorStateMatcher: ErrorStateMatcher;\r\n\r\n /** All of the defined select options. */\r\n @ContentChildren(OuiOption, { descendants: true })\r\n options: QueryList;\r\n\r\n /** Event emitted when the select has been opened. */\r\n // eslint-disable-next-line @angular-eslint/no-output-rename\r\n @Output('opened')\r\n readonly _openedStream: Observable = this.openedChange.pipe(\r\n filter((o) => o),\r\n map(() => {})\r\n );\r\n\r\n /** Event emitted when the select has been closed. */\r\n // eslint-disable-next-line @angular-eslint/no-output-rename\r\n @Output('closed')\r\n readonly _closedStream: Observable = this.openedChange.pipe(\r\n filter((o) => !o),\r\n map(() => {\r\n this.isSearchFieldPresent = false;\r\n })\r\n );\r\n\r\n /** Event emitted when the selected value has been changed by the user. */\r\n @Output()\r\n readonly selectionChange: EventEmitter =\r\n new EventEmitter();\r\n\r\n /** Event emitted when the selected value has been changed and saved by the user. */\r\n @Output()\r\n readonly saveSelectionChange: EventEmitter =\r\n new EventEmitter();\r\n\r\n /** All of the defined groups of options. */\r\n @ContentChildren(OuiOptgroup) optionGroups: QueryList;\r\n\r\n /** User-supplied override of the trigger element. */\r\n @ContentChild(OuiSelectTrigger)\r\n customTrigger: OuiSelectTrigger;\r\n\r\n /** Classes to be passed to the select panel. Supports the same syntax as `ngClass`. */\r\n @Input() panelClass: string | string[] | Set | { [key: string]: any };\r\n\r\n /** Overlay pane containing the options. */\r\n @ViewChild(CdkConnectedOverlay)\r\n overlayDir: CdkConnectedOverlay;\r\n\r\n /** Emits when the panel element is finished transforming in. */\r\n _panelDoneAnimatingStream = new Subject();\r\n\r\n /** Comparison function to specify which option is displayed. Defaults to object equality. */\r\n private _compareWith = (o1: any, o2: any) => o1 === o2;\r\n\r\n /** Whether the select is focused. */\r\n get focused(): boolean {\r\n return this._focused || this._panelOpen;\r\n }\r\n /**\r\n * @deprecated Setter to be removed as this property is intended to be readonly.\r\n */\r\n set focused(value: boolean) {\r\n this._focused = value;\r\n }\r\n /** `View -> model callback called when value changes` */\r\n _onChange: (value: any) => void = () => {};\r\n\r\n /** `View -> model callback called when select has been touched` */\r\n _onTouched = () => {};\r\n\r\n /** Placeholder to be shown if no value has been selected. */\r\n @Input()\r\n get placeholder(): string {\r\n return this._placeholder;\r\n }\r\n set placeholder(value: string) {\r\n this._placeholder = value;\r\n this.stateChanges.next();\r\n }\r\n\r\n /** Whether the component is required. */\r\n @Input()\r\n get required(): boolean {\r\n return this._required;\r\n }\r\n set required(value: boolean) {\r\n this._required = coerceBooleanProperty(value);\r\n this.stateChanges.next();\r\n }\r\n\r\n /** Whether the user should be allowed to select multiple options. */\r\n @Input()\r\n get multiple(): boolean {\r\n return this._multiple;\r\n }\r\n set multiple(value: boolean) {\r\n if (this._selectionModel) {\r\n throw getOuiSelectDynamicMultipleError();\r\n }\r\n\r\n this._multiple = coerceBooleanProperty(value);\r\n }\r\n\r\n /** Whether the action items are required and use saveSelectionChange instead of selectionChange. */\r\n @Input()\r\n get actionItems(): boolean {\r\n return this._actionItems;\r\n }\r\n set actionItems(value: boolean) {\r\n if (this._multiple) {\r\n this._actionItems = coerceBooleanProperty(value);\r\n this.stateChanges.next();\r\n }\r\n }\r\n\r\n /** Whether to center the active option over the trigger. */\r\n @Input()\r\n get disableOptionCentering(): boolean {\r\n return this._disableOptionCentering;\r\n }\r\n set disableOptionCentering(value: boolean) {\r\n this._disableOptionCentering = coerceBooleanProperty(value);\r\n }\r\n\r\n /**\r\n * Function to compare the option values with the selected values. The first argument\r\n * is a value from an option. The second is a value from the selection. A boolean\r\n * should be returned.\r\n */\r\n @Input()\r\n get compareWith() {\r\n return this._compareWith;\r\n }\r\n set compareWith(fn: (o1: any, o2: any) => boolean) {\r\n if (typeof fn !== 'function') {\r\n throw getOuiSelectNonFunctionValueError();\r\n }\r\n this._compareWith = fn;\r\n if (this._selectionModel) {\r\n // A different comparator means the selection could change.\r\n this._initializeSelection();\r\n }\r\n }\r\n\r\n /** Value of the select control. */\r\n @Input()\r\n get value(): any {\r\n return this._value;\r\n }\r\n set value(newValue: any) {\r\n if (newValue !== this._value) {\r\n this.writeValue(newValue);\r\n this._value = newValue;\r\n }\r\n }\r\n\r\n /** Unique id of the element. */\r\n @Input()\r\n get id(): string {\r\n return this._id;\r\n }\r\n set id(value: string) {\r\n this._id = value || this._uid;\r\n this.stateChanges.next();\r\n }\r\n\r\n constructor(\r\n private _changeDetectorRef: ChangeDetectorRef,\r\n private _ngZone: NgZone,\r\n _defaultErrorStateMatcher: ErrorStateMatcher,\r\n elementRef: ElementRef,\r\n private _focusMonitor: FocusMonitor,\r\n @Optional() private _dir: Directionality,\r\n @Optional() _parentForm: NgForm,\r\n @Optional() _parentFormGroup: FormGroupDirective,\r\n @Optional() private _parentFormField: OuiFormField,\r\n @Self() @Optional() public ngControl: NgControl,\r\n @Attribute('tabindex') tabIndex: string,\r\n @Optional() @Inject(DOCUMENT) private _document: any,\r\n public _elementRef: ElementRef,\r\n public _ouiIconRegistry: OuiIconRegistry,\r\n private _domSanitizer: DomSanitizer\r\n ) {\r\n super(\r\n elementRef,\r\n _defaultErrorStateMatcher,\r\n _parentForm,\r\n _parentFormGroup,\r\n ngControl\r\n );\r\n this._monitorSubscription = this._focusMonitor\r\n .monitor(this._elementRef, true)\r\n .subscribe(() => this._ngZone.run(() => {}));\r\n this._ouiIconRegistry.addSvgIconLiteral(\r\n `select-arrow-icon`,\r\n this._domSanitizer.bypassSecurityTrustHtml(ICONS.SELECT_ARROW_ICON)\r\n );\r\n\r\n if (this.ngControl) {\r\n // Note: we provide the value accessor through here, instead of\r\n // the `providers` to avoid running into a circular import.\r\n this.ngControl.valueAccessor = this;\r\n }\r\n\r\n this.tabIndex = parseInt(tabIndex, 10) || 0;\r\n\r\n // Force setter to be called in case id was not specified.\r\n this.id = this.id;\r\n }\r\n\r\n ngOnInit() {\r\n this._selectionModel = new SelectionModel(this.multiple);\r\n this.stateChanges.next();\r\n\r\n // We need `distinctUntilChanged` here, because some browsers will\r\n // fire the animation end event twice for the same animation. See:\r\n // https://github.com/angular/angular/issues/24084\r\n this._panelDoneAnimatingStream\r\n .pipe(distinctUntilChanged(), takeUntil(this._destroy))\r\n .subscribe(() => {\r\n if (this.panelOpen) {\r\n this._scrollTop = 0;\r\n this.openedChange.emit(true);\r\n } else {\r\n this.openedChange.emit(false);\r\n this.overlayDir.offsetX = 0;\r\n this._changeDetectorRef.markForCheck();\r\n }\r\n });\r\n }\r\n\r\n ngAfterContentInit() {\r\n this._initKeyManager();\r\n\r\n this._selectionModel.changed\r\n .pipe(takeUntil(this._destroy))\r\n .subscribe((event) => {\r\n event.added.forEach((option) => option.select());\r\n event.removed.forEach((option) => option.deselect());\r\n });\r\n\r\n this.options.changes\r\n .pipe(startWith(null), takeUntil(this._destroy))\r\n .subscribe(() => {\r\n this._resetOptions();\r\n this._initializeSelection();\r\n });\r\n }\r\n\r\n ngDoCheck() {\r\n if (this.ngControl) {\r\n this.updateErrorState();\r\n }\r\n }\r\n\r\n ngOnChanges(changes: SimpleChanges) {\r\n // Updating the disabled state is handled by `mixinDisabled`, but we need to additionally let\r\n // the parent form field know to run change detection when the disabled state changes.\r\n if (changes.disabled) {\r\n this.stateChanges.next();\r\n }\r\n }\r\n\r\n ngOnDestroy() {\r\n this._monitorSubscription.unsubscribe();\r\n this._focusMonitor.stopMonitoring(this._elementRef);\r\n this._destroy.next();\r\n this._destroy.complete();\r\n this.stateChanges.complete();\r\n }\r\n\r\n /** Toggles the overlay panel open or closed. */\r\n toggle(): void {\r\n this.panelOpen ? this.close() : this.open();\r\n }\r\n\r\n /** Opens the overlay panel. */\r\n open(): void {\r\n if (\r\n this.disabled ||\r\n !this.options ||\r\n !this.options.length ||\r\n this._panelOpen\r\n ) {\r\n return;\r\n }\r\n\r\n this._triggerRect = this.trigger.nativeElement.getBoundingClientRect();\r\n\r\n this._panelOpen = true;\r\n this._keyManager.withHorizontalOrientation(null);\r\n\r\n this._highlightCorrectOption();\r\n this._changeDetectorRef.markForCheck();\r\n this.openedChange.emit(true);\r\n this._elementRef.nativeElement.classList.add(\r\n 'oui-select-list-options-opened'\r\n );\r\n }\r\n\r\n /** Closes the overlay panel and focuses the host element. */\r\n close(): void {\r\n if (this._panelOpen) {\r\n this._panelOpen = false;\r\n this._keyManager.withHorizontalOrientation(this._isRtl() ? 'rtl' : 'ltr');\r\n this._changeDetectorRef.markForCheck();\r\n this._onTouched();\r\n this.openedChange.emit(false);\r\n this._elementRef.nativeElement.classList.remove(\r\n 'oui-select-list-options-opened'\r\n );\r\n setTimeout((_) => this._document.activeElement.blur());\r\n }\r\n }\r\n\r\n /**\r\n * Sets the select's value. Part of the ControlValueAccessor interface\r\n * required to integrate with Angular's core forms API.\r\n *\r\n * @param value New value to be written to the model.\r\n */\r\n writeValue(value: any): void {\r\n if (this.options) {\r\n this._setSelectionByValue(value);\r\n }\r\n }\r\n\r\n /**\r\n * Saves a callback function to be invoked when the select's value\r\n * changes from user input. Part of the ControlValueAccessor interface\r\n * required to integrate with Angular's core forms API.\r\n *\r\n * @param fn Callback to be triggered when the value changes.\r\n */\r\n registerOnChange(fn: (value: any) => void): void {\r\n this._onChange = fn;\r\n }\r\n\r\n /**\r\n * Saves a callback function to be invoked when the select is blurred\r\n * by the user. Part of the ControlValueAccessor interface required\r\n * to integrate with Angular's core forms API.\r\n *\r\n * @param fn Callback to be triggered when the component has been touched.\r\n */\r\n registerOnTouched(fn: () => {}): void {\r\n this._onTouched = fn;\r\n }\r\n\r\n /**\r\n * Disables the select. Part of the ControlValueAccessor interface required\r\n * to integrate with Angular's core forms API.\r\n *\r\n * @param isDisabled Sets whether the component is disabled.\r\n */\r\n setDisabledState(isDisabled: boolean): void {\r\n this.disabled = isDisabled;\r\n this._changeDetectorRef.markForCheck();\r\n this.stateChanges.next();\r\n }\r\n\r\n /** Whether or not the overlay panel is open. */\r\n get panelOpen(): boolean {\r\n return this._panelOpen;\r\n }\r\n\r\n /** The currently selected option. */\r\n get selected(): OuiOption | OuiOption[] {\r\n return this.multiple\r\n ? this._selectionModel.selected\r\n : this._selectionModel.selected[0];\r\n }\r\n\r\n /** The value displayed in the trigger. */\r\n get triggerValue(): string {\r\n if (this.empty) {\r\n return '';\r\n }\r\n if (this._multiple) {\r\n const selectedOptions = this._selectionModel.selected.map(\r\n (option) => option.viewValueForSelect\r\n );\r\n\r\n if (this._isRtl()) {\r\n selectedOptions.reverse();\r\n }\r\n return selectedOptions.join(', ');\r\n }\r\n return this._selectionModel.selected[0].viewValueForSelect;\r\n }\r\n\r\n /** Whether the element is in RTL mode. */\r\n _isRtl(): boolean {\r\n return this._dir ? this._dir.value === 'rtl' : false;\r\n }\r\n\r\n /** Handles all keydown events on the select. */\r\n _handleKeydown(event: KeyboardEvent): void {\r\n if (!this.disabled) {\r\n this.panelOpen\r\n ? this._handleOpenKeydown(event)\r\n : this._handleClosedKeydown(event);\r\n }\r\n }\r\n\r\n /** Handles keyboard events while the select is closed. */\r\n private _handleClosedKeydown(event: KeyboardEvent): void {\r\n const keyCode = event.keyCode;\r\n const isArrowKey =\r\n keyCode === DOWN_ARROW ||\r\n keyCode === UP_ARROW ||\r\n keyCode === LEFT_ARROW ||\r\n keyCode === RIGHT_ARROW;\r\n const isOpenKey = keyCode === ENTER || keyCode === SPACE;\r\n const manager = this._keyManager;\r\n\r\n // Open the select on ALT + arrow key to match the native \r\n event.preventDefault();\r\n this.close();\r\n } else if (\r\n (keyCode === ENTER || keyCode === SPACE) &&\r\n manager.activeItem &&\r\n !hasModifierKey(event)\r\n ) {\r\n event.preventDefault();\r\n manager.activeItem._selectViaInteraction();\r\n } else if (this._multiple && keyCode === A && event.ctrlKey) {\r\n event.preventDefault();\r\n this.handleCtrlKey();\r\n } else if (normalNavigationCheck) {\r\n // Check for non multiple select dropdown that the key pressed is not Tab, Space, Enter\r\n if (!this.isSearchFieldPresent) this.focus();\r\n this.handleScrolling(manager, event, isArrowKey, keyCode);\r\n }\r\n }\r\n\r\n /**\r\n * Handle ctrl key\r\n */\r\n private handleCtrlKey() {\r\n const hasDeselectedOptions = this.options.some(\r\n (opt) => !opt.disabled && !opt.selected\r\n );\r\n\r\n this.options.forEach((option) => {\r\n if (!option.disabled) {\r\n hasDeselectedOptions ? option.select() : option.deselect();\r\n }\r\n });\r\n }\r\n\r\n /**\r\n * @param manager\r\n * @param event\r\n * @param isArrowKey\r\n * @param keyCode\r\n */\r\n private handleScrolling(\r\n manager: ActiveDescendantKeyManager,\r\n event: KeyboardEvent,\r\n isArrowKey: boolean,\r\n keyCode: number\r\n ) {\r\n const previouslyFocusedIndex = manager.activeItemIndex;\r\n\r\n manager.onKeydown(event);\r\n\r\n if (\r\n this._multiple &&\r\n isArrowKey &&\r\n event.shiftKey &&\r\n manager.activeItem &&\r\n manager.activeItemIndex !== previouslyFocusedIndex\r\n ) {\r\n manager.activeItem._selectViaInteraction();\r\n }\r\n if (isArrowKey && manager.activeItemIndex !== previouslyFocusedIndex) {\r\n this._scrollToOption();\r\n } else {\r\n // First or last\r\n if (keyCode === DOWN_ARROW) {\r\n manager.setFirstItemActive();\r\n this._setScrollTop(0);\r\n }\r\n if (keyCode === UP_ARROW) {\r\n manager.setLastItemActive();\r\n this._scrollToOption();\r\n }\r\n }\r\n }\r\n\r\n _onFocus() {\r\n if (!this.disabled) {\r\n this._focused = true;\r\n this.stateChanges.next();\r\n }\r\n }\r\n\r\n /**\r\n * Calls the touched callback only if the panel is closed. Otherwise, the trigger will\r\n * \"blur\" to the panel when it opens, causing a false positive.\r\n */\r\n _onBlur() {\r\n this._focused = false;\r\n // this.isSearchFieldPresent = false;\r\n\r\n if (!this.disabled && !this.panelOpen) {\r\n this._onTouched();\r\n this._changeDetectorRef.markForCheck();\r\n this.stateChanges.next();\r\n }\r\n }\r\n\r\n /**\r\n * Callback that is invoked when the overlay panel has been attached.\r\n */\r\n _onAttached(): void {\r\n this.overlayDir.positionChange.pipe(take(1)).subscribe(() => {\r\n this._setPseudoCheckboxPaddingSize();\r\n this._changeDetectorRef.detectChanges();\r\n this.panel.nativeElement.scrollTop = this._scrollTop;\r\n });\r\n }\r\n\r\n /** Returns the theme to be used on the panel. */\r\n _getPanelTheme(): string {\r\n return this._parentFormField ? `oui-${this._parentFormField.color}` : '';\r\n }\r\n\r\n // TODO(josephperrott): Remove after 2018 spec updates are fully merged.\r\n /** Sets the pseudo checkbox padding size based on the width of the pseudo checkbox. */\r\n private _setPseudoCheckboxPaddingSize() {\r\n if (!SELECT_MULTIPLE_PANEL_PADDING_X && this.multiple) {\r\n const pseudoCheckbox = this.panel.nativeElement.querySelector(\r\n '.oui-pseudo-checkbox'\r\n );\r\n if (pseudoCheckbox) {\r\n SELECT_MULTIPLE_PANEL_PADDING_X =\r\n SELECT_PANEL_PADDING_X * 1.5 + pseudoCheckbox.offsetWidth;\r\n }\r\n }\r\n }\r\n\r\n /** Whether the select has a value. */\r\n get empty(): boolean {\r\n return !this._selectionModel || this._selectionModel.isEmpty();\r\n }\r\n\r\n private _initializeSelection(): void {\r\n // Defer setting the value in order to avoid the \"Expression\r\n // has changed after it was checked\" errors from Angular.\r\n Promise.resolve().then(() => {\r\n this._setSelectionByValue(\r\n this.ngControl ? this.ngControl.value : this._value\r\n );\r\n this.savedValues = this.ngControl ? this.ngControl.value : this._value;\r\n if (this.multiple) {\r\n this._highlightFirstFilteredOption();\r\n }\r\n });\r\n }\r\n\r\n /**\r\n * Sets the selected option based on a value. If no option can be\r\n * found with the designated value, the select trigger is cleared.\r\n */\r\n private _setSelectionByValue(value: any | any[]): void {\r\n if (this.multiple && value) {\r\n if (!Array.isArray(value)) {\r\n throw getOuiSelectNonArrayValueError();\r\n }\r\n\r\n this._selectionModel.clear();\r\n value.forEach((currentValue: any) => this._selectValue(currentValue));\r\n this._sortValues();\r\n } else {\r\n this._selectionModel.clear();\r\n const correspondingOption = this._selectValue(value);\r\n // Shift focus to the active item. Note that we shouldn't do this in multiple\r\n // mode, because we don't know what option the user interacted with last.\r\n if (correspondingOption) {\r\n this._keyManager.setActiveItem(correspondingOption);\r\n }\r\n }\r\n this._changeDetectorRef.markForCheck();\r\n }\r\n\r\n /**\r\n * Finds and selects and option based on its value.\r\n *\r\n * @returns Option that has the corresponding value.\r\n */\r\n private _selectValue(value: any): OuiOption | undefined {\r\n const correspondingOption = this.options.find((option: OuiOption) => {\r\n try {\r\n // Treat null as a special reset value.\r\n return option.value != null && this._compareWith(option.value, value);\r\n } catch (error) {\r\n if (isDevMode()) {\r\n // Notify developers of errors in their comparator.\r\n console.warn(error);\r\n }\r\n return false;\r\n }\r\n });\r\n\r\n if (correspondingOption) {\r\n this._selectionModel.select(correspondingOption);\r\n }\r\n\r\n return correspondingOption;\r\n }\r\n\r\n /** Sets up a key manager to listen to keyboard events on the overlay panel. */\r\n private _initKeyManager() {\r\n this._keyManager = new ActiveDescendantKeyManager(this.options)\r\n .withTypeAhead()\r\n .withVerticalOrientation()\r\n .withHorizontalOrientation(this._isRtl() ? 'rtl' : 'ltr')\r\n .withAllowedModifierKeys(['shiftKey']);\r\n\r\n this._keyManager.tabOut.pipe(takeUntil(this._destroy)).subscribe(() => {\r\n // Restore focus to the trigger before closing. Ensures that the focus\r\n // position won't be lost if the user got focus into the overlay.\r\n this.focus();\r\n this.close();\r\n });\r\n\r\n this._keyManager.change.pipe(takeUntil(this._destroy)).subscribe(() => {\r\n if (this._panelOpen && this.panel) {\r\n // Panel is opened\r\n // Need not to scroll\r\n } else if (\r\n !this._panelOpen &&\r\n !this.multiple &&\r\n this._keyManager.activeItem\r\n ) {\r\n this._keyManager.activeItem._selectViaInteraction();\r\n }\r\n });\r\n }\r\n\r\n /** Drops current option subscriptions and IDs and resets from scratch. */\r\n private _resetOptions(): void {\r\n const changedOrDestroyed = merge(this.options.changes, this._destroy);\r\n\r\n this.optionSelectionChanges\r\n .pipe(takeUntil(changedOrDestroyed))\r\n .subscribe((event) => {\r\n this._onSelect(event.source, event.isUserInput);\r\n\r\n if (event.isUserInput && !this.multiple && this._panelOpen) {\r\n this.close();\r\n this.focus();\r\n }\r\n });\r\n\r\n // Listen to changes in the internal state of the options and react accordingly.\r\n // Handles cases like the labels of the selected options changing.\r\n merge(...this.options.map((option) => option._stateChanges))\r\n .pipe(takeUntil(changedOrDestroyed))\r\n .subscribe(() => {\r\n this._changeDetectorRef.markForCheck();\r\n this.stateChanges.next();\r\n });\r\n\r\n this._setOptionIds();\r\n }\r\n\r\n /** Invoked when an option is clicked. */\r\n private _onSelect(option: OuiOption, isUserInput: boolean): void {\r\n const wasSelected = this._selectionModel.isSelected(option);\r\n\r\n if (option.value == null && !this._multiple) {\r\n option.deselect();\r\n this._selectionModel.clear();\r\n this._propagateChanges(option.value);\r\n } else {\r\n option.selected\r\n ? this._selectionModel.select(option)\r\n : this._selectionModel.deselect(option);\r\n\r\n if (isUserInput) {\r\n this._keyManager.setActiveItem(option);\r\n }\r\n\r\n if (this.multiple) {\r\n this._sortValues();\r\n\r\n if (isUserInput) {\r\n // In case the user selected the option with their mouse, we\r\n // want to restore focus back to the trigger, in order to\r\n // prevent the select keyboard controls from clashing with\r\n // the ones from `oui-option`.\r\n this.focus();\r\n }\r\n }\r\n }\r\n\r\n if (wasSelected !== this._selectionModel.isSelected(option)) {\r\n this._propagateChanges();\r\n }\r\n this.disableDoneButton = false;\r\n this.stateChanges.next();\r\n }\r\n discardRecentChanges() {\r\n this.value = this.savedValues;\r\n this._setSelectionByValue(this.value);\r\n this.disableDoneButton = true;\r\n this.close();\r\n }\r\n doneRecentChanges() {\r\n this.savedValues = this.value;\r\n this.disableDoneButton = true;\r\n this.saveSelectionChange.emit(new OuiSelectChange(this, this.value));\r\n this.close();\r\n }\r\n /** Sorts the selected values in the selected based on their order in the panel. */\r\n private _sortValues() {\r\n if (this.multiple) {\r\n const options = this.options.toArray();\r\n\r\n this._selectionModel.sort((a, b) =>\r\n this.sortComparator\r\n ? this.sortComparator(a, b, options)\r\n : options.indexOf(a) - options.indexOf(b)\r\n );\r\n this.stateChanges.next();\r\n }\r\n }\r\n\r\n /** Emits change event to set the model value. */\r\n private _propagateChanges(fallbackValue?: any): void {\r\n let valueToEmit: any = null;\r\n\r\n if (this.multiple) {\r\n valueToEmit = (this.selected as OuiOption[]).map(\r\n (option) => option.value\r\n );\r\n } else {\r\n valueToEmit = this.selected\r\n ? (this.selected as OuiOption).value\r\n : fallbackValue;\r\n }\r\n\r\n this._value = valueToEmit;\r\n this.valueChange.emit(valueToEmit);\r\n this._onChange(valueToEmit);\r\n this.selectionChange.emit(new OuiSelectChange(this, valueToEmit));\r\n this._changeDetectorRef.markForCheck();\r\n }\r\n\r\n /** Records option IDs to pass to the aria-owns property. */\r\n private _setOptionIds() {\r\n this._optionIds = this.options.map((option) => option.id).join(' ');\r\n }\r\n\r\n /**\r\n * Highlights the selected item. If no option is selected, it will highlight\r\n * the first item instead.\r\n */\r\n private _highlightCorrectOption(): void {\r\n if (this.multiple) {\r\n this._highlightFirstFilteredOption();\r\n } else if (this._keyManager) {\r\n if (this.empty) {\r\n this._keyManager.setFirstItemActive();\r\n } else {\r\n this._keyManager.setActiveItem(this._selectionModel.selected[0]);\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * Highlights the first of the filtered options if no element is currently highlighted\r\n */\r\n private _highlightFirstFilteredOption(): void {\r\n if (this._keyManager) {\r\n const activeElement = this._keyManager.activeItem?._getHostElement();\r\n // activeElement is not part of DOM if there is no parent element\r\n if (!activeElement || !activeElement.parentElement) {\r\n // highlight first element if there is no active element or active element is not part of DOM\r\n this._keyManager.setFirstItemActive();\r\n }\r\n }\r\n }\r\n\r\n /** Focuses the select element. */\r\n focus(): void {\r\n this._elementRef.nativeElement.focus();\r\n }\r\n\r\n /** Returns the aria-label of the select component. */\r\n _getAriaLabel(): string | null {\r\n // If an ariaLabelledby value has been set by the consumer, the select should not overwrite the\r\n // `aria-labelledby` value by setting the ariaLabel to the placeholder.\r\n return this.ariaLabelledby ? null : this.ariaLabel || this.placeholder;\r\n }\r\n\r\n /** Returns the aria-labelledby of the select component. */\r\n _getAriaLabelledby(): string | null {\r\n if (this.ariaLabelledby) {\r\n return this.ariaLabelledby;\r\n }\r\n\r\n return null;\r\n }\r\n\r\n /** Determines the `aria-activedescendant` to be set on the host. */\r\n _getAriaActiveDescendant(): string | null {\r\n if (this.panelOpen && this._keyManager && this._keyManager.activeItem) {\r\n return this._keyManager.activeItem.id;\r\n }\r\n\r\n return null;\r\n }\r\n\r\n /**\r\n * Implemented as part of OuiFormFieldControl.\r\n *\r\n * @docs-private\r\n */\r\n setDescribedByIds(ids: string[]) {\r\n this._ariaDescribedby = ids.join(' ');\r\n }\r\n\r\n /**\r\n * Implemented as part of OuiFormFieldControl.\r\n *\r\n * @docs-private\r\n */\r\n onContainerClick() {\r\n this.focus();\r\n this.open();\r\n }\r\n\r\n /**\r\n * Implemented as part of OuiFormFieldControl.\r\n *\r\n * @docs-private\r\n */\r\n get shouldLabelFloat(): boolean {\r\n return this._panelOpen || !this.empty;\r\n }\r\n\r\n /**\r\n * Add outer class to perfect scrollbar\r\n * This is added only when there is a search field\r\n */\r\n ouiSelectInputOuter() {\r\n this.ouiSelectInputOuterClassName = 'oui-select-input-outer';\r\n }\r\n\r\n /**\r\n * Custom overlay class for cdk overlay container\r\n */\r\n openCdk() {\r\n this.overlayDir.positionChange.pipe(take(1)).subscribe((e) => {\r\n this.cdkConnectionOverlayPanel = '';\r\n if (e.connectionPair.originY === 'top') {\r\n this.cdkConnectionOverlayPanel = 'select-overlay-top';\r\n }\r\n this._changeDetectorRef.detectChanges();\r\n setTimeout((_) => this._scrollToOption());\r\n });\r\n\r\n const cdkOverLayContainer = this._document.querySelector(\r\n '.cdk-overlay-container'\r\n );\r\n const ouiSelectPanel = this._document.querySelector('.oui-select-panel');\r\n cdkOverLayContainer.classList.add('oui-select-overlay-container');\r\n const containerWidth = this._elementRef.nativeElement.offsetWidth;\r\n ouiSelectPanel.style.width = `${containerWidth}px`;\r\n const searchQueryString = '.oui-select-search-inner';\r\n if (this._document.querySelector(searchQueryString)) {\r\n this.scrollCalc(searchQueryString);\r\n }\r\n const actionItemsQueryString = '.oui-select-action-items';\r\n if (this._document.querySelector(actionItemsQueryString)) {\r\n this.scrollCalc(actionItemsQueryString);\r\n }\r\n }\r\n scrollCalc(selectQueryString: string) {\r\n const searchInput = this._document.querySelector(selectQueryString);\r\n const outter = this._document.querySelector('.oui-select-panel');\r\n let inner = this._document.querySelector('.oui-option');\r\n if (inner === null) {\r\n inner = 0;\r\n }\r\n const scrollbarWidth = outter.offsetWidth - inner.offsetWidth;\r\n if (scrollbarWidth > 5) {\r\n searchInput.style.width = `${inner.offsetWidth}px`;\r\n } else {\r\n searchInput.style.width = `calc(100% + 8px)`;\r\n }\r\n }\r\n\r\n /**\r\n * Given that we are not actually focusing active options, we must manually adjust scroll\r\n * to reveal options below the fold. First, we find the offset of the option from the top\r\n * of the panel. If that offset is below the fold, the new scrollTop will be the offset -\r\n * the panel height + the option height, so the active option will be just visible at the\r\n * bottom of the panel. If that offset is above the top of the visible panel, the new scrollTop\r\n * will become the offset. If that offset is visible within the panel already, the scrollTop is\r\n * not adjusted.\r\n */\r\n private _scrollToOption(): void {\r\n const manager = this._keyManager;\r\n const index = manager.activeItemIndex || 0;\r\n const labelCount = _countGroupLabelsBeforeOption(\r\n index,\r\n this.options,\r\n this.optionGroups\r\n );\r\n const scrollTop = this._getScrollTop();\r\n const newScrollPosition = _getOptionScrollPosition(\r\n index + labelCount,\r\n SELECT_OPTION_HEIGHT,\r\n scrollTop,\r\n SELECT_PANEL_HEIGHT\r\n );\r\n this._setScrollTop(newScrollPosition);\r\n }\r\n\r\n /**\r\n * Sets the panel scrollTop. This allows us to manually scroll to display options\r\n * above or below the fold, as they are not actually being focused when active.\r\n */\r\n _setScrollTop(scrollTop: number): void {\r\n if (this.panel) {\r\n this.panel.nativeElement.scrollTop = scrollTop;\r\n }\r\n }\r\n\r\n /** Returns the panel's scrollTop. */\r\n _getScrollTop(): number {\r\n return this.panel ? this.panel.nativeElement.scrollTop : 0;\r\n }\r\n}\r\n", "constructorObj": { "name": "constructor", "description": "", @@ -10036,7 +10113,7 @@ "description": "", "line": 146, "modifierKind": [ - 123 + 125 ] }, { @@ -10048,7 +10125,7 @@ "description": "", "line": 145, "modifierKind": [ - 123 + 125 ] }, { @@ -10060,7 +10137,7 @@ "description": "", "line": 147, "modifierKind": [ - 123 + 125 ] }, { @@ -10072,7 +10149,7 @@ "description": "", "line": 148, "modifierKind": [ - 123 + 125 ] }, { @@ -10084,12 +10161,13 @@ "description": "", "line": 149, "modifierKind": [ - 123 + 125 ] } ], "methods": [], "indexSignatures": [], + "extends": [], "inputsClass": [], "outputsClass": [], "hostBindings": [], @@ -10097,12 +10175,12 @@ }, { "name": "OuiSelectChange", - "id": "class-OuiSelectChange-d85db46eab36d315c1fdcd891bdac570b57a0ccdc711e79255f204f23073d94dc6b0707254460df0585b83b8338fb5a5a8a9bcb9d49bc6bf529c53c663cbdac2", + "id": "class-OuiSelectChange-69627b742fec8101b0c412f353bb903b4d499f0f8291080ef1d6ac0c418484f2235fec3981e84104b948fe2f242b0a29fea2c39687b9ed9b01e6aa4fcda7ba37", "file": "ui/src/components/select/select.component.ts", "deprecated": false, "deprecationMessage": "", "type": "class", - "sourceCode": "import { ActiveDescendantKeyManager, FocusMonitor } from '@angular/cdk/a11y';\nimport { Directionality } from '@angular/cdk/bidi';\nimport { coerceBooleanProperty } from '@angular/cdk/coercion';\nimport { SelectionModel } from '@angular/cdk/collections';\nimport {\n A,\n DOWN_ARROW,\n END,\n ENTER,\n HOME,\n LEFT_ARROW,\n RIGHT_ARROW,\n SPACE,\n UP_ARROW,\n hasModifierKey,\n TAB,\n} from '@angular/cdk/keycodes';\nimport { CdkConnectedOverlay } from '@angular/cdk/overlay';\nimport {\n AfterContentInit,\n Attribute,\n ChangeDetectionStrategy,\n ChangeDetectorRef,\n Component,\n ContentChild,\n ContentChildren,\n Directive,\n DoCheck,\n ElementRef,\n EventEmitter,\n Input,\n isDevMode,\n NgZone,\n OnChanges,\n OnDestroy,\n OnInit,\n Optional,\n Output,\n QueryList,\n Self,\n SimpleChanges,\n ViewChild,\n ViewEncapsulation,\n Inject,\n} from '@angular/core';\nimport {\n ControlValueAccessor,\n FormGroupDirective,\n NgControl,\n NgForm,\n} from '@angular/forms';\nimport {\n _countGroupLabelsBeforeOption,\n _getOptionScrollPosition,\n CanDisable,\n CanDisableCtor,\n CanUpdateErrorState,\n CanUpdateErrorStateCtor,\n HasTabIndex,\n HasTabIndexCtor,\n OuiOptionSelectionChange,\n mixinErrorState,\n mixinTabIndex,\n mixinDisabled,\n} from '../core';\nimport { OuiFormField, OuiFormFieldControl } from '../form-field/public-api';\nimport { DOCUMENT } from '@angular/common';\nimport { OUI_OPTION_PARENT_COMPONENT, OuiOption } from '../core/option/option';\nimport { OuiOptgroup } from '../core/option/optgroup';\nimport { ErrorStateMatcher } from '../core/error/error-options';\nimport { defer, merge, Observable, Subject } from 'rxjs';\nimport {\n distinctUntilChanged,\n filter,\n map,\n startWith,\n switchMap,\n take,\n takeUntil,\n} from 'rxjs/operators';\nimport {\n getOuiSelectDynamicMultipleError,\n getOuiSelectNonArrayValueError,\n getOuiSelectNonFunctionValueError,\n} from './select-errors';\nimport { OuiIconRegistry } from '../icon/icon-registery';\nimport { DomSanitizer } from '@angular/platform-browser';\nimport { ICONS } from '../core/shared/icons';\n\nlet nextUniqueId = 0;\n\n/**\n * The following style constants are necessary to save here in order\n * to properly calculate the alignment of the selected option over\n * the trigger element.\n */\n\n/** The height of each select option. */\nexport const SELECT_OPTION_HEIGHT = 40;\n\n/** The panel's padding on the x-axis */\nexport const SELECT_PANEL_PADDING_X = 16;\n\n/** The panel's x axis padding if it is indented (e.g. there is an option group). */\nexport const SELECT_PANEL_INDENT_PADDING_X = SELECT_PANEL_PADDING_X * 2;\n\n/** The height of the select items in `em` units. */\nexport const SELECT_ITEM_HEIGHT_EM = 3;\n\n/** The total height of the select panel. */\nexport const SELECT_PANEL_HEIGHT = 200;\n\n// TODO(josephperrott): Revert to a constant after 2018 spec updates are fully merged.\n/**\n * Distance between the panel edge and the option text in\n * multi-selection mode.\n *\n * Calculated as:\n * (SELECT_PANEL_PADDING_X * 1.5) + 20 = 44\n * The padding is multiplied by 1.5 because the checkbox's margin is half the padding.\n * The checkbox width is 16px.\n */\nexport let SELECT_MULTIPLE_PANEL_PADDING_X = 0;\n\n/**\n * The select panel will only \"fit\" inside the viewport if it is positioned at\n * this value or more away from the viewport boundary.\n */\nexport const SELECT_PANEL_VIEWPORT_PADDING = 8;\n\n/** Change event object that is emitted when the select value has changed. */\nexport class OuiSelectChange {\n constructor(\n /** Reference to the select that emitted the change event. */\n public source: OuiSelect,\n /** Current value of the select that emitted the event. */\n public value: any\n ) {}\n}\n\n// Boilerplate for applying mixins to OuiSelect.\n/** @docs-private */\nexport class OuiSelectBase {\n constructor(\n public _elementRef: ElementRef,\n public _defaultErrorStateMatcher: ErrorStateMatcher,\n public _parentForm: NgForm,\n public _parentFormGroup: FormGroupDirective,\n public ngControl: NgControl\n ) {}\n}\n\nexport const _OuiSelectMixinBase: CanDisableCtor &\n HasTabIndexCtor &\n CanUpdateErrorStateCtor &\n typeof OuiSelectBase = mixinTabIndex(\n mixinDisabled(mixinErrorState(OuiSelectBase))\n);\n\n/**\n * Allows the user to customize the trigger that is displayed when the select has a value.\n */\n@Directive({\n // eslint-disable-next-line @angular-eslint/directive-selector\n selector: 'oui-select-trigger',\n})\nexport class OuiSelectTrigger {}\n\n@Component({\n selector: 'oui-select',\n exportAs: 'ouiSelect',\n templateUrl: 'select.html',\n styleUrls: ['select.scss'],\n // eslint-disable-next-line @angular-eslint/no-inputs-metadata-property\n inputs: ['disabled', 'tabIndex'],\n encapsulation: ViewEncapsulation.None,\n changeDetection: ChangeDetectionStrategy.OnPush,\n // eslint-disable-next-line @angular-eslint/no-host-metadata-property\n host: {\n role: 'listbox',\n '[attr.id]': 'id',\n '[attr.tabindex]': 'tabIndex',\n '[attr.aria-label]': '_getAriaLabel()',\n '[attr.aria-labelledby]': '_getAriaLabelledby()',\n '[attr.aria-required]': 'required.toString()',\n '[attr.aria-disabled]': 'disabled.toString()',\n '[attr.aria-invalid]': 'errorState',\n '[attr.aria-owns]': 'panelOpen ? _optionIds : null',\n '[attr.aria-multiselectable]': 'multiple',\n '[attr.aria-describedby]': '_ariaDescribedby || null',\n '[attr.aria-activedescendant]': '_getAriaActiveDescendant()',\n '[class.oui-select-disabled]': 'disabled',\n '[class.oui-select-invalid]': 'errorState',\n '[class.oui-select-required]': 'required',\n '[class.oui-select-empty]': 'empty',\n class: 'oui-select oui-input',\n '(keydown)': '_handleKeydown($event)',\n '(focus)': '_onFocus()',\n '(blur)': '_onBlur()',\n },\n providers: [\n { provide: OuiFormFieldControl, useExisting: OuiSelect },\n { provide: OUI_OPTION_PARENT_COMPONENT, useExisting: OuiSelect },\n ],\n})\nexport class OuiSelect\n extends _OuiSelectMixinBase\n implements\n AfterContentInit,\n OnChanges,\n OnDestroy,\n OnInit,\n DoCheck,\n ControlValueAccessor,\n CanDisable,\n HasTabIndex,\n OuiFormFieldControl,\n CanUpdateErrorState\n{\n /**Holds selected values after done */\n @Input() savedValues = [];\n /**Done button disabled until dropdown is dirty */\n disableDoneButton = true;\n /** Whether or not the overlay panel is open. */\n private _panelOpen = false;\n\n /** Whether filling out the select is required in the form. */\n private _required = false;\n\n /** Whether filling out the select is required in the form. */\n private _actionItems = false;\n\n /** The scroll position of the overlay panel, calculated to center the selected option. */\n private _scrollTop = 0;\n\n /** The placeholder displayed in the trigger of the select. */\n private _placeholder: string;\n\n /** Whether the component is in multiple selection mode. */\n private _multiple = false;\n\n /** Search input field **/\n isSearchFieldPresent: boolean;\n\n /** Unique id for this input. */\n private _uid = `oui-select-${nextUniqueId++}`;\n\n /** The last measured value for the trigger's client bounding rect. */\n _triggerRect: ClientRect;\n\n /** The aria-describedby attribute on the select for improved a11y. */\n _ariaDescribedby: string;\n\n /** The cached font-size of the trigger element. */\n _triggerFontSize = 0;\n\n /** Deals with the selection logic. */\n _selectionModel: SelectionModel;\n\n /** Manages keyboard events for options in the panel. */\n _keyManager: ActiveDescendantKeyManager;\n\n /** The IDs of child options to be passed to the aria-owns attribute. */\n _optionIds = '';\n\n /** The value of the select panel's transform-origin property. */\n _transformOrigin = 'top';\n\n /** If there is search input field a class is added dynamically to the perfect scrollbar **/\n ouiSelectInputOuterClassName: string;\n\n /** Adding top class to overlay panel */\n cdkConnectionOverlayPanel = '';\n\n /**\n * The y-offset of the overlay panel in relation to the trigger's top start corner.\n * This must be adjusted to align the selected option text over the trigger text.\n * when the panel opens. Will change based on the y-position of the selected option.\n */\n _offsetY = 0;\n\n /**\n * This position config ensures that the top \"start\" corner of the overlay\n * is aligned with with the top \"start\" of the origin by default (overlapping\n * the trigger completely). If the panel cannot fit below the trigger, it\n * will fall back to a position above the trigger.\n */\n _positions = [\n {\n originX: 'start',\n originY: 'top',\n overlayX: 'start',\n overlayY: 'top',\n },\n {\n originX: 'start',\n originY: 'bottom',\n overlayX: 'start',\n overlayY: 'bottom',\n },\n ];\n /** Emits whenever the component is destroyed. */\n private readonly _destroy = new Subject();\n\n /** Whether the component is disabling centering of the active option over the trigger. */\n private _disableOptionCentering = false;\n\n private _focused = false;\n\n /** A name for this control that can be used by `oui-form-field`. */\n controlType = 'oui-select';\n\n /** Trigger that opens the select. */\n @ViewChild('trigger') trigger: ElementRef;\n\n /** Trigger that opens the select. */\n @ViewChild('ddCancelButton', { read: ElementRef }) ddCancelButton: ElementRef;\n\n /** Trigger that opens the select. */\n @ViewChild('ddDoneButton', { read: ElementRef }) ddDoneButton: ElementRef;\n\n /** Panel containing the select options. */\n @ViewChild('panel', { read: ElementRef }) panel: ElementRef;\n\n private _value: any;\n\n /**\n * Function used to sort the values in a select in multiple mode.\n * Follows the same logic as `Array.prototype.sort`.\n */\n @Input() sortComparator: (\n a: OuiOption,\n b: OuiOption,\n options: OuiOption[]\n ) => number;\n\n /** Aria label of the select. If not specified, the placeholder will be used as label. */\n @Input('aria-label') ariaLabel = '';\n\n /** Input that can be used to specify the `aria-labelledby` attribute. */\n @Input('aria-labelledby') ariaLabelledby: string;\n private _large = false;\n _monitorSubscription: any;\n\n /** Whether the oui-select is of large size. */\n @Input()\n get large(): boolean {\n return this._large;\n }\n set large(value) {\n this._large = coerceBooleanProperty(value);\n this._changeDetectorRef.markForCheck();\n }\n\n private _id: string;\n\n /** Event emitted when the select panel has been toggled. */\n @Output()\n readonly openedChange: EventEmitter = new EventEmitter();\n\n /** Combined stream of all of the child options' change events. */\n readonly optionSelectionChanges: Observable = defer(\n (): Observable => {\n if (this.options) {\n return merge(...this.options.map((option) => option.onSelectionChange));\n }\n\n return this._ngZone.onStable.asObservable().pipe(\n take(1),\n switchMap(() => this.optionSelectionChanges)\n );\n }\n );\n\n /**\n * Event that emits whenever the raw value of the select changes. This is here primarily\n * to facilitate the two-way binding for the `value` input.\n *\n * @docs-private\n */\n @Output() readonly valueChange: EventEmitter = new EventEmitter();\n\n /** Object used to control when error messages are shown. */\n @Input() errorStateMatcher: ErrorStateMatcher;\n\n /** All of the defined select options. */\n @ContentChildren(OuiOption, { descendants: true })\n options: QueryList;\n\n /** Event emitted when the select has been opened. */\n // eslint-disable-next-line @angular-eslint/no-output-rename\n @Output('opened')\n readonly _openedStream: Observable = this.openedChange.pipe(\n filter((o) => o),\n map(() => {})\n );\n\n /** Event emitted when the select has been closed. */\n // eslint-disable-next-line @angular-eslint/no-output-rename\n @Output('closed')\n readonly _closedStream: Observable = this.openedChange.pipe(\n filter((o) => !o),\n map(() => {\n this.isSearchFieldPresent = false;\n })\n );\n\n /** Event emitted when the selected value has been changed by the user. */\n @Output()\n readonly selectionChange: EventEmitter =\n new EventEmitter();\n\n /** Event emitted when the selected value has been changed and saved by the user. */\n @Output()\n readonly saveSelectionChange: EventEmitter =\n new EventEmitter();\n\n /** All of the defined groups of options. */\n @ContentChildren(OuiOptgroup) optionGroups: QueryList;\n\n /** User-supplied override of the trigger element. */\n @ContentChild(OuiSelectTrigger)\n customTrigger: OuiSelectTrigger;\n\n /** Classes to be passed to the select panel. Supports the same syntax as `ngClass`. */\n @Input() panelClass: string | string[] | Set | { [key: string]: any };\n\n /** Overlay pane containing the options. */\n @ViewChild(CdkConnectedOverlay)\n overlayDir: CdkConnectedOverlay;\n\n /** Emits when the panel element is finished transforming in. */\n _panelDoneAnimatingStream = new Subject();\n\n /** Comparison function to specify which option is displayed. Defaults to object equality. */\n private _compareWith = (o1: any, o2: any) => o1 === o2;\n\n /** Whether the select is focused. */\n get focused(): boolean {\n return this._focused || this._panelOpen;\n }\n /**\n * @deprecated Setter to be removed as this property is intended to be readonly.\n */\n set focused(value: boolean) {\n this._focused = value;\n }\n /** `View -> model callback called when value changes` */\n _onChange: (value: any) => void = () => {};\n\n /** `View -> model callback called when select has been touched` */\n _onTouched = () => {};\n\n /** Placeholder to be shown if no value has been selected. */\n @Input()\n get placeholder(): string {\n return this._placeholder;\n }\n set placeholder(value: string) {\n this._placeholder = value;\n this.stateChanges.next();\n }\n\n /** Whether the component is required. */\n @Input()\n get required(): boolean {\n return this._required;\n }\n set required(value: boolean) {\n this._required = coerceBooleanProperty(value);\n this.stateChanges.next();\n }\n\n /** Whether the user should be allowed to select multiple options. */\n @Input()\n get multiple(): boolean {\n return this._multiple;\n }\n set multiple(value: boolean) {\n if (this._selectionModel) {\n throw getOuiSelectDynamicMultipleError();\n }\n\n this._multiple = coerceBooleanProperty(value);\n }\n\n /** Whether the action items are required and use saveSelectionChange instead of selectionChange. */\n @Input()\n get actionItems(): boolean {\n return this._actionItems;\n }\n set actionItems(value: boolean) {\n if (this._multiple) {\n this._actionItems = coerceBooleanProperty(value);\n this.stateChanges.next();\n }\n }\n\n /** Whether to center the active option over the trigger. */\n @Input()\n get disableOptionCentering(): boolean {\n return this._disableOptionCentering;\n }\n set disableOptionCentering(value: boolean) {\n this._disableOptionCentering = coerceBooleanProperty(value);\n }\n\n /**\n * Function to compare the option values with the selected values. The first argument\n * is a value from an option. The second is a value from the selection. A boolean\n * should be returned.\n */\n @Input()\n get compareWith() {\n return this._compareWith;\n }\n set compareWith(fn: (o1: any, o2: any) => boolean) {\n if (typeof fn !== 'function') {\n throw getOuiSelectNonFunctionValueError();\n }\n this._compareWith = fn;\n if (this._selectionModel) {\n // A different comparator means the selection could change.\n this._initializeSelection();\n }\n }\n\n /** Value of the select control. */\n @Input()\n get value(): any {\n return this._value;\n }\n set value(newValue: any) {\n if (newValue !== this._value) {\n this.writeValue(newValue);\n this._value = newValue;\n }\n }\n\n /** Unique id of the element. */\n @Input()\n get id(): string {\n return this._id;\n }\n set id(value: string) {\n this._id = value || this._uid;\n this.stateChanges.next();\n }\n\n constructor(\n private _changeDetectorRef: ChangeDetectorRef,\n private _ngZone: NgZone,\n _defaultErrorStateMatcher: ErrorStateMatcher,\n elementRef: ElementRef,\n private _focusMonitor: FocusMonitor,\n @Optional() private _dir: Directionality,\n @Optional() _parentForm: NgForm,\n @Optional() _parentFormGroup: FormGroupDirective,\n @Optional() private _parentFormField: OuiFormField,\n @Self() @Optional() public ngControl: NgControl,\n @Attribute('tabindex') tabIndex: string,\n @Optional() @Inject(DOCUMENT) private _document: any,\n public _elementRef: ElementRef,\n public _ouiIconRegistry: OuiIconRegistry,\n private _domSanitizer: DomSanitizer\n ) {\n super(\n elementRef,\n _defaultErrorStateMatcher,\n _parentForm,\n _parentFormGroup,\n ngControl\n );\n this._monitorSubscription = this._focusMonitor\n .monitor(this._elementRef, true)\n .subscribe(() => this._ngZone.run(() => {}));\n this._ouiIconRegistry.addSvgIconLiteral(\n `select-arrow-icon`,\n this._domSanitizer.bypassSecurityTrustHtml(ICONS.SELECT_ARROW_ICON)\n );\n\n if (this.ngControl) {\n // Note: we provide the value accessor through here, instead of\n // the `providers` to avoid running into a circular import.\n this.ngControl.valueAccessor = this;\n }\n\n this.tabIndex = parseInt(tabIndex, 10) || 0;\n\n // Force setter to be called in case id was not specified.\n this.id = this.id;\n }\n\n ngOnInit() {\n this._selectionModel = new SelectionModel(this.multiple);\n this.stateChanges.next();\n\n // We need `distinctUntilChanged` here, because some browsers will\n // fire the animation end event twice for the same animation. See:\n // https://github.com/angular/angular/issues/24084\n this._panelDoneAnimatingStream\n .pipe(distinctUntilChanged(), takeUntil(this._destroy))\n .subscribe(() => {\n if (this.panelOpen) {\n this._scrollTop = 0;\n this.openedChange.emit(true);\n } else {\n this.openedChange.emit(false);\n this.overlayDir.offsetX = 0;\n this._changeDetectorRef.markForCheck();\n }\n });\n }\n\n ngAfterContentInit() {\n this._initKeyManager();\n\n this._selectionModel.changed\n .pipe(takeUntil(this._destroy))\n .subscribe((event) => {\n event.added.forEach((option) => option.select());\n event.removed.forEach((option) => option.deselect());\n });\n\n this.options.changes\n .pipe(startWith(null), takeUntil(this._destroy))\n .subscribe(() => {\n this._resetOptions();\n this._initializeSelection();\n });\n }\n\n ngDoCheck() {\n if (this.ngControl) {\n this.updateErrorState();\n }\n }\n\n ngOnChanges(changes: SimpleChanges) {\n // Updating the disabled state is handled by `mixinDisabled`, but we need to additionally let\n // the parent form field know to run change detection when the disabled state changes.\n if (changes.disabled) {\n this.stateChanges.next();\n }\n }\n\n ngOnDestroy() {\n this._monitorSubscription.unsubscribe();\n this._focusMonitor.stopMonitoring(this._elementRef);\n this._destroy.next();\n this._destroy.complete();\n this.stateChanges.complete();\n }\n\n /** Toggles the overlay panel open or closed. */\n toggle(): void {\n this.panelOpen ? this.close() : this.open();\n }\n\n /** Opens the overlay panel. */\n open(): void {\n if (\n this.disabled ||\n !this.options ||\n !this.options.length ||\n this._panelOpen\n ) {\n return;\n }\n\n this._triggerRect = this.trigger.nativeElement.getBoundingClientRect();\n\n this._panelOpen = true;\n this._keyManager.withHorizontalOrientation(null);\n\n this._highlightCorrectOption();\n this._changeDetectorRef.markForCheck();\n this.openedChange.emit(true);\n this._elementRef.nativeElement.classList.add(\n 'oui-select-list-options-opened'\n );\n }\n\n /** Closes the overlay panel and focuses the host element. */\n close(): void {\n if (this._panelOpen) {\n this._panelOpen = false;\n this._keyManager.withHorizontalOrientation(this._isRtl() ? 'rtl' : 'ltr');\n this._changeDetectorRef.markForCheck();\n this._onTouched();\n this.openedChange.emit(false);\n this._elementRef.nativeElement.classList.remove(\n 'oui-select-list-options-opened'\n );\n setTimeout((_) => this._document.activeElement.blur());\n }\n }\n\n /**\n * Sets the select's value. Part of the ControlValueAccessor interface\n * required to integrate with Angular's core forms API.\n *\n * @param value New value to be written to the model.\n */\n writeValue(value: any): void {\n if (this.options) {\n this._setSelectionByValue(value);\n }\n }\n\n /**\n * Saves a callback function to be invoked when the select's value\n * changes from user input. Part of the ControlValueAccessor interface\n * required to integrate with Angular's core forms API.\n *\n * @param fn Callback to be triggered when the value changes.\n */\n registerOnChange(fn: (value: any) => void): void {\n this._onChange = fn;\n }\n\n /**\n * Saves a callback function to be invoked when the select is blurred\n * by the user. Part of the ControlValueAccessor interface required\n * to integrate with Angular's core forms API.\n *\n * @param fn Callback to be triggered when the component has been touched.\n */\n registerOnTouched(fn: () => {}): void {\n this._onTouched = fn;\n }\n\n /**\n * Disables the select. Part of the ControlValueAccessor interface required\n * to integrate with Angular's core forms API.\n *\n * @param isDisabled Sets whether the component is disabled.\n */\n setDisabledState(isDisabled: boolean): void {\n this.disabled = isDisabled;\n this._changeDetectorRef.markForCheck();\n this.stateChanges.next();\n }\n\n /** Whether or not the overlay panel is open. */\n get panelOpen(): boolean {\n return this._panelOpen;\n }\n\n /** The currently selected option. */\n get selected(): OuiOption | OuiOption[] {\n return this.multiple\n ? this._selectionModel.selected\n : this._selectionModel.selected[0];\n }\n\n /** The value displayed in the trigger. */\n get triggerValue(): string {\n if (this.empty) {\n return '';\n }\n if (this._multiple) {\n const selectedOptions = this._selectionModel.selected.map(\n (option) => option.viewValueForSelect\n );\n\n if (this._isRtl()) {\n selectedOptions.reverse();\n }\n return selectedOptions.join(', ');\n }\n return this._selectionModel.selected[0].viewValueForSelect;\n }\n\n /** Whether the element is in RTL mode. */\n _isRtl(): boolean {\n return this._dir ? this._dir.value === 'rtl' : false;\n }\n\n /** Handles all keydown events on the select. */\n _handleKeydown(event: KeyboardEvent): void {\n if (!this.disabled) {\n this.panelOpen\n ? this._handleOpenKeydown(event)\n : this._handleClosedKeydown(event);\n }\n }\n\n /** Handles keyboard events while the select is closed. */\n private _handleClosedKeydown(event: KeyboardEvent): void {\n const keyCode = event.keyCode;\n const isArrowKey =\n keyCode === DOWN_ARROW ||\n keyCode === UP_ARROW ||\n keyCode === LEFT_ARROW ||\n keyCode === RIGHT_ARROW;\n const isOpenKey = keyCode === ENTER || keyCode === SPACE;\n const manager = this._keyManager;\n\n // Open the select on ALT + arrow key to match the native \n event.preventDefault();\n this.close();\n } else if (\n (keyCode === ENTER || keyCode === SPACE) &&\n manager.activeItem &&\n !hasModifierKey(event)\n ) {\n event.preventDefault();\n manager.activeItem._selectViaInteraction();\n } else if (this._multiple && keyCode === A && event.ctrlKey) {\n event.preventDefault();\n this.handleCtrlKey();\n } else if (normalNavigationCheck) {\n // Check for non multiple select dropdown that the key pressed is not Tab, Space, Enter\n if (!this.isSearchFieldPresent) this.focus();\n this.handleScrolling(manager, event, isArrowKey, keyCode);\n }\n }\n\n /**\n * Handle ctrl key\n */\n private handleCtrlKey() {\n const hasDeselectedOptions = this.options.some(\n (opt) => !opt.disabled && !opt.selected\n );\n\n this.options.forEach((option) => {\n if (!option.disabled) {\n hasDeselectedOptions ? option.select() : option.deselect();\n }\n });\n }\n\n /**\n * @param manager\n * @param event\n * @param isArrowKey\n * @param keyCode\n */\n private handleScrolling(\n manager: ActiveDescendantKeyManager,\n event: KeyboardEvent,\n isArrowKey: boolean,\n keyCode: number\n ) {\n const previouslyFocusedIndex = manager.activeItemIndex;\n\n manager.onKeydown(event);\n\n if (\n this._multiple &&\n isArrowKey &&\n event.shiftKey &&\n manager.activeItem &&\n manager.activeItemIndex !== previouslyFocusedIndex\n ) {\n manager.activeItem._selectViaInteraction();\n }\n if (isArrowKey && manager.activeItemIndex !== previouslyFocusedIndex) {\n this._scrollToOption();\n } else {\n // First or last\n if (keyCode === DOWN_ARROW) {\n manager.setFirstItemActive();\n this._setScrollTop(0);\n }\n if (keyCode === UP_ARROW) {\n manager.setLastItemActive();\n this._scrollToOption();\n }\n }\n }\n\n _onFocus() {\n if (!this.disabled) {\n this._focused = true;\n this.stateChanges.next();\n }\n }\n\n /**\n * Calls the touched callback only if the panel is closed. Otherwise, the trigger will\n * \"blur\" to the panel when it opens, causing a false positive.\n */\n _onBlur() {\n this._focused = false;\n // this.isSearchFieldPresent = false;\n\n if (!this.disabled && !this.panelOpen) {\n this._onTouched();\n this._changeDetectorRef.markForCheck();\n this.stateChanges.next();\n }\n }\n\n /**\n * Callback that is invoked when the overlay panel has been attached.\n */\n _onAttached(): void {\n this.overlayDir.positionChange.pipe(take(1)).subscribe(() => {\n this._setPseudoCheckboxPaddingSize();\n this._changeDetectorRef.detectChanges();\n this.panel.nativeElement.scrollTop = this._scrollTop;\n });\n }\n\n /** Returns the theme to be used on the panel. */\n _getPanelTheme(): string {\n return this._parentFormField ? `oui-${this._parentFormField.color}` : '';\n }\n\n // TODO(josephperrott): Remove after 2018 spec updates are fully merged.\n /** Sets the pseudo checkbox padding size based on the width of the pseudo checkbox. */\n private _setPseudoCheckboxPaddingSize() {\n if (!SELECT_MULTIPLE_PANEL_PADDING_X && this.multiple) {\n const pseudoCheckbox = this.panel.nativeElement.querySelector(\n '.oui-pseudo-checkbox'\n );\n if (pseudoCheckbox) {\n SELECT_MULTIPLE_PANEL_PADDING_X =\n SELECT_PANEL_PADDING_X * 1.5 + pseudoCheckbox.offsetWidth;\n }\n }\n }\n\n /** Whether the select has a value. */\n get empty(): boolean {\n return !this._selectionModel || this._selectionModel.isEmpty();\n }\n\n private _initializeSelection(): void {\n // Defer setting the value in order to avoid the \"Expression\n // has changed after it was checked\" errors from Angular.\n Promise.resolve().then(() => {\n this._setSelectionByValue(\n this.ngControl ? this.ngControl.value : this._value\n );\n this.savedValues = this.ngControl ? this.ngControl.value : this._value;\n if (this.multiple) {\n this._highlightFirstFilteredOption();\n }\n });\n }\n\n /**\n * Sets the selected option based on a value. If no option can be\n * found with the designated value, the select trigger is cleared.\n */\n private _setSelectionByValue(value: any | any[]): void {\n if (this.multiple && value) {\n if (!Array.isArray(value)) {\n throw getOuiSelectNonArrayValueError();\n }\n\n this._selectionModel.clear();\n value.forEach((currentValue: any) => this._selectValue(currentValue));\n this._sortValues();\n } else {\n this._selectionModel.clear();\n const correspondingOption = this._selectValue(value);\n // Shift focus to the active item. Note that we shouldn't do this in multiple\n // mode, because we don't know what option the user interacted with last.\n if (correspondingOption) {\n this._keyManager.setActiveItem(correspondingOption);\n }\n }\n this._changeDetectorRef.markForCheck();\n }\n\n /**\n * Finds and selects and option based on its value.\n *\n * @returns Option that has the corresponding value.\n */\n private _selectValue(value: any): OuiOption | undefined {\n const correspondingOption = this.options.find((option: OuiOption) => {\n try {\n // Treat null as a special reset value.\n return option.value != null && this._compareWith(option.value, value);\n } catch (error) {\n if (isDevMode()) {\n // Notify developers of errors in their comparator.\n console.warn(error);\n }\n return false;\n }\n });\n\n if (correspondingOption) {\n this._selectionModel.select(correspondingOption);\n }\n\n return correspondingOption;\n }\n\n /** Sets up a key manager to listen to keyboard events on the overlay panel. */\n private _initKeyManager() {\n this._keyManager = new ActiveDescendantKeyManager(this.options)\n .withTypeAhead()\n .withVerticalOrientation()\n .withHorizontalOrientation(this._isRtl() ? 'rtl' : 'ltr')\n .withAllowedModifierKeys(['shiftKey']);\n\n this._keyManager.tabOut.pipe(takeUntil(this._destroy)).subscribe(() => {\n // Restore focus to the trigger before closing. Ensures that the focus\n // position won't be lost if the user got focus into the overlay.\n this.focus();\n this.close();\n });\n\n this._keyManager.change.pipe(takeUntil(this._destroy)).subscribe(() => {\n if (this._panelOpen && this.panel) {\n // Panel is opened\n // Need not to scroll\n } else if (\n !this._panelOpen &&\n !this.multiple &&\n this._keyManager.activeItem\n ) {\n this._keyManager.activeItem._selectViaInteraction();\n }\n });\n }\n\n /** Drops current option subscriptions and IDs and resets from scratch. */\n private _resetOptions(): void {\n const changedOrDestroyed = merge(this.options.changes, this._destroy);\n\n this.optionSelectionChanges\n .pipe(takeUntil(changedOrDestroyed))\n .subscribe((event) => {\n this._onSelect(event.source, event.isUserInput);\n\n if (event.isUserInput && !this.multiple && this._panelOpen) {\n this.close();\n this.focus();\n }\n });\n\n // Listen to changes in the internal state of the options and react accordingly.\n // Handles cases like the labels of the selected options changing.\n merge(...this.options.map((option) => option._stateChanges))\n .pipe(takeUntil(changedOrDestroyed))\n .subscribe(() => {\n this._changeDetectorRef.markForCheck();\n this.stateChanges.next();\n });\n\n this._setOptionIds();\n }\n\n /** Invoked when an option is clicked. */\n private _onSelect(option: OuiOption, isUserInput: boolean): void {\n const wasSelected = this._selectionModel.isSelected(option);\n\n if (option.value == null && !this._multiple) {\n option.deselect();\n this._selectionModel.clear();\n this._propagateChanges(option.value);\n } else {\n option.selected\n ? this._selectionModel.select(option)\n : this._selectionModel.deselect(option);\n\n if (isUserInput) {\n this._keyManager.setActiveItem(option);\n }\n\n if (this.multiple) {\n this._sortValues();\n\n if (isUserInput) {\n // In case the user selected the option with their mouse, we\n // want to restore focus back to the trigger, in order to\n // prevent the select keyboard controls from clashing with\n // the ones from `oui-option`.\n this.focus();\n }\n }\n }\n\n if (wasSelected !== this._selectionModel.isSelected(option)) {\n this._propagateChanges();\n }\n this.disableDoneButton = false;\n this.stateChanges.next();\n }\n discardRecentChanges() {\n this.value = this.savedValues;\n this._setSelectionByValue(this.value);\n this.disableDoneButton = true;\n this.close();\n }\n doneRecentChanges() {\n this.savedValues = this.value;\n this.disableDoneButton = true;\n this.saveSelectionChange.emit(new OuiSelectChange(this, this.value));\n this.close();\n }\n /** Sorts the selected values in the selected based on their order in the panel. */\n private _sortValues() {\n if (this.multiple) {\n const options = this.options.toArray();\n\n this._selectionModel.sort((a, b) =>\n this.sortComparator\n ? this.sortComparator(a, b, options)\n : options.indexOf(a) - options.indexOf(b)\n );\n this.stateChanges.next();\n }\n }\n\n /** Emits change event to set the model value. */\n private _propagateChanges(fallbackValue?: any): void {\n let valueToEmit: any = null;\n\n if (this.multiple) {\n valueToEmit = (this.selected as OuiOption[]).map(\n (option) => option.value\n );\n } else {\n valueToEmit = this.selected\n ? (this.selected as OuiOption).value\n : fallbackValue;\n }\n\n this._value = valueToEmit;\n this.valueChange.emit(valueToEmit);\n this._onChange(valueToEmit);\n this.selectionChange.emit(new OuiSelectChange(this, valueToEmit));\n this._changeDetectorRef.markForCheck();\n }\n\n /** Records option IDs to pass to the aria-owns property. */\n private _setOptionIds() {\n this._optionIds = this.options.map((option) => option.id).join(' ');\n }\n\n /**\n * Highlights the selected item. If no option is selected, it will highlight\n * the first item instead.\n */\n private _highlightCorrectOption(): void {\n if (this.multiple) {\n this._highlightFirstFilteredOption();\n } else if (this._keyManager) {\n if (this.empty) {\n this._keyManager.setFirstItemActive();\n } else {\n this._keyManager.setActiveItem(this._selectionModel.selected[0]);\n }\n }\n }\n\n /**\n * Highlights the first of the filtered options if no element is currently highlighted\n */\n private _highlightFirstFilteredOption(): void {\n if (this._keyManager) {\n const activeElement = this._keyManager.activeItem?._getHostElement();\n // activeElement is not part of DOM if there is no parent element\n if (!activeElement || !activeElement.parentElement) {\n // highlight first element if there is no active element or active element is not part of DOM\n this._keyManager.setFirstItemActive();\n }\n }\n }\n\n /** Focuses the select element. */\n focus(): void {\n this._elementRef.nativeElement.focus();\n }\n\n /** Returns the aria-label of the select component. */\n _getAriaLabel(): string | null {\n // If an ariaLabelledby value has been set by the consumer, the select should not overwrite the\n // `aria-labelledby` value by setting the ariaLabel to the placeholder.\n return this.ariaLabelledby ? null : this.ariaLabel || this.placeholder;\n }\n\n /** Returns the aria-labelledby of the select component. */\n _getAriaLabelledby(): string | null {\n if (this.ariaLabelledby) {\n return this.ariaLabelledby;\n }\n\n return null;\n }\n\n /** Determines the `aria-activedescendant` to be set on the host. */\n _getAriaActiveDescendant(): string | null {\n if (this.panelOpen && this._keyManager && this._keyManager.activeItem) {\n return this._keyManager.activeItem.id;\n }\n\n return null;\n }\n\n /**\n * Implemented as part of OuiFormFieldControl.\n *\n * @docs-private\n */\n setDescribedByIds(ids: string[]) {\n this._ariaDescribedby = ids.join(' ');\n }\n\n /**\n * Implemented as part of OuiFormFieldControl.\n *\n * @docs-private\n */\n onContainerClick() {\n this.focus();\n this.open();\n }\n\n /**\n * Implemented as part of OuiFormFieldControl.\n *\n * @docs-private\n */\n get shouldLabelFloat(): boolean {\n return this._panelOpen || !this.empty;\n }\n\n /**\n * Add outer class to perfect scrollbar\n * This is added only when there is a search field\n */\n ouiSelectInputOuter() {\n this.ouiSelectInputOuterClassName = 'oui-select-input-outer';\n }\n\n /**\n * Custom overlay class for cdk overlay container\n */\n openCdk() {\n this.overlayDir.positionChange.pipe(take(1)).subscribe((e) => {\n this.cdkConnectionOverlayPanel = '';\n if (e.connectionPair.originY === 'top') {\n this.cdkConnectionOverlayPanel = 'select-overlay-top';\n }\n this._changeDetectorRef.detectChanges();\n setTimeout((_) => this._scrollToOption());\n });\n\n const cdkOverLayContainer = this._document.querySelector(\n '.cdk-overlay-container'\n );\n const ouiSelectPanel = this._document.querySelector('.oui-select-panel');\n cdkOverLayContainer.classList.add('oui-select-overlay-container');\n const containerWidth = this._elementRef.nativeElement.offsetWidth;\n ouiSelectPanel.style.width = `${containerWidth}px`;\n const searchQueryString = '.oui-select-search-inner';\n if (this._document.querySelector(searchQueryString)) {\n this.scrollCalc(searchQueryString);\n this.isSearchFieldPresent = true;\n }\n }\n scrollCalc(selectQueryString: string) {\n const searchInput = this._document.querySelector(selectQueryString);\n const outter = this._document.querySelector('.oui-select-panel');\n let inner = this._document.querySelector('.oui-option');\n if (inner === null) {\n inner = 0;\n }\n const scrollbarWidth = outter.offsetWidth - inner.offsetWidth;\n if (scrollbarWidth > 5) {\n searchInput.style.width = `${inner.offsetWidth}px`;\n } else {\n searchInput.style.width = `calc(100% + 8px)`;\n }\n }\n\n /**\n * Given that we are not actually focusing active options, we must manually adjust scroll\n * to reveal options below the fold. First, we find the offset of the option from the top\n * of the panel. If that offset is below the fold, the new scrollTop will be the offset -\n * the panel height + the option height, so the active option will be just visible at the\n * bottom of the panel. If that offset is above the top of the visible panel, the new scrollTop\n * will become the offset. If that offset is visible within the panel already, the scrollTop is\n * not adjusted.\n */\n private _scrollToOption(): void {\n const manager = this._keyManager;\n const index = manager.activeItemIndex || 0;\n const labelCount = _countGroupLabelsBeforeOption(\n index,\n this.options,\n this.optionGroups\n );\n const scrollTop = this._getScrollTop();\n const newScrollPosition = _getOptionScrollPosition(\n index + labelCount,\n SELECT_OPTION_HEIGHT,\n scrollTop,\n this.actionItems && this.isSearchFieldPresent && labelCount\n ? SELECT_PANEL_HEIGHT - (50 + labelCount * 19)\n : (this.actionItems && this.isSearchFieldPresent && !labelCount) ||\n (this.actionItems && !this.isSearchFieldPresent && labelCount) ||\n (!this.actionItems && this.isSearchFieldPresent && labelCount)\n ? SELECT_PANEL_HEIGHT - 50\n : SELECT_PANEL_HEIGHT\n );\n this._setScrollTop(newScrollPosition);\n }\n\n /**\n * Sets the panel scrollTop. This allows us to manually scroll to display options\n * above or below the fold, as they are not actually being focused when active.\n */\n _setScrollTop(scrollTop: number): void {\n if (this.panel) {\n this.panel.nativeElement.querySelector('.oui-select-options').scrollTop =\n scrollTop;\n }\n }\n\n /** Returns the panel's scrollTop. */\n _getScrollTop(): number {\n return this.panel ? this.panel.nativeElement.scrollTop : 0;\n }\n}\n", + "sourceCode": "import { ActiveDescendantKeyManager, FocusMonitor } from '@angular/cdk/a11y';\r\nimport { Directionality } from '@angular/cdk/bidi';\r\nimport { coerceBooleanProperty } from '@angular/cdk/coercion';\r\nimport { SelectionModel } from '@angular/cdk/collections';\r\nimport {\r\n A,\r\n DOWN_ARROW,\r\n END,\r\n ENTER,\r\n HOME,\r\n LEFT_ARROW,\r\n RIGHT_ARROW,\r\n SPACE,\r\n UP_ARROW,\r\n hasModifierKey,\r\n TAB,\r\n} from '@angular/cdk/keycodes';\r\nimport { CdkConnectedOverlay } from '@angular/cdk/overlay';\r\nimport {\r\n AfterContentInit,\r\n Attribute,\r\n ChangeDetectionStrategy,\r\n ChangeDetectorRef,\r\n Component,\r\n ContentChild,\r\n ContentChildren,\r\n Directive,\r\n DoCheck,\r\n ElementRef,\r\n EventEmitter,\r\n Input,\r\n isDevMode,\r\n NgZone,\r\n OnChanges,\r\n OnDestroy,\r\n OnInit,\r\n Optional,\r\n Output,\r\n QueryList,\r\n Self,\r\n SimpleChanges,\r\n ViewChild,\r\n ViewEncapsulation,\r\n Inject,\r\n} from '@angular/core';\r\nimport {\r\n ControlValueAccessor,\r\n FormGroupDirective,\r\n NgControl,\r\n NgForm,\r\n} from '@angular/forms';\r\nimport {\r\n _countGroupLabelsBeforeOption,\r\n _getOptionScrollPosition,\r\n CanDisable,\r\n CanDisableCtor,\r\n CanUpdateErrorState,\r\n CanUpdateErrorStateCtor,\r\n HasTabIndex,\r\n HasTabIndexCtor,\r\n OuiOptionSelectionChange,\r\n mixinErrorState,\r\n mixinTabIndex,\r\n mixinDisabled,\r\n} from '../core';\r\nimport { OuiFormField, OuiFormFieldControl } from '../form-field/public-api';\r\nimport { DOCUMENT } from '@angular/common';\r\nimport { OUI_OPTION_PARENT_COMPONENT, OuiOption } from '../core/option/option';\r\nimport { OuiOptgroup } from '../core/option/optgroup';\r\nimport { ErrorStateMatcher } from '../core/error/error-options';\r\nimport { defer, merge, Observable, Subject } from 'rxjs';\r\nimport {\r\n distinctUntilChanged,\r\n filter,\r\n map,\r\n startWith,\r\n switchMap,\r\n take,\r\n takeUntil,\r\n} from 'rxjs/operators';\r\nimport {\r\n getOuiSelectDynamicMultipleError,\r\n getOuiSelectNonArrayValueError,\r\n getOuiSelectNonFunctionValueError,\r\n} from './select-errors';\r\nimport { OuiIconRegistry } from '../icon/icon-registery';\r\nimport { DomSanitizer } from '@angular/platform-browser';\r\nimport { ICONS } from '../core/shared/icons';\r\n\r\nlet nextUniqueId = 0;\r\n\r\n/**\r\n * The following style constants are necessary to save here in order\r\n * to properly calculate the alignment of the selected option over\r\n * the trigger element.\r\n */\r\n\r\n/** The height of each select option. */\r\nexport const SELECT_OPTION_HEIGHT = 40;\r\n\r\n/** The panel's padding on the x-axis */\r\nexport const SELECT_PANEL_PADDING_X = 16;\r\n\r\n/** The panel's x axis padding if it is indented (e.g. there is an option group). */\r\nexport const SELECT_PANEL_INDENT_PADDING_X = SELECT_PANEL_PADDING_X * 2;\r\n\r\n/** The height of the select items in `em` units. */\r\nexport const SELECT_ITEM_HEIGHT_EM = 3;\r\n\r\n/** The total height of the select panel. */\r\nexport const SELECT_PANEL_HEIGHT = 200;\r\n\r\n// TODO(josephperrott): Revert to a constant after 2018 spec updates are fully merged.\r\n/**\r\n * Distance between the panel edge and the option text in\r\n * multi-selection mode.\r\n *\r\n * Calculated as:\r\n * (SELECT_PANEL_PADDING_X * 1.5) + 20 = 44\r\n * The padding is multiplied by 1.5 because the checkbox's margin is half the padding.\r\n * The checkbox width is 16px.\r\n */\r\nexport let SELECT_MULTIPLE_PANEL_PADDING_X = 0;\r\n\r\n/**\r\n * The select panel will only \"fit\" inside the viewport if it is positioned at\r\n * this value or more away from the viewport boundary.\r\n */\r\nexport const SELECT_PANEL_VIEWPORT_PADDING = 8;\r\n\r\n/** Change event object that is emitted when the select value has changed. */\r\nexport class OuiSelectChange {\r\n constructor(\r\n /** Reference to the select that emitted the change event. */\r\n public source: OuiSelect,\r\n /** Current value of the select that emitted the event. */\r\n public value: any\r\n ) {}\r\n}\r\n\r\n// Boilerplate for applying mixins to OuiSelect.\r\n/** @docs-private */\r\nexport class OuiSelectBase {\r\n constructor(\r\n public _elementRef: ElementRef,\r\n public _defaultErrorStateMatcher: ErrorStateMatcher,\r\n public _parentForm: NgForm,\r\n public _parentFormGroup: FormGroupDirective,\r\n public ngControl: NgControl\r\n ) {}\r\n}\r\n\r\nexport const _OuiSelectMixinBase: CanDisableCtor &\r\n HasTabIndexCtor &\r\n CanUpdateErrorStateCtor &\r\n typeof OuiSelectBase = mixinTabIndex(\r\n mixinDisabled(mixinErrorState(OuiSelectBase))\r\n);\r\n\r\n/**\r\n * Allows the user to customize the trigger that is displayed when the select has a value.\r\n */\r\n@Directive({\r\n // eslint-disable-next-line @angular-eslint/directive-selector\r\n selector: 'oui-select-trigger',\r\n})\r\nexport class OuiSelectTrigger {}\r\n\r\n@Component({\r\n selector: 'oui-select',\r\n exportAs: 'ouiSelect',\r\n templateUrl: 'select.html',\r\n styleUrls: ['select.scss'],\r\n // eslint-disable-next-line @angular-eslint/no-inputs-metadata-property\r\n inputs: ['disabled', 'tabIndex'],\r\n encapsulation: ViewEncapsulation.None,\r\n changeDetection: ChangeDetectionStrategy.OnPush,\r\n // eslint-disable-next-line @angular-eslint/no-host-metadata-property\r\n host: {\r\n role: 'listbox',\r\n '[attr.id]': 'id',\r\n '[attr.tabindex]': 'tabIndex',\r\n '[attr.aria-label]': '_getAriaLabel()',\r\n '[attr.aria-labelledby]': '_getAriaLabelledby()',\r\n '[attr.aria-required]': 'required.toString()',\r\n '[attr.aria-disabled]': 'disabled.toString()',\r\n '[attr.aria-invalid]': 'errorState',\r\n '[attr.aria-owns]': 'panelOpen ? _optionIds : null',\r\n '[attr.aria-multiselectable]': 'multiple',\r\n '[attr.aria-describedby]': '_ariaDescribedby || null',\r\n '[attr.aria-activedescendant]': '_getAriaActiveDescendant()',\r\n '[class.oui-select-disabled]': 'disabled',\r\n '[class.oui-select-invalid]': 'errorState',\r\n '[class.oui-select-required]': 'required',\r\n '[class.oui-select-empty]': 'empty',\r\n class: 'oui-select oui-input',\r\n '(keydown)': '_handleKeydown($event)',\r\n '(focus)': '_onFocus()',\r\n '(blur)': '_onBlur()',\r\n },\r\n providers: [\r\n { provide: OuiFormFieldControl, useExisting: OuiSelect },\r\n { provide: OUI_OPTION_PARENT_COMPONENT, useExisting: OuiSelect },\r\n ],\r\n})\r\nexport class OuiSelect\r\n extends _OuiSelectMixinBase\r\n implements\r\n AfterContentInit,\r\n OnChanges,\r\n OnDestroy,\r\n OnInit,\r\n DoCheck,\r\n ControlValueAccessor,\r\n CanDisable,\r\n HasTabIndex,\r\n OuiFormFieldControl,\r\n CanUpdateErrorState\r\n{\r\n /**Holds selected values after done */\r\n @Input() savedValues = [];\r\n /**Done button disabled until dropdown is dirty */\r\n disableDoneButton = true;\r\n /** Whether or not the overlay panel is open. */\r\n private _panelOpen = false;\r\n\r\n /** Whether filling out the select is required in the form. */\r\n private _required = false;\r\n\r\n /** Whether filling out the select is required in the form. */\r\n private _actionItems = false;\r\n\r\n /** The scroll position of the overlay panel, calculated to center the selected option. */\r\n private _scrollTop = 0;\r\n\r\n /** The placeholder displayed in the trigger of the select. */\r\n private _placeholder: string;\r\n\r\n /** Whether the component is in multiple selection mode. */\r\n private _multiple = false;\r\n\r\n /** Search input field **/\r\n isSearchFieldPresent: boolean;\r\n\r\n /** Unique id for this input. */\r\n private _uid = `oui-select-${nextUniqueId++}`;\r\n\r\n /** The last measured value for the trigger's client bounding rect. */\r\n _triggerRect: ClientRect;\r\n\r\n /** The aria-describedby attribute on the select for improved a11y. */\r\n _ariaDescribedby: string;\r\n\r\n /** The cached font-size of the trigger element. */\r\n _triggerFontSize = 0;\r\n\r\n /** Deals with the selection logic. */\r\n _selectionModel: SelectionModel;\r\n\r\n /** Manages keyboard events for options in the panel. */\r\n _keyManager: ActiveDescendantKeyManager;\r\n\r\n /** The IDs of child options to be passed to the aria-owns attribute. */\r\n _optionIds = '';\r\n\r\n /** The value of the select panel's transform-origin property. */\r\n _transformOrigin = 'top';\r\n\r\n /** If there is search input field a class is added dynamically to the perfect scrollbar **/\r\n ouiSelectInputOuterClassName: string;\r\n\r\n /** Adding top class to overlay panel */\r\n cdkConnectionOverlayPanel = '';\r\n\r\n /**\r\n * The y-offset of the overlay panel in relation to the trigger's top start corner.\r\n * This must be adjusted to align the selected option text over the trigger text.\r\n * when the panel opens. Will change based on the y-position of the selected option.\r\n */\r\n _offsetY = 0;\r\n\r\n /**\r\n * This position config ensures that the top \"start\" corner of the overlay\r\n * is aligned with with the top \"start\" of the origin by default (overlapping\r\n * the trigger completely). If the panel cannot fit below the trigger, it\r\n * will fall back to a position above the trigger.\r\n */\r\n _positions = [\r\n {\r\n originX: 'start',\r\n originY: 'top',\r\n overlayX: 'start',\r\n overlayY: 'top',\r\n },\r\n {\r\n originX: 'start',\r\n originY: 'bottom',\r\n overlayX: 'start',\r\n overlayY: 'bottom',\r\n },\r\n ];\r\n /** Emits whenever the component is destroyed. */\r\n private readonly _destroy = new Subject();\r\n\r\n /** Whether the component is disabling centering of the active option over the trigger. */\r\n private _disableOptionCentering = false;\r\n\r\n private _focused = false;\r\n\r\n /** A name for this control that can be used by `oui-form-field`. */\r\n controlType = 'oui-select';\r\n\r\n /** Trigger that opens the select. */\r\n @ViewChild('trigger') trigger: ElementRef;\r\n\r\n /** Trigger that opens the select. */\r\n @ViewChild('ddCancelButton', { read: ElementRef }) ddCancelButton: ElementRef;\r\n\r\n /** Trigger that opens the select. */\r\n @ViewChild('ddDoneButton', { read: ElementRef }) ddDoneButton: ElementRef;\r\n\r\n /** Panel containing the select options. */\r\n @ViewChild('panel', { read: ElementRef }) panel: ElementRef;\r\n\r\n private _value: any;\r\n\r\n /**\r\n * Function used to sort the values in a select in multiple mode.\r\n * Follows the same logic as `Array.prototype.sort`.\r\n */\r\n @Input() sortComparator: (\r\n a: OuiOption,\r\n b: OuiOption,\r\n options: OuiOption[]\r\n ) => number;\r\n\r\n /** Aria label of the select. If not specified, the placeholder will be used as label. */\r\n @Input('aria-label') ariaLabel = '';\r\n\r\n /** Input that can be used to specify the `aria-labelledby` attribute. */\r\n @Input('aria-labelledby') ariaLabelledby: string;\r\n private _large = false;\r\n _monitorSubscription: any;\r\n\r\n /** Whether the oui-select is of large size. */\r\n @Input()\r\n get large(): boolean {\r\n return this._large;\r\n }\r\n set large(value) {\r\n this._large = coerceBooleanProperty(value);\r\n this._changeDetectorRef.markForCheck();\r\n }\r\n\r\n private _id: string;\r\n\r\n /** Event emitted when the select panel has been toggled. */\r\n @Output()\r\n readonly openedChange: EventEmitter = new EventEmitter();\r\n\r\n /** Combined stream of all of the child options' change events. */\r\n readonly optionSelectionChanges: Observable = defer(\r\n (): Observable => {\r\n if (this.options) {\r\n return merge(...this.options.map((option) => option.onSelectionChange));\r\n }\r\n\r\n return this._ngZone.onStable.asObservable().pipe(\r\n take(1),\r\n switchMap(() => this.optionSelectionChanges)\r\n );\r\n }\r\n );\r\n\r\n /**\r\n * Event that emits whenever the raw value of the select changes. This is here primarily\r\n * to facilitate the two-way binding for the `value` input.\r\n *\r\n * @docs-private\r\n */\r\n @Output() readonly valueChange: EventEmitter = new EventEmitter();\r\n\r\n /** Object used to control when error messages are shown. */\r\n @Input() errorStateMatcher: ErrorStateMatcher;\r\n\r\n /** All of the defined select options. */\r\n @ContentChildren(OuiOption, { descendants: true })\r\n options: QueryList;\r\n\r\n /** Event emitted when the select has been opened. */\r\n // eslint-disable-next-line @angular-eslint/no-output-rename\r\n @Output('opened')\r\n readonly _openedStream: Observable = this.openedChange.pipe(\r\n filter((o) => o),\r\n map(() => {})\r\n );\r\n\r\n /** Event emitted when the select has been closed. */\r\n // eslint-disable-next-line @angular-eslint/no-output-rename\r\n @Output('closed')\r\n readonly _closedStream: Observable = this.openedChange.pipe(\r\n filter((o) => !o),\r\n map(() => {\r\n this.isSearchFieldPresent = false;\r\n })\r\n );\r\n\r\n /** Event emitted when the selected value has been changed by the user. */\r\n @Output()\r\n readonly selectionChange: EventEmitter =\r\n new EventEmitter();\r\n\r\n /** Event emitted when the selected value has been changed and saved by the user. */\r\n @Output()\r\n readonly saveSelectionChange: EventEmitter =\r\n new EventEmitter();\r\n\r\n /** All of the defined groups of options. */\r\n @ContentChildren(OuiOptgroup) optionGroups: QueryList;\r\n\r\n /** User-supplied override of the trigger element. */\r\n @ContentChild(OuiSelectTrigger)\r\n customTrigger: OuiSelectTrigger;\r\n\r\n /** Classes to be passed to the select panel. Supports the same syntax as `ngClass`. */\r\n @Input() panelClass: string | string[] | Set | { [key: string]: any };\r\n\r\n /** Overlay pane containing the options. */\r\n @ViewChild(CdkConnectedOverlay)\r\n overlayDir: CdkConnectedOverlay;\r\n\r\n /** Emits when the panel element is finished transforming in. */\r\n _panelDoneAnimatingStream = new Subject();\r\n\r\n /** Comparison function to specify which option is displayed. Defaults to object equality. */\r\n private _compareWith = (o1: any, o2: any) => o1 === o2;\r\n\r\n /** Whether the select is focused. */\r\n get focused(): boolean {\r\n return this._focused || this._panelOpen;\r\n }\r\n /**\r\n * @deprecated Setter to be removed as this property is intended to be readonly.\r\n */\r\n set focused(value: boolean) {\r\n this._focused = value;\r\n }\r\n /** `View -> model callback called when value changes` */\r\n _onChange: (value: any) => void = () => {};\r\n\r\n /** `View -> model callback called when select has been touched` */\r\n _onTouched = () => {};\r\n\r\n /** Placeholder to be shown if no value has been selected. */\r\n @Input()\r\n get placeholder(): string {\r\n return this._placeholder;\r\n }\r\n set placeholder(value: string) {\r\n this._placeholder = value;\r\n this.stateChanges.next();\r\n }\r\n\r\n /** Whether the component is required. */\r\n @Input()\r\n get required(): boolean {\r\n return this._required;\r\n }\r\n set required(value: boolean) {\r\n this._required = coerceBooleanProperty(value);\r\n this.stateChanges.next();\r\n }\r\n\r\n /** Whether the user should be allowed to select multiple options. */\r\n @Input()\r\n get multiple(): boolean {\r\n return this._multiple;\r\n }\r\n set multiple(value: boolean) {\r\n if (this._selectionModel) {\r\n throw getOuiSelectDynamicMultipleError();\r\n }\r\n\r\n this._multiple = coerceBooleanProperty(value);\r\n }\r\n\r\n /** Whether the action items are required and use saveSelectionChange instead of selectionChange. */\r\n @Input()\r\n get actionItems(): boolean {\r\n return this._actionItems;\r\n }\r\n set actionItems(value: boolean) {\r\n if (this._multiple) {\r\n this._actionItems = coerceBooleanProperty(value);\r\n this.stateChanges.next();\r\n }\r\n }\r\n\r\n /** Whether to center the active option over the trigger. */\r\n @Input()\r\n get disableOptionCentering(): boolean {\r\n return this._disableOptionCentering;\r\n }\r\n set disableOptionCentering(value: boolean) {\r\n this._disableOptionCentering = coerceBooleanProperty(value);\r\n }\r\n\r\n /**\r\n * Function to compare the option values with the selected values. The first argument\r\n * is a value from an option. The second is a value from the selection. A boolean\r\n * should be returned.\r\n */\r\n @Input()\r\n get compareWith() {\r\n return this._compareWith;\r\n }\r\n set compareWith(fn: (o1: any, o2: any) => boolean) {\r\n if (typeof fn !== 'function') {\r\n throw getOuiSelectNonFunctionValueError();\r\n }\r\n this._compareWith = fn;\r\n if (this._selectionModel) {\r\n // A different comparator means the selection could change.\r\n this._initializeSelection();\r\n }\r\n }\r\n\r\n /** Value of the select control. */\r\n @Input()\r\n get value(): any {\r\n return this._value;\r\n }\r\n set value(newValue: any) {\r\n if (newValue !== this._value) {\r\n this.writeValue(newValue);\r\n this._value = newValue;\r\n }\r\n }\r\n\r\n /** Unique id of the element. */\r\n @Input()\r\n get id(): string {\r\n return this._id;\r\n }\r\n set id(value: string) {\r\n this._id = value || this._uid;\r\n this.stateChanges.next();\r\n }\r\n\r\n constructor(\r\n private _changeDetectorRef: ChangeDetectorRef,\r\n private _ngZone: NgZone,\r\n _defaultErrorStateMatcher: ErrorStateMatcher,\r\n elementRef: ElementRef,\r\n private _focusMonitor: FocusMonitor,\r\n @Optional() private _dir: Directionality,\r\n @Optional() _parentForm: NgForm,\r\n @Optional() _parentFormGroup: FormGroupDirective,\r\n @Optional() private _parentFormField: OuiFormField,\r\n @Self() @Optional() public ngControl: NgControl,\r\n @Attribute('tabindex') tabIndex: string,\r\n @Optional() @Inject(DOCUMENT) private _document: any,\r\n public _elementRef: ElementRef,\r\n public _ouiIconRegistry: OuiIconRegistry,\r\n private _domSanitizer: DomSanitizer\r\n ) {\r\n super(\r\n elementRef,\r\n _defaultErrorStateMatcher,\r\n _parentForm,\r\n _parentFormGroup,\r\n ngControl\r\n );\r\n this._monitorSubscription = this._focusMonitor\r\n .monitor(this._elementRef, true)\r\n .subscribe(() => this._ngZone.run(() => {}));\r\n this._ouiIconRegistry.addSvgIconLiteral(\r\n `select-arrow-icon`,\r\n this._domSanitizer.bypassSecurityTrustHtml(ICONS.SELECT_ARROW_ICON)\r\n );\r\n\r\n if (this.ngControl) {\r\n // Note: we provide the value accessor through here, instead of\r\n // the `providers` to avoid running into a circular import.\r\n this.ngControl.valueAccessor = this;\r\n }\r\n\r\n this.tabIndex = parseInt(tabIndex, 10) || 0;\r\n\r\n // Force setter to be called in case id was not specified.\r\n this.id = this.id;\r\n }\r\n\r\n ngOnInit() {\r\n this._selectionModel = new SelectionModel(this.multiple);\r\n this.stateChanges.next();\r\n\r\n // We need `distinctUntilChanged` here, because some browsers will\r\n // fire the animation end event twice for the same animation. See:\r\n // https://github.com/angular/angular/issues/24084\r\n this._panelDoneAnimatingStream\r\n .pipe(distinctUntilChanged(), takeUntil(this._destroy))\r\n .subscribe(() => {\r\n if (this.panelOpen) {\r\n this._scrollTop = 0;\r\n this.openedChange.emit(true);\r\n } else {\r\n this.openedChange.emit(false);\r\n this.overlayDir.offsetX = 0;\r\n this._changeDetectorRef.markForCheck();\r\n }\r\n });\r\n }\r\n\r\n ngAfterContentInit() {\r\n this._initKeyManager();\r\n\r\n this._selectionModel.changed\r\n .pipe(takeUntil(this._destroy))\r\n .subscribe((event) => {\r\n event.added.forEach((option) => option.select());\r\n event.removed.forEach((option) => option.deselect());\r\n });\r\n\r\n this.options.changes\r\n .pipe(startWith(null), takeUntil(this._destroy))\r\n .subscribe(() => {\r\n this._resetOptions();\r\n this._initializeSelection();\r\n });\r\n }\r\n\r\n ngDoCheck() {\r\n if (this.ngControl) {\r\n this.updateErrorState();\r\n }\r\n }\r\n\r\n ngOnChanges(changes: SimpleChanges) {\r\n // Updating the disabled state is handled by `mixinDisabled`, but we need to additionally let\r\n // the parent form field know to run change detection when the disabled state changes.\r\n if (changes.disabled) {\r\n this.stateChanges.next();\r\n }\r\n }\r\n\r\n ngOnDestroy() {\r\n this._monitorSubscription.unsubscribe();\r\n this._focusMonitor.stopMonitoring(this._elementRef);\r\n this._destroy.next();\r\n this._destroy.complete();\r\n this.stateChanges.complete();\r\n }\r\n\r\n /** Toggles the overlay panel open or closed. */\r\n toggle(): void {\r\n this.panelOpen ? this.close() : this.open();\r\n }\r\n\r\n /** Opens the overlay panel. */\r\n open(): void {\r\n if (\r\n this.disabled ||\r\n !this.options ||\r\n !this.options.length ||\r\n this._panelOpen\r\n ) {\r\n return;\r\n }\r\n\r\n this._triggerRect = this.trigger.nativeElement.getBoundingClientRect();\r\n\r\n this._panelOpen = true;\r\n this._keyManager.withHorizontalOrientation(null);\r\n\r\n this._highlightCorrectOption();\r\n this._changeDetectorRef.markForCheck();\r\n this.openedChange.emit(true);\r\n this._elementRef.nativeElement.classList.add(\r\n 'oui-select-list-options-opened'\r\n );\r\n }\r\n\r\n /** Closes the overlay panel and focuses the host element. */\r\n close(): void {\r\n if (this._panelOpen) {\r\n this._panelOpen = false;\r\n this._keyManager.withHorizontalOrientation(this._isRtl() ? 'rtl' : 'ltr');\r\n this._changeDetectorRef.markForCheck();\r\n this._onTouched();\r\n this.openedChange.emit(false);\r\n this._elementRef.nativeElement.classList.remove(\r\n 'oui-select-list-options-opened'\r\n );\r\n setTimeout((_) => this._document.activeElement.blur());\r\n }\r\n }\r\n\r\n /**\r\n * Sets the select's value. Part of the ControlValueAccessor interface\r\n * required to integrate with Angular's core forms API.\r\n *\r\n * @param value New value to be written to the model.\r\n */\r\n writeValue(value: any): void {\r\n if (this.options) {\r\n this._setSelectionByValue(value);\r\n }\r\n }\r\n\r\n /**\r\n * Saves a callback function to be invoked when the select's value\r\n * changes from user input. Part of the ControlValueAccessor interface\r\n * required to integrate with Angular's core forms API.\r\n *\r\n * @param fn Callback to be triggered when the value changes.\r\n */\r\n registerOnChange(fn: (value: any) => void): void {\r\n this._onChange = fn;\r\n }\r\n\r\n /**\r\n * Saves a callback function to be invoked when the select is blurred\r\n * by the user. Part of the ControlValueAccessor interface required\r\n * to integrate with Angular's core forms API.\r\n *\r\n * @param fn Callback to be triggered when the component has been touched.\r\n */\r\n registerOnTouched(fn: () => {}): void {\r\n this._onTouched = fn;\r\n }\r\n\r\n /**\r\n * Disables the select. Part of the ControlValueAccessor interface required\r\n * to integrate with Angular's core forms API.\r\n *\r\n * @param isDisabled Sets whether the component is disabled.\r\n */\r\n setDisabledState(isDisabled: boolean): void {\r\n this.disabled = isDisabled;\r\n this._changeDetectorRef.markForCheck();\r\n this.stateChanges.next();\r\n }\r\n\r\n /** Whether or not the overlay panel is open. */\r\n get panelOpen(): boolean {\r\n return this._panelOpen;\r\n }\r\n\r\n /** The currently selected option. */\r\n get selected(): OuiOption | OuiOption[] {\r\n return this.multiple\r\n ? this._selectionModel.selected\r\n : this._selectionModel.selected[0];\r\n }\r\n\r\n /** The value displayed in the trigger. */\r\n get triggerValue(): string {\r\n if (this.empty) {\r\n return '';\r\n }\r\n if (this._multiple) {\r\n const selectedOptions = this._selectionModel.selected.map(\r\n (option) => option.viewValueForSelect\r\n );\r\n\r\n if (this._isRtl()) {\r\n selectedOptions.reverse();\r\n }\r\n return selectedOptions.join(', ');\r\n }\r\n return this._selectionModel.selected[0].viewValueForSelect;\r\n }\r\n\r\n /** Whether the element is in RTL mode. */\r\n _isRtl(): boolean {\r\n return this._dir ? this._dir.value === 'rtl' : false;\r\n }\r\n\r\n /** Handles all keydown events on the select. */\r\n _handleKeydown(event: KeyboardEvent): void {\r\n if (!this.disabled) {\r\n this.panelOpen\r\n ? this._handleOpenKeydown(event)\r\n : this._handleClosedKeydown(event);\r\n }\r\n }\r\n\r\n /** Handles keyboard events while the select is closed. */\r\n private _handleClosedKeydown(event: KeyboardEvent): void {\r\n const keyCode = event.keyCode;\r\n const isArrowKey =\r\n keyCode === DOWN_ARROW ||\r\n keyCode === UP_ARROW ||\r\n keyCode === LEFT_ARROW ||\r\n keyCode === RIGHT_ARROW;\r\n const isOpenKey = keyCode === ENTER || keyCode === SPACE;\r\n const manager = this._keyManager;\r\n\r\n // Open the select on ALT + arrow key to match the native \r\n event.preventDefault();\r\n this.close();\r\n } else if (\r\n (keyCode === ENTER || keyCode === SPACE) &&\r\n manager.activeItem &&\r\n !hasModifierKey(event)\r\n ) {\r\n event.preventDefault();\r\n manager.activeItem._selectViaInteraction();\r\n } else if (this._multiple && keyCode === A && event.ctrlKey) {\r\n event.preventDefault();\r\n this.handleCtrlKey();\r\n } else if (normalNavigationCheck) {\r\n // Check for non multiple select dropdown that the key pressed is not Tab, Space, Enter\r\n if (!this.isSearchFieldPresent) this.focus();\r\n this.handleScrolling(manager, event, isArrowKey, keyCode);\r\n }\r\n }\r\n\r\n /**\r\n * Handle ctrl key\r\n */\r\n private handleCtrlKey() {\r\n const hasDeselectedOptions = this.options.some(\r\n (opt) => !opt.disabled && !opt.selected\r\n );\r\n\r\n this.options.forEach((option) => {\r\n if (!option.disabled) {\r\n hasDeselectedOptions ? option.select() : option.deselect();\r\n }\r\n });\r\n }\r\n\r\n /**\r\n * @param manager\r\n * @param event\r\n * @param isArrowKey\r\n * @param keyCode\r\n */\r\n private handleScrolling(\r\n manager: ActiveDescendantKeyManager,\r\n event: KeyboardEvent,\r\n isArrowKey: boolean,\r\n keyCode: number\r\n ) {\r\n const previouslyFocusedIndex = manager.activeItemIndex;\r\n\r\n manager.onKeydown(event);\r\n\r\n if (\r\n this._multiple &&\r\n isArrowKey &&\r\n event.shiftKey &&\r\n manager.activeItem &&\r\n manager.activeItemIndex !== previouslyFocusedIndex\r\n ) {\r\n manager.activeItem._selectViaInteraction();\r\n }\r\n if (isArrowKey && manager.activeItemIndex !== previouslyFocusedIndex) {\r\n this._scrollToOption();\r\n } else {\r\n // First or last\r\n if (keyCode === DOWN_ARROW) {\r\n manager.setFirstItemActive();\r\n this._setScrollTop(0);\r\n }\r\n if (keyCode === UP_ARROW) {\r\n manager.setLastItemActive();\r\n this._scrollToOption();\r\n }\r\n }\r\n }\r\n\r\n _onFocus() {\r\n if (!this.disabled) {\r\n this._focused = true;\r\n this.stateChanges.next();\r\n }\r\n }\r\n\r\n /**\r\n * Calls the touched callback only if the panel is closed. Otherwise, the trigger will\r\n * \"blur\" to the panel when it opens, causing a false positive.\r\n */\r\n _onBlur() {\r\n this._focused = false;\r\n // this.isSearchFieldPresent = false;\r\n\r\n if (!this.disabled && !this.panelOpen) {\r\n this._onTouched();\r\n this._changeDetectorRef.markForCheck();\r\n this.stateChanges.next();\r\n }\r\n }\r\n\r\n /**\r\n * Callback that is invoked when the overlay panel has been attached.\r\n */\r\n _onAttached(): void {\r\n this.overlayDir.positionChange.pipe(take(1)).subscribe(() => {\r\n this._setPseudoCheckboxPaddingSize();\r\n this._changeDetectorRef.detectChanges();\r\n this.panel.nativeElement.scrollTop = this._scrollTop;\r\n });\r\n }\r\n\r\n /** Returns the theme to be used on the panel. */\r\n _getPanelTheme(): string {\r\n return this._parentFormField ? `oui-${this._parentFormField.color}` : '';\r\n }\r\n\r\n // TODO(josephperrott): Remove after 2018 spec updates are fully merged.\r\n /** Sets the pseudo checkbox padding size based on the width of the pseudo checkbox. */\r\n private _setPseudoCheckboxPaddingSize() {\r\n if (!SELECT_MULTIPLE_PANEL_PADDING_X && this.multiple) {\r\n const pseudoCheckbox = this.panel.nativeElement.querySelector(\r\n '.oui-pseudo-checkbox'\r\n );\r\n if (pseudoCheckbox) {\r\n SELECT_MULTIPLE_PANEL_PADDING_X =\r\n SELECT_PANEL_PADDING_X * 1.5 + pseudoCheckbox.offsetWidth;\r\n }\r\n }\r\n }\r\n\r\n /** Whether the select has a value. */\r\n get empty(): boolean {\r\n return !this._selectionModel || this._selectionModel.isEmpty();\r\n }\r\n\r\n private _initializeSelection(): void {\r\n // Defer setting the value in order to avoid the \"Expression\r\n // has changed after it was checked\" errors from Angular.\r\n Promise.resolve().then(() => {\r\n this._setSelectionByValue(\r\n this.ngControl ? this.ngControl.value : this._value\r\n );\r\n this.savedValues = this.ngControl ? this.ngControl.value : this._value;\r\n if (this.multiple) {\r\n this._highlightFirstFilteredOption();\r\n }\r\n });\r\n }\r\n\r\n /**\r\n * Sets the selected option based on a value. If no option can be\r\n * found with the designated value, the select trigger is cleared.\r\n */\r\n private _setSelectionByValue(value: any | any[]): void {\r\n if (this.multiple && value) {\r\n if (!Array.isArray(value)) {\r\n throw getOuiSelectNonArrayValueError();\r\n }\r\n\r\n this._selectionModel.clear();\r\n value.forEach((currentValue: any) => this._selectValue(currentValue));\r\n this._sortValues();\r\n } else {\r\n this._selectionModel.clear();\r\n const correspondingOption = this._selectValue(value);\r\n // Shift focus to the active item. Note that we shouldn't do this in multiple\r\n // mode, because we don't know what option the user interacted with last.\r\n if (correspondingOption) {\r\n this._keyManager.setActiveItem(correspondingOption);\r\n }\r\n }\r\n this._changeDetectorRef.markForCheck();\r\n }\r\n\r\n /**\r\n * Finds and selects and option based on its value.\r\n *\r\n * @returns Option that has the corresponding value.\r\n */\r\n private _selectValue(value: any): OuiOption | undefined {\r\n const correspondingOption = this.options.find((option: OuiOption) => {\r\n try {\r\n // Treat null as a special reset value.\r\n return option.value != null && this._compareWith(option.value, value);\r\n } catch (error) {\r\n if (isDevMode()) {\r\n // Notify developers of errors in their comparator.\r\n console.warn(error);\r\n }\r\n return false;\r\n }\r\n });\r\n\r\n if (correspondingOption) {\r\n this._selectionModel.select(correspondingOption);\r\n }\r\n\r\n return correspondingOption;\r\n }\r\n\r\n /** Sets up a key manager to listen to keyboard events on the overlay panel. */\r\n private _initKeyManager() {\r\n this._keyManager = new ActiveDescendantKeyManager(this.options)\r\n .withTypeAhead()\r\n .withVerticalOrientation()\r\n .withHorizontalOrientation(this._isRtl() ? 'rtl' : 'ltr')\r\n .withAllowedModifierKeys(['shiftKey']);\r\n\r\n this._keyManager.tabOut.pipe(takeUntil(this._destroy)).subscribe(() => {\r\n // Restore focus to the trigger before closing. Ensures that the focus\r\n // position won't be lost if the user got focus into the overlay.\r\n this.focus();\r\n this.close();\r\n });\r\n\r\n this._keyManager.change.pipe(takeUntil(this._destroy)).subscribe(() => {\r\n if (this._panelOpen && this.panel) {\r\n // Panel is opened\r\n // Need not to scroll\r\n } else if (\r\n !this._panelOpen &&\r\n !this.multiple &&\r\n this._keyManager.activeItem\r\n ) {\r\n this._keyManager.activeItem._selectViaInteraction();\r\n }\r\n });\r\n }\r\n\r\n /** Drops current option subscriptions and IDs and resets from scratch. */\r\n private _resetOptions(): void {\r\n const changedOrDestroyed = merge(this.options.changes, this._destroy);\r\n\r\n this.optionSelectionChanges\r\n .pipe(takeUntil(changedOrDestroyed))\r\n .subscribe((event) => {\r\n this._onSelect(event.source, event.isUserInput);\r\n\r\n if (event.isUserInput && !this.multiple && this._panelOpen) {\r\n this.close();\r\n this.focus();\r\n }\r\n });\r\n\r\n // Listen to changes in the internal state of the options and react accordingly.\r\n // Handles cases like the labels of the selected options changing.\r\n merge(...this.options.map((option) => option._stateChanges))\r\n .pipe(takeUntil(changedOrDestroyed))\r\n .subscribe(() => {\r\n this._changeDetectorRef.markForCheck();\r\n this.stateChanges.next();\r\n });\r\n\r\n this._setOptionIds();\r\n }\r\n\r\n /** Invoked when an option is clicked. */\r\n private _onSelect(option: OuiOption, isUserInput: boolean): void {\r\n const wasSelected = this._selectionModel.isSelected(option);\r\n\r\n if (option.value == null && !this._multiple) {\r\n option.deselect();\r\n this._selectionModel.clear();\r\n this._propagateChanges(option.value);\r\n } else {\r\n option.selected\r\n ? this._selectionModel.select(option)\r\n : this._selectionModel.deselect(option);\r\n\r\n if (isUserInput) {\r\n this._keyManager.setActiveItem(option);\r\n }\r\n\r\n if (this.multiple) {\r\n this._sortValues();\r\n\r\n if (isUserInput) {\r\n // In case the user selected the option with their mouse, we\r\n // want to restore focus back to the trigger, in order to\r\n // prevent the select keyboard controls from clashing with\r\n // the ones from `oui-option`.\r\n this.focus();\r\n }\r\n }\r\n }\r\n\r\n if (wasSelected !== this._selectionModel.isSelected(option)) {\r\n this._propagateChanges();\r\n }\r\n this.disableDoneButton = false;\r\n this.stateChanges.next();\r\n }\r\n discardRecentChanges() {\r\n this.value = this.savedValues;\r\n this._setSelectionByValue(this.value);\r\n this.disableDoneButton = true;\r\n this.close();\r\n }\r\n doneRecentChanges() {\r\n this.savedValues = this.value;\r\n this.disableDoneButton = true;\r\n this.saveSelectionChange.emit(new OuiSelectChange(this, this.value));\r\n this.close();\r\n }\r\n /** Sorts the selected values in the selected based on their order in the panel. */\r\n private _sortValues() {\r\n if (this.multiple) {\r\n const options = this.options.toArray();\r\n\r\n this._selectionModel.sort((a, b) =>\r\n this.sortComparator\r\n ? this.sortComparator(a, b, options)\r\n : options.indexOf(a) - options.indexOf(b)\r\n );\r\n this.stateChanges.next();\r\n }\r\n }\r\n\r\n /** Emits change event to set the model value. */\r\n private _propagateChanges(fallbackValue?: any): void {\r\n let valueToEmit: any = null;\r\n\r\n if (this.multiple) {\r\n valueToEmit = (this.selected as OuiOption[]).map(\r\n (option) => option.value\r\n );\r\n } else {\r\n valueToEmit = this.selected\r\n ? (this.selected as OuiOption).value\r\n : fallbackValue;\r\n }\r\n\r\n this._value = valueToEmit;\r\n this.valueChange.emit(valueToEmit);\r\n this._onChange(valueToEmit);\r\n this.selectionChange.emit(new OuiSelectChange(this, valueToEmit));\r\n this._changeDetectorRef.markForCheck();\r\n }\r\n\r\n /** Records option IDs to pass to the aria-owns property. */\r\n private _setOptionIds() {\r\n this._optionIds = this.options.map((option) => option.id).join(' ');\r\n }\r\n\r\n /**\r\n * Highlights the selected item. If no option is selected, it will highlight\r\n * the first item instead.\r\n */\r\n private _highlightCorrectOption(): void {\r\n if (this.multiple) {\r\n this._highlightFirstFilteredOption();\r\n } else if (this._keyManager) {\r\n if (this.empty) {\r\n this._keyManager.setFirstItemActive();\r\n } else {\r\n this._keyManager.setActiveItem(this._selectionModel.selected[0]);\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * Highlights the first of the filtered options if no element is currently highlighted\r\n */\r\n private _highlightFirstFilteredOption(): void {\r\n if (this._keyManager) {\r\n const activeElement = this._keyManager.activeItem?._getHostElement();\r\n // activeElement is not part of DOM if there is no parent element\r\n if (!activeElement || !activeElement.parentElement) {\r\n // highlight first element if there is no active element or active element is not part of DOM\r\n this._keyManager.setFirstItemActive();\r\n }\r\n }\r\n }\r\n\r\n /** Focuses the select element. */\r\n focus(): void {\r\n this._elementRef.nativeElement.focus();\r\n }\r\n\r\n /** Returns the aria-label of the select component. */\r\n _getAriaLabel(): string | null {\r\n // If an ariaLabelledby value has been set by the consumer, the select should not overwrite the\r\n // `aria-labelledby` value by setting the ariaLabel to the placeholder.\r\n return this.ariaLabelledby ? null : this.ariaLabel || this.placeholder;\r\n }\r\n\r\n /** Returns the aria-labelledby of the select component. */\r\n _getAriaLabelledby(): string | null {\r\n if (this.ariaLabelledby) {\r\n return this.ariaLabelledby;\r\n }\r\n\r\n return null;\r\n }\r\n\r\n /** Determines the `aria-activedescendant` to be set on the host. */\r\n _getAriaActiveDescendant(): string | null {\r\n if (this.panelOpen && this._keyManager && this._keyManager.activeItem) {\r\n return this._keyManager.activeItem.id;\r\n }\r\n\r\n return null;\r\n }\r\n\r\n /**\r\n * Implemented as part of OuiFormFieldControl.\r\n *\r\n * @docs-private\r\n */\r\n setDescribedByIds(ids: string[]) {\r\n this._ariaDescribedby = ids.join(' ');\r\n }\r\n\r\n /**\r\n * Implemented as part of OuiFormFieldControl.\r\n *\r\n * @docs-private\r\n */\r\n onContainerClick() {\r\n this.focus();\r\n this.open();\r\n }\r\n\r\n /**\r\n * Implemented as part of OuiFormFieldControl.\r\n *\r\n * @docs-private\r\n */\r\n get shouldLabelFloat(): boolean {\r\n return this._panelOpen || !this.empty;\r\n }\r\n\r\n /**\r\n * Add outer class to perfect scrollbar\r\n * This is added only when there is a search field\r\n */\r\n ouiSelectInputOuter() {\r\n this.ouiSelectInputOuterClassName = 'oui-select-input-outer';\r\n }\r\n\r\n /**\r\n * Custom overlay class for cdk overlay container\r\n */\r\n openCdk() {\r\n this.overlayDir.positionChange.pipe(take(1)).subscribe((e) => {\r\n this.cdkConnectionOverlayPanel = '';\r\n if (e.connectionPair.originY === 'top') {\r\n this.cdkConnectionOverlayPanel = 'select-overlay-top';\r\n }\r\n this._changeDetectorRef.detectChanges();\r\n setTimeout((_) => this._scrollToOption());\r\n });\r\n\r\n const cdkOverLayContainer = this._document.querySelector(\r\n '.cdk-overlay-container'\r\n );\r\n const ouiSelectPanel = this._document.querySelector('.oui-select-panel');\r\n cdkOverLayContainer.classList.add('oui-select-overlay-container');\r\n const containerWidth = this._elementRef.nativeElement.offsetWidth;\r\n ouiSelectPanel.style.width = `${containerWidth}px`;\r\n const searchQueryString = '.oui-select-search-inner';\r\n if (this._document.querySelector(searchQueryString)) {\r\n this.scrollCalc(searchQueryString);\r\n }\r\n const actionItemsQueryString = '.oui-select-action-items';\r\n if (this._document.querySelector(actionItemsQueryString)) {\r\n this.scrollCalc(actionItemsQueryString);\r\n }\r\n }\r\n scrollCalc(selectQueryString: string) {\r\n const searchInput = this._document.querySelector(selectQueryString);\r\n const outter = this._document.querySelector('.oui-select-panel');\r\n let inner = this._document.querySelector('.oui-option');\r\n if (inner === null) {\r\n inner = 0;\r\n }\r\n const scrollbarWidth = outter.offsetWidth - inner.offsetWidth;\r\n if (scrollbarWidth > 5) {\r\n searchInput.style.width = `${inner.offsetWidth}px`;\r\n } else {\r\n searchInput.style.width = `calc(100% + 8px)`;\r\n }\r\n }\r\n\r\n /**\r\n * Given that we are not actually focusing active options, we must manually adjust scroll\r\n * to reveal options below the fold. First, we find the offset of the option from the top\r\n * of the panel. If that offset is below the fold, the new scrollTop will be the offset -\r\n * the panel height + the option height, so the active option will be just visible at the\r\n * bottom of the panel. If that offset is above the top of the visible panel, the new scrollTop\r\n * will become the offset. If that offset is visible within the panel already, the scrollTop is\r\n * not adjusted.\r\n */\r\n private _scrollToOption(): void {\r\n const manager = this._keyManager;\r\n const index = manager.activeItemIndex || 0;\r\n const labelCount = _countGroupLabelsBeforeOption(\r\n index,\r\n this.options,\r\n this.optionGroups\r\n );\r\n const scrollTop = this._getScrollTop();\r\n const newScrollPosition = _getOptionScrollPosition(\r\n index + labelCount,\r\n SELECT_OPTION_HEIGHT,\r\n scrollTop,\r\n SELECT_PANEL_HEIGHT\r\n );\r\n this._setScrollTop(newScrollPosition);\r\n }\r\n\r\n /**\r\n * Sets the panel scrollTop. This allows us to manually scroll to display options\r\n * above or below the fold, as they are not actually being focused when active.\r\n */\r\n _setScrollTop(scrollTop: number): void {\r\n if (this.panel) {\r\n this.panel.nativeElement.scrollTop = scrollTop;\r\n }\r\n }\r\n\r\n /** Returns the panel's scrollTop. */\r\n _getScrollTop(): number {\r\n return this.panel ? this.panel.nativeElement.scrollTop : 0;\r\n }\r\n}\r\n", "constructorObj": { "name": "constructor", "description": "", @@ -10155,7 +10233,7 @@ "line": 135, "rawdescription": "\nReference to the select that emitted the change event.", "modifierKind": [ - 123 + 125 ] }, { @@ -10168,7 +10246,7 @@ "line": 137, "rawdescription": "\nCurrent value of the select that emitted the event.", "modifierKind": [ - 123 + 125 ] } ], @@ -10176,6 +10254,7 @@ "rawdescription": "\nChange event object that is emitted when the select value has changed.", "methods": [], "indexSignatures": [], + "extends": [], "inputsClass": [], "outputsClass": [], "hostBindings": [], @@ -10225,12 +10304,13 @@ "description": "", "line": 35, "modifierKind": [ - 123 + 125 ] } ], "methods": [], "indexSignatures": [], + "extends": [], "inputsClass": [], "outputsClass": [], "hostBindings": [], @@ -10247,6 +10327,7 @@ "properties": [], "methods": [], "indexSignatures": [], + "extends": [], "inputsClass": [], "outputsClass": [], "hostBindings": [], @@ -10263,6 +10344,7 @@ "properties": [], "methods": [], "indexSignatures": [], + "extends": [], "inputsClass": [], "outputsClass": [], "hostBindings": [], @@ -10270,12 +10352,12 @@ }, { "name": "OuiTabChangeEvent", - "id": "class-OuiTabChangeEvent-4d0b5030ca195d184c74343feab780aa235b8d985fd04212cdaaa64ed005edd09a6056c8ba4c4954752c47f07323482c45b313640a731c2d5d0547df5865b67d", + "id": "class-OuiTabChangeEvent-589c514ba2f48297f4aa02fd4ced821bdcbc822779026ff6c817d949a12f81fcb79562a1d57b8975a29ae4b3cacdebafe77cf4a4035a5d582aa823ca4fafe395", "file": "ui/src/components/tabs/tab-group.ts", "deprecated": false, "deprecationMessage": "", "type": "class", - "sourceCode": "import {\n AfterContentChecked,\n AfterContentInit,\n ChangeDetectionStrategy,\n ChangeDetectorRef,\n Component,\n ContentChildren,\n ElementRef,\n EventEmitter,\n Inject,\n Input,\n OnDestroy,\n Optional,\n Output,\n QueryList,\n ViewChild,\n ViewEncapsulation,\n} from '@angular/core';\nimport { ANIMATION_MODULE_TYPE } from '@angular/platform-browser/animations';\nimport { OUI_TAB_GROUP, OuiTab } from './tab';\nimport { OuiTabHeader } from './tab-header';\nimport {\n BooleanInput,\n coerceBooleanProperty,\n coerceNumberProperty,\n NumberInput,\n} from '@angular/cdk/coercion';\nimport {\n CanColor,\n CanDisableRipple,\n mixinColor,\n mixinDisableRipple,\n ThemePalette,\n} from '../core';\nimport { merge, Subscription } from 'rxjs';\nimport { OUI_TABS_CONFIG, OuiTabsConfig } from './tab-config';\nimport { startWith } from 'rxjs/operators';\nimport { FocusOrigin } from '@angular/cdk/a11y';\n\n/** Used to generate unique ID's for each tab component */\nlet nextId = 0;\n\n// Boilerplate for applying mixins to ouiTabGroup.\n/** @docs-private */\nconst _OuiTabGroupMixinBase = mixinColor(\n mixinDisableRipple(\n class {\n constructor(public _elementRef: ElementRef) {}\n }\n ),\n 'primary'\n);\n\n/** @docs-private */\nexport interface OuiTabGroupBaseHeader {\n _alignInkBarToSelectedTab(): void;\n updatePagination(): void;\n focusIndex: number;\n}\n\n/** Possible positions for the tab header. */\nexport type OuiTabHeaderPosition = 'above' | 'below';\n\n/**\n * Material design tab-group component. Supports basic tab pairs (label + content) and includes\n * animated ink-bar, keyboard navigation, and screen reader.\n * See: https://material.io/design/components/tabs.html\n */\n@Component({\n selector: 'oui-tab-group',\n exportAs: 'ouiTabGroup',\n templateUrl: 'tab-group.html',\n styleUrls: ['tab-group.scss'],\n encapsulation: ViewEncapsulation.None,\n // tslint:disable-next-line:validate-decorators\n changeDetection: ChangeDetectionStrategy.Default,\n // eslint-disable-next-line\n inputs: ['color', 'disableRipple'],\n providers: [\n {\n provide: OUI_TAB_GROUP,\n useExisting: ouiTabGroup,\n },\n ],\n // eslint-disable-next-line\n host: {\n ngSkipHydration: '',\n class: 'oui-mdc-tab-group oui-tab',\n '[class.oui-mdc-tab-group-dynamic-height]': 'dynamicHeight',\n '[class.oui-mdc-tab-group-inverted-header]': 'headerPosition === \"below\"',\n '[class.oui-mdc-tab-group-stretch-tabs]': 'stretchTabs',\n '[style.--oui-tab-animation-duration]': 'animationDuration',\n },\n})\nexport class ouiTabGroup\n extends _OuiTabGroupMixinBase\n implements\n AfterContentInit,\n AfterContentChecked,\n OnDestroy,\n CanColor,\n CanDisableRipple\n{\n /**\n * All tabs inside the tab group. This includes tabs that belong to groups that are nested\n * inside the current one. We filter out only the tabs that belong to this group in `_tabs`.\n */\n @ContentChildren(OuiTab, { descendants: true }) _allTabs: QueryList;\n @ViewChild('tabBodyWrapper') _tabBodyWrapper: ElementRef;\n @ViewChild('tabHeader') _tabHeader: OuiTabHeader;\n\n /** All of the tabs that belong to the group. */\n _tabs: QueryList = new QueryList();\n\n /** The tab index that should be selected after the content has been checked. */\n private _indexToSelect: number | null = 0;\n\n /** Index of the tab that was focused last. */\n private _lastFocusedTabIndex: number | null = null;\n\n /** Snapshot of the height of the tab body wrapper before another tab is activated. */\n private _tabBodyWrapperHeight = 0;\n\n /** Subscription to tabs being added/removed. */\n private _tabsSubscription = Subscription.EMPTY;\n\n /** Subscription to changes in the tab labels. */\n private _tabLabelSubscription = Subscription.EMPTY;\n\n /** Whether the ink bar should fit its width to the size of the tab label content. */\n @Input()\n get fitInkBarToContent(): boolean {\n return this._fitInkBarToContent;\n }\n set fitInkBarToContent(v: BooleanInput) {\n this._fitInkBarToContent = coerceBooleanProperty(v);\n this._changeDetectorRef.markForCheck();\n }\n private _fitInkBarToContent = false;\n\n /** Whether tabs should be stretched to fill the header. */\n @Input('oui-stretch-tabs')\n get stretchTabs(): boolean {\n return this._stretchTabs;\n }\n set stretchTabs(v: BooleanInput) {\n this._stretchTabs = coerceBooleanProperty(v);\n }\n private _stretchTabs = true;\n\n /** Whether the tab group should grow to the size of the active tab. */\n @Input()\n get dynamicHeight(): boolean {\n return this._dynamicHeight;\n }\n\n set dynamicHeight(value: BooleanInput) {\n this._dynamicHeight = coerceBooleanProperty(value);\n }\n\n private _dynamicHeight = false;\n\n /** The index of the active tab. */\n @Input()\n get selectedIndex(): number | null {\n return this._selectedIndex;\n }\n\n set selectedIndex(value: NumberInput) {\n this._indexToSelect = coerceNumberProperty(value, null);\n }\n\n private _selectedIndex: number | null = null;\n\n /** Position of the tab header. */\n @Input() headerPosition: OuiTabHeaderPosition = 'above';\n\n /** Duration for the tab animation. Will be normalized to milliseconds if no units are set. */\n @Input()\n get animationDuration(): string {\n return this._animationDuration;\n }\n\n set animationDuration(value: NumberInput) {\n // eslint-disable-next-line @typescript-eslint/restrict-plus-operands\n this._animationDuration = /^\\d+$/.test(value + '') // eslint-disable-next-line @typescript-eslint/restrict-plus-operands\n ? value + 'ms'\n : (value as string);\n }\n\n private _animationDuration: string;\n\n /**\n * `tabindex` to be set on the inner element that wraps the tab content. Can be used for improved\n * accessibility when the tab does not have focusable elements or if it has scrollable content.\n * The `tabindex` will be removed automatically for inactive tabs.\n * Read more at https://www.w3.org/TR/wai-aria-practices/examples/tabs/tabs-2/tabs.html\n */\n @Input()\n get contentTabIndex(): number | null {\n return this._contentTabIndex;\n }\n\n set contentTabIndex(value: NumberInput) {\n this._contentTabIndex = coerceNumberProperty(value, null);\n }\n\n private _contentTabIndex: number | null;\n\n /**\n * Whether pagination should be disabled. This can be used to avoid unnecessary\n * layout recalculations if it's known that pagination won't be required.\n */\n @Input()\n get disablePagination(): boolean {\n return this._disablePagination;\n }\n\n set disablePagination(value: BooleanInput) {\n this._disablePagination = coerceBooleanProperty(value);\n }\n\n private _disablePagination = false;\n\n /**\n * By default tabs remove their content from the DOM while it's off-screen.\n * Setting this to `true` will keep it in the DOM which will prevent elements\n * like iframes and videos from reloading next time it comes back into the view.\n */\n @Input()\n get preserveContent(): boolean {\n return this._preserveContent;\n }\n\n set preserveContent(value: BooleanInput) {\n this._preserveContent = coerceBooleanProperty(value);\n }\n\n private _preserveContent = false;\n\n /** Background color of the tab group. */\n @Input()\n get backgroundColor(): ThemePalette {\n return this._backgroundColor;\n }\n\n set backgroundColor(value: ThemePalette) {\n const classList: DOMTokenList = this._elementRef.nativeElement.classList;\n\n classList.remove(\n 'oui-tabs-with-background',\n `oui-background-${this.backgroundColor}`\n );\n\n if (value) {\n classList.add('oui-tabs-with-background', `oui-background-${value}`);\n }\n\n this._backgroundColor = value;\n }\n\n private _backgroundColor: ThemePalette;\n\n /** Output to enable support for two-way binding on `[(selectedIndex)]` */\n @Output() readonly selectedIndexChange: EventEmitter =\n new EventEmitter();\n\n /** Event emitted when focus has changed within a tab group. */\n @Output() readonly focusChange: EventEmitter =\n new EventEmitter();\n\n /** Event emitted when the body animation has completed */\n @Output() readonly animationDone: EventEmitter =\n new EventEmitter();\n\n /** Event emitted when the tab selection has changed. */\n @Output() readonly selectedTabChange: EventEmitter =\n new EventEmitter(true);\n\n private _groupId: number;\n getHTMLText: any;\n updatedTabHTML: any;\n\n constructor(\n elementRef: ElementRef,\n private _changeDetectorRef: ChangeDetectorRef,\n @Inject(OUI_TABS_CONFIG) @Optional() defaultConfig?: OuiTabsConfig,\n @Optional() @Inject(ANIMATION_MODULE_TYPE) public _animationMode?: string\n ) {\n super(elementRef);\n this._groupId = nextId++;\n this.animationDuration =\n defaultConfig && defaultConfig.animationDuration\n ? defaultConfig.animationDuration\n : '500ms';\n this.disablePagination =\n defaultConfig && defaultConfig.disablePagination != null\n ? defaultConfig.disablePagination\n : false;\n this.dynamicHeight =\n defaultConfig && defaultConfig.dynamicHeight != null\n ? defaultConfig.dynamicHeight\n : false;\n this.contentTabIndex = defaultConfig?.contentTabIndex ?? null;\n this.preserveContent = !!defaultConfig?.preserveContent;\n this.fitInkBarToContent =\n defaultConfig && defaultConfig.fitInkBarToContent != null\n ? defaultConfig.fitInkBarToContent\n : false;\n this.stretchTabs =\n defaultConfig && defaultConfig.stretchTabs != null\n ? defaultConfig.stretchTabs\n : true;\n }\n\n /**\n * After the content is checked, this component knows what tabs have been defined\n * and what the selected index should be. This is where we can know exactly what position\n * each tab should be in according to the new selected index, and additionally we know how\n * a new selected tab should transition in (from the left or right).\n */\n ngAfterContentChecked() {\n // Don't clamp the `indexToSelect` immediately in the setter because it can happen that\n // the amount of tabs changes before the actual change detection runs.\n const indexToSelect = (this._indexToSelect = this._clampTabIndex(\n this._indexToSelect\n ));\n\n // If there is a change in selected index, emit a change event. Should not trigger if\n // the selected index has not yet been initialized.\n if (this._selectedIndex != indexToSelect) {\n const isFirstRun = this._selectedIndex == null;\n\n if (!isFirstRun) {\n this.selectedTabChange.emit(this._createChangeEvent(indexToSelect));\n // Preserve the height so page doesn't scroll up during tab change.\n // Fixes https://stackblitz.com/edit/mat-tabs-scroll-page-top-on-tab-change\n const wrapper = this._tabBodyWrapper.nativeElement;\n // eslint-disable-next-line @typescript-eslint/restrict-plus-operands\n wrapper.style.minHeight = wrapper.clientHeight + 'px';\n }\n\n // Changing these values after change detection has run\n // since the checked content may contain references to them.\n Promise.resolve().then(() => {\n this._tabs.forEach(\n (tab, index) => (tab.isActive = index === indexToSelect)\n );\n\n if (!isFirstRun) {\n this.selectedIndexChange.emit(indexToSelect);\n // Clear the min-height, this was needed during tab change to avoid\n // unnecessary scrolling.\n this._tabBodyWrapper.nativeElement.style.minHeight = '';\n }\n });\n }\n\n // Setup the position for each tab and optionally setup an origin on the next selected tab.\n this._tabs.forEach((tab: OuiTab, index: number) => {\n tab.position = index - indexToSelect;\n\n // If there is already a selected tab, then set up an origin for the next selected tab\n // if it doesn't have one already.\n if (this._selectedIndex != null && tab.position == 0 && !tab.origin) {\n tab.origin = indexToSelect - this._selectedIndex;\n }\n });\n\n if (this._selectedIndex !== indexToSelect) {\n this._selectedIndex = indexToSelect;\n this._lastFocusedTabIndex = null;\n this._changeDetectorRef.markForCheck();\n }\n }\n\n ngAfterContentInit() {\n this._subscribeToAllTabChanges();\n this._subscribeToTabLabels();\n // Subscribe to changes in the amount of tabs, in order to be\n // able to re-render the content as new tabs are added or removed.\n this._tabsSubscription = this._tabs.changes.subscribe(() => {\n const indexToSelect = this._clampTabIndex(this._indexToSelect);\n\n // Maintain the previously-selected tab if a new tab is added or removed and there is no\n // explicit change that selects a different tab.\n if (indexToSelect === this._selectedIndex) {\n const tabs = this._tabs.toArray();\n let selectedTab: OuiTab | undefined;\n\n for (let i = 0; i < tabs.length; i++) {\n if (tabs[i].isActive) {\n // Assign both to the `_indexToSelect` and `_selectedIndex` so we don't fire a changed\n // event, otherwise the consumer may end up in an infinite loop in some edge cases like\n // adding a tab within the `selectedIndexChange` event.\n this._indexToSelect = this._selectedIndex = i;\n this._lastFocusedTabIndex = null;\n selectedTab = tabs[i];\n break;\n }\n }\n\n // If we haven't found an active tab and a tab exists at the selected index, it means\n // that the active tab was swapped out. Since this won't be picked up by the rendering\n // loop in `ngAfterContentChecked`, we need to sync it up manually.\n if (!selectedTab && tabs[indexToSelect]) {\n Promise.resolve().then(() => {\n tabs[indexToSelect].isActive = true;\n this.selectedTabChange.emit(this._createChangeEvent(indexToSelect));\n });\n }\n }\n\n this._changeDetectorRef.markForCheck();\n });\n }\n\n /** Listens to changes in all of the tabs. */\n private _subscribeToAllTabChanges() {\n // Since we use a query with `descendants: true` to pick up the tabs, we may end up catching\n // some that are inside of nested tab groups. We filter them out manually by checking that\n // the closest group to the tab is the current one.\n this.getHTMLText = this._allTabs['_results'][0].givenText;\n this.updatedTabHTML = this.getHTMLText;\n this._allTabs.changes\n .pipe(startWith(this._allTabs))\n .subscribe((tabs: QueryList) => {\n this._tabs.reset(\n tabs.filter((tab) => {\n return tab._closestTabGroup === this || !tab._closestTabGroup;\n })\n );\n this._tabs.notifyOnChanges();\n });\n }\n\n ngOnDestroy() {\n this._tabs.destroy();\n this._tabsSubscription.unsubscribe();\n this._tabLabelSubscription.unsubscribe();\n }\n\n /** Re-aligns the ink bar to the selected tab element. */\n realignInkBar() {\n if (this._tabHeader) {\n this._tabHeader._alignInkBarToSelectedTab();\n }\n }\n\n /**\n * Recalculates the tab group's pagination dimensions.\n *\n * WARNING: Calling this method can be very costly in terms of performance. It should be called\n * as infrequently as possible from outside of the Tabs component as it causes a reflow of the\n * page.\n */\n updatePagination() {\n if (this._tabHeader) {\n this._tabHeader.updatePagination();\n }\n }\n\n /**\n * Sets focus to a particular tab.\n * @param index Index of the tab to be focused.\n */\n focusTab(index: number) {\n const header = this._tabHeader;\n\n if (header) {\n header.focusIndex = index;\n }\n }\n\n _focusChanged(index: number) {\n this._lastFocusedTabIndex = index;\n this.focusChange.emit(this._createChangeEvent(index));\n }\n\n private _createChangeEvent(index: number): OuiTabChangeEvent {\n const event = new OuiTabChangeEvent();\n event.index = index;\n if (this._tabs && this._tabs.length) {\n event.tab = this._tabs.toArray()[index];\n this.updatedTabHTML = event.tab.givenText;\n }\n return event;\n }\n\n _handleEnter() {\n this.getHTMLText = this.updatedTabHTML;\n }\n\n /**\n * Subscribes to changes in the tab labels. This is needed, because the @Input for the label is\n * on the OuiTab component, whereas the data binding is inside the ouiTabGroup. In order for the\n * binding to be updated, we need to subscribe to changes in it and trigger change detection\n * manually.\n */\n private _subscribeToTabLabels() {\n if (this._tabLabelSubscription) {\n this._tabLabelSubscription.unsubscribe();\n }\n\n this._tabLabelSubscription = merge(\n ...this._tabs.map((tab) => tab._stateChanges)\n ).subscribe(() => this._changeDetectorRef.markForCheck());\n }\n\n /** Clamps the given index to the bounds of 0 and the tabs length. */\n private _clampTabIndex(index: number | null): number {\n // Note the `|| 0`, which ensures that values like NaN can't get through\n // and which would otherwise throw the component into an infinite loop\n // (since Math.max(NaN, 0) === NaN).\n return Math.min(this._tabs.length - 1, Math.max(index || 0, 0));\n }\n\n /** Returns a unique id for each tab label element */\n _getTabLabelId(i: number): string {\n return `oui-tab-label-${this._groupId}-${i}`;\n }\n\n /** Returns a unique id for each tab content element */\n _getTabContentId(i: number): string {\n return `oui-tab-content-${this._groupId}-${i}`;\n }\n\n /**\n * Sets the height of the body wrapper to the height of the activating tab if dynamic\n * height property is true.\n */\n _setTabBodyWrapperHeight(tabHeight: number): void {\n if (!this._dynamicHeight || !this._tabBodyWrapperHeight) {\n return;\n }\n\n const wrapper: HTMLElement = this._tabBodyWrapper.nativeElement;\n // eslint-disable-next-line @typescript-eslint/restrict-plus-operands\n wrapper.style.height = this._tabBodyWrapperHeight + 'px';\n\n // This conditional forces the browser to paint the height so that\n // the animation to the new height can have an origin.\n if (this._tabBodyWrapper.nativeElement.offsetHeight) {\n // eslint-disable-next-line @typescript-eslint/restrict-plus-operands\n wrapper.style.height = tabHeight + 'px';\n }\n }\n\n /** Removes the height of the tab body wrapper. */\n _removeTabBodyWrapperHeight(): void {\n const wrapper = this._tabBodyWrapper.nativeElement;\n this._tabBodyWrapperHeight = wrapper.clientHeight;\n wrapper.style.height = '';\n this.animationDone.emit();\n }\n\n /** Handle click events, setting new selected index if appropriate. */\n _handleClick(tab: OuiTab, tabHeader: OuiTabGroupBaseHeader, index: number) {\n tabHeader.focusIndex = index;\n this.getHTMLText = this.updatedTabHTML;\n\n if (!tab.disabled) {\n this.selectedIndex = index;\n }\n }\n\n /** Retrieves the tabindex for the tab. */\n _getTabIndex(index: number): number {\n const targetIndex = this._lastFocusedTabIndex ?? this.selectedIndex;\n return index === targetIndex ? 0 : -1;\n }\n\n /** Callback for when the focused state of a tab has changed. */\n _tabFocusChanged(focusOrigin: FocusOrigin, index: number) {\n // Mouse/touch focus happens during the `mousedown`/`touchstart` phase which\n // can cause the tab to be moved out from under the pointer, interrupting the\n // click sequence (see #21898). We don't need to scroll the tab into view for\n // such cases anyway, because it will be done when the tab becomes selected.\n if (focusOrigin && focusOrigin !== 'mouse' && focusOrigin !== 'touch') {\n this._tabHeader.focusIndex = index;\n }\n }\n}\n\n/** A simple change event emitted on focus or selection changes. */\nexport class OuiTabChangeEvent {\n /** Index of the currently-selected tab. */\n index: number;\n /** Reference to the currently-selected tab. */\n tab: OuiTab;\n event: Event;\n}\n", + "sourceCode": "import {\r\n AfterContentChecked,\r\n AfterContentInit,\r\n ChangeDetectionStrategy,\r\n ChangeDetectorRef,\r\n Component,\r\n ContentChildren,\r\n ElementRef,\r\n EventEmitter,\r\n Inject,\r\n Input,\r\n OnDestroy,\r\n Optional,\r\n Output,\r\n QueryList,\r\n ViewChild,\r\n ViewEncapsulation,\r\n} from '@angular/core';\r\nimport { ANIMATION_MODULE_TYPE } from '@angular/platform-browser/animations';\r\nimport { OUI_TAB_GROUP, OuiTab } from './tab';\r\nimport { OuiTabHeader } from './tab-header';\r\nimport {\r\n BooleanInput,\r\n coerceBooleanProperty,\r\n coerceNumberProperty,\r\n NumberInput,\r\n} from '@angular/cdk/coercion';\r\nimport {\r\n CanColor,\r\n CanDisableRipple,\r\n mixinColor,\r\n mixinDisableRipple,\r\n ThemePalette,\r\n} from '../core';\r\nimport { merge, Subscription } from 'rxjs';\r\nimport { OUI_TABS_CONFIG, OuiTabsConfig } from './tab-config';\r\nimport { startWith } from 'rxjs/operators';\r\nimport { FocusOrigin } from '@angular/cdk/a11y';\r\n\r\n/** Used to generate unique ID's for each tab component */\r\nlet nextId = 0;\r\n\r\n// Boilerplate for applying mixins to ouiTabGroup.\r\n/** @docs-private */\r\nconst _OuiTabGroupMixinBase = mixinColor(\r\n mixinDisableRipple(\r\n class {\r\n constructor(public _elementRef: ElementRef) {}\r\n }\r\n ),\r\n 'primary'\r\n);\r\n\r\n/** @docs-private */\r\nexport interface OuiTabGroupBaseHeader {\r\n _alignInkBarToSelectedTab(): void;\r\n updatePagination(): void;\r\n focusIndex: number;\r\n}\r\n\r\n/** Possible positions for the tab header. */\r\nexport type OuiTabHeaderPosition = 'above' | 'below';\r\n\r\n/**\r\n * Material design tab-group component. Supports basic tab pairs (label + content) and includes\r\n * animated ink-bar, keyboard navigation, and screen reader.\r\n * See: https://material.io/design/components/tabs.html\r\n */\r\n@Component({\r\n selector: 'oui-tab-group',\r\n exportAs: 'ouiTabGroup',\r\n templateUrl: 'tab-group.html',\r\n styleUrls: ['tab-group.scss'],\r\n encapsulation: ViewEncapsulation.None,\r\n // tslint:disable-next-line:validate-decorators\r\n changeDetection: ChangeDetectionStrategy.Default,\r\n // eslint-disable-next-line\r\n inputs: ['color', 'disableRipple'],\r\n providers: [\r\n {\r\n provide: OUI_TAB_GROUP,\r\n useExisting: ouiTabGroup,\r\n },\r\n ],\r\n // eslint-disable-next-line\r\n host: {\r\n ngSkipHydration: '',\r\n class: 'oui-mdc-tab-group oui-tab',\r\n '[class.oui-mdc-tab-group-dynamic-height]': 'dynamicHeight',\r\n '[class.oui-mdc-tab-group-inverted-header]': 'headerPosition === \"below\"',\r\n '[class.oui-mdc-tab-group-stretch-tabs]': 'stretchTabs',\r\n '[style.--oui-tab-animation-duration]': 'animationDuration',\r\n },\r\n})\r\nexport class ouiTabGroup\r\n extends _OuiTabGroupMixinBase\r\n implements\r\n AfterContentInit,\r\n AfterContentChecked,\r\n OnDestroy,\r\n CanColor,\r\n CanDisableRipple\r\n{\r\n /**\r\n * All tabs inside the tab group. This includes tabs that belong to groups that are nested\r\n * inside the current one. We filter out only the tabs that belong to this group in `_tabs`.\r\n */\r\n @ContentChildren(OuiTab, { descendants: true }) _allTabs: QueryList;\r\n @ViewChild('tabBodyWrapper') _tabBodyWrapper: ElementRef;\r\n @ViewChild('tabHeader') _tabHeader: OuiTabHeader;\r\n\r\n /** All of the tabs that belong to the group. */\r\n _tabs: QueryList = new QueryList();\r\n\r\n /** The tab index that should be selected after the content has been checked. */\r\n private _indexToSelect: number | null = 0;\r\n\r\n /** Index of the tab that was focused last. */\r\n private _lastFocusedTabIndex: number | null = null;\r\n\r\n /** Snapshot of the height of the tab body wrapper before another tab is activated. */\r\n private _tabBodyWrapperHeight = 0;\r\n\r\n /** Subscription to tabs being added/removed. */\r\n private _tabsSubscription = Subscription.EMPTY;\r\n\r\n /** Subscription to changes in the tab labels. */\r\n private _tabLabelSubscription = Subscription.EMPTY;\r\n\r\n /** Whether the ink bar should fit its width to the size of the tab label content. */\r\n @Input()\r\n get fitInkBarToContent(): boolean {\r\n return this._fitInkBarToContent;\r\n }\r\n set fitInkBarToContent(v: BooleanInput) {\r\n this._fitInkBarToContent = coerceBooleanProperty(v);\r\n this._changeDetectorRef.markForCheck();\r\n }\r\n private _fitInkBarToContent = false;\r\n\r\n /** Whether tabs should be stretched to fill the header. */\r\n @Input('oui-stretch-tabs')\r\n get stretchTabs(): boolean {\r\n return this._stretchTabs;\r\n }\r\n set stretchTabs(v: BooleanInput) {\r\n this._stretchTabs = coerceBooleanProperty(v);\r\n }\r\n private _stretchTabs = true;\r\n\r\n /** Whether the tab group should grow to the size of the active tab. */\r\n @Input()\r\n get dynamicHeight(): boolean {\r\n return this._dynamicHeight;\r\n }\r\n\r\n set dynamicHeight(value: BooleanInput) {\r\n this._dynamicHeight = coerceBooleanProperty(value);\r\n }\r\n\r\n private _dynamicHeight = false;\r\n\r\n /** The index of the active tab. */\r\n @Input()\r\n get selectedIndex(): number | null {\r\n return this._selectedIndex;\r\n }\r\n\r\n set selectedIndex(value: NumberInput) {\r\n this._indexToSelect = coerceNumberProperty(value, null);\r\n }\r\n\r\n private _selectedIndex: number | null = null;\r\n\r\n /** Position of the tab header. */\r\n @Input() headerPosition: OuiTabHeaderPosition = 'above';\r\n\r\n /** Duration for the tab animation. Will be normalized to milliseconds if no units are set. */\r\n @Input()\r\n get animationDuration(): string {\r\n return this._animationDuration;\r\n }\r\n\r\n set animationDuration(value: NumberInput) {\r\n // eslint-disable-next-line @typescript-eslint/restrict-plus-operands\r\n this._animationDuration = /^\\d+$/.test(value + '') // eslint-disable-next-line @typescript-eslint/restrict-plus-operands\r\n ? value + 'ms'\r\n : (value as string);\r\n }\r\n\r\n private _animationDuration: string;\r\n\r\n /**\r\n * `tabindex` to be set on the inner element that wraps the tab content. Can be used for improved\r\n * accessibility when the tab does not have focusable elements or if it has scrollable content.\r\n * The `tabindex` will be removed automatically for inactive tabs.\r\n * Read more at https://www.w3.org/TR/wai-aria-practices/examples/tabs/tabs-2/tabs.html\r\n */\r\n @Input()\r\n get contentTabIndex(): number | null {\r\n return this._contentTabIndex;\r\n }\r\n\r\n set contentTabIndex(value: NumberInput) {\r\n this._contentTabIndex = coerceNumberProperty(value, null);\r\n }\r\n\r\n private _contentTabIndex: number | null;\r\n\r\n /**\r\n * Whether pagination should be disabled. This can be used to avoid unnecessary\r\n * layout recalculations if it's known that pagination won't be required.\r\n */\r\n @Input()\r\n get disablePagination(): boolean {\r\n return this._disablePagination;\r\n }\r\n\r\n set disablePagination(value: BooleanInput) {\r\n this._disablePagination = coerceBooleanProperty(value);\r\n }\r\n\r\n private _disablePagination = false;\r\n\r\n /**\r\n * By default tabs remove their content from the DOM while it's off-screen.\r\n * Setting this to `true` will keep it in the DOM which will prevent elements\r\n * like iframes and videos from reloading next time it comes back into the view.\r\n */\r\n @Input()\r\n get preserveContent(): boolean {\r\n return this._preserveContent;\r\n }\r\n\r\n set preserveContent(value: BooleanInput) {\r\n this._preserveContent = coerceBooleanProperty(value);\r\n }\r\n\r\n private _preserveContent = false;\r\n\r\n /** Background color of the tab group. */\r\n @Input()\r\n get backgroundColor(): ThemePalette {\r\n return this._backgroundColor;\r\n }\r\n\r\n set backgroundColor(value: ThemePalette) {\r\n const classList: DOMTokenList = this._elementRef.nativeElement.classList;\r\n\r\n classList.remove(\r\n 'oui-tabs-with-background',\r\n `oui-background-${this.backgroundColor}`\r\n );\r\n\r\n if (value) {\r\n classList.add('oui-tabs-with-background', `oui-background-${value}`);\r\n }\r\n\r\n this._backgroundColor = value;\r\n }\r\n\r\n private _backgroundColor: ThemePalette;\r\n\r\n /** Output to enable support for two-way binding on `[(selectedIndex)]` */\r\n @Output() readonly selectedIndexChange: EventEmitter =\r\n new EventEmitter();\r\n\r\n /** Event emitted when focus has changed within a tab group. */\r\n @Output() readonly focusChange: EventEmitter =\r\n new EventEmitter();\r\n\r\n /** Event emitted when the body animation has completed */\r\n @Output() readonly animationDone: EventEmitter =\r\n new EventEmitter();\r\n\r\n /** Event emitted when the tab selection has changed. */\r\n @Output() readonly selectedTabChange: EventEmitter =\r\n new EventEmitter(true);\r\n\r\n private _groupId: number;\r\n getHTMLText: any;\r\n updatedTabHTML: any;\r\n\r\n constructor(\r\n elementRef: ElementRef,\r\n private _changeDetectorRef: ChangeDetectorRef,\r\n @Inject(OUI_TABS_CONFIG) @Optional() defaultConfig?: OuiTabsConfig,\r\n @Optional() @Inject(ANIMATION_MODULE_TYPE) public _animationMode?: string\r\n ) {\r\n super(elementRef);\r\n this._groupId = nextId++;\r\n this.animationDuration =\r\n defaultConfig && defaultConfig.animationDuration\r\n ? defaultConfig.animationDuration\r\n : '500ms';\r\n this.disablePagination =\r\n defaultConfig && defaultConfig.disablePagination != null\r\n ? defaultConfig.disablePagination\r\n : false;\r\n this.dynamicHeight =\r\n defaultConfig && defaultConfig.dynamicHeight != null\r\n ? defaultConfig.dynamicHeight\r\n : false;\r\n this.contentTabIndex = defaultConfig?.contentTabIndex ?? null;\r\n this.preserveContent = !!defaultConfig?.preserveContent;\r\n this.fitInkBarToContent =\r\n defaultConfig && defaultConfig.fitInkBarToContent != null\r\n ? defaultConfig.fitInkBarToContent\r\n : false;\r\n this.stretchTabs =\r\n defaultConfig && defaultConfig.stretchTabs != null\r\n ? defaultConfig.stretchTabs\r\n : true;\r\n }\r\n\r\n /**\r\n * After the content is checked, this component knows what tabs have been defined\r\n * and what the selected index should be. This is where we can know exactly what position\r\n * each tab should be in according to the new selected index, and additionally we know how\r\n * a new selected tab should transition in (from the left or right).\r\n */\r\n ngAfterContentChecked() {\r\n // Don't clamp the `indexToSelect` immediately in the setter because it can happen that\r\n // the amount of tabs changes before the actual change detection runs.\r\n const indexToSelect = (this._indexToSelect = this._clampTabIndex(\r\n this._indexToSelect\r\n ));\r\n\r\n // If there is a change in selected index, emit a change event. Should not trigger if\r\n // the selected index has not yet been initialized.\r\n if (this._selectedIndex != indexToSelect) {\r\n const isFirstRun = this._selectedIndex == null;\r\n\r\n if (!isFirstRun) {\r\n this.selectedTabChange.emit(this._createChangeEvent(indexToSelect));\r\n // Preserve the height so page doesn't scroll up during tab change.\r\n // Fixes https://stackblitz.com/edit/mat-tabs-scroll-page-top-on-tab-change\r\n const wrapper = this._tabBodyWrapper.nativeElement;\r\n // eslint-disable-next-line @typescript-eslint/restrict-plus-operands\r\n wrapper.style.minHeight = wrapper.clientHeight + 'px';\r\n }\r\n\r\n // Changing these values after change detection has run\r\n // since the checked content may contain references to them.\r\n Promise.resolve().then(() => {\r\n this._tabs.forEach(\r\n (tab, index) => (tab.isActive = index === indexToSelect)\r\n );\r\n\r\n if (!isFirstRun) {\r\n this.selectedIndexChange.emit(indexToSelect);\r\n // Clear the min-height, this was needed during tab change to avoid\r\n // unnecessary scrolling.\r\n this._tabBodyWrapper.nativeElement.style.minHeight = '';\r\n }\r\n });\r\n }\r\n\r\n // Setup the position for each tab and optionally setup an origin on the next selected tab.\r\n this._tabs.forEach((tab: OuiTab, index: number) => {\r\n tab.position = index - indexToSelect;\r\n\r\n // If there is already a selected tab, then set up an origin for the next selected tab\r\n // if it doesn't have one already.\r\n if (this._selectedIndex != null && tab.position == 0 && !tab.origin) {\r\n tab.origin = indexToSelect - this._selectedIndex;\r\n }\r\n });\r\n\r\n if (this._selectedIndex !== indexToSelect) {\r\n this._selectedIndex = indexToSelect;\r\n this._lastFocusedTabIndex = null;\r\n this._changeDetectorRef.markForCheck();\r\n }\r\n }\r\n\r\n ngAfterContentInit() {\r\n this._subscribeToAllTabChanges();\r\n this._subscribeToTabLabels();\r\n // Subscribe to changes in the amount of tabs, in order to be\r\n // able to re-render the content as new tabs are added or removed.\r\n this._tabsSubscription = this._tabs.changes.subscribe(() => {\r\n const indexToSelect = this._clampTabIndex(this._indexToSelect);\r\n\r\n // Maintain the previously-selected tab if a new tab is added or removed and there is no\r\n // explicit change that selects a different tab.\r\n if (indexToSelect === this._selectedIndex) {\r\n const tabs = this._tabs.toArray();\r\n let selectedTab: OuiTab | undefined;\r\n\r\n for (let i = 0; i < tabs.length; i++) {\r\n if (tabs[i].isActive) {\r\n // Assign both to the `_indexToSelect` and `_selectedIndex` so we don't fire a changed\r\n // event, otherwise the consumer may end up in an infinite loop in some edge cases like\r\n // adding a tab within the `selectedIndexChange` event.\r\n this._indexToSelect = this._selectedIndex = i;\r\n this._lastFocusedTabIndex = null;\r\n selectedTab = tabs[i];\r\n break;\r\n }\r\n }\r\n\r\n // If we haven't found an active tab and a tab exists at the selected index, it means\r\n // that the active tab was swapped out. Since this won't be picked up by the rendering\r\n // loop in `ngAfterContentChecked`, we need to sync it up manually.\r\n if (!selectedTab && tabs[indexToSelect]) {\r\n Promise.resolve().then(() => {\r\n tabs[indexToSelect].isActive = true;\r\n this.selectedTabChange.emit(this._createChangeEvent(indexToSelect));\r\n });\r\n }\r\n }\r\n\r\n this._changeDetectorRef.markForCheck();\r\n });\r\n }\r\n\r\n /** Listens to changes in all of the tabs. */\r\n private _subscribeToAllTabChanges() {\r\n // Since we use a query with `descendants: true` to pick up the tabs, we may end up catching\r\n // some that are inside of nested tab groups. We filter them out manually by checking that\r\n // the closest group to the tab is the current one.\r\n this.getHTMLText = this._allTabs['_results'][0].givenText;\r\n this.updatedTabHTML = this.getHTMLText;\r\n this._allTabs.changes\r\n .pipe(startWith(this._allTabs))\r\n .subscribe((tabs: QueryList) => {\r\n this._tabs.reset(\r\n tabs.filter((tab) => {\r\n return tab._closestTabGroup === this || !tab._closestTabGroup;\r\n })\r\n );\r\n this._tabs.notifyOnChanges();\r\n });\r\n }\r\n\r\n ngOnDestroy() {\r\n this._tabs.destroy();\r\n this._tabsSubscription.unsubscribe();\r\n this._tabLabelSubscription.unsubscribe();\r\n }\r\n\r\n /** Re-aligns the ink bar to the selected tab element. */\r\n realignInkBar() {\r\n if (this._tabHeader) {\r\n this._tabHeader._alignInkBarToSelectedTab();\r\n }\r\n }\r\n\r\n /**\r\n * Recalculates the tab group's pagination dimensions.\r\n *\r\n * WARNING: Calling this method can be very costly in terms of performance. It should be called\r\n * as infrequently as possible from outside of the Tabs component as it causes a reflow of the\r\n * page.\r\n */\r\n updatePagination() {\r\n if (this._tabHeader) {\r\n this._tabHeader.updatePagination();\r\n }\r\n }\r\n\r\n /**\r\n * Sets focus to a particular tab.\r\n * @param index Index of the tab to be focused.\r\n */\r\n focusTab(index: number) {\r\n const header = this._tabHeader;\r\n\r\n if (header) {\r\n header.focusIndex = index;\r\n }\r\n }\r\n\r\n _focusChanged(index: number) {\r\n this._lastFocusedTabIndex = index;\r\n this.focusChange.emit(this._createChangeEvent(index));\r\n }\r\n\r\n private _createChangeEvent(index: number): OuiTabChangeEvent {\r\n const event = new OuiTabChangeEvent();\r\n event.index = index;\r\n if (this._tabs && this._tabs.length) {\r\n event.tab = this._tabs.toArray()[index];\r\n this.updatedTabHTML = event.tab.givenText;\r\n }\r\n return event;\r\n }\r\n\r\n _handleEnter() {\r\n this.getHTMLText = this.updatedTabHTML;\r\n }\r\n\r\n /**\r\n * Subscribes to changes in the tab labels. This is needed, because the @Input for the label is\r\n * on the OuiTab component, whereas the data binding is inside the ouiTabGroup. In order for the\r\n * binding to be updated, we need to subscribe to changes in it and trigger change detection\r\n * manually.\r\n */\r\n private _subscribeToTabLabels() {\r\n if (this._tabLabelSubscription) {\r\n this._tabLabelSubscription.unsubscribe();\r\n }\r\n\r\n this._tabLabelSubscription = merge(\r\n ...this._tabs.map((tab) => tab._stateChanges)\r\n ).subscribe(() => this._changeDetectorRef.markForCheck());\r\n }\r\n\r\n /** Clamps the given index to the bounds of 0 and the tabs length. */\r\n private _clampTabIndex(index: number | null): number {\r\n // Note the `|| 0`, which ensures that values like NaN can't get through\r\n // and which would otherwise throw the component into an infinite loop\r\n // (since Math.max(NaN, 0) === NaN).\r\n return Math.min(this._tabs.length - 1, Math.max(index || 0, 0));\r\n }\r\n\r\n /** Returns a unique id for each tab label element */\r\n _getTabLabelId(i: number): string {\r\n return `oui-tab-label-${this._groupId}-${i}`;\r\n }\r\n\r\n /** Returns a unique id for each tab content element */\r\n _getTabContentId(i: number): string {\r\n return `oui-tab-content-${this._groupId}-${i}`;\r\n }\r\n\r\n /**\r\n * Sets the height of the body wrapper to the height of the activating tab if dynamic\r\n * height property is true.\r\n */\r\n _setTabBodyWrapperHeight(tabHeight: number): void {\r\n if (!this._dynamicHeight || !this._tabBodyWrapperHeight) {\r\n return;\r\n }\r\n\r\n const wrapper: HTMLElement = this._tabBodyWrapper.nativeElement;\r\n // eslint-disable-next-line @typescript-eslint/restrict-plus-operands\r\n wrapper.style.height = this._tabBodyWrapperHeight + 'px';\r\n\r\n // This conditional forces the browser to paint the height so that\r\n // the animation to the new height can have an origin.\r\n if (this._tabBodyWrapper.nativeElement.offsetHeight) {\r\n // eslint-disable-next-line @typescript-eslint/restrict-plus-operands\r\n wrapper.style.height = tabHeight + 'px';\r\n }\r\n }\r\n\r\n /** Removes the height of the tab body wrapper. */\r\n _removeTabBodyWrapperHeight(): void {\r\n const wrapper = this._tabBodyWrapper.nativeElement;\r\n this._tabBodyWrapperHeight = wrapper.clientHeight;\r\n wrapper.style.height = '';\r\n this.animationDone.emit();\r\n }\r\n\r\n /** Handle click events, setting new selected index if appropriate. */\r\n _handleClick(tab: OuiTab, tabHeader: OuiTabGroupBaseHeader, index: number) {\r\n tabHeader.focusIndex = index;\r\n this.getHTMLText = this.updatedTabHTML;\r\n\r\n if (!tab.disabled) {\r\n this.selectedIndex = index;\r\n }\r\n }\r\n\r\n /** Retrieves the tabindex for the tab. */\r\n _getTabIndex(index: number): number {\r\n const targetIndex = this._lastFocusedTabIndex ?? this.selectedIndex;\r\n return index === targetIndex ? 0 : -1;\r\n }\r\n\r\n /** Callback for when the focused state of a tab has changed. */\r\n _tabFocusChanged(focusOrigin: FocusOrigin, index: number) {\r\n // Mouse/touch focus happens during the `mousedown`/`touchstart` phase which\r\n // can cause the tab to be moved out from under the pointer, interrupting the\r\n // click sequence (see #21898). We don't need to scroll the tab into view for\r\n // such cases anyway, because it will be done when the tab becomes selected.\r\n if (focusOrigin && focusOrigin !== 'mouse' && focusOrigin !== 'touch') {\r\n this._tabHeader.focusIndex = index;\r\n }\r\n }\r\n}\r\n\r\n/** A simple change event emitted on focus or selection changes. */\r\nexport class OuiTabChangeEvent {\r\n /** Index of the currently-selected tab. */\r\n index: number;\r\n /** Reference to the currently-selected tab. */\r\n tab: OuiTab;\r\n event: Event;\r\n}\r\n", "properties": [ { "name": "event", @@ -10311,6 +10393,7 @@ "rawdescription": "\nA simple change event emitted on focus or selection changes.", "methods": [], "indexSignatures": [], + "extends": [], "inputsClass": [], "outputsClass": [], "hostBindings": [], @@ -10363,8 +10446,8 @@ "line": 31, "rawdescription": "\nStream that emits when a new data array is set on the data source.", "modifierKind": [ - 121, - 144 + 123, + 148 ] }, { @@ -10378,8 +10461,8 @@ "line": 37, "rawdescription": "\nStream that emits when a new filter string is set on the data source.", "modifierKind": [ - 121, - 144 + 123, + 148 ] }, { @@ -10391,7 +10474,7 @@ "description": "", "line": 102, "modifierKind": [ - 121 + 123 ] }, { @@ -10416,8 +10499,8 @@ "line": 34, "rawdescription": "\nStream emitting render data to the table (depends on ordered data changes).", "modifierKind": [ - 121, - 144 + 123, + 148 ] }, { @@ -10429,7 +10512,7 @@ "description": "", "line": 83, "modifierKind": [ - 121 + 123 ] }, { @@ -10456,27 +10539,27 @@ { "pos": 7220, "end": 7283, - "flags": 4227072, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 338, + "kind": 348, "tagName": { "pos": 7221, "end": 7226, - "flags": 4227072, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "param" }, "comment": "

Data object used to check against the filter.

\n", "name": { "pos": 7227, "end": 7231, - "flags": 4227072, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "data" }, "isNameFirst": true, @@ -10485,27 +10568,27 @@ { "pos": 7283, "end": 7354, - "flags": 4227072, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 338, + "kind": 348, "tagName": { "pos": 7284, "end": 7289, - "flags": 4227072, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "param" }, "comment": "

Filter string that has been set on the data source.

\n", "name": { "pos": 7290, "end": 7296, - "flags": 4227072, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "filter" }, "isNameFirst": true, @@ -10514,17 +10597,17 @@ { "pos": 7354, "end": 7410, - "flags": 4227072, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 339, + "kind": 349, "tagName": { "pos": 7355, "end": 7362, - "flags": 4227072, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "returns" }, "comment": "

Whether the filter matches against the data

\n" @@ -10545,27 +10628,27 @@ { "pos": 5252, "end": 5310, - "flags": 4227072, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 338, + "kind": 348, "tagName": { "pos": 5253, "end": 5258, - "flags": 4227072, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "param" }, "comment": "

The array of data that should be sorted.

\n", "name": { "pos": 5259, "end": 5263, - "flags": 4227072, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "data" }, "isNameFirst": true, @@ -10574,27 +10657,27 @@ { "pos": 5310, "end": 5382, - "flags": 4227072, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 338, + "kind": 348, "tagName": { "pos": 5311, "end": 5316, - "flags": 4227072, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "param" }, "comment": "

The connected OuiSort that holds the current sort state.

\n", "name": { "pos": 5317, "end": 5321, - "flags": 4227072, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "sort" }, "isNameFirst": true, @@ -10616,27 +10699,27 @@ { "pos": 4185, "end": 4238, - "flags": 4227072, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 338, + "kind": 348, "tagName": { "pos": 4186, "end": 4191, - "flags": 4227072, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "param" }, "comment": "

Data object that is being accessed.

\n", "name": { "pos": 4192, "end": 4196, - "flags": 4227072, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "data" }, "isNameFirst": true, @@ -10645,27 +10728,27 @@ { "pos": 4238, "end": 4310, - "flags": 4227072, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 338, + "kind": 348, "tagName": { "pos": 4239, "end": 4244, - "flags": 4227072, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "param" }, "comment": "

The name of the column that represents the data.

\n", "name": { "pos": 4245, "end": 4257, - "flags": 4227072, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "sortHeaderId" }, "isNameFirst": true, @@ -10837,7 +10920,9 @@ } ], "indexSignatures": [], - "extends": "DataSource", + "extends": [ + "DataSource" + ], "accessors": { "data": { "name": "data", @@ -10999,12 +11084,12 @@ }, { "name": "OuiTabsBase", - "id": "class-OuiTabsBase-45bae687b6cd051731506a0bb8869f3a20d3380d7104d6f3cdfb49e2bd1fdb6c4a90a32d60d32382a5489b93a236c24544d86f0a65f4cca3d9f50ece71ea5c93", + "id": "class-OuiTabsBase-90101422686a726eb69c50499e9ec74197febce4088a5e86c3b704858597fd644e9b89a1b60a173f1983d03998f71c65913b11ac249b411b2c954bfd8a2e0b22", "file": "ui/src/components/tabs/tab.ts", "deprecated": false, "deprecationMessage": "", "type": "class", - "sourceCode": "import {\n ChangeDetectionStrategy,\n Component,\n ContentChild,\n ElementRef,\n Inject,\n InjectionToken,\n Input,\n OnChanges,\n OnDestroy,\n OnInit,\n Optional,\n SimpleChanges,\n TemplateRef,\n ViewChild,\n ViewContainerRef,\n ViewEncapsulation,\n} from '@angular/core';\nimport { OuiTabContent } from './tab-content';\nimport { OUI_TAB, OuiTabLabel } from './tab-label';\nimport { CanDisable, mixinColor } from '../core';\nimport { TemplatePortal } from '@angular/cdk/portal';\nimport { Subject } from 'rxjs';\n\nexport class OuiTabsBase {\n constructor(public _elementRef: ElementRef) {}\n}\n// Boilerplate for applying mixins to OuiTab.\n/** @docs-private */\nconst _OuiTabMixinBase: typeof OuiTabsBase = mixinColor(OuiTabsBase);\n\n/**\n * Used to provide a tab group to a tab without causing a circular dependency.\n * @docs-private\n */\nexport const OUI_TAB_GROUP = new InjectionToken('OUI_TAB_GROUP');\n\n/** Default color palette for the tab */\nconst DEFAULT_COLOR = 'primary';\n\n@Component({\n selector: 'oui-tab',\n\n // Note that usually we'd go through a bit more trouble and set up another class so that\n // the inlined template of `OuiTab` isn't duplicated, however the template is small enough\n // that creating the extra class will generate more code than just duplicating the template.\n templateUrl: 'tab.html',\n // eslint-disable-next-line @angular-eslint/no-inputs-metadata-property\n inputs: ['disabled'],\n // eslint-disable-next-line @angular-eslint/no-inputs-metadata-property\n changeDetection: ChangeDetectionStrategy.Default,\n encapsulation: ViewEncapsulation.None,\n exportAs: 'OuiTab',\n providers: [{ provide: OUI_TAB, useExisting: OuiTab }],\n})\nexport class OuiTab\n extends _OuiTabMixinBase\n implements CanDisable, OnInit, OnChanges, OnDestroy\n{\n /** Content for the tab label given by ``. */\n private _templateLabel: OuiTabLabel;\n disabled: any;\n @ContentChild(OuiTabLabel)\n get templateLabel(): OuiTabLabel {\n return this._templateLabel;\n }\n set templateLabel(value: OuiTabLabel) {\n this._setTemplateLabelInput(value);\n }\n\n /**\n * Template provided in the tab content that will be used if present, used to enable lazy-loading\n */\n @ContentChild(OuiTabContent, { read: TemplateRef, static: true })\n // We need an initializer here to avoid a TS error. The value will be set in `ngAfterViewInit`.\n private _explicitContent: TemplateRef = undefined!;\n\n /** Template inside the OuiTab view that contains an ``. */\n @ViewChild(TemplateRef, { static: true }) _implicitContent: TemplateRef;\n\n /** Plain text label for the tab, used when there is no template label. */\n @Input('label') textLabel = '';\n\n @Input('text') givenText = '';\n\n /** Aria label for the tab. */\n @Input('aria-label') ariaLabel: string;\n\n @Input() color = 'accent';\n\n /**\n * Reference to the element that the tab is labelled by.\n * Will be cleared if `aria-label` is set at the same time.\n */\n @Input('aria-labelledby') ariaLabelledby: string;\n\n /**\n * Classes to be passed to the tab label inside the oui-tab-header container.\n * Supports string and string array values, same as `ngClass`.\n */\n @Input() labelClass: string | string[];\n\n /**\n * Classes to be passed to the tab oui-tab-body container.\n * Supports string and string array values, same as `ngClass`.\n */\n @Input() bodyClass: string | string[];\n\n /** Portal that will be the hosted content of the tab */\n private _contentPortal: TemplatePortal | null = null;\n\n /** @docs-private */\n get content(): TemplatePortal | null {\n return this._contentPortal;\n }\n\n /** Emits whenever the internal state of the tab changes. */\n readonly _stateChanges = new Subject();\n\n /**\n * The relatively indexed position where 0 represents the center, negative is left, and positive\n * represents the right.\n */\n position: number | null = null;\n\n /**\n * The initial relatively index origin of the tab if it was created and selected after there\n * was already a selected tab. Provides context of what position the tab should originate from.\n */\n origin: number | null = null;\n\n /**\n * Whether the tab is currently active.\n */\n isActive = false;\n\n @ViewChild('tab1') _tab1: ElementRef;\n constructor(\n private _viewContainerRef: ViewContainerRef,\n @Inject(OUI_TAB_GROUP) @Optional() public _closestTabGroup: any,\n _elementRef: ElementRef\n ) {\n super(_elementRef);\n this.addThemeColor();\n }\n\n ngOnChanges(changes: SimpleChanges): void {\n if (\n Object.prototype.hasOwnProperty.call(changes, 'textLabel') ||\n Object.prototype.hasOwnProperty.call(changes, 'disabled')\n ) {\n this._stateChanges.next();\n }\n if (\n Object.prototype.hasOwnProperty.call(changes, '_tab2') ||\n Object.prototype.hasOwnProperty.call(changes, 'disabled')\n ) {\n this._stateChanges.next();\n }\n }\n\n addThemeColor() {\n if (!this.color) {\n this.color = DEFAULT_COLOR;\n }\n }\n\n ngOnDestroy(): void {\n this._stateChanges.complete();\n }\n\n ngOnInit(): void {\n this._contentPortal = new TemplatePortal(\n this._explicitContent || this._implicitContent,\n this._viewContainerRef,\n this._tab1\n );\n }\n\n /**\n * This has been extracted to a util because of TS 4 and VE.\n * View Engine doesn't support property rename inheritance.\n * TS 4.0 doesn't allow properties to override accessors or vice-versa.\n * @docs-private\n */\n private _setTemplateLabelInput(value: OuiTabLabel | undefined) {\n // Only update the label if the query managed to find one. This works around an issue where a\n // user may have manually set `templateLabel` during creation mode, which would then get\n // clobbered by `undefined` when the query resolves. Also note that we check that the closest\n // tab matches the current one so that we don't pick up labels from nested tabs.\n if (value && value._closestTab === this) {\n this._templateLabel = value;\n }\n }\n}\n", + "sourceCode": "import {\r\n ChangeDetectionStrategy,\r\n Component,\r\n ContentChild,\r\n ElementRef,\r\n Inject,\r\n InjectionToken,\r\n Input,\r\n OnChanges,\r\n OnDestroy,\r\n OnInit,\r\n Optional,\r\n SimpleChanges,\r\n TemplateRef,\r\n ViewChild,\r\n ViewContainerRef,\r\n ViewEncapsulation,\r\n} from '@angular/core';\r\nimport { OuiTabContent } from './tab-content';\r\nimport { OUI_TAB, OuiTabLabel } from './tab-label';\r\nimport { CanDisable, mixinColor } from '../core';\r\nimport { TemplatePortal } from '@angular/cdk/portal';\r\nimport { Subject } from 'rxjs';\r\n\r\nexport class OuiTabsBase {\r\n constructor(public _elementRef: ElementRef) {}\r\n}\r\n// Boilerplate for applying mixins to OuiTab.\r\n/** @docs-private */\r\nconst _OuiTabMixinBase: typeof OuiTabsBase = mixinColor(OuiTabsBase);\r\n\r\n/**\r\n * Used to provide a tab group to a tab without causing a circular dependency.\r\n * @docs-private\r\n */\r\nexport const OUI_TAB_GROUP = new InjectionToken('OUI_TAB_GROUP');\r\n\r\n/** Default color palette for the tab */\r\nconst DEFAULT_COLOR = 'primary';\r\n\r\n@Component({\r\n selector: 'oui-tab',\r\n\r\n // Note that usually we'd go through a bit more trouble and set up another class so that\r\n // the inlined template of `OuiTab` isn't duplicated, however the template is small enough\r\n // that creating the extra class will generate more code than just duplicating the template.\r\n templateUrl: 'tab.html',\r\n // eslint-disable-next-line @angular-eslint/no-inputs-metadata-property\r\n inputs: ['disabled'],\r\n // eslint-disable-next-line @angular-eslint/no-inputs-metadata-property\r\n changeDetection: ChangeDetectionStrategy.Default,\r\n encapsulation: ViewEncapsulation.None,\r\n exportAs: 'OuiTab',\r\n providers: [{ provide: OUI_TAB, useExisting: OuiTab }],\r\n})\r\nexport class OuiTab\r\n extends _OuiTabMixinBase\r\n implements CanDisable, OnInit, OnChanges, OnDestroy\r\n{\r\n /** Content for the tab label given by ``. */\r\n private _templateLabel: OuiTabLabel;\r\n disabled: any;\r\n @ContentChild(OuiTabLabel)\r\n get templateLabel(): OuiTabLabel {\r\n return this._templateLabel;\r\n }\r\n set templateLabel(value: OuiTabLabel) {\r\n this._setTemplateLabelInput(value);\r\n }\r\n\r\n /**\r\n * Template provided in the tab content that will be used if present, used to enable lazy-loading\r\n */\r\n @ContentChild(OuiTabContent, { read: TemplateRef, static: true })\r\n // We need an initializer here to avoid a TS error. The value will be set in `ngAfterViewInit`.\r\n private _explicitContent: TemplateRef = undefined!;\r\n\r\n /** Template inside the OuiTab view that contains an ``. */\r\n @ViewChild(TemplateRef, { static: true }) _implicitContent: TemplateRef;\r\n\r\n /** Plain text label for the tab, used when there is no template label. */\r\n @Input('label') textLabel = '';\r\n\r\n @Input('text') givenText = '';\r\n\r\n /** Aria label for the tab. */\r\n @Input('aria-label') ariaLabel: string;\r\n\r\n @Input() color = 'accent';\r\n\r\n /**\r\n * Reference to the element that the tab is labelled by.\r\n * Will be cleared if `aria-label` is set at the same time.\r\n */\r\n @Input('aria-labelledby') ariaLabelledby: string;\r\n\r\n /**\r\n * Classes to be passed to the tab label inside the oui-tab-header container.\r\n * Supports string and string array values, same as `ngClass`.\r\n */\r\n @Input() labelClass: string | string[];\r\n\r\n /**\r\n * Classes to be passed to the tab oui-tab-body container.\r\n * Supports string and string array values, same as `ngClass`.\r\n */\r\n @Input() bodyClass: string | string[];\r\n\r\n /** Portal that will be the hosted content of the tab */\r\n private _contentPortal: TemplatePortal | null = null;\r\n\r\n /** @docs-private */\r\n get content(): TemplatePortal | null {\r\n return this._contentPortal;\r\n }\r\n\r\n /** Emits whenever the internal state of the tab changes. */\r\n readonly _stateChanges = new Subject();\r\n\r\n /**\r\n * The relatively indexed position where 0 represents the center, negative is left, and positive\r\n * represents the right.\r\n */\r\n position: number | null = null;\r\n\r\n /**\r\n * The initial relatively index origin of the tab if it was created and selected after there\r\n * was already a selected tab. Provides context of what position the tab should originate from.\r\n */\r\n origin: number | null = null;\r\n\r\n /**\r\n * Whether the tab is currently active.\r\n */\r\n isActive = false;\r\n\r\n @ViewChild('tab1') _tab1: ElementRef;\r\n constructor(\r\n private _viewContainerRef: ViewContainerRef,\r\n @Inject(OUI_TAB_GROUP) @Optional() public _closestTabGroup: any,\r\n _elementRef: ElementRef\r\n ) {\r\n super(_elementRef);\r\n this.addThemeColor();\r\n }\r\n\r\n ngOnChanges(changes: SimpleChanges): void {\r\n if (\r\n Object.prototype.hasOwnProperty.call(changes, 'textLabel') ||\r\n Object.prototype.hasOwnProperty.call(changes, 'disabled')\r\n ) {\r\n this._stateChanges.next();\r\n }\r\n if (\r\n Object.prototype.hasOwnProperty.call(changes, '_tab2') ||\r\n Object.prototype.hasOwnProperty.call(changes, 'disabled')\r\n ) {\r\n this._stateChanges.next();\r\n }\r\n }\r\n\r\n addThemeColor() {\r\n if (!this.color) {\r\n this.color = DEFAULT_COLOR;\r\n }\r\n }\r\n\r\n ngOnDestroy(): void {\r\n this._stateChanges.complete();\r\n }\r\n\r\n ngOnInit(): void {\r\n this._contentPortal = new TemplatePortal(\r\n this._explicitContent || this._implicitContent,\r\n this._viewContainerRef,\r\n this._tab1\r\n );\r\n }\r\n\r\n /**\r\n * This has been extracted to a util because of TS 4 and VE.\r\n * View Engine doesn't support property rename inheritance.\r\n * TS 4.0 doesn't allow properties to override accessors or vice-versa.\r\n * @docs-private\r\n */\r\n private _setTemplateLabelInput(value: OuiTabLabel | undefined) {\r\n // Only update the label if the query managed to find one. This works around an issue where a\r\n // user may have manually set `templateLabel` during creation mode, which would then get\r\n // clobbered by `undefined` when the query resolves. Also note that we check that the closest\r\n // tab matches the current one so that we don't pick up labels from nested tabs.\r\n if (value && value._closestTab === this) {\r\n this._templateLabel = value;\r\n }\r\n }\r\n}\r\n", "constructorObj": { "name": "constructor", "description": "", @@ -11041,12 +11126,13 @@ "description": "", "line": 34, "modifierKind": [ - 123 + 125 ] } ], "methods": [], "indexSignatures": [], + "extends": [], "inputsClass": [], "outputsClass": [], "hostBindings": [], @@ -11104,17 +11190,17 @@ { "pos": 893, "end": 956, - "flags": 4227072, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 325, + "kind": 334, "tagName": { "pos": 894, "end": 909, - "flags": 4227072, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "breaking-change" }, "comment": "

8.0.0 To be made into a required property.

\n" @@ -11126,6 +11212,7 @@ "rawdescription": "\n\nChange event object that is emitted when the user selects a\ndifferent page size or navigates to another page.\n", "methods": [], "indexSignatures": [], + "extends": [], "inputsClass": [], "outputsClass": [], "hostBindings": [], @@ -11191,7 +11278,7 @@ "description": "", "line": 11, "modifierKind": [ - 121 + 123 ] }, { @@ -11204,7 +11291,7 @@ "description": "", "line": 45, "modifierKind": [ - 121 + 123 ] }, { @@ -11217,7 +11304,7 @@ "description": "", "line": 79, "modifierKind": [ - 121 + 123 ] }, { @@ -11230,7 +11317,7 @@ "description": "", "line": 113, "modifierKind": [ - 121 + 123 ] }, { @@ -11242,7 +11329,7 @@ "description": "", "line": 147, "modifierKind": [ - 121 + 123 ] }, { @@ -11254,7 +11341,7 @@ "description": "", "line": 148, "modifierKind": [ - 121 + 123 ] } ], @@ -11271,6 +11358,7 @@ } ], "indexSignatures": [], + "extends": [], "inputsClass": [], "outputsClass": [], "hostBindings": [], @@ -11334,6 +11422,7 @@ "rawdescription": "\n\nConfiguration for an icon, including the URL and possibly the cached SVG element.\n", "methods": [], "indexSignatures": [], + "extends": [], "inputsClass": [], "outputsClass": [], "hostBindings": [], @@ -11355,6 +11444,8 @@ "name": "{\n provide: _VIEW_REPEATER_STRATEGY, useClass: _RecycleViewRepeaterStrategy,\n}" } ], + "hostDirectives": [], + "standalone": false, "inputsClass": [], "outputsClass": [], "deprecated": false, @@ -11362,7 +11453,8 @@ "hostBindings": [], "hostListeners": [], "propertiesClass": [], - "methodsClass": [] + "methodsClass": [], + "extends": [] }, { "name": "OuiAutocompleteOrigin", @@ -11374,6 +11466,9 @@ "sourceCode": "import { Directive, ElementRef } from '@angular/core';\n\n/**\n * Directive applied to an element to make it usable\n * as a connection point for an autocomplete panel.\n */\n@Directive({\n selector: '[ouiAutocompleteOrigin]',\n exportAs: 'ouiAutocompleteOrigin',\n})\nexport class OuiAutocompleteOrigin {\n constructor(\n /** Reference to the element on which the directive is applied. */\n public elementRef: ElementRef\n ) {}\n}\n", "selector": "[ouiAutocompleteOrigin]", "providers": [], + "exportAs": "ouiAutocompleteOrigin", + "hostDirectives": [], + "standalone": false, "inputsClass": [], "outputsClass": [], "deprecated": false, @@ -11391,11 +11486,12 @@ "line": 14, "rawdescription": "\nReference to the element on which the directive is applied.", "modifierKind": [ - 123 + 125 ] } ], "methodsClass": [], + "extends": [], "constructorObj": { "name": "constructor", "description": "", @@ -11437,6 +11533,9 @@ "name": "OUI_AUTOCOMPLETE_VALUE_ACCESSOR" } ], + "exportAs": "ouiAutocompleteTrigger", + "hostDirectives": [], + "standalone": false, "inputsClass": [ { "name": "autocomplete", @@ -11447,17 +11546,17 @@ { "pos": 6473, "end": 6490, - "flags": 4227072, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 325, + "kind": 334, "tagName": { "pos": 6474, "end": 6486, - "flags": 4227072, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "docs-private" }, "comment": "" @@ -11516,7 +11615,7 @@ "description": "", "line": 133, "modifierKind": [ - 121 + 123 ] }, { @@ -11530,7 +11629,7 @@ "line": 153, "rawdescription": "\n\nWhether the autocomplete can open the next time it is focused. Used to prevent a focused,\nclosed autocomplete from being reopened if the user switches to another browser tab and then\ncomes back.\n", "modifierKind": [ - 121 + 123 ] }, { @@ -11544,8 +11643,8 @@ "line": 156, "rawdescription": "\nStream of keyboard events that can close the panel.", "modifierKind": [ - 121, - 144 + 123, + 148 ] }, { @@ -11558,7 +11657,7 @@ "line": 143, "rawdescription": "\nThe subscription for closing actions (some are bound to document).", "modifierKind": [ - 121 + 123 ] }, { @@ -11571,7 +11670,7 @@ "description": "", "line": 132, "modifierKind": [ - 121 + 123 ] }, { @@ -11606,7 +11705,7 @@ "description": "", "line": 159, "modifierKind": [ - 121 + 123 ] }, { @@ -11618,7 +11717,7 @@ "description": "", "line": 130, "modifierKind": [ - 121 + 123 ] }, { @@ -11630,7 +11729,7 @@ "description": "", "line": 131, "modifierKind": [ - 121 + 123 ] }, { @@ -11643,7 +11742,7 @@ "line": 140, "rawdescription": "\nStrategy that is used to position the panel.", "modifierKind": [ - 121 + 123 ] }, { @@ -11656,7 +11755,7 @@ "line": 137, "rawdescription": "\nOld value of the native input. Used to work around issues with the `input` event on IE.", "modifierKind": [ - 121 + 123 ] }, { @@ -11668,7 +11767,7 @@ "description": "", "line": 134, "modifierKind": [ - 121 + 123 ] }, { @@ -11682,7 +11781,7 @@ "line": 146, "rawdescription": "\nSubscription to viewport size changes.", "modifierKind": [ - 121 + 123 ] }, { @@ -11696,7 +11795,7 @@ "line": 205, "rawdescription": "\n\nEvent handler for when the window is blurred. Needs to be an\narrow function in order to preserve the context.\n", "modifierKind": [ - 121 + 123 ] }, { @@ -11710,7 +11809,7 @@ "line": 162, "rawdescription": "\nStream of autocomplete option selections.", "modifierKind": [ - 144 + 148 ] } ], @@ -11725,7 +11824,7 @@ "deprecated": false, "deprecationMessage": "", "modifierKind": [ - 121 + 123 ] }, { @@ -11740,7 +11839,7 @@ "rawdescription": "\nDetermines whether the panel can be opened.", "description": "

Determines whether the panel can be opened.

\n", "modifierKind": [ - 121 + 123 ] }, { @@ -11762,7 +11861,7 @@ "rawdescription": "\n\nClear any previous selected option and emit a selection change event for this option\n", "description": "

Clear any previous selected option and emit a selection change event for this option

\n", "modifierKind": [ - 121 + 123 ], "jsdoctags": [ { @@ -11788,7 +11887,7 @@ "rawdescription": "\nDestroys the autocomplete suggestion panel.", "description": "

Destroys the autocomplete suggestion panel.

\n", "modifierKind": [ - 121 + 123 ] }, { @@ -11801,7 +11900,7 @@ "deprecated": false, "deprecationMessage": "", "modifierKind": [ - 121 + 123 ] }, { @@ -11816,7 +11915,7 @@ "rawdescription": "\nReturns the width of the input element, so the panel width can match it.", "description": "

Returns the width of the input element, so the panel width can match it.

\n", "modifierKind": [ - 121 + 123 ] }, { @@ -11831,7 +11930,7 @@ "rawdescription": "\nStream of clicks outside of the autocomplete panel.", "description": "

Stream of clicks outside of the autocomplete panel.

\n", "modifierKind": [ - 121 + 123 ] }, { @@ -11844,7 +11943,7 @@ "deprecated": false, "deprecationMessage": "", "modifierKind": [ - 121 + 123 ] }, { @@ -11857,7 +11956,7 @@ "deprecated": false, "deprecationMessage": "", "modifierKind": [ - 121 + 123 ] }, { @@ -11870,7 +11969,7 @@ "deprecated": false, "deprecationMessage": "", "modifierKind": [ - 121 + 123 ] }, { @@ -11951,7 +12050,7 @@ "rawdescription": "\n\nResets the active item to -1 so arrow events will activate the\ncorrect options, or to 0 if the consumer opted into it.\n", "description": "

Resets the active item to -1 so arrow events will activate the\ncorrect options, or to 0 if the consumer opted into it.

\n", "modifierKind": [ - 121 + 123 ] }, { @@ -11966,7 +12065,7 @@ "rawdescription": "\n\nGiven that we are not actually focusing active options, we must manually adjust scroll\nto reveal options below the fold. First, we find the offset of the option from the top\nof the panel. If that offset is below the fold, the new scrollTop will be the offset -\nthe panel height + the option height, so the active option will be just visible at the\nbottom of the panel. If that offset is above the top of the visible panel, the new scrollTop\nwill become the offset. If that offset is visible within the panel already, the scrollTop is\nnot adjusted.\n", "description": "

Given that we are not actually focusing active options, we must manually adjust scroll\nto reveal options below the fold. First, we find the offset of the option from the top\nof the panel. If that offset is below the fold, the new scrollTop will be the offset -\nthe panel height + the option height, so the active option will be just visible at the\nbottom of the panel. If that offset is above the top of the visible panel, the new scrollTop\nwill become the offset. If that offset is visible within the panel already, the scrollTop is\nnot adjusted.

\n", "modifierKind": [ - 121 + 123 ] }, { @@ -11986,7 +12085,7 @@ "deprecated": false, "deprecationMessage": "", "modifierKind": [ - 121 + 123 ], "jsdoctags": [ { @@ -12019,7 +12118,7 @@ "rawdescription": "\n\nThis method closes the panel, and if a value is specified, also sets the associated\ncontrol to that value. It will also mark the control as dirty if this interaction\nstemmed from the user.\n", "description": "

This method closes the panel, and if a value is specified, also sets the associated\ncontrol to that value. It will also mark the control as dirty if this interaction\nstemmed from the user.

\n", "modifierKind": [ - 121 + 123 ], "jsdoctags": [ { @@ -12045,7 +12144,7 @@ "rawdescription": "\n\nThis method listens to a stream of panel closing actions and resets the\nstream every time the option list changes.\n", "description": "

This method listens to a stream of panel closing actions and resets the\nstream every time the option list changes.

\n", "modifierKind": [ - 121 + 123 ] }, { @@ -12225,6 +12324,7 @@ ] } ], + "extends": [], "implements": [ "ControlValueAccessor", "OnDestroy" @@ -12461,6 +12561,8 @@ "sourceCode": "import { Directive, ElementRef, Input } from '@angular/core';\nimport {\n CdkCell,\n CdkCellDef,\n CdkColumnDef,\n CdkFooterCell,\n CdkFooterCellDef,\n CdkHeaderCell,\n CdkHeaderCellDef,\n} from '@angular/cdk/table';\n\n/**\n * Cell definition for the oui-table.\n * Captures the template of a column's data row cell as well as cell-specific properties.\n */\n@Directive({\n selector: '[ouiCellDef]',\n providers: [{ provide: CdkCellDef, useExisting: OuiCellDef }],\n})\nexport class OuiCellDef extends CdkCellDef {}\n\n/**\n * Header cell definition for the oui-table.\n * Captures the template of a column's header cell and as well as cell-specific properties.\n */\n@Directive({\n selector: '[ouiHeaderCellDef]',\n providers: [{ provide: CdkHeaderCellDef, useExisting: OuiHeaderCellDef }],\n})\nexport class OuiHeaderCellDef extends CdkHeaderCellDef {}\n\n/**\n * Footer cell definition for the oui-table.\n * Captures the template of a column's footer cell and as well as cell-specific properties.\n */\n@Directive({\n selector: '[ouiFooterCellDef]',\n providers: [{ provide: CdkFooterCellDef, useExisting: OuiFooterCellDef }],\n})\nexport class OuiFooterCellDef extends CdkFooterCellDef {}\n\n/**\n * Column definition for the oui-table.\n * Defines a set of cells available for a table column.\n */\n@Directive({\n selector: '[ouiColumnDef]',\n providers: [\n { provide: CdkColumnDef, useExisting: OuiColumnDef },\n { provide: 'OUI_SORT_HEADER_COLUMN_DEF', useExisting: OuiColumnDef },\n ],\n})\nexport class OuiColumnDef extends CdkColumnDef {\n /** Unique name for this column. */\n @Input('ouiColumnDef')\n get name(): string {\n return this._name;\n }\n set name(name: string) {\n this._setNameInput(name);\n }\n}\n\n/** Header cell template container that adds the right classes and role. */\n@Directive({\n // eslint-disable-next-line @angular-eslint/directive-selector\n selector: 'oui-header-cell, th[oui-header-cell]',\n // eslint-disable-next-line @angular-eslint/no-host-metadata-property\n host: {\n class: 'oui-header-cell',\n role: 'columnheader',\n },\n})\nexport class OuiHeaderCell extends CdkHeaderCell {\n constructor(columnDef: CdkColumnDef, elementRef: ElementRef) {\n super(columnDef, elementRef);\n elementRef.nativeElement.classList.add(\n `oui-column-${columnDef.cssClassFriendlyName}`\n );\n }\n}\n\n/** Footer cell template container that adds the right classes and role. */\n@Directive({\n // eslint-disable-next-line @angular-eslint/directive-selector\n selector: 'oui-footer-cell, td[oui-footer-cell]',\n // eslint-disable-next-line @angular-eslint/no-host-metadata-property\n host: {\n class: 'oui-footer-cell',\n role: 'gridcell',\n },\n})\nexport class OuiFooterCell extends CdkFooterCell {\n constructor(columnDef: CdkColumnDef, elementRef: ElementRef) {\n super(columnDef, elementRef);\n elementRef.nativeElement.classList.add(\n `oui-column-${columnDef.cssClassFriendlyName}`\n );\n }\n}\n\n/** Cell template container that adds the right classes and role. */\n@Directive({\n // eslint-disable-next-line @angular-eslint/directive-selector\n selector: 'oui-cell, td[oui-cell]',\n // eslint-disable-next-line @angular-eslint/no-host-metadata-property\n host: {\n class: 'oui-cell',\n role: 'gridcell',\n },\n})\nexport class OuiCell extends CdkCell {\n constructor(columnDef: CdkColumnDef, elementRef: ElementRef) {\n super(columnDef, elementRef);\n elementRef.nativeElement.classList.add(\n `oui-column-${columnDef.cssClassFriendlyName}`\n );\n }\n}\n", "selector": "oui-cell, td[oui-cell]", "providers": [], + "hostDirectives": [], + "standalone": false, "inputsClass": [], "outputsClass": [], "deprecated": false, @@ -12469,7 +12571,9 @@ "hostListeners": [], "propertiesClass": [], "methodsClass": [], - "extends": "CdkCell", + "extends": [ + "CdkCell" + ], "constructorObj": { "name": "constructor", "description": "", @@ -12526,6 +12630,8 @@ "name": "{ provide: CdkCellDef, useExisting: OuiCellDef }" } ], + "hostDirectives": [], + "standalone": false, "inputsClass": [], "outputsClass": [], "deprecated": false, @@ -12534,7 +12640,9 @@ "hostListeners": [], "propertiesClass": [], "methodsClass": [], - "extends": "CdkCellDef" + "extends": [ + "CdkCellDef" + ] }, { "name": "OuiColumnDef", @@ -12553,6 +12661,8 @@ "name": "{ provide: , useExisting: OuiColumnDef }" } ], + "hostDirectives": [], + "standalone": false, "inputsClass": [ { "name": "ouiColumnDef", @@ -12572,7 +12682,9 @@ "hostListeners": [], "propertiesClass": [], "methodsClass": [], - "extends": "CdkColumnDef", + "extends": [ + "CdkColumnDef" + ], "accessors": { "name": { "name": "name", @@ -12634,6 +12746,9 @@ "name": "{ provide: OUI_INPUT_VALUE_ACCESSOR, useExisting: OuiDatepickerInput }" } ], + "exportAs": "ouiDatepickerInput", + "hostDirectives": [], + "standalone": false, "inputsClass": [ { "name": "disabled", @@ -12733,7 +12848,7 @@ "description": "", "line": 226, "modifierKind": [ - 121 + 123 ] }, { @@ -12751,7 +12866,8 @@ } ], "modifierKind": [ - 123 + 170, + 125 ] }, { @@ -12792,7 +12908,7 @@ "description": "", "line": 108, "modifierKind": [ - 121 + 123 ] }, { @@ -12804,7 +12920,7 @@ "description": "", "line": 93, "modifierKind": [ - 121 + 123 ] }, { @@ -12829,7 +12945,7 @@ "line": 265, "rawdescription": "\nThe form control validator for the date filter.", "modifierKind": [ - 121 + 123 ] }, { @@ -12843,7 +12959,7 @@ "line": 113, "rawdescription": "\nWhether the last value set on the input was valid.", "modifierKind": [ - 121 + 123 ] }, { @@ -12856,7 +12972,7 @@ "description": "", "line": 110, "modifierKind": [ - 121 + 123 ] }, { @@ -12868,7 +12984,7 @@ "description": "", "line": 192, "modifierKind": [ - 121 + 123 ] }, { @@ -12882,7 +12998,7 @@ "line": 251, "rawdescription": "\nThe form control validator for the max date.", "modifierKind": [ - 121 + 123 ] }, { @@ -12894,7 +13010,7 @@ "description": "", "line": 181, "modifierKind": [ - 121 + 123 ] }, { @@ -12908,7 +13024,7 @@ "line": 237, "rawdescription": "\nThe form control validator for the min date.", "modifierKind": [ - 121 + 123 ] }, { @@ -12931,7 +13047,7 @@ "description": "", "line": 115, "modifierKind": [ - 121 + 123 ] }, { @@ -12945,7 +13061,7 @@ "line": 231, "rawdescription": "\nThe form control validator for whether the input parses.", "modifierKind": [ - 121 + 123 ] }, { @@ -12959,7 +13075,7 @@ "line": 278, "rawdescription": "\nThe combined form control validator for this input.", "modifierKind": [ - 121 + 123 ] }, { @@ -12972,7 +13088,7 @@ "description": "", "line": 228, "modifierKind": [ - 121 + 123 ] }, { @@ -12984,7 +13100,7 @@ "description": "", "line": 170, "modifierKind": [ - 121 + 123 ] }, { @@ -13019,7 +13135,7 @@ "rawdescription": "\nFormats a value and sets it on the input element.", "description": "

Formats a value and sets it on the input element.

\n", "modifierKind": [ - 121 + 123 ], "jsdoctags": [ { @@ -13064,17 +13180,17 @@ "rawdescription": "\n\n", "description": "", "modifierKind": [ - 121 + 123 ], "jsdoctags": [ { "name": { "pos": 12987, "end": 12990, - "flags": 4227072, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "obj" }, "type": "any", @@ -13083,10 +13199,10 @@ "tagName": { "pos": 12981, "end": 12986, - "flags": 4227072, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "param" }, "comment": "

The object to check.

\n" @@ -13095,10 +13211,10 @@ "tagName": { "pos": 13018, "end": 13025, - "flags": 4227072, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "returns" }, "comment": "

The given object if it is both a date instance and valid, otherwise null.

\n" @@ -13219,11 +13335,10 @@ "tagName": { "pos": 10696, "end": 10702, - "flags": 4227072, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, - "originalKeywordKind": 105, + "kind": 80, "escapedText": "return" }, "comment": "

The element to connect the popup to.

\n" @@ -13452,6 +13567,7 @@ ] } ], + "extends": [], "implements": [ "ControlValueAccessor", "OnDestroy", @@ -13774,6 +13890,8 @@ "sourceCode": "import { coerceBooleanProperty } from '@angular/cdk/coercion';\nimport {\n AfterContentInit,\n Attribute,\n ChangeDetectionStrategy,\n ChangeDetectorRef,\n Component,\n ContentChild,\n Directive,\n Input,\n OnChanges,\n OnDestroy,\n SimpleChanges,\n ViewEncapsulation,\n ViewChild,\n} from '@angular/core';\nimport { OuiButton } from '../button/button';\nimport { merge, Observable, of as observableOf, Subscription } from 'rxjs';\nimport { OuiDatepicker } from './datepicker';\nimport { OuiDatepickerIntl } from './datepicker-intl';\n\n/** Can be used to override the icon of a `ouiDatepickerToggle`. */\n@Directive({\n selector: '[ouiDatepickerToggleIcon]',\n})\nexport class OuiDatepickerToggleIcon {}\n\n@Component({\n selector: 'oui-datepicker-toggle',\n templateUrl: 'datepicker-toggle.html',\n styleUrls: ['datepicker-toggle.scss'],\n // eslint-disable-next-line @angular-eslint/no-host-metadata-property\n host: {\n class: 'oui-datepicker-toggle',\n // Always set the tabindex to -1 so that it doesn't overlap with any custom tabindex the\n // consumer may have provided, while still being able to receive focus.\n '[attr.tabindex]': '-1',\n '[class.oui-datepicker-toggle-active]': 'datepicker && datepicker.opened',\n '[class.oui-accent]': 'datepicker && datepicker.color === \"accent\"',\n '[class.oui-warn]': 'datepicker && datepicker.color === \"warn\"',\n '(focus)': '_button.focus()',\n '[class.oui-datepicker-disabled]': 'disabled',\n },\n exportAs: 'ouiDatepickerToggle',\n encapsulation: ViewEncapsulation.None,\n changeDetection: ChangeDetectionStrategy.OnPush,\n})\nexport class OuiDatepickerToggle\n implements AfterContentInit, OnChanges, OnDestroy\n{\n private _stateChanges = Subscription.EMPTY;\n\n /** Datepicker instance that the button will toggle. */\n // eslint-disable-next-line @angular-eslint/no-input-rename\n @Input('for') datepicker: OuiDatepicker;\n\n /** Tabindex for the toggle. */\n @Input() tabIndex: number | null;\n\n /** Whether the toggle button is disabled. */\n @Input()\n get disabled(): boolean {\n return this._disabled === undefined\n ? this.datepicker.disabled\n : !!this._disabled;\n }\n set disabled(value: boolean) {\n this._disabled = coerceBooleanProperty(value);\n }\n private _disabled: boolean;\n\n /** Custom icon set by the consumer. */\n @ContentChild(OuiDatepickerToggleIcon)\n _customIcon: OuiDatepickerToggleIcon;\n\n /** Underlying button element. */\n @ViewChild('button') _button: OuiButton;\n\n constructor(\n public _intl: OuiDatepickerIntl,\n private _changeDetectorRef: ChangeDetectorRef,\n @Attribute('tabindex') defaultTabIndex: string\n ) {\n const parsedTabIndex = Number(defaultTabIndex);\n this.tabIndex =\n parsedTabIndex || parsedTabIndex === 0 ? parsedTabIndex : null;\n }\n\n ngOnChanges(changes: SimpleChanges) {\n if (changes.datepicker) {\n this._watchStateChanges();\n }\n }\n\n ngOnDestroy() {\n this._stateChanges.unsubscribe();\n }\n\n ngAfterContentInit() {\n this._watchStateChanges();\n }\n\n _open(event: Event): void {\n if (this.datepicker && !this.disabled) {\n this.datepicker.open();\n event.stopPropagation();\n }\n }\n\n private _watchStateChanges() {\n const datepickerDisabled = this.datepicker\n ? this.datepicker._disabledChange\n : observableOf();\n const inputDisabled =\n this.datepicker && this.datepicker._datepickerInput\n ? this.datepicker._datepickerInput._disabledChange\n : observableOf();\n const datepickerToggled = this.datepicker\n ? merge(this.datepicker.openedStream, this.datepicker.closedStream)\n : observableOf();\n\n this._stateChanges.unsubscribe();\n this._stateChanges = merge(\n this._intl.changes,\n datepickerDisabled as Observable,\n inputDisabled as Observable,\n datepickerToggled\n ).subscribe(() => this._changeDetectorRef.markForCheck());\n }\n}\n", "selector": "[ouiDatepickerToggleIcon]", "providers": [], + "hostDirectives": [], + "standalone": false, "inputsClass": [], "outputsClass": [], "deprecated": false, @@ -13781,7 +13899,8 @@ "hostBindings": [], "hostListeners": [], "propertiesClass": [], - "methodsClass": [] + "methodsClass": [], + "extends": [] }, { "name": "OuiDialogClose", @@ -13793,6 +13912,9 @@ "sourceCode": "import {\n Directive,\n Input,\n OnChanges,\n OnInit,\n Optional,\n SimpleChanges,\n ElementRef,\n Component,\n NgZone,\n OnDestroy,\n} from '@angular/core';\nimport { OuiDialog } from './dialog';\nimport { OuiDialogRef } from './dialog-ref';\nimport { OuiIconRegistry } from '../icon/icon-registery';\nimport { DomSanitizer } from '@angular/platform-browser';\nimport { ICONS } from '../core/shared/icons';\nimport { Subscription } from 'rxjs';\nimport { FocusMonitor } from '@angular/cdk/a11y';\n\n/** Counter used to generate unique IDs for dialog elements. */\nlet dialogElementUid = 0;\n\n/**\n * Header section of ui.\n */\n@Directive({\n selector: '[oui-dialog-header], [ouiDialogHeader]',\n exportAs: 'ouiDialogHeader',\n // eslint-disable-next-line @angular-eslint/no-host-metadata-property\n host: {\n class: 'oui-dialog-header',\n },\n})\nexport class OuiDialogHeader {\n constructor() {}\n}\n\n/**\n * Header Title of ui.\n */\n@Directive({\n selector: '[oui-dialog-header-title], [ouiDialogHeaderTitle]',\n exportAs: 'ouiDialogHeaderTitle',\n // eslint-disable-next-line @angular-eslint/no-host-metadata-property\n host: {\n class: 'oui-dialog-header-title',\n },\n})\nexport class OuiDialogHeaderTitle {\n constructor() {}\n}\n\n/**\n * Header Image of ui.\n */\n@Directive({\n selector: '[oui-dialog-header-image], [ouiDialogHeaderImage]',\n exportAs: 'ouiDialogHeaderImage',\n // eslint-disable-next-line @angular-eslint/no-host-metadata-property\n host: {\n class: 'oui-dialog-header-image',\n },\n})\nexport class OuiDialogHeaderImage {\n constructor() {}\n}\n\n/**\n * Header action area of dialog.\n */\n@Directive({\n selector: '[oui-dialog-header-action], [ouiDialogHeaderAction]',\n exportAs: 'ouiDialogHeaderAction',\n // eslint-disable-next-line @angular-eslint/no-host-metadata-property\n host: {\n class: 'oui-dialog-header-action',\n },\n})\nexport class OuiDialogHeaderAction {\n constructor() {}\n}\n\n/**\n * header action article.\n */\n@Component({\n // eslint-disable-next-line @angular-eslint/component-selector\n selector: '[oui-dialog-header-article], [ouiDialogHeaderArticle]',\n template: '',\n exportAs: 'ouiDialogHeaderArticle',\n // eslint-disable-next-line @angular-eslint/no-host-metadata-property\n host: {\n class: 'oui-dialog-header-article',\n },\n})\nexport class OuiDialogHeaderArticle implements OnDestroy {\n private _monitorSubscription: Subscription = Subscription.EMPTY;\n constructor(\n private ouiIconRegistry: OuiIconRegistry,\n private domSanitizer: DomSanitizer,\n protected elementRef: ElementRef,\n private _focusMonitor: FocusMonitor,\n private _ngZone: NgZone\n ) {\n this.ouiIconRegistry.addSvgIconLiteral(\n `article-icon`,\n this.domSanitizer.bypassSecurityTrustHtml(ICONS.ARTICLE_ICON)\n );\n this._monitorSubscription = this._focusMonitor\n .monitor(this.elementRef, true)\n .subscribe(() => this._ngZone.run(() => {}));\n }\n ngOnDestroy() {\n this._monitorSubscription.unsubscribe();\n }\n}\n\n/**\n * header action article.\n */\n@Component({\n // eslint-disable-next-line @angular-eslint/component-selector\n selector: '[oui-dialog-header-video], [ouiDialogHeaderVideo]',\n template: '',\n exportAs: 'ouiDialogHeaderVideo',\n // eslint-disable-next-line @angular-eslint/no-host-metadata-property\n host: {\n class: 'oui-dialog-header-video',\n },\n})\nexport class OuiDialogHeaderVideo implements OnDestroy {\n private _monitorSubscription: Subscription = Subscription.EMPTY;\n\n constructor(\n private ouiIconRegistry: OuiIconRegistry,\n private domSanitizer: DomSanitizer,\n protected elementRef: ElementRef,\n private _focusMonitor: FocusMonitor,\n private _ngZone: NgZone\n ) {\n this.ouiIconRegistry.addSvgIconLiteral(\n `video-icon`,\n this.domSanitizer.bypassSecurityTrustHtml(ICONS.VIDEO_ICON)\n );\n this._monitorSubscription = this._focusMonitor\n .monitor(this.elementRef, true)\n .subscribe(() => this._ngZone.run(() => {}));\n }\n ngOnDestroy() {\n this._monitorSubscription.unsubscribe();\n }\n}\n\n/**\n * header action close\n */\n@Component({\n // eslint-disable-next-line @angular-eslint/component-selector\n selector: '[oui-dialog-header-close], [ouiDialogHeaderClose]',\n template: '',\n exportAs: 'ouiDialogHeaderClose',\n // eslint-disable-next-line @angular-eslint/no-host-metadata-property\n host: {\n class: 'oui-dialog-header-close',\n '[attr.tabindex]': '0',\n },\n})\nexport class OuiDialogHeaderClose implements OnDestroy {\n private _monitorSubscription: Subscription = Subscription.EMPTY;\n constructor(\n private ouiIconRegistry: OuiIconRegistry,\n private domSanitizer: DomSanitizer,\n protected elementRef: ElementRef,\n private _focusMonitor: FocusMonitor,\n private _ngZone: NgZone\n ) {\n this.ouiIconRegistry.addSvgIconLiteral(\n `close-icon`,\n this.domSanitizer.bypassSecurityTrustHtml(ICONS.CLOSE_ICON)\n );\n this._monitorSubscription = this._focusMonitor\n .monitor(this.elementRef, true)\n .subscribe(() => this._ngZone.run(() => {}));\n }\n ngOnDestroy() {\n this._monitorSubscription.unsubscribe();\n }\n}\n\n/**\n * header action separator close\n */\n@Directive({\n selector: '[oui-dialog-header-separator], [ouiDialogHeaderSeparator]',\n exportAs: 'ouiDialogHeaderSeparator',\n // eslint-disable-next-line @angular-eslint/no-host-metadata-property\n host: {\n class: 'oui-dialog-header-separator',\n },\n})\nexport class OuiDialogHeaderSeparator {\n constructor() {}\n}\n\n/**\n * directive for close the current dialog.\n */\n@Directive({\n selector: `[oui-dialog-close], [ouiDialogClose]`,\n exportAs: 'ouiDialogClose',\n // eslint-disable-next-line @angular-eslint/no-host-metadata-property\n host: {\n '[class.cross-disabled]': 'dialogResult===false',\n '(click)': 'closeDialog()',\n '[attr.aria-label]': 'ariaLabel',\n '(keyup.space)': 'handleKeydown($event)',\n '(keydown.enter)': 'handleKeydown($event)',\n },\n})\nexport class OuiDialogClose implements OnInit, OnChanges {\n /** Screenreader label for the button. */\n @Input('aria-label')\n ariaLabel = 'Close dialog';\n\n /** Dialog close input. */\n @Input('oui-dialog-close')\n dialogResult: any;\n\n @Input('ouiDialogClose')\n _ouiDialogClose: any;\n\n constructor(\n @Optional() public dialogRef: OuiDialogRef,\n private _elementRef: ElementRef,\n private _dialog: OuiDialog\n ) {}\n\n /** Ensures the option is selected when activated from the keyboard. */\n handleKeydown(event: KeyboardEvent): void {\n this.closeDialog();\n event.preventDefault();\n }\n\n closeDialog() {\n if (this.dialogResult !== false) {\n this.dialogRef.close(this.dialogResult);\n }\n }\n\n ngOnInit() {\n if (!this.dialogRef) {\n // When this directive is included in a dialog via TemplateRef (rather than being\n // in a Component), the DialogRef isn't available via injection because embedded\n // views cannot be given a custom injector. Instead, we look up the DialogRef by\n // ID. This must occur in `onInit`, as the ID binding for the dialog container won't\n // be resolved at constructor time.\n this.dialogRef = getClosestDialog(\n this._elementRef,\n this._dialog.openDialogs\n )!;\n }\n }\n\n ngOnChanges(changes: SimpleChanges) {\n const proxiedChange =\n changes._ouiDialogClose || changes._ouiDialogCloseResult;\n if (proxiedChange) {\n this.dialogResult = proxiedChange.currentValue;\n }\n }\n}\n\n/**\n * Content section of dialog.\n */\n@Directive({\n selector: '[oui-dialog-content], [ouiDialogContent]',\n exportAs: 'ouiDialogContent',\n // eslint-disable-next-line @angular-eslint/no-host-metadata-property\n host: {\n class: 'oui-dialog-content',\n },\n})\nexport class OuiDialogContent implements OnInit {\n constructor(\n @Optional() public dialogRef: OuiDialogRef,\n private _elementRef: ElementRef,\n private _dialog: OuiDialog\n ) {}\n\n ngOnInit() {\n if (!this.dialogRef) {\n // When this directive is included in a dialog via TemplateRef (rather than being\n // in a Component), the DialogRef isn't available via injection because embedded\n // views cannot be given a custom injector. Instead, we look up the DialogRef by\n // ID. This must occur in `onInit`, as the ID binding for the dialog container won't\n // be resolved at constructor time.\n this.dialogRef = getClosestDialog(\n this._elementRef,\n this._dialog.openDialogs\n )!;\n }\n this._setContentHeight();\n }\n /* prevent content scroll in default scroll strategy **/\n private _setContentHeight() {\n if (!this.dialogRef.dialogConfig.scrollStrategy) {\n this._elementRef.nativeElement.style.maxHeight = 'none';\n this._elementRef.nativeElement.style.overflow = 'visible';\n }\n }\n}\n\n/**\n * Content section of dialog.\n */\n@Directive({\n selector: '[oui-dialog-footer], [ouiDialogFooter]',\n exportAs: 'ouiDialogFooter',\n // eslint-disable-next-line @angular-eslint/no-host-metadata-property\n host: {\n class: 'oui-dialog-footer',\n },\n})\nexport class OuiDialogFooter {\n @Input()\n id = `oui-dialog-footer-${dialogElementUid++}`;\n constructor() {}\n}\n\n/**\n * footer action left\n */\n@Directive({\n selector: '[oui-dialog-footer-action-left], [ouiDialogFooterActionLeft]',\n exportAs: 'ouiDialogFooterActionLeft',\n // eslint-disable-next-line @angular-eslint/no-host-metadata-property\n host: {\n class: 'oui-dialog-footer-action-left',\n },\n})\nexport class OuiDialogFooterActionLeft {\n constructor() {}\n}\n\n/**\n * footer action right\n */\n@Directive({\n selector: '[oui-dialog-footer-action-right], [ouiDialogFooterActionRight]',\n exportAs: 'ouiDialogFooterActionRight',\n // eslint-disable-next-line @angular-eslint/no-host-metadata-property\n host: {\n class: 'oui-dialog-footer-action-right',\n },\n})\nexport class OuiDialogFooterActionRight {\n constructor() {}\n}\n\n/**\n * Finds the closest MatDialogRef to an element by looking at the DOM.\n *\n * @param element Element relative to which to look for a dialog.\n * @param openDialogs References to the currently-open dialogs.\n */\nfunction getClosestDialog(\n element: ElementRef,\n openDialogs: OuiDialogRef[]\n) {\n let parent: HTMLElement | null = element.nativeElement.parentElement;\n\n while (parent && !parent.classList.contains('oui-dialog-container')) {\n parent = parent.parentElement;\n }\n\n return parent ? openDialogs.find((dialog) => dialog.id === parent!.id) : null;\n}\n", "selector": "[oui-dialog-close], [ouiDialogClose]", "providers": [], + "exportAs": "ouiDialogClose", + "hostDirectives": [], + "standalone": false, "inputsClass": [ { "name": "aria-label", @@ -13845,7 +13967,8 @@ } ], "modifierKind": [ - 123 + 170, + 125 ] } ], @@ -13929,6 +14052,7 @@ "deprecationMessage": "" } ], + "extends": [], "implements": [ "OnInit", "OnChanges" @@ -14000,6 +14124,9 @@ "sourceCode": "import {\n Directive,\n Input,\n OnChanges,\n OnInit,\n Optional,\n SimpleChanges,\n ElementRef,\n Component,\n NgZone,\n OnDestroy,\n} from '@angular/core';\nimport { OuiDialog } from './dialog';\nimport { OuiDialogRef } from './dialog-ref';\nimport { OuiIconRegistry } from '../icon/icon-registery';\nimport { DomSanitizer } from '@angular/platform-browser';\nimport { ICONS } from '../core/shared/icons';\nimport { Subscription } from 'rxjs';\nimport { FocusMonitor } from '@angular/cdk/a11y';\n\n/** Counter used to generate unique IDs for dialog elements. */\nlet dialogElementUid = 0;\n\n/**\n * Header section of ui.\n */\n@Directive({\n selector: '[oui-dialog-header], [ouiDialogHeader]',\n exportAs: 'ouiDialogHeader',\n // eslint-disable-next-line @angular-eslint/no-host-metadata-property\n host: {\n class: 'oui-dialog-header',\n },\n})\nexport class OuiDialogHeader {\n constructor() {}\n}\n\n/**\n * Header Title of ui.\n */\n@Directive({\n selector: '[oui-dialog-header-title], [ouiDialogHeaderTitle]',\n exportAs: 'ouiDialogHeaderTitle',\n // eslint-disable-next-line @angular-eslint/no-host-metadata-property\n host: {\n class: 'oui-dialog-header-title',\n },\n})\nexport class OuiDialogHeaderTitle {\n constructor() {}\n}\n\n/**\n * Header Image of ui.\n */\n@Directive({\n selector: '[oui-dialog-header-image], [ouiDialogHeaderImage]',\n exportAs: 'ouiDialogHeaderImage',\n // eslint-disable-next-line @angular-eslint/no-host-metadata-property\n host: {\n class: 'oui-dialog-header-image',\n },\n})\nexport class OuiDialogHeaderImage {\n constructor() {}\n}\n\n/**\n * Header action area of dialog.\n */\n@Directive({\n selector: '[oui-dialog-header-action], [ouiDialogHeaderAction]',\n exportAs: 'ouiDialogHeaderAction',\n // eslint-disable-next-line @angular-eslint/no-host-metadata-property\n host: {\n class: 'oui-dialog-header-action',\n },\n})\nexport class OuiDialogHeaderAction {\n constructor() {}\n}\n\n/**\n * header action article.\n */\n@Component({\n // eslint-disable-next-line @angular-eslint/component-selector\n selector: '[oui-dialog-header-article], [ouiDialogHeaderArticle]',\n template: '',\n exportAs: 'ouiDialogHeaderArticle',\n // eslint-disable-next-line @angular-eslint/no-host-metadata-property\n host: {\n class: 'oui-dialog-header-article',\n },\n})\nexport class OuiDialogHeaderArticle implements OnDestroy {\n private _monitorSubscription: Subscription = Subscription.EMPTY;\n constructor(\n private ouiIconRegistry: OuiIconRegistry,\n private domSanitizer: DomSanitizer,\n protected elementRef: ElementRef,\n private _focusMonitor: FocusMonitor,\n private _ngZone: NgZone\n ) {\n this.ouiIconRegistry.addSvgIconLiteral(\n `article-icon`,\n this.domSanitizer.bypassSecurityTrustHtml(ICONS.ARTICLE_ICON)\n );\n this._monitorSubscription = this._focusMonitor\n .monitor(this.elementRef, true)\n .subscribe(() => this._ngZone.run(() => {}));\n }\n ngOnDestroy() {\n this._monitorSubscription.unsubscribe();\n }\n}\n\n/**\n * header action article.\n */\n@Component({\n // eslint-disable-next-line @angular-eslint/component-selector\n selector: '[oui-dialog-header-video], [ouiDialogHeaderVideo]',\n template: '',\n exportAs: 'ouiDialogHeaderVideo',\n // eslint-disable-next-line @angular-eslint/no-host-metadata-property\n host: {\n class: 'oui-dialog-header-video',\n },\n})\nexport class OuiDialogHeaderVideo implements OnDestroy {\n private _monitorSubscription: Subscription = Subscription.EMPTY;\n\n constructor(\n private ouiIconRegistry: OuiIconRegistry,\n private domSanitizer: DomSanitizer,\n protected elementRef: ElementRef,\n private _focusMonitor: FocusMonitor,\n private _ngZone: NgZone\n ) {\n this.ouiIconRegistry.addSvgIconLiteral(\n `video-icon`,\n this.domSanitizer.bypassSecurityTrustHtml(ICONS.VIDEO_ICON)\n );\n this._monitorSubscription = this._focusMonitor\n .monitor(this.elementRef, true)\n .subscribe(() => this._ngZone.run(() => {}));\n }\n ngOnDestroy() {\n this._monitorSubscription.unsubscribe();\n }\n}\n\n/**\n * header action close\n */\n@Component({\n // eslint-disable-next-line @angular-eslint/component-selector\n selector: '[oui-dialog-header-close], [ouiDialogHeaderClose]',\n template: '',\n exportAs: 'ouiDialogHeaderClose',\n // eslint-disable-next-line @angular-eslint/no-host-metadata-property\n host: {\n class: 'oui-dialog-header-close',\n '[attr.tabindex]': '0',\n },\n})\nexport class OuiDialogHeaderClose implements OnDestroy {\n private _monitorSubscription: Subscription = Subscription.EMPTY;\n constructor(\n private ouiIconRegistry: OuiIconRegistry,\n private domSanitizer: DomSanitizer,\n protected elementRef: ElementRef,\n private _focusMonitor: FocusMonitor,\n private _ngZone: NgZone\n ) {\n this.ouiIconRegistry.addSvgIconLiteral(\n `close-icon`,\n this.domSanitizer.bypassSecurityTrustHtml(ICONS.CLOSE_ICON)\n );\n this._monitorSubscription = this._focusMonitor\n .monitor(this.elementRef, true)\n .subscribe(() => this._ngZone.run(() => {}));\n }\n ngOnDestroy() {\n this._monitorSubscription.unsubscribe();\n }\n}\n\n/**\n * header action separator close\n */\n@Directive({\n selector: '[oui-dialog-header-separator], [ouiDialogHeaderSeparator]',\n exportAs: 'ouiDialogHeaderSeparator',\n // eslint-disable-next-line @angular-eslint/no-host-metadata-property\n host: {\n class: 'oui-dialog-header-separator',\n },\n})\nexport class OuiDialogHeaderSeparator {\n constructor() {}\n}\n\n/**\n * directive for close the current dialog.\n */\n@Directive({\n selector: `[oui-dialog-close], [ouiDialogClose]`,\n exportAs: 'ouiDialogClose',\n // eslint-disable-next-line @angular-eslint/no-host-metadata-property\n host: {\n '[class.cross-disabled]': 'dialogResult===false',\n '(click)': 'closeDialog()',\n '[attr.aria-label]': 'ariaLabel',\n '(keyup.space)': 'handleKeydown($event)',\n '(keydown.enter)': 'handleKeydown($event)',\n },\n})\nexport class OuiDialogClose implements OnInit, OnChanges {\n /** Screenreader label for the button. */\n @Input('aria-label')\n ariaLabel = 'Close dialog';\n\n /** Dialog close input. */\n @Input('oui-dialog-close')\n dialogResult: any;\n\n @Input('ouiDialogClose')\n _ouiDialogClose: any;\n\n constructor(\n @Optional() public dialogRef: OuiDialogRef,\n private _elementRef: ElementRef,\n private _dialog: OuiDialog\n ) {}\n\n /** Ensures the option is selected when activated from the keyboard. */\n handleKeydown(event: KeyboardEvent): void {\n this.closeDialog();\n event.preventDefault();\n }\n\n closeDialog() {\n if (this.dialogResult !== false) {\n this.dialogRef.close(this.dialogResult);\n }\n }\n\n ngOnInit() {\n if (!this.dialogRef) {\n // When this directive is included in a dialog via TemplateRef (rather than being\n // in a Component), the DialogRef isn't available via injection because embedded\n // views cannot be given a custom injector. Instead, we look up the DialogRef by\n // ID. This must occur in `onInit`, as the ID binding for the dialog container won't\n // be resolved at constructor time.\n this.dialogRef = getClosestDialog(\n this._elementRef,\n this._dialog.openDialogs\n )!;\n }\n }\n\n ngOnChanges(changes: SimpleChanges) {\n const proxiedChange =\n changes._ouiDialogClose || changes._ouiDialogCloseResult;\n if (proxiedChange) {\n this.dialogResult = proxiedChange.currentValue;\n }\n }\n}\n\n/**\n * Content section of dialog.\n */\n@Directive({\n selector: '[oui-dialog-content], [ouiDialogContent]',\n exportAs: 'ouiDialogContent',\n // eslint-disable-next-line @angular-eslint/no-host-metadata-property\n host: {\n class: 'oui-dialog-content',\n },\n})\nexport class OuiDialogContent implements OnInit {\n constructor(\n @Optional() public dialogRef: OuiDialogRef,\n private _elementRef: ElementRef,\n private _dialog: OuiDialog\n ) {}\n\n ngOnInit() {\n if (!this.dialogRef) {\n // When this directive is included in a dialog via TemplateRef (rather than being\n // in a Component), the DialogRef isn't available via injection because embedded\n // views cannot be given a custom injector. Instead, we look up the DialogRef by\n // ID. This must occur in `onInit`, as the ID binding for the dialog container won't\n // be resolved at constructor time.\n this.dialogRef = getClosestDialog(\n this._elementRef,\n this._dialog.openDialogs\n )!;\n }\n this._setContentHeight();\n }\n /* prevent content scroll in default scroll strategy **/\n private _setContentHeight() {\n if (!this.dialogRef.dialogConfig.scrollStrategy) {\n this._elementRef.nativeElement.style.maxHeight = 'none';\n this._elementRef.nativeElement.style.overflow = 'visible';\n }\n }\n}\n\n/**\n * Content section of dialog.\n */\n@Directive({\n selector: '[oui-dialog-footer], [ouiDialogFooter]',\n exportAs: 'ouiDialogFooter',\n // eslint-disable-next-line @angular-eslint/no-host-metadata-property\n host: {\n class: 'oui-dialog-footer',\n },\n})\nexport class OuiDialogFooter {\n @Input()\n id = `oui-dialog-footer-${dialogElementUid++}`;\n constructor() {}\n}\n\n/**\n * footer action left\n */\n@Directive({\n selector: '[oui-dialog-footer-action-left], [ouiDialogFooterActionLeft]',\n exportAs: 'ouiDialogFooterActionLeft',\n // eslint-disable-next-line @angular-eslint/no-host-metadata-property\n host: {\n class: 'oui-dialog-footer-action-left',\n },\n})\nexport class OuiDialogFooterActionLeft {\n constructor() {}\n}\n\n/**\n * footer action right\n */\n@Directive({\n selector: '[oui-dialog-footer-action-right], [ouiDialogFooterActionRight]',\n exportAs: 'ouiDialogFooterActionRight',\n // eslint-disable-next-line @angular-eslint/no-host-metadata-property\n host: {\n class: 'oui-dialog-footer-action-right',\n },\n})\nexport class OuiDialogFooterActionRight {\n constructor() {}\n}\n\n/**\n * Finds the closest MatDialogRef to an element by looking at the DOM.\n *\n * @param element Element relative to which to look for a dialog.\n * @param openDialogs References to the currently-open dialogs.\n */\nfunction getClosestDialog(\n element: ElementRef,\n openDialogs: OuiDialogRef[]\n) {\n let parent: HTMLElement | null = element.nativeElement.parentElement;\n\n while (parent && !parent.classList.contains('oui-dialog-container')) {\n parent = parent.parentElement;\n }\n\n return parent ? openDialogs.find((dialog) => dialog.id === parent!.id) : null;\n}\n", "selector": "[oui-dialog-content], [ouiDialogContent]", "providers": [], + "exportAs": "ouiDialogContent", + "hostDirectives": [], + "standalone": false, "inputsClass": [], "outputsClass": [], "deprecated": false, @@ -14022,7 +14149,8 @@ } ], "modifierKind": [ - 123 + 170, + 125 ] } ], @@ -14037,7 +14165,7 @@ "deprecated": false, "deprecationMessage": "", "modifierKind": [ - 121 + 123 ] }, { @@ -14051,6 +14179,7 @@ "deprecationMessage": "" } ], + "extends": [], "implements": [ "OnInit" ], @@ -14121,6 +14250,9 @@ "sourceCode": "import {\n Directive,\n Input,\n OnChanges,\n OnInit,\n Optional,\n SimpleChanges,\n ElementRef,\n Component,\n NgZone,\n OnDestroy,\n} from '@angular/core';\nimport { OuiDialog } from './dialog';\nimport { OuiDialogRef } from './dialog-ref';\nimport { OuiIconRegistry } from '../icon/icon-registery';\nimport { DomSanitizer } from '@angular/platform-browser';\nimport { ICONS } from '../core/shared/icons';\nimport { Subscription } from 'rxjs';\nimport { FocusMonitor } from '@angular/cdk/a11y';\n\n/** Counter used to generate unique IDs for dialog elements. */\nlet dialogElementUid = 0;\n\n/**\n * Header section of ui.\n */\n@Directive({\n selector: '[oui-dialog-header], [ouiDialogHeader]',\n exportAs: 'ouiDialogHeader',\n // eslint-disable-next-line @angular-eslint/no-host-metadata-property\n host: {\n class: 'oui-dialog-header',\n },\n})\nexport class OuiDialogHeader {\n constructor() {}\n}\n\n/**\n * Header Title of ui.\n */\n@Directive({\n selector: '[oui-dialog-header-title], [ouiDialogHeaderTitle]',\n exportAs: 'ouiDialogHeaderTitle',\n // eslint-disable-next-line @angular-eslint/no-host-metadata-property\n host: {\n class: 'oui-dialog-header-title',\n },\n})\nexport class OuiDialogHeaderTitle {\n constructor() {}\n}\n\n/**\n * Header Image of ui.\n */\n@Directive({\n selector: '[oui-dialog-header-image], [ouiDialogHeaderImage]',\n exportAs: 'ouiDialogHeaderImage',\n // eslint-disable-next-line @angular-eslint/no-host-metadata-property\n host: {\n class: 'oui-dialog-header-image',\n },\n})\nexport class OuiDialogHeaderImage {\n constructor() {}\n}\n\n/**\n * Header action area of dialog.\n */\n@Directive({\n selector: '[oui-dialog-header-action], [ouiDialogHeaderAction]',\n exportAs: 'ouiDialogHeaderAction',\n // eslint-disable-next-line @angular-eslint/no-host-metadata-property\n host: {\n class: 'oui-dialog-header-action',\n },\n})\nexport class OuiDialogHeaderAction {\n constructor() {}\n}\n\n/**\n * header action article.\n */\n@Component({\n // eslint-disable-next-line @angular-eslint/component-selector\n selector: '[oui-dialog-header-article], [ouiDialogHeaderArticle]',\n template: '',\n exportAs: 'ouiDialogHeaderArticle',\n // eslint-disable-next-line @angular-eslint/no-host-metadata-property\n host: {\n class: 'oui-dialog-header-article',\n },\n})\nexport class OuiDialogHeaderArticle implements OnDestroy {\n private _monitorSubscription: Subscription = Subscription.EMPTY;\n constructor(\n private ouiIconRegistry: OuiIconRegistry,\n private domSanitizer: DomSanitizer,\n protected elementRef: ElementRef,\n private _focusMonitor: FocusMonitor,\n private _ngZone: NgZone\n ) {\n this.ouiIconRegistry.addSvgIconLiteral(\n `article-icon`,\n this.domSanitizer.bypassSecurityTrustHtml(ICONS.ARTICLE_ICON)\n );\n this._monitorSubscription = this._focusMonitor\n .monitor(this.elementRef, true)\n .subscribe(() => this._ngZone.run(() => {}));\n }\n ngOnDestroy() {\n this._monitorSubscription.unsubscribe();\n }\n}\n\n/**\n * header action article.\n */\n@Component({\n // eslint-disable-next-line @angular-eslint/component-selector\n selector: '[oui-dialog-header-video], [ouiDialogHeaderVideo]',\n template: '',\n exportAs: 'ouiDialogHeaderVideo',\n // eslint-disable-next-line @angular-eslint/no-host-metadata-property\n host: {\n class: 'oui-dialog-header-video',\n },\n})\nexport class OuiDialogHeaderVideo implements OnDestroy {\n private _monitorSubscription: Subscription = Subscription.EMPTY;\n\n constructor(\n private ouiIconRegistry: OuiIconRegistry,\n private domSanitizer: DomSanitizer,\n protected elementRef: ElementRef,\n private _focusMonitor: FocusMonitor,\n private _ngZone: NgZone\n ) {\n this.ouiIconRegistry.addSvgIconLiteral(\n `video-icon`,\n this.domSanitizer.bypassSecurityTrustHtml(ICONS.VIDEO_ICON)\n );\n this._monitorSubscription = this._focusMonitor\n .monitor(this.elementRef, true)\n .subscribe(() => this._ngZone.run(() => {}));\n }\n ngOnDestroy() {\n this._monitorSubscription.unsubscribe();\n }\n}\n\n/**\n * header action close\n */\n@Component({\n // eslint-disable-next-line @angular-eslint/component-selector\n selector: '[oui-dialog-header-close], [ouiDialogHeaderClose]',\n template: '',\n exportAs: 'ouiDialogHeaderClose',\n // eslint-disable-next-line @angular-eslint/no-host-metadata-property\n host: {\n class: 'oui-dialog-header-close',\n '[attr.tabindex]': '0',\n },\n})\nexport class OuiDialogHeaderClose implements OnDestroy {\n private _monitorSubscription: Subscription = Subscription.EMPTY;\n constructor(\n private ouiIconRegistry: OuiIconRegistry,\n private domSanitizer: DomSanitizer,\n protected elementRef: ElementRef,\n private _focusMonitor: FocusMonitor,\n private _ngZone: NgZone\n ) {\n this.ouiIconRegistry.addSvgIconLiteral(\n `close-icon`,\n this.domSanitizer.bypassSecurityTrustHtml(ICONS.CLOSE_ICON)\n );\n this._monitorSubscription = this._focusMonitor\n .monitor(this.elementRef, true)\n .subscribe(() => this._ngZone.run(() => {}));\n }\n ngOnDestroy() {\n this._monitorSubscription.unsubscribe();\n }\n}\n\n/**\n * header action separator close\n */\n@Directive({\n selector: '[oui-dialog-header-separator], [ouiDialogHeaderSeparator]',\n exportAs: 'ouiDialogHeaderSeparator',\n // eslint-disable-next-line @angular-eslint/no-host-metadata-property\n host: {\n class: 'oui-dialog-header-separator',\n },\n})\nexport class OuiDialogHeaderSeparator {\n constructor() {}\n}\n\n/**\n * directive for close the current dialog.\n */\n@Directive({\n selector: `[oui-dialog-close], [ouiDialogClose]`,\n exportAs: 'ouiDialogClose',\n // eslint-disable-next-line @angular-eslint/no-host-metadata-property\n host: {\n '[class.cross-disabled]': 'dialogResult===false',\n '(click)': 'closeDialog()',\n '[attr.aria-label]': 'ariaLabel',\n '(keyup.space)': 'handleKeydown($event)',\n '(keydown.enter)': 'handleKeydown($event)',\n },\n})\nexport class OuiDialogClose implements OnInit, OnChanges {\n /** Screenreader label for the button. */\n @Input('aria-label')\n ariaLabel = 'Close dialog';\n\n /** Dialog close input. */\n @Input('oui-dialog-close')\n dialogResult: any;\n\n @Input('ouiDialogClose')\n _ouiDialogClose: any;\n\n constructor(\n @Optional() public dialogRef: OuiDialogRef,\n private _elementRef: ElementRef,\n private _dialog: OuiDialog\n ) {}\n\n /** Ensures the option is selected when activated from the keyboard. */\n handleKeydown(event: KeyboardEvent): void {\n this.closeDialog();\n event.preventDefault();\n }\n\n closeDialog() {\n if (this.dialogResult !== false) {\n this.dialogRef.close(this.dialogResult);\n }\n }\n\n ngOnInit() {\n if (!this.dialogRef) {\n // When this directive is included in a dialog via TemplateRef (rather than being\n // in a Component), the DialogRef isn't available via injection because embedded\n // views cannot be given a custom injector. Instead, we look up the DialogRef by\n // ID. This must occur in `onInit`, as the ID binding for the dialog container won't\n // be resolved at constructor time.\n this.dialogRef = getClosestDialog(\n this._elementRef,\n this._dialog.openDialogs\n )!;\n }\n }\n\n ngOnChanges(changes: SimpleChanges) {\n const proxiedChange =\n changes._ouiDialogClose || changes._ouiDialogCloseResult;\n if (proxiedChange) {\n this.dialogResult = proxiedChange.currentValue;\n }\n }\n}\n\n/**\n * Content section of dialog.\n */\n@Directive({\n selector: '[oui-dialog-content], [ouiDialogContent]',\n exportAs: 'ouiDialogContent',\n // eslint-disable-next-line @angular-eslint/no-host-metadata-property\n host: {\n class: 'oui-dialog-content',\n },\n})\nexport class OuiDialogContent implements OnInit {\n constructor(\n @Optional() public dialogRef: OuiDialogRef,\n private _elementRef: ElementRef,\n private _dialog: OuiDialog\n ) {}\n\n ngOnInit() {\n if (!this.dialogRef) {\n // When this directive is included in a dialog via TemplateRef (rather than being\n // in a Component), the DialogRef isn't available via injection because embedded\n // views cannot be given a custom injector. Instead, we look up the DialogRef by\n // ID. This must occur in `onInit`, as the ID binding for the dialog container won't\n // be resolved at constructor time.\n this.dialogRef = getClosestDialog(\n this._elementRef,\n this._dialog.openDialogs\n )!;\n }\n this._setContentHeight();\n }\n /* prevent content scroll in default scroll strategy **/\n private _setContentHeight() {\n if (!this.dialogRef.dialogConfig.scrollStrategy) {\n this._elementRef.nativeElement.style.maxHeight = 'none';\n this._elementRef.nativeElement.style.overflow = 'visible';\n }\n }\n}\n\n/**\n * Content section of dialog.\n */\n@Directive({\n selector: '[oui-dialog-footer], [ouiDialogFooter]',\n exportAs: 'ouiDialogFooter',\n // eslint-disable-next-line @angular-eslint/no-host-metadata-property\n host: {\n class: 'oui-dialog-footer',\n },\n})\nexport class OuiDialogFooter {\n @Input()\n id = `oui-dialog-footer-${dialogElementUid++}`;\n constructor() {}\n}\n\n/**\n * footer action left\n */\n@Directive({\n selector: '[oui-dialog-footer-action-left], [ouiDialogFooterActionLeft]',\n exportAs: 'ouiDialogFooterActionLeft',\n // eslint-disable-next-line @angular-eslint/no-host-metadata-property\n host: {\n class: 'oui-dialog-footer-action-left',\n },\n})\nexport class OuiDialogFooterActionLeft {\n constructor() {}\n}\n\n/**\n * footer action right\n */\n@Directive({\n selector: '[oui-dialog-footer-action-right], [ouiDialogFooterActionRight]',\n exportAs: 'ouiDialogFooterActionRight',\n // eslint-disable-next-line @angular-eslint/no-host-metadata-property\n host: {\n class: 'oui-dialog-footer-action-right',\n },\n})\nexport class OuiDialogFooterActionRight {\n constructor() {}\n}\n\n/**\n * Finds the closest MatDialogRef to an element by looking at the DOM.\n *\n * @param element Element relative to which to look for a dialog.\n * @param openDialogs References to the currently-open dialogs.\n */\nfunction getClosestDialog(\n element: ElementRef,\n openDialogs: OuiDialogRef[]\n) {\n let parent: HTMLElement | null = element.nativeElement.parentElement;\n\n while (parent && !parent.classList.contains('oui-dialog-container')) {\n parent = parent.parentElement;\n }\n\n return parent ? openDialogs.find((dialog) => dialog.id === parent!.id) : null;\n}\n", "selector": "[oui-dialog-footer], [ouiDialogFooter]", "providers": [], + "exportAs": "ouiDialogFooter", + "hostDirectives": [], + "standalone": false, "inputsClass": [ { "name": "id", @@ -14139,6 +14271,7 @@ "hostListeners": [], "propertiesClass": [], "methodsClass": [], + "extends": [], "constructorObj": { "name": "constructor", "description": "", @@ -14158,6 +14291,9 @@ "sourceCode": "import {\n Directive,\n Input,\n OnChanges,\n OnInit,\n Optional,\n SimpleChanges,\n ElementRef,\n Component,\n NgZone,\n OnDestroy,\n} from '@angular/core';\nimport { OuiDialog } from './dialog';\nimport { OuiDialogRef } from './dialog-ref';\nimport { OuiIconRegistry } from '../icon/icon-registery';\nimport { DomSanitizer } from '@angular/platform-browser';\nimport { ICONS } from '../core/shared/icons';\nimport { Subscription } from 'rxjs';\nimport { FocusMonitor } from '@angular/cdk/a11y';\n\n/** Counter used to generate unique IDs for dialog elements. */\nlet dialogElementUid = 0;\n\n/**\n * Header section of ui.\n */\n@Directive({\n selector: '[oui-dialog-header], [ouiDialogHeader]',\n exportAs: 'ouiDialogHeader',\n // eslint-disable-next-line @angular-eslint/no-host-metadata-property\n host: {\n class: 'oui-dialog-header',\n },\n})\nexport class OuiDialogHeader {\n constructor() {}\n}\n\n/**\n * Header Title of ui.\n */\n@Directive({\n selector: '[oui-dialog-header-title], [ouiDialogHeaderTitle]',\n exportAs: 'ouiDialogHeaderTitle',\n // eslint-disable-next-line @angular-eslint/no-host-metadata-property\n host: {\n class: 'oui-dialog-header-title',\n },\n})\nexport class OuiDialogHeaderTitle {\n constructor() {}\n}\n\n/**\n * Header Image of ui.\n */\n@Directive({\n selector: '[oui-dialog-header-image], [ouiDialogHeaderImage]',\n exportAs: 'ouiDialogHeaderImage',\n // eslint-disable-next-line @angular-eslint/no-host-metadata-property\n host: {\n class: 'oui-dialog-header-image',\n },\n})\nexport class OuiDialogHeaderImage {\n constructor() {}\n}\n\n/**\n * Header action area of dialog.\n */\n@Directive({\n selector: '[oui-dialog-header-action], [ouiDialogHeaderAction]',\n exportAs: 'ouiDialogHeaderAction',\n // eslint-disable-next-line @angular-eslint/no-host-metadata-property\n host: {\n class: 'oui-dialog-header-action',\n },\n})\nexport class OuiDialogHeaderAction {\n constructor() {}\n}\n\n/**\n * header action article.\n */\n@Component({\n // eslint-disable-next-line @angular-eslint/component-selector\n selector: '[oui-dialog-header-article], [ouiDialogHeaderArticle]',\n template: '',\n exportAs: 'ouiDialogHeaderArticle',\n // eslint-disable-next-line @angular-eslint/no-host-metadata-property\n host: {\n class: 'oui-dialog-header-article',\n },\n})\nexport class OuiDialogHeaderArticle implements OnDestroy {\n private _monitorSubscription: Subscription = Subscription.EMPTY;\n constructor(\n private ouiIconRegistry: OuiIconRegistry,\n private domSanitizer: DomSanitizer,\n protected elementRef: ElementRef,\n private _focusMonitor: FocusMonitor,\n private _ngZone: NgZone\n ) {\n this.ouiIconRegistry.addSvgIconLiteral(\n `article-icon`,\n this.domSanitizer.bypassSecurityTrustHtml(ICONS.ARTICLE_ICON)\n );\n this._monitorSubscription = this._focusMonitor\n .monitor(this.elementRef, true)\n .subscribe(() => this._ngZone.run(() => {}));\n }\n ngOnDestroy() {\n this._monitorSubscription.unsubscribe();\n }\n}\n\n/**\n * header action article.\n */\n@Component({\n // eslint-disable-next-line @angular-eslint/component-selector\n selector: '[oui-dialog-header-video], [ouiDialogHeaderVideo]',\n template: '',\n exportAs: 'ouiDialogHeaderVideo',\n // eslint-disable-next-line @angular-eslint/no-host-metadata-property\n host: {\n class: 'oui-dialog-header-video',\n },\n})\nexport class OuiDialogHeaderVideo implements OnDestroy {\n private _monitorSubscription: Subscription = Subscription.EMPTY;\n\n constructor(\n private ouiIconRegistry: OuiIconRegistry,\n private domSanitizer: DomSanitizer,\n protected elementRef: ElementRef,\n private _focusMonitor: FocusMonitor,\n private _ngZone: NgZone\n ) {\n this.ouiIconRegistry.addSvgIconLiteral(\n `video-icon`,\n this.domSanitizer.bypassSecurityTrustHtml(ICONS.VIDEO_ICON)\n );\n this._monitorSubscription = this._focusMonitor\n .monitor(this.elementRef, true)\n .subscribe(() => this._ngZone.run(() => {}));\n }\n ngOnDestroy() {\n this._monitorSubscription.unsubscribe();\n }\n}\n\n/**\n * header action close\n */\n@Component({\n // eslint-disable-next-line @angular-eslint/component-selector\n selector: '[oui-dialog-header-close], [ouiDialogHeaderClose]',\n template: '',\n exportAs: 'ouiDialogHeaderClose',\n // eslint-disable-next-line @angular-eslint/no-host-metadata-property\n host: {\n class: 'oui-dialog-header-close',\n '[attr.tabindex]': '0',\n },\n})\nexport class OuiDialogHeaderClose implements OnDestroy {\n private _monitorSubscription: Subscription = Subscription.EMPTY;\n constructor(\n private ouiIconRegistry: OuiIconRegistry,\n private domSanitizer: DomSanitizer,\n protected elementRef: ElementRef,\n private _focusMonitor: FocusMonitor,\n private _ngZone: NgZone\n ) {\n this.ouiIconRegistry.addSvgIconLiteral(\n `close-icon`,\n this.domSanitizer.bypassSecurityTrustHtml(ICONS.CLOSE_ICON)\n );\n this._monitorSubscription = this._focusMonitor\n .monitor(this.elementRef, true)\n .subscribe(() => this._ngZone.run(() => {}));\n }\n ngOnDestroy() {\n this._monitorSubscription.unsubscribe();\n }\n}\n\n/**\n * header action separator close\n */\n@Directive({\n selector: '[oui-dialog-header-separator], [ouiDialogHeaderSeparator]',\n exportAs: 'ouiDialogHeaderSeparator',\n // eslint-disable-next-line @angular-eslint/no-host-metadata-property\n host: {\n class: 'oui-dialog-header-separator',\n },\n})\nexport class OuiDialogHeaderSeparator {\n constructor() {}\n}\n\n/**\n * directive for close the current dialog.\n */\n@Directive({\n selector: `[oui-dialog-close], [ouiDialogClose]`,\n exportAs: 'ouiDialogClose',\n // eslint-disable-next-line @angular-eslint/no-host-metadata-property\n host: {\n '[class.cross-disabled]': 'dialogResult===false',\n '(click)': 'closeDialog()',\n '[attr.aria-label]': 'ariaLabel',\n '(keyup.space)': 'handleKeydown($event)',\n '(keydown.enter)': 'handleKeydown($event)',\n },\n})\nexport class OuiDialogClose implements OnInit, OnChanges {\n /** Screenreader label for the button. */\n @Input('aria-label')\n ariaLabel = 'Close dialog';\n\n /** Dialog close input. */\n @Input('oui-dialog-close')\n dialogResult: any;\n\n @Input('ouiDialogClose')\n _ouiDialogClose: any;\n\n constructor(\n @Optional() public dialogRef: OuiDialogRef,\n private _elementRef: ElementRef,\n private _dialog: OuiDialog\n ) {}\n\n /** Ensures the option is selected when activated from the keyboard. */\n handleKeydown(event: KeyboardEvent): void {\n this.closeDialog();\n event.preventDefault();\n }\n\n closeDialog() {\n if (this.dialogResult !== false) {\n this.dialogRef.close(this.dialogResult);\n }\n }\n\n ngOnInit() {\n if (!this.dialogRef) {\n // When this directive is included in a dialog via TemplateRef (rather than being\n // in a Component), the DialogRef isn't available via injection because embedded\n // views cannot be given a custom injector. Instead, we look up the DialogRef by\n // ID. This must occur in `onInit`, as the ID binding for the dialog container won't\n // be resolved at constructor time.\n this.dialogRef = getClosestDialog(\n this._elementRef,\n this._dialog.openDialogs\n )!;\n }\n }\n\n ngOnChanges(changes: SimpleChanges) {\n const proxiedChange =\n changes._ouiDialogClose || changes._ouiDialogCloseResult;\n if (proxiedChange) {\n this.dialogResult = proxiedChange.currentValue;\n }\n }\n}\n\n/**\n * Content section of dialog.\n */\n@Directive({\n selector: '[oui-dialog-content], [ouiDialogContent]',\n exportAs: 'ouiDialogContent',\n // eslint-disable-next-line @angular-eslint/no-host-metadata-property\n host: {\n class: 'oui-dialog-content',\n },\n})\nexport class OuiDialogContent implements OnInit {\n constructor(\n @Optional() public dialogRef: OuiDialogRef,\n private _elementRef: ElementRef,\n private _dialog: OuiDialog\n ) {}\n\n ngOnInit() {\n if (!this.dialogRef) {\n // When this directive is included in a dialog via TemplateRef (rather than being\n // in a Component), the DialogRef isn't available via injection because embedded\n // views cannot be given a custom injector. Instead, we look up the DialogRef by\n // ID. This must occur in `onInit`, as the ID binding for the dialog container won't\n // be resolved at constructor time.\n this.dialogRef = getClosestDialog(\n this._elementRef,\n this._dialog.openDialogs\n )!;\n }\n this._setContentHeight();\n }\n /* prevent content scroll in default scroll strategy **/\n private _setContentHeight() {\n if (!this.dialogRef.dialogConfig.scrollStrategy) {\n this._elementRef.nativeElement.style.maxHeight = 'none';\n this._elementRef.nativeElement.style.overflow = 'visible';\n }\n }\n}\n\n/**\n * Content section of dialog.\n */\n@Directive({\n selector: '[oui-dialog-footer], [ouiDialogFooter]',\n exportAs: 'ouiDialogFooter',\n // eslint-disable-next-line @angular-eslint/no-host-metadata-property\n host: {\n class: 'oui-dialog-footer',\n },\n})\nexport class OuiDialogFooter {\n @Input()\n id = `oui-dialog-footer-${dialogElementUid++}`;\n constructor() {}\n}\n\n/**\n * footer action left\n */\n@Directive({\n selector: '[oui-dialog-footer-action-left], [ouiDialogFooterActionLeft]',\n exportAs: 'ouiDialogFooterActionLeft',\n // eslint-disable-next-line @angular-eslint/no-host-metadata-property\n host: {\n class: 'oui-dialog-footer-action-left',\n },\n})\nexport class OuiDialogFooterActionLeft {\n constructor() {}\n}\n\n/**\n * footer action right\n */\n@Directive({\n selector: '[oui-dialog-footer-action-right], [ouiDialogFooterActionRight]',\n exportAs: 'ouiDialogFooterActionRight',\n // eslint-disable-next-line @angular-eslint/no-host-metadata-property\n host: {\n class: 'oui-dialog-footer-action-right',\n },\n})\nexport class OuiDialogFooterActionRight {\n constructor() {}\n}\n\n/**\n * Finds the closest MatDialogRef to an element by looking at the DOM.\n *\n * @param element Element relative to which to look for a dialog.\n * @param openDialogs References to the currently-open dialogs.\n */\nfunction getClosestDialog(\n element: ElementRef,\n openDialogs: OuiDialogRef[]\n) {\n let parent: HTMLElement | null = element.nativeElement.parentElement;\n\n while (parent && !parent.classList.contains('oui-dialog-container')) {\n parent = parent.parentElement;\n }\n\n return parent ? openDialogs.find((dialog) => dialog.id === parent!.id) : null;\n}\n", "selector": "[oui-dialog-footer-action-left], [ouiDialogFooterActionLeft]", "providers": [], + "exportAs": "ouiDialogFooterActionLeft", + "hostDirectives": [], + "standalone": false, "inputsClass": [], "outputsClass": [], "deprecated": false, @@ -14166,6 +14302,7 @@ "hostListeners": [], "propertiesClass": [], "methodsClass": [], + "extends": [], "constructorObj": { "name": "constructor", "description": "", @@ -14185,6 +14322,9 @@ "sourceCode": "import {\n Directive,\n Input,\n OnChanges,\n OnInit,\n Optional,\n SimpleChanges,\n ElementRef,\n Component,\n NgZone,\n OnDestroy,\n} from '@angular/core';\nimport { OuiDialog } from './dialog';\nimport { OuiDialogRef } from './dialog-ref';\nimport { OuiIconRegistry } from '../icon/icon-registery';\nimport { DomSanitizer } from '@angular/platform-browser';\nimport { ICONS } from '../core/shared/icons';\nimport { Subscription } from 'rxjs';\nimport { FocusMonitor } from '@angular/cdk/a11y';\n\n/** Counter used to generate unique IDs for dialog elements. */\nlet dialogElementUid = 0;\n\n/**\n * Header section of ui.\n */\n@Directive({\n selector: '[oui-dialog-header], [ouiDialogHeader]',\n exportAs: 'ouiDialogHeader',\n // eslint-disable-next-line @angular-eslint/no-host-metadata-property\n host: {\n class: 'oui-dialog-header',\n },\n})\nexport class OuiDialogHeader {\n constructor() {}\n}\n\n/**\n * Header Title of ui.\n */\n@Directive({\n selector: '[oui-dialog-header-title], [ouiDialogHeaderTitle]',\n exportAs: 'ouiDialogHeaderTitle',\n // eslint-disable-next-line @angular-eslint/no-host-metadata-property\n host: {\n class: 'oui-dialog-header-title',\n },\n})\nexport class OuiDialogHeaderTitle {\n constructor() {}\n}\n\n/**\n * Header Image of ui.\n */\n@Directive({\n selector: '[oui-dialog-header-image], [ouiDialogHeaderImage]',\n exportAs: 'ouiDialogHeaderImage',\n // eslint-disable-next-line @angular-eslint/no-host-metadata-property\n host: {\n class: 'oui-dialog-header-image',\n },\n})\nexport class OuiDialogHeaderImage {\n constructor() {}\n}\n\n/**\n * Header action area of dialog.\n */\n@Directive({\n selector: '[oui-dialog-header-action], [ouiDialogHeaderAction]',\n exportAs: 'ouiDialogHeaderAction',\n // eslint-disable-next-line @angular-eslint/no-host-metadata-property\n host: {\n class: 'oui-dialog-header-action',\n },\n})\nexport class OuiDialogHeaderAction {\n constructor() {}\n}\n\n/**\n * header action article.\n */\n@Component({\n // eslint-disable-next-line @angular-eslint/component-selector\n selector: '[oui-dialog-header-article], [ouiDialogHeaderArticle]',\n template: '',\n exportAs: 'ouiDialogHeaderArticle',\n // eslint-disable-next-line @angular-eslint/no-host-metadata-property\n host: {\n class: 'oui-dialog-header-article',\n },\n})\nexport class OuiDialogHeaderArticle implements OnDestroy {\n private _monitorSubscription: Subscription = Subscription.EMPTY;\n constructor(\n private ouiIconRegistry: OuiIconRegistry,\n private domSanitizer: DomSanitizer,\n protected elementRef: ElementRef,\n private _focusMonitor: FocusMonitor,\n private _ngZone: NgZone\n ) {\n this.ouiIconRegistry.addSvgIconLiteral(\n `article-icon`,\n this.domSanitizer.bypassSecurityTrustHtml(ICONS.ARTICLE_ICON)\n );\n this._monitorSubscription = this._focusMonitor\n .monitor(this.elementRef, true)\n .subscribe(() => this._ngZone.run(() => {}));\n }\n ngOnDestroy() {\n this._monitorSubscription.unsubscribe();\n }\n}\n\n/**\n * header action article.\n */\n@Component({\n // eslint-disable-next-line @angular-eslint/component-selector\n selector: '[oui-dialog-header-video], [ouiDialogHeaderVideo]',\n template: '',\n exportAs: 'ouiDialogHeaderVideo',\n // eslint-disable-next-line @angular-eslint/no-host-metadata-property\n host: {\n class: 'oui-dialog-header-video',\n },\n})\nexport class OuiDialogHeaderVideo implements OnDestroy {\n private _monitorSubscription: Subscription = Subscription.EMPTY;\n\n constructor(\n private ouiIconRegistry: OuiIconRegistry,\n private domSanitizer: DomSanitizer,\n protected elementRef: ElementRef,\n private _focusMonitor: FocusMonitor,\n private _ngZone: NgZone\n ) {\n this.ouiIconRegistry.addSvgIconLiteral(\n `video-icon`,\n this.domSanitizer.bypassSecurityTrustHtml(ICONS.VIDEO_ICON)\n );\n this._monitorSubscription = this._focusMonitor\n .monitor(this.elementRef, true)\n .subscribe(() => this._ngZone.run(() => {}));\n }\n ngOnDestroy() {\n this._monitorSubscription.unsubscribe();\n }\n}\n\n/**\n * header action close\n */\n@Component({\n // eslint-disable-next-line @angular-eslint/component-selector\n selector: '[oui-dialog-header-close], [ouiDialogHeaderClose]',\n template: '',\n exportAs: 'ouiDialogHeaderClose',\n // eslint-disable-next-line @angular-eslint/no-host-metadata-property\n host: {\n class: 'oui-dialog-header-close',\n '[attr.tabindex]': '0',\n },\n})\nexport class OuiDialogHeaderClose implements OnDestroy {\n private _monitorSubscription: Subscription = Subscription.EMPTY;\n constructor(\n private ouiIconRegistry: OuiIconRegistry,\n private domSanitizer: DomSanitizer,\n protected elementRef: ElementRef,\n private _focusMonitor: FocusMonitor,\n private _ngZone: NgZone\n ) {\n this.ouiIconRegistry.addSvgIconLiteral(\n `close-icon`,\n this.domSanitizer.bypassSecurityTrustHtml(ICONS.CLOSE_ICON)\n );\n this._monitorSubscription = this._focusMonitor\n .monitor(this.elementRef, true)\n .subscribe(() => this._ngZone.run(() => {}));\n }\n ngOnDestroy() {\n this._monitorSubscription.unsubscribe();\n }\n}\n\n/**\n * header action separator close\n */\n@Directive({\n selector: '[oui-dialog-header-separator], [ouiDialogHeaderSeparator]',\n exportAs: 'ouiDialogHeaderSeparator',\n // eslint-disable-next-line @angular-eslint/no-host-metadata-property\n host: {\n class: 'oui-dialog-header-separator',\n },\n})\nexport class OuiDialogHeaderSeparator {\n constructor() {}\n}\n\n/**\n * directive for close the current dialog.\n */\n@Directive({\n selector: `[oui-dialog-close], [ouiDialogClose]`,\n exportAs: 'ouiDialogClose',\n // eslint-disable-next-line @angular-eslint/no-host-metadata-property\n host: {\n '[class.cross-disabled]': 'dialogResult===false',\n '(click)': 'closeDialog()',\n '[attr.aria-label]': 'ariaLabel',\n '(keyup.space)': 'handleKeydown($event)',\n '(keydown.enter)': 'handleKeydown($event)',\n },\n})\nexport class OuiDialogClose implements OnInit, OnChanges {\n /** Screenreader label for the button. */\n @Input('aria-label')\n ariaLabel = 'Close dialog';\n\n /** Dialog close input. */\n @Input('oui-dialog-close')\n dialogResult: any;\n\n @Input('ouiDialogClose')\n _ouiDialogClose: any;\n\n constructor(\n @Optional() public dialogRef: OuiDialogRef,\n private _elementRef: ElementRef,\n private _dialog: OuiDialog\n ) {}\n\n /** Ensures the option is selected when activated from the keyboard. */\n handleKeydown(event: KeyboardEvent): void {\n this.closeDialog();\n event.preventDefault();\n }\n\n closeDialog() {\n if (this.dialogResult !== false) {\n this.dialogRef.close(this.dialogResult);\n }\n }\n\n ngOnInit() {\n if (!this.dialogRef) {\n // When this directive is included in a dialog via TemplateRef (rather than being\n // in a Component), the DialogRef isn't available via injection because embedded\n // views cannot be given a custom injector. Instead, we look up the DialogRef by\n // ID. This must occur in `onInit`, as the ID binding for the dialog container won't\n // be resolved at constructor time.\n this.dialogRef = getClosestDialog(\n this._elementRef,\n this._dialog.openDialogs\n )!;\n }\n }\n\n ngOnChanges(changes: SimpleChanges) {\n const proxiedChange =\n changes._ouiDialogClose || changes._ouiDialogCloseResult;\n if (proxiedChange) {\n this.dialogResult = proxiedChange.currentValue;\n }\n }\n}\n\n/**\n * Content section of dialog.\n */\n@Directive({\n selector: '[oui-dialog-content], [ouiDialogContent]',\n exportAs: 'ouiDialogContent',\n // eslint-disable-next-line @angular-eslint/no-host-metadata-property\n host: {\n class: 'oui-dialog-content',\n },\n})\nexport class OuiDialogContent implements OnInit {\n constructor(\n @Optional() public dialogRef: OuiDialogRef,\n private _elementRef: ElementRef,\n private _dialog: OuiDialog\n ) {}\n\n ngOnInit() {\n if (!this.dialogRef) {\n // When this directive is included in a dialog via TemplateRef (rather than being\n // in a Component), the DialogRef isn't available via injection because embedded\n // views cannot be given a custom injector. Instead, we look up the DialogRef by\n // ID. This must occur in `onInit`, as the ID binding for the dialog container won't\n // be resolved at constructor time.\n this.dialogRef = getClosestDialog(\n this._elementRef,\n this._dialog.openDialogs\n )!;\n }\n this._setContentHeight();\n }\n /* prevent content scroll in default scroll strategy **/\n private _setContentHeight() {\n if (!this.dialogRef.dialogConfig.scrollStrategy) {\n this._elementRef.nativeElement.style.maxHeight = 'none';\n this._elementRef.nativeElement.style.overflow = 'visible';\n }\n }\n}\n\n/**\n * Content section of dialog.\n */\n@Directive({\n selector: '[oui-dialog-footer], [ouiDialogFooter]',\n exportAs: 'ouiDialogFooter',\n // eslint-disable-next-line @angular-eslint/no-host-metadata-property\n host: {\n class: 'oui-dialog-footer',\n },\n})\nexport class OuiDialogFooter {\n @Input()\n id = `oui-dialog-footer-${dialogElementUid++}`;\n constructor() {}\n}\n\n/**\n * footer action left\n */\n@Directive({\n selector: '[oui-dialog-footer-action-left], [ouiDialogFooterActionLeft]',\n exportAs: 'ouiDialogFooterActionLeft',\n // eslint-disable-next-line @angular-eslint/no-host-metadata-property\n host: {\n class: 'oui-dialog-footer-action-left',\n },\n})\nexport class OuiDialogFooterActionLeft {\n constructor() {}\n}\n\n/**\n * footer action right\n */\n@Directive({\n selector: '[oui-dialog-footer-action-right], [ouiDialogFooterActionRight]',\n exportAs: 'ouiDialogFooterActionRight',\n // eslint-disable-next-line @angular-eslint/no-host-metadata-property\n host: {\n class: 'oui-dialog-footer-action-right',\n },\n})\nexport class OuiDialogFooterActionRight {\n constructor() {}\n}\n\n/**\n * Finds the closest MatDialogRef to an element by looking at the DOM.\n *\n * @param element Element relative to which to look for a dialog.\n * @param openDialogs References to the currently-open dialogs.\n */\nfunction getClosestDialog(\n element: ElementRef,\n openDialogs: OuiDialogRef[]\n) {\n let parent: HTMLElement | null = element.nativeElement.parentElement;\n\n while (parent && !parent.classList.contains('oui-dialog-container')) {\n parent = parent.parentElement;\n }\n\n return parent ? openDialogs.find((dialog) => dialog.id === parent!.id) : null;\n}\n", "selector": "[oui-dialog-footer-action-right], [ouiDialogFooterActionRight]", "providers": [], + "exportAs": "ouiDialogFooterActionRight", + "hostDirectives": [], + "standalone": false, "inputsClass": [], "outputsClass": [], "deprecated": false, @@ -14193,6 +14333,7 @@ "hostListeners": [], "propertiesClass": [], "methodsClass": [], + "extends": [], "constructorObj": { "name": "constructor", "description": "", @@ -14212,6 +14353,9 @@ "sourceCode": "import {\n Directive,\n Input,\n OnChanges,\n OnInit,\n Optional,\n SimpleChanges,\n ElementRef,\n Component,\n NgZone,\n OnDestroy,\n} from '@angular/core';\nimport { OuiDialog } from './dialog';\nimport { OuiDialogRef } from './dialog-ref';\nimport { OuiIconRegistry } from '../icon/icon-registery';\nimport { DomSanitizer } from '@angular/platform-browser';\nimport { ICONS } from '../core/shared/icons';\nimport { Subscription } from 'rxjs';\nimport { FocusMonitor } from '@angular/cdk/a11y';\n\n/** Counter used to generate unique IDs for dialog elements. */\nlet dialogElementUid = 0;\n\n/**\n * Header section of ui.\n */\n@Directive({\n selector: '[oui-dialog-header], [ouiDialogHeader]',\n exportAs: 'ouiDialogHeader',\n // eslint-disable-next-line @angular-eslint/no-host-metadata-property\n host: {\n class: 'oui-dialog-header',\n },\n})\nexport class OuiDialogHeader {\n constructor() {}\n}\n\n/**\n * Header Title of ui.\n */\n@Directive({\n selector: '[oui-dialog-header-title], [ouiDialogHeaderTitle]',\n exportAs: 'ouiDialogHeaderTitle',\n // eslint-disable-next-line @angular-eslint/no-host-metadata-property\n host: {\n class: 'oui-dialog-header-title',\n },\n})\nexport class OuiDialogHeaderTitle {\n constructor() {}\n}\n\n/**\n * Header Image of ui.\n */\n@Directive({\n selector: '[oui-dialog-header-image], [ouiDialogHeaderImage]',\n exportAs: 'ouiDialogHeaderImage',\n // eslint-disable-next-line @angular-eslint/no-host-metadata-property\n host: {\n class: 'oui-dialog-header-image',\n },\n})\nexport class OuiDialogHeaderImage {\n constructor() {}\n}\n\n/**\n * Header action area of dialog.\n */\n@Directive({\n selector: '[oui-dialog-header-action], [ouiDialogHeaderAction]',\n exportAs: 'ouiDialogHeaderAction',\n // eslint-disable-next-line @angular-eslint/no-host-metadata-property\n host: {\n class: 'oui-dialog-header-action',\n },\n})\nexport class OuiDialogHeaderAction {\n constructor() {}\n}\n\n/**\n * header action article.\n */\n@Component({\n // eslint-disable-next-line @angular-eslint/component-selector\n selector: '[oui-dialog-header-article], [ouiDialogHeaderArticle]',\n template: '',\n exportAs: 'ouiDialogHeaderArticle',\n // eslint-disable-next-line @angular-eslint/no-host-metadata-property\n host: {\n class: 'oui-dialog-header-article',\n },\n})\nexport class OuiDialogHeaderArticle implements OnDestroy {\n private _monitorSubscription: Subscription = Subscription.EMPTY;\n constructor(\n private ouiIconRegistry: OuiIconRegistry,\n private domSanitizer: DomSanitizer,\n protected elementRef: ElementRef,\n private _focusMonitor: FocusMonitor,\n private _ngZone: NgZone\n ) {\n this.ouiIconRegistry.addSvgIconLiteral(\n `article-icon`,\n this.domSanitizer.bypassSecurityTrustHtml(ICONS.ARTICLE_ICON)\n );\n this._monitorSubscription = this._focusMonitor\n .monitor(this.elementRef, true)\n .subscribe(() => this._ngZone.run(() => {}));\n }\n ngOnDestroy() {\n this._monitorSubscription.unsubscribe();\n }\n}\n\n/**\n * header action article.\n */\n@Component({\n // eslint-disable-next-line @angular-eslint/component-selector\n selector: '[oui-dialog-header-video], [ouiDialogHeaderVideo]',\n template: '',\n exportAs: 'ouiDialogHeaderVideo',\n // eslint-disable-next-line @angular-eslint/no-host-metadata-property\n host: {\n class: 'oui-dialog-header-video',\n },\n})\nexport class OuiDialogHeaderVideo implements OnDestroy {\n private _monitorSubscription: Subscription = Subscription.EMPTY;\n\n constructor(\n private ouiIconRegistry: OuiIconRegistry,\n private domSanitizer: DomSanitizer,\n protected elementRef: ElementRef,\n private _focusMonitor: FocusMonitor,\n private _ngZone: NgZone\n ) {\n this.ouiIconRegistry.addSvgIconLiteral(\n `video-icon`,\n this.domSanitizer.bypassSecurityTrustHtml(ICONS.VIDEO_ICON)\n );\n this._monitorSubscription = this._focusMonitor\n .monitor(this.elementRef, true)\n .subscribe(() => this._ngZone.run(() => {}));\n }\n ngOnDestroy() {\n this._monitorSubscription.unsubscribe();\n }\n}\n\n/**\n * header action close\n */\n@Component({\n // eslint-disable-next-line @angular-eslint/component-selector\n selector: '[oui-dialog-header-close], [ouiDialogHeaderClose]',\n template: '',\n exportAs: 'ouiDialogHeaderClose',\n // eslint-disable-next-line @angular-eslint/no-host-metadata-property\n host: {\n class: 'oui-dialog-header-close',\n '[attr.tabindex]': '0',\n },\n})\nexport class OuiDialogHeaderClose implements OnDestroy {\n private _monitorSubscription: Subscription = Subscription.EMPTY;\n constructor(\n private ouiIconRegistry: OuiIconRegistry,\n private domSanitizer: DomSanitizer,\n protected elementRef: ElementRef,\n private _focusMonitor: FocusMonitor,\n private _ngZone: NgZone\n ) {\n this.ouiIconRegistry.addSvgIconLiteral(\n `close-icon`,\n this.domSanitizer.bypassSecurityTrustHtml(ICONS.CLOSE_ICON)\n );\n this._monitorSubscription = this._focusMonitor\n .monitor(this.elementRef, true)\n .subscribe(() => this._ngZone.run(() => {}));\n }\n ngOnDestroy() {\n this._monitorSubscription.unsubscribe();\n }\n}\n\n/**\n * header action separator close\n */\n@Directive({\n selector: '[oui-dialog-header-separator], [ouiDialogHeaderSeparator]',\n exportAs: 'ouiDialogHeaderSeparator',\n // eslint-disable-next-line @angular-eslint/no-host-metadata-property\n host: {\n class: 'oui-dialog-header-separator',\n },\n})\nexport class OuiDialogHeaderSeparator {\n constructor() {}\n}\n\n/**\n * directive for close the current dialog.\n */\n@Directive({\n selector: `[oui-dialog-close], [ouiDialogClose]`,\n exportAs: 'ouiDialogClose',\n // eslint-disable-next-line @angular-eslint/no-host-metadata-property\n host: {\n '[class.cross-disabled]': 'dialogResult===false',\n '(click)': 'closeDialog()',\n '[attr.aria-label]': 'ariaLabel',\n '(keyup.space)': 'handleKeydown($event)',\n '(keydown.enter)': 'handleKeydown($event)',\n },\n})\nexport class OuiDialogClose implements OnInit, OnChanges {\n /** Screenreader label for the button. */\n @Input('aria-label')\n ariaLabel = 'Close dialog';\n\n /** Dialog close input. */\n @Input('oui-dialog-close')\n dialogResult: any;\n\n @Input('ouiDialogClose')\n _ouiDialogClose: any;\n\n constructor(\n @Optional() public dialogRef: OuiDialogRef,\n private _elementRef: ElementRef,\n private _dialog: OuiDialog\n ) {}\n\n /** Ensures the option is selected when activated from the keyboard. */\n handleKeydown(event: KeyboardEvent): void {\n this.closeDialog();\n event.preventDefault();\n }\n\n closeDialog() {\n if (this.dialogResult !== false) {\n this.dialogRef.close(this.dialogResult);\n }\n }\n\n ngOnInit() {\n if (!this.dialogRef) {\n // When this directive is included in a dialog via TemplateRef (rather than being\n // in a Component), the DialogRef isn't available via injection because embedded\n // views cannot be given a custom injector. Instead, we look up the DialogRef by\n // ID. This must occur in `onInit`, as the ID binding for the dialog container won't\n // be resolved at constructor time.\n this.dialogRef = getClosestDialog(\n this._elementRef,\n this._dialog.openDialogs\n )!;\n }\n }\n\n ngOnChanges(changes: SimpleChanges) {\n const proxiedChange =\n changes._ouiDialogClose || changes._ouiDialogCloseResult;\n if (proxiedChange) {\n this.dialogResult = proxiedChange.currentValue;\n }\n }\n}\n\n/**\n * Content section of dialog.\n */\n@Directive({\n selector: '[oui-dialog-content], [ouiDialogContent]',\n exportAs: 'ouiDialogContent',\n // eslint-disable-next-line @angular-eslint/no-host-metadata-property\n host: {\n class: 'oui-dialog-content',\n },\n})\nexport class OuiDialogContent implements OnInit {\n constructor(\n @Optional() public dialogRef: OuiDialogRef,\n private _elementRef: ElementRef,\n private _dialog: OuiDialog\n ) {}\n\n ngOnInit() {\n if (!this.dialogRef) {\n // When this directive is included in a dialog via TemplateRef (rather than being\n // in a Component), the DialogRef isn't available via injection because embedded\n // views cannot be given a custom injector. Instead, we look up the DialogRef by\n // ID. This must occur in `onInit`, as the ID binding for the dialog container won't\n // be resolved at constructor time.\n this.dialogRef = getClosestDialog(\n this._elementRef,\n this._dialog.openDialogs\n )!;\n }\n this._setContentHeight();\n }\n /* prevent content scroll in default scroll strategy **/\n private _setContentHeight() {\n if (!this.dialogRef.dialogConfig.scrollStrategy) {\n this._elementRef.nativeElement.style.maxHeight = 'none';\n this._elementRef.nativeElement.style.overflow = 'visible';\n }\n }\n}\n\n/**\n * Content section of dialog.\n */\n@Directive({\n selector: '[oui-dialog-footer], [ouiDialogFooter]',\n exportAs: 'ouiDialogFooter',\n // eslint-disable-next-line @angular-eslint/no-host-metadata-property\n host: {\n class: 'oui-dialog-footer',\n },\n})\nexport class OuiDialogFooter {\n @Input()\n id = `oui-dialog-footer-${dialogElementUid++}`;\n constructor() {}\n}\n\n/**\n * footer action left\n */\n@Directive({\n selector: '[oui-dialog-footer-action-left], [ouiDialogFooterActionLeft]',\n exportAs: 'ouiDialogFooterActionLeft',\n // eslint-disable-next-line @angular-eslint/no-host-metadata-property\n host: {\n class: 'oui-dialog-footer-action-left',\n },\n})\nexport class OuiDialogFooterActionLeft {\n constructor() {}\n}\n\n/**\n * footer action right\n */\n@Directive({\n selector: '[oui-dialog-footer-action-right], [ouiDialogFooterActionRight]',\n exportAs: 'ouiDialogFooterActionRight',\n // eslint-disable-next-line @angular-eslint/no-host-metadata-property\n host: {\n class: 'oui-dialog-footer-action-right',\n },\n})\nexport class OuiDialogFooterActionRight {\n constructor() {}\n}\n\n/**\n * Finds the closest MatDialogRef to an element by looking at the DOM.\n *\n * @param element Element relative to which to look for a dialog.\n * @param openDialogs References to the currently-open dialogs.\n */\nfunction getClosestDialog(\n element: ElementRef,\n openDialogs: OuiDialogRef[]\n) {\n let parent: HTMLElement | null = element.nativeElement.parentElement;\n\n while (parent && !parent.classList.contains('oui-dialog-container')) {\n parent = parent.parentElement;\n }\n\n return parent ? openDialogs.find((dialog) => dialog.id === parent!.id) : null;\n}\n", "selector": "[oui-dialog-header], [ouiDialogHeader]", "providers": [], + "exportAs": "ouiDialogHeader", + "hostDirectives": [], + "standalone": false, "inputsClass": [], "outputsClass": [], "deprecated": false, @@ -14220,6 +14364,7 @@ "hostListeners": [], "propertiesClass": [], "methodsClass": [], + "extends": [], "constructorObj": { "name": "constructor", "description": "", @@ -14239,6 +14384,9 @@ "sourceCode": "import {\n Directive,\n Input,\n OnChanges,\n OnInit,\n Optional,\n SimpleChanges,\n ElementRef,\n Component,\n NgZone,\n OnDestroy,\n} from '@angular/core';\nimport { OuiDialog } from './dialog';\nimport { OuiDialogRef } from './dialog-ref';\nimport { OuiIconRegistry } from '../icon/icon-registery';\nimport { DomSanitizer } from '@angular/platform-browser';\nimport { ICONS } from '../core/shared/icons';\nimport { Subscription } from 'rxjs';\nimport { FocusMonitor } from '@angular/cdk/a11y';\n\n/** Counter used to generate unique IDs for dialog elements. */\nlet dialogElementUid = 0;\n\n/**\n * Header section of ui.\n */\n@Directive({\n selector: '[oui-dialog-header], [ouiDialogHeader]',\n exportAs: 'ouiDialogHeader',\n // eslint-disable-next-line @angular-eslint/no-host-metadata-property\n host: {\n class: 'oui-dialog-header',\n },\n})\nexport class OuiDialogHeader {\n constructor() {}\n}\n\n/**\n * Header Title of ui.\n */\n@Directive({\n selector: '[oui-dialog-header-title], [ouiDialogHeaderTitle]',\n exportAs: 'ouiDialogHeaderTitle',\n // eslint-disable-next-line @angular-eslint/no-host-metadata-property\n host: {\n class: 'oui-dialog-header-title',\n },\n})\nexport class OuiDialogHeaderTitle {\n constructor() {}\n}\n\n/**\n * Header Image of ui.\n */\n@Directive({\n selector: '[oui-dialog-header-image], [ouiDialogHeaderImage]',\n exportAs: 'ouiDialogHeaderImage',\n // eslint-disable-next-line @angular-eslint/no-host-metadata-property\n host: {\n class: 'oui-dialog-header-image',\n },\n})\nexport class OuiDialogHeaderImage {\n constructor() {}\n}\n\n/**\n * Header action area of dialog.\n */\n@Directive({\n selector: '[oui-dialog-header-action], [ouiDialogHeaderAction]',\n exportAs: 'ouiDialogHeaderAction',\n // eslint-disable-next-line @angular-eslint/no-host-metadata-property\n host: {\n class: 'oui-dialog-header-action',\n },\n})\nexport class OuiDialogHeaderAction {\n constructor() {}\n}\n\n/**\n * header action article.\n */\n@Component({\n // eslint-disable-next-line @angular-eslint/component-selector\n selector: '[oui-dialog-header-article], [ouiDialogHeaderArticle]',\n template: '',\n exportAs: 'ouiDialogHeaderArticle',\n // eslint-disable-next-line @angular-eslint/no-host-metadata-property\n host: {\n class: 'oui-dialog-header-article',\n },\n})\nexport class OuiDialogHeaderArticle implements OnDestroy {\n private _monitorSubscription: Subscription = Subscription.EMPTY;\n constructor(\n private ouiIconRegistry: OuiIconRegistry,\n private domSanitizer: DomSanitizer,\n protected elementRef: ElementRef,\n private _focusMonitor: FocusMonitor,\n private _ngZone: NgZone\n ) {\n this.ouiIconRegistry.addSvgIconLiteral(\n `article-icon`,\n this.domSanitizer.bypassSecurityTrustHtml(ICONS.ARTICLE_ICON)\n );\n this._monitorSubscription = this._focusMonitor\n .monitor(this.elementRef, true)\n .subscribe(() => this._ngZone.run(() => {}));\n }\n ngOnDestroy() {\n this._monitorSubscription.unsubscribe();\n }\n}\n\n/**\n * header action article.\n */\n@Component({\n // eslint-disable-next-line @angular-eslint/component-selector\n selector: '[oui-dialog-header-video], [ouiDialogHeaderVideo]',\n template: '',\n exportAs: 'ouiDialogHeaderVideo',\n // eslint-disable-next-line @angular-eslint/no-host-metadata-property\n host: {\n class: 'oui-dialog-header-video',\n },\n})\nexport class OuiDialogHeaderVideo implements OnDestroy {\n private _monitorSubscription: Subscription = Subscription.EMPTY;\n\n constructor(\n private ouiIconRegistry: OuiIconRegistry,\n private domSanitizer: DomSanitizer,\n protected elementRef: ElementRef,\n private _focusMonitor: FocusMonitor,\n private _ngZone: NgZone\n ) {\n this.ouiIconRegistry.addSvgIconLiteral(\n `video-icon`,\n this.domSanitizer.bypassSecurityTrustHtml(ICONS.VIDEO_ICON)\n );\n this._monitorSubscription = this._focusMonitor\n .monitor(this.elementRef, true)\n .subscribe(() => this._ngZone.run(() => {}));\n }\n ngOnDestroy() {\n this._monitorSubscription.unsubscribe();\n }\n}\n\n/**\n * header action close\n */\n@Component({\n // eslint-disable-next-line @angular-eslint/component-selector\n selector: '[oui-dialog-header-close], [ouiDialogHeaderClose]',\n template: '',\n exportAs: 'ouiDialogHeaderClose',\n // eslint-disable-next-line @angular-eslint/no-host-metadata-property\n host: {\n class: 'oui-dialog-header-close',\n '[attr.tabindex]': '0',\n },\n})\nexport class OuiDialogHeaderClose implements OnDestroy {\n private _monitorSubscription: Subscription = Subscription.EMPTY;\n constructor(\n private ouiIconRegistry: OuiIconRegistry,\n private domSanitizer: DomSanitizer,\n protected elementRef: ElementRef,\n private _focusMonitor: FocusMonitor,\n private _ngZone: NgZone\n ) {\n this.ouiIconRegistry.addSvgIconLiteral(\n `close-icon`,\n this.domSanitizer.bypassSecurityTrustHtml(ICONS.CLOSE_ICON)\n );\n this._monitorSubscription = this._focusMonitor\n .monitor(this.elementRef, true)\n .subscribe(() => this._ngZone.run(() => {}));\n }\n ngOnDestroy() {\n this._monitorSubscription.unsubscribe();\n }\n}\n\n/**\n * header action separator close\n */\n@Directive({\n selector: '[oui-dialog-header-separator], [ouiDialogHeaderSeparator]',\n exportAs: 'ouiDialogHeaderSeparator',\n // eslint-disable-next-line @angular-eslint/no-host-metadata-property\n host: {\n class: 'oui-dialog-header-separator',\n },\n})\nexport class OuiDialogHeaderSeparator {\n constructor() {}\n}\n\n/**\n * directive for close the current dialog.\n */\n@Directive({\n selector: `[oui-dialog-close], [ouiDialogClose]`,\n exportAs: 'ouiDialogClose',\n // eslint-disable-next-line @angular-eslint/no-host-metadata-property\n host: {\n '[class.cross-disabled]': 'dialogResult===false',\n '(click)': 'closeDialog()',\n '[attr.aria-label]': 'ariaLabel',\n '(keyup.space)': 'handleKeydown($event)',\n '(keydown.enter)': 'handleKeydown($event)',\n },\n})\nexport class OuiDialogClose implements OnInit, OnChanges {\n /** Screenreader label for the button. */\n @Input('aria-label')\n ariaLabel = 'Close dialog';\n\n /** Dialog close input. */\n @Input('oui-dialog-close')\n dialogResult: any;\n\n @Input('ouiDialogClose')\n _ouiDialogClose: any;\n\n constructor(\n @Optional() public dialogRef: OuiDialogRef,\n private _elementRef: ElementRef,\n private _dialog: OuiDialog\n ) {}\n\n /** Ensures the option is selected when activated from the keyboard. */\n handleKeydown(event: KeyboardEvent): void {\n this.closeDialog();\n event.preventDefault();\n }\n\n closeDialog() {\n if (this.dialogResult !== false) {\n this.dialogRef.close(this.dialogResult);\n }\n }\n\n ngOnInit() {\n if (!this.dialogRef) {\n // When this directive is included in a dialog via TemplateRef (rather than being\n // in a Component), the DialogRef isn't available via injection because embedded\n // views cannot be given a custom injector. Instead, we look up the DialogRef by\n // ID. This must occur in `onInit`, as the ID binding for the dialog container won't\n // be resolved at constructor time.\n this.dialogRef = getClosestDialog(\n this._elementRef,\n this._dialog.openDialogs\n )!;\n }\n }\n\n ngOnChanges(changes: SimpleChanges) {\n const proxiedChange =\n changes._ouiDialogClose || changes._ouiDialogCloseResult;\n if (proxiedChange) {\n this.dialogResult = proxiedChange.currentValue;\n }\n }\n}\n\n/**\n * Content section of dialog.\n */\n@Directive({\n selector: '[oui-dialog-content], [ouiDialogContent]',\n exportAs: 'ouiDialogContent',\n // eslint-disable-next-line @angular-eslint/no-host-metadata-property\n host: {\n class: 'oui-dialog-content',\n },\n})\nexport class OuiDialogContent implements OnInit {\n constructor(\n @Optional() public dialogRef: OuiDialogRef,\n private _elementRef: ElementRef,\n private _dialog: OuiDialog\n ) {}\n\n ngOnInit() {\n if (!this.dialogRef) {\n // When this directive is included in a dialog via TemplateRef (rather than being\n // in a Component), the DialogRef isn't available via injection because embedded\n // views cannot be given a custom injector. Instead, we look up the DialogRef by\n // ID. This must occur in `onInit`, as the ID binding for the dialog container won't\n // be resolved at constructor time.\n this.dialogRef = getClosestDialog(\n this._elementRef,\n this._dialog.openDialogs\n )!;\n }\n this._setContentHeight();\n }\n /* prevent content scroll in default scroll strategy **/\n private _setContentHeight() {\n if (!this.dialogRef.dialogConfig.scrollStrategy) {\n this._elementRef.nativeElement.style.maxHeight = 'none';\n this._elementRef.nativeElement.style.overflow = 'visible';\n }\n }\n}\n\n/**\n * Content section of dialog.\n */\n@Directive({\n selector: '[oui-dialog-footer], [ouiDialogFooter]',\n exportAs: 'ouiDialogFooter',\n // eslint-disable-next-line @angular-eslint/no-host-metadata-property\n host: {\n class: 'oui-dialog-footer',\n },\n})\nexport class OuiDialogFooter {\n @Input()\n id = `oui-dialog-footer-${dialogElementUid++}`;\n constructor() {}\n}\n\n/**\n * footer action left\n */\n@Directive({\n selector: '[oui-dialog-footer-action-left], [ouiDialogFooterActionLeft]',\n exportAs: 'ouiDialogFooterActionLeft',\n // eslint-disable-next-line @angular-eslint/no-host-metadata-property\n host: {\n class: 'oui-dialog-footer-action-left',\n },\n})\nexport class OuiDialogFooterActionLeft {\n constructor() {}\n}\n\n/**\n * footer action right\n */\n@Directive({\n selector: '[oui-dialog-footer-action-right], [ouiDialogFooterActionRight]',\n exportAs: 'ouiDialogFooterActionRight',\n // eslint-disable-next-line @angular-eslint/no-host-metadata-property\n host: {\n class: 'oui-dialog-footer-action-right',\n },\n})\nexport class OuiDialogFooterActionRight {\n constructor() {}\n}\n\n/**\n * Finds the closest MatDialogRef to an element by looking at the DOM.\n *\n * @param element Element relative to which to look for a dialog.\n * @param openDialogs References to the currently-open dialogs.\n */\nfunction getClosestDialog(\n element: ElementRef,\n openDialogs: OuiDialogRef[]\n) {\n let parent: HTMLElement | null = element.nativeElement.parentElement;\n\n while (parent && !parent.classList.contains('oui-dialog-container')) {\n parent = parent.parentElement;\n }\n\n return parent ? openDialogs.find((dialog) => dialog.id === parent!.id) : null;\n}\n", "selector": "[oui-dialog-header-action], [ouiDialogHeaderAction]", "providers": [], + "exportAs": "ouiDialogHeaderAction", + "hostDirectives": [], + "standalone": false, "inputsClass": [], "outputsClass": [], "deprecated": false, @@ -14247,6 +14395,7 @@ "hostListeners": [], "propertiesClass": [], "methodsClass": [], + "extends": [], "constructorObj": { "name": "constructor", "description": "", @@ -14266,6 +14415,9 @@ "sourceCode": "import {\n Directive,\n Input,\n OnChanges,\n OnInit,\n Optional,\n SimpleChanges,\n ElementRef,\n Component,\n NgZone,\n OnDestroy,\n} from '@angular/core';\nimport { OuiDialog } from './dialog';\nimport { OuiDialogRef } from './dialog-ref';\nimport { OuiIconRegistry } from '../icon/icon-registery';\nimport { DomSanitizer } from '@angular/platform-browser';\nimport { ICONS } from '../core/shared/icons';\nimport { Subscription } from 'rxjs';\nimport { FocusMonitor } from '@angular/cdk/a11y';\n\n/** Counter used to generate unique IDs for dialog elements. */\nlet dialogElementUid = 0;\n\n/**\n * Header section of ui.\n */\n@Directive({\n selector: '[oui-dialog-header], [ouiDialogHeader]',\n exportAs: 'ouiDialogHeader',\n // eslint-disable-next-line @angular-eslint/no-host-metadata-property\n host: {\n class: 'oui-dialog-header',\n },\n})\nexport class OuiDialogHeader {\n constructor() {}\n}\n\n/**\n * Header Title of ui.\n */\n@Directive({\n selector: '[oui-dialog-header-title], [ouiDialogHeaderTitle]',\n exportAs: 'ouiDialogHeaderTitle',\n // eslint-disable-next-line @angular-eslint/no-host-metadata-property\n host: {\n class: 'oui-dialog-header-title',\n },\n})\nexport class OuiDialogHeaderTitle {\n constructor() {}\n}\n\n/**\n * Header Image of ui.\n */\n@Directive({\n selector: '[oui-dialog-header-image], [ouiDialogHeaderImage]',\n exportAs: 'ouiDialogHeaderImage',\n // eslint-disable-next-line @angular-eslint/no-host-metadata-property\n host: {\n class: 'oui-dialog-header-image',\n },\n})\nexport class OuiDialogHeaderImage {\n constructor() {}\n}\n\n/**\n * Header action area of dialog.\n */\n@Directive({\n selector: '[oui-dialog-header-action], [ouiDialogHeaderAction]',\n exportAs: 'ouiDialogHeaderAction',\n // eslint-disable-next-line @angular-eslint/no-host-metadata-property\n host: {\n class: 'oui-dialog-header-action',\n },\n})\nexport class OuiDialogHeaderAction {\n constructor() {}\n}\n\n/**\n * header action article.\n */\n@Component({\n // eslint-disable-next-line @angular-eslint/component-selector\n selector: '[oui-dialog-header-article], [ouiDialogHeaderArticle]',\n template: '',\n exportAs: 'ouiDialogHeaderArticle',\n // eslint-disable-next-line @angular-eslint/no-host-metadata-property\n host: {\n class: 'oui-dialog-header-article',\n },\n})\nexport class OuiDialogHeaderArticle implements OnDestroy {\n private _monitorSubscription: Subscription = Subscription.EMPTY;\n constructor(\n private ouiIconRegistry: OuiIconRegistry,\n private domSanitizer: DomSanitizer,\n protected elementRef: ElementRef,\n private _focusMonitor: FocusMonitor,\n private _ngZone: NgZone\n ) {\n this.ouiIconRegistry.addSvgIconLiteral(\n `article-icon`,\n this.domSanitizer.bypassSecurityTrustHtml(ICONS.ARTICLE_ICON)\n );\n this._monitorSubscription = this._focusMonitor\n .monitor(this.elementRef, true)\n .subscribe(() => this._ngZone.run(() => {}));\n }\n ngOnDestroy() {\n this._monitorSubscription.unsubscribe();\n }\n}\n\n/**\n * header action article.\n */\n@Component({\n // eslint-disable-next-line @angular-eslint/component-selector\n selector: '[oui-dialog-header-video], [ouiDialogHeaderVideo]',\n template: '',\n exportAs: 'ouiDialogHeaderVideo',\n // eslint-disable-next-line @angular-eslint/no-host-metadata-property\n host: {\n class: 'oui-dialog-header-video',\n },\n})\nexport class OuiDialogHeaderVideo implements OnDestroy {\n private _monitorSubscription: Subscription = Subscription.EMPTY;\n\n constructor(\n private ouiIconRegistry: OuiIconRegistry,\n private domSanitizer: DomSanitizer,\n protected elementRef: ElementRef,\n private _focusMonitor: FocusMonitor,\n private _ngZone: NgZone\n ) {\n this.ouiIconRegistry.addSvgIconLiteral(\n `video-icon`,\n this.domSanitizer.bypassSecurityTrustHtml(ICONS.VIDEO_ICON)\n );\n this._monitorSubscription = this._focusMonitor\n .monitor(this.elementRef, true)\n .subscribe(() => this._ngZone.run(() => {}));\n }\n ngOnDestroy() {\n this._monitorSubscription.unsubscribe();\n }\n}\n\n/**\n * header action close\n */\n@Component({\n // eslint-disable-next-line @angular-eslint/component-selector\n selector: '[oui-dialog-header-close], [ouiDialogHeaderClose]',\n template: '',\n exportAs: 'ouiDialogHeaderClose',\n // eslint-disable-next-line @angular-eslint/no-host-metadata-property\n host: {\n class: 'oui-dialog-header-close',\n '[attr.tabindex]': '0',\n },\n})\nexport class OuiDialogHeaderClose implements OnDestroy {\n private _monitorSubscription: Subscription = Subscription.EMPTY;\n constructor(\n private ouiIconRegistry: OuiIconRegistry,\n private domSanitizer: DomSanitizer,\n protected elementRef: ElementRef,\n private _focusMonitor: FocusMonitor,\n private _ngZone: NgZone\n ) {\n this.ouiIconRegistry.addSvgIconLiteral(\n `close-icon`,\n this.domSanitizer.bypassSecurityTrustHtml(ICONS.CLOSE_ICON)\n );\n this._monitorSubscription = this._focusMonitor\n .monitor(this.elementRef, true)\n .subscribe(() => this._ngZone.run(() => {}));\n }\n ngOnDestroy() {\n this._monitorSubscription.unsubscribe();\n }\n}\n\n/**\n * header action separator close\n */\n@Directive({\n selector: '[oui-dialog-header-separator], [ouiDialogHeaderSeparator]',\n exportAs: 'ouiDialogHeaderSeparator',\n // eslint-disable-next-line @angular-eslint/no-host-metadata-property\n host: {\n class: 'oui-dialog-header-separator',\n },\n})\nexport class OuiDialogHeaderSeparator {\n constructor() {}\n}\n\n/**\n * directive for close the current dialog.\n */\n@Directive({\n selector: `[oui-dialog-close], [ouiDialogClose]`,\n exportAs: 'ouiDialogClose',\n // eslint-disable-next-line @angular-eslint/no-host-metadata-property\n host: {\n '[class.cross-disabled]': 'dialogResult===false',\n '(click)': 'closeDialog()',\n '[attr.aria-label]': 'ariaLabel',\n '(keyup.space)': 'handleKeydown($event)',\n '(keydown.enter)': 'handleKeydown($event)',\n },\n})\nexport class OuiDialogClose implements OnInit, OnChanges {\n /** Screenreader label for the button. */\n @Input('aria-label')\n ariaLabel = 'Close dialog';\n\n /** Dialog close input. */\n @Input('oui-dialog-close')\n dialogResult: any;\n\n @Input('ouiDialogClose')\n _ouiDialogClose: any;\n\n constructor(\n @Optional() public dialogRef: OuiDialogRef,\n private _elementRef: ElementRef,\n private _dialog: OuiDialog\n ) {}\n\n /** Ensures the option is selected when activated from the keyboard. */\n handleKeydown(event: KeyboardEvent): void {\n this.closeDialog();\n event.preventDefault();\n }\n\n closeDialog() {\n if (this.dialogResult !== false) {\n this.dialogRef.close(this.dialogResult);\n }\n }\n\n ngOnInit() {\n if (!this.dialogRef) {\n // When this directive is included in a dialog via TemplateRef (rather than being\n // in a Component), the DialogRef isn't available via injection because embedded\n // views cannot be given a custom injector. Instead, we look up the DialogRef by\n // ID. This must occur in `onInit`, as the ID binding for the dialog container won't\n // be resolved at constructor time.\n this.dialogRef = getClosestDialog(\n this._elementRef,\n this._dialog.openDialogs\n )!;\n }\n }\n\n ngOnChanges(changes: SimpleChanges) {\n const proxiedChange =\n changes._ouiDialogClose || changes._ouiDialogCloseResult;\n if (proxiedChange) {\n this.dialogResult = proxiedChange.currentValue;\n }\n }\n}\n\n/**\n * Content section of dialog.\n */\n@Directive({\n selector: '[oui-dialog-content], [ouiDialogContent]',\n exportAs: 'ouiDialogContent',\n // eslint-disable-next-line @angular-eslint/no-host-metadata-property\n host: {\n class: 'oui-dialog-content',\n },\n})\nexport class OuiDialogContent implements OnInit {\n constructor(\n @Optional() public dialogRef: OuiDialogRef,\n private _elementRef: ElementRef,\n private _dialog: OuiDialog\n ) {}\n\n ngOnInit() {\n if (!this.dialogRef) {\n // When this directive is included in a dialog via TemplateRef (rather than being\n // in a Component), the DialogRef isn't available via injection because embedded\n // views cannot be given a custom injector. Instead, we look up the DialogRef by\n // ID. This must occur in `onInit`, as the ID binding for the dialog container won't\n // be resolved at constructor time.\n this.dialogRef = getClosestDialog(\n this._elementRef,\n this._dialog.openDialogs\n )!;\n }\n this._setContentHeight();\n }\n /* prevent content scroll in default scroll strategy **/\n private _setContentHeight() {\n if (!this.dialogRef.dialogConfig.scrollStrategy) {\n this._elementRef.nativeElement.style.maxHeight = 'none';\n this._elementRef.nativeElement.style.overflow = 'visible';\n }\n }\n}\n\n/**\n * Content section of dialog.\n */\n@Directive({\n selector: '[oui-dialog-footer], [ouiDialogFooter]',\n exportAs: 'ouiDialogFooter',\n // eslint-disable-next-line @angular-eslint/no-host-metadata-property\n host: {\n class: 'oui-dialog-footer',\n },\n})\nexport class OuiDialogFooter {\n @Input()\n id = `oui-dialog-footer-${dialogElementUid++}`;\n constructor() {}\n}\n\n/**\n * footer action left\n */\n@Directive({\n selector: '[oui-dialog-footer-action-left], [ouiDialogFooterActionLeft]',\n exportAs: 'ouiDialogFooterActionLeft',\n // eslint-disable-next-line @angular-eslint/no-host-metadata-property\n host: {\n class: 'oui-dialog-footer-action-left',\n },\n})\nexport class OuiDialogFooterActionLeft {\n constructor() {}\n}\n\n/**\n * footer action right\n */\n@Directive({\n selector: '[oui-dialog-footer-action-right], [ouiDialogFooterActionRight]',\n exportAs: 'ouiDialogFooterActionRight',\n // eslint-disable-next-line @angular-eslint/no-host-metadata-property\n host: {\n class: 'oui-dialog-footer-action-right',\n },\n})\nexport class OuiDialogFooterActionRight {\n constructor() {}\n}\n\n/**\n * Finds the closest MatDialogRef to an element by looking at the DOM.\n *\n * @param element Element relative to which to look for a dialog.\n * @param openDialogs References to the currently-open dialogs.\n */\nfunction getClosestDialog(\n element: ElementRef,\n openDialogs: OuiDialogRef[]\n) {\n let parent: HTMLElement | null = element.nativeElement.parentElement;\n\n while (parent && !parent.classList.contains('oui-dialog-container')) {\n parent = parent.parentElement;\n }\n\n return parent ? openDialogs.find((dialog) => dialog.id === parent!.id) : null;\n}\n", "selector": "[oui-dialog-header-image], [ouiDialogHeaderImage]", "providers": [], + "exportAs": "ouiDialogHeaderImage", + "hostDirectives": [], + "standalone": false, "inputsClass": [], "outputsClass": [], "deprecated": false, @@ -14274,6 +14426,7 @@ "hostListeners": [], "propertiesClass": [], "methodsClass": [], + "extends": [], "constructorObj": { "name": "constructor", "description": "", @@ -14293,6 +14446,9 @@ "sourceCode": "import {\n Directive,\n Input,\n OnChanges,\n OnInit,\n Optional,\n SimpleChanges,\n ElementRef,\n Component,\n NgZone,\n OnDestroy,\n} from '@angular/core';\nimport { OuiDialog } from './dialog';\nimport { OuiDialogRef } from './dialog-ref';\nimport { OuiIconRegistry } from '../icon/icon-registery';\nimport { DomSanitizer } from '@angular/platform-browser';\nimport { ICONS } from '../core/shared/icons';\nimport { Subscription } from 'rxjs';\nimport { FocusMonitor } from '@angular/cdk/a11y';\n\n/** Counter used to generate unique IDs for dialog elements. */\nlet dialogElementUid = 0;\n\n/**\n * Header section of ui.\n */\n@Directive({\n selector: '[oui-dialog-header], [ouiDialogHeader]',\n exportAs: 'ouiDialogHeader',\n // eslint-disable-next-line @angular-eslint/no-host-metadata-property\n host: {\n class: 'oui-dialog-header',\n },\n})\nexport class OuiDialogHeader {\n constructor() {}\n}\n\n/**\n * Header Title of ui.\n */\n@Directive({\n selector: '[oui-dialog-header-title], [ouiDialogHeaderTitle]',\n exportAs: 'ouiDialogHeaderTitle',\n // eslint-disable-next-line @angular-eslint/no-host-metadata-property\n host: {\n class: 'oui-dialog-header-title',\n },\n})\nexport class OuiDialogHeaderTitle {\n constructor() {}\n}\n\n/**\n * Header Image of ui.\n */\n@Directive({\n selector: '[oui-dialog-header-image], [ouiDialogHeaderImage]',\n exportAs: 'ouiDialogHeaderImage',\n // eslint-disable-next-line @angular-eslint/no-host-metadata-property\n host: {\n class: 'oui-dialog-header-image',\n },\n})\nexport class OuiDialogHeaderImage {\n constructor() {}\n}\n\n/**\n * Header action area of dialog.\n */\n@Directive({\n selector: '[oui-dialog-header-action], [ouiDialogHeaderAction]',\n exportAs: 'ouiDialogHeaderAction',\n // eslint-disable-next-line @angular-eslint/no-host-metadata-property\n host: {\n class: 'oui-dialog-header-action',\n },\n})\nexport class OuiDialogHeaderAction {\n constructor() {}\n}\n\n/**\n * header action article.\n */\n@Component({\n // eslint-disable-next-line @angular-eslint/component-selector\n selector: '[oui-dialog-header-article], [ouiDialogHeaderArticle]',\n template: '',\n exportAs: 'ouiDialogHeaderArticle',\n // eslint-disable-next-line @angular-eslint/no-host-metadata-property\n host: {\n class: 'oui-dialog-header-article',\n },\n})\nexport class OuiDialogHeaderArticle implements OnDestroy {\n private _monitorSubscription: Subscription = Subscription.EMPTY;\n constructor(\n private ouiIconRegistry: OuiIconRegistry,\n private domSanitizer: DomSanitizer,\n protected elementRef: ElementRef,\n private _focusMonitor: FocusMonitor,\n private _ngZone: NgZone\n ) {\n this.ouiIconRegistry.addSvgIconLiteral(\n `article-icon`,\n this.domSanitizer.bypassSecurityTrustHtml(ICONS.ARTICLE_ICON)\n );\n this._monitorSubscription = this._focusMonitor\n .monitor(this.elementRef, true)\n .subscribe(() => this._ngZone.run(() => {}));\n }\n ngOnDestroy() {\n this._monitorSubscription.unsubscribe();\n }\n}\n\n/**\n * header action article.\n */\n@Component({\n // eslint-disable-next-line @angular-eslint/component-selector\n selector: '[oui-dialog-header-video], [ouiDialogHeaderVideo]',\n template: '',\n exportAs: 'ouiDialogHeaderVideo',\n // eslint-disable-next-line @angular-eslint/no-host-metadata-property\n host: {\n class: 'oui-dialog-header-video',\n },\n})\nexport class OuiDialogHeaderVideo implements OnDestroy {\n private _monitorSubscription: Subscription = Subscription.EMPTY;\n\n constructor(\n private ouiIconRegistry: OuiIconRegistry,\n private domSanitizer: DomSanitizer,\n protected elementRef: ElementRef,\n private _focusMonitor: FocusMonitor,\n private _ngZone: NgZone\n ) {\n this.ouiIconRegistry.addSvgIconLiteral(\n `video-icon`,\n this.domSanitizer.bypassSecurityTrustHtml(ICONS.VIDEO_ICON)\n );\n this._monitorSubscription = this._focusMonitor\n .monitor(this.elementRef, true)\n .subscribe(() => this._ngZone.run(() => {}));\n }\n ngOnDestroy() {\n this._monitorSubscription.unsubscribe();\n }\n}\n\n/**\n * header action close\n */\n@Component({\n // eslint-disable-next-line @angular-eslint/component-selector\n selector: '[oui-dialog-header-close], [ouiDialogHeaderClose]',\n template: '',\n exportAs: 'ouiDialogHeaderClose',\n // eslint-disable-next-line @angular-eslint/no-host-metadata-property\n host: {\n class: 'oui-dialog-header-close',\n '[attr.tabindex]': '0',\n },\n})\nexport class OuiDialogHeaderClose implements OnDestroy {\n private _monitorSubscription: Subscription = Subscription.EMPTY;\n constructor(\n private ouiIconRegistry: OuiIconRegistry,\n private domSanitizer: DomSanitizer,\n protected elementRef: ElementRef,\n private _focusMonitor: FocusMonitor,\n private _ngZone: NgZone\n ) {\n this.ouiIconRegistry.addSvgIconLiteral(\n `close-icon`,\n this.domSanitizer.bypassSecurityTrustHtml(ICONS.CLOSE_ICON)\n );\n this._monitorSubscription = this._focusMonitor\n .monitor(this.elementRef, true)\n .subscribe(() => this._ngZone.run(() => {}));\n }\n ngOnDestroy() {\n this._monitorSubscription.unsubscribe();\n }\n}\n\n/**\n * header action separator close\n */\n@Directive({\n selector: '[oui-dialog-header-separator], [ouiDialogHeaderSeparator]',\n exportAs: 'ouiDialogHeaderSeparator',\n // eslint-disable-next-line @angular-eslint/no-host-metadata-property\n host: {\n class: 'oui-dialog-header-separator',\n },\n})\nexport class OuiDialogHeaderSeparator {\n constructor() {}\n}\n\n/**\n * directive for close the current dialog.\n */\n@Directive({\n selector: `[oui-dialog-close], [ouiDialogClose]`,\n exportAs: 'ouiDialogClose',\n // eslint-disable-next-line @angular-eslint/no-host-metadata-property\n host: {\n '[class.cross-disabled]': 'dialogResult===false',\n '(click)': 'closeDialog()',\n '[attr.aria-label]': 'ariaLabel',\n '(keyup.space)': 'handleKeydown($event)',\n '(keydown.enter)': 'handleKeydown($event)',\n },\n})\nexport class OuiDialogClose implements OnInit, OnChanges {\n /** Screenreader label for the button. */\n @Input('aria-label')\n ariaLabel = 'Close dialog';\n\n /** Dialog close input. */\n @Input('oui-dialog-close')\n dialogResult: any;\n\n @Input('ouiDialogClose')\n _ouiDialogClose: any;\n\n constructor(\n @Optional() public dialogRef: OuiDialogRef,\n private _elementRef: ElementRef,\n private _dialog: OuiDialog\n ) {}\n\n /** Ensures the option is selected when activated from the keyboard. */\n handleKeydown(event: KeyboardEvent): void {\n this.closeDialog();\n event.preventDefault();\n }\n\n closeDialog() {\n if (this.dialogResult !== false) {\n this.dialogRef.close(this.dialogResult);\n }\n }\n\n ngOnInit() {\n if (!this.dialogRef) {\n // When this directive is included in a dialog via TemplateRef (rather than being\n // in a Component), the DialogRef isn't available via injection because embedded\n // views cannot be given a custom injector. Instead, we look up the DialogRef by\n // ID. This must occur in `onInit`, as the ID binding for the dialog container won't\n // be resolved at constructor time.\n this.dialogRef = getClosestDialog(\n this._elementRef,\n this._dialog.openDialogs\n )!;\n }\n }\n\n ngOnChanges(changes: SimpleChanges) {\n const proxiedChange =\n changes._ouiDialogClose || changes._ouiDialogCloseResult;\n if (proxiedChange) {\n this.dialogResult = proxiedChange.currentValue;\n }\n }\n}\n\n/**\n * Content section of dialog.\n */\n@Directive({\n selector: '[oui-dialog-content], [ouiDialogContent]',\n exportAs: 'ouiDialogContent',\n // eslint-disable-next-line @angular-eslint/no-host-metadata-property\n host: {\n class: 'oui-dialog-content',\n },\n})\nexport class OuiDialogContent implements OnInit {\n constructor(\n @Optional() public dialogRef: OuiDialogRef,\n private _elementRef: ElementRef,\n private _dialog: OuiDialog\n ) {}\n\n ngOnInit() {\n if (!this.dialogRef) {\n // When this directive is included in a dialog via TemplateRef (rather than being\n // in a Component), the DialogRef isn't available via injection because embedded\n // views cannot be given a custom injector. Instead, we look up the DialogRef by\n // ID. This must occur in `onInit`, as the ID binding for the dialog container won't\n // be resolved at constructor time.\n this.dialogRef = getClosestDialog(\n this._elementRef,\n this._dialog.openDialogs\n )!;\n }\n this._setContentHeight();\n }\n /* prevent content scroll in default scroll strategy **/\n private _setContentHeight() {\n if (!this.dialogRef.dialogConfig.scrollStrategy) {\n this._elementRef.nativeElement.style.maxHeight = 'none';\n this._elementRef.nativeElement.style.overflow = 'visible';\n }\n }\n}\n\n/**\n * Content section of dialog.\n */\n@Directive({\n selector: '[oui-dialog-footer], [ouiDialogFooter]',\n exportAs: 'ouiDialogFooter',\n // eslint-disable-next-line @angular-eslint/no-host-metadata-property\n host: {\n class: 'oui-dialog-footer',\n },\n})\nexport class OuiDialogFooter {\n @Input()\n id = `oui-dialog-footer-${dialogElementUid++}`;\n constructor() {}\n}\n\n/**\n * footer action left\n */\n@Directive({\n selector: '[oui-dialog-footer-action-left], [ouiDialogFooterActionLeft]',\n exportAs: 'ouiDialogFooterActionLeft',\n // eslint-disable-next-line @angular-eslint/no-host-metadata-property\n host: {\n class: 'oui-dialog-footer-action-left',\n },\n})\nexport class OuiDialogFooterActionLeft {\n constructor() {}\n}\n\n/**\n * footer action right\n */\n@Directive({\n selector: '[oui-dialog-footer-action-right], [ouiDialogFooterActionRight]',\n exportAs: 'ouiDialogFooterActionRight',\n // eslint-disable-next-line @angular-eslint/no-host-metadata-property\n host: {\n class: 'oui-dialog-footer-action-right',\n },\n})\nexport class OuiDialogFooterActionRight {\n constructor() {}\n}\n\n/**\n * Finds the closest MatDialogRef to an element by looking at the DOM.\n *\n * @param element Element relative to which to look for a dialog.\n * @param openDialogs References to the currently-open dialogs.\n */\nfunction getClosestDialog(\n element: ElementRef,\n openDialogs: OuiDialogRef[]\n) {\n let parent: HTMLElement | null = element.nativeElement.parentElement;\n\n while (parent && !parent.classList.contains('oui-dialog-container')) {\n parent = parent.parentElement;\n }\n\n return parent ? openDialogs.find((dialog) => dialog.id === parent!.id) : null;\n}\n", "selector": "[oui-dialog-header-separator], [ouiDialogHeaderSeparator]", "providers": [], + "exportAs": "ouiDialogHeaderSeparator", + "hostDirectives": [], + "standalone": false, "inputsClass": [], "outputsClass": [], "deprecated": false, @@ -14301,6 +14457,7 @@ "hostListeners": [], "propertiesClass": [], "methodsClass": [], + "extends": [], "constructorObj": { "name": "constructor", "description": "", @@ -14320,6 +14477,9 @@ "sourceCode": "import {\n Directive,\n Input,\n OnChanges,\n OnInit,\n Optional,\n SimpleChanges,\n ElementRef,\n Component,\n NgZone,\n OnDestroy,\n} from '@angular/core';\nimport { OuiDialog } from './dialog';\nimport { OuiDialogRef } from './dialog-ref';\nimport { OuiIconRegistry } from '../icon/icon-registery';\nimport { DomSanitizer } from '@angular/platform-browser';\nimport { ICONS } from '../core/shared/icons';\nimport { Subscription } from 'rxjs';\nimport { FocusMonitor } from '@angular/cdk/a11y';\n\n/** Counter used to generate unique IDs for dialog elements. */\nlet dialogElementUid = 0;\n\n/**\n * Header section of ui.\n */\n@Directive({\n selector: '[oui-dialog-header], [ouiDialogHeader]',\n exportAs: 'ouiDialogHeader',\n // eslint-disable-next-line @angular-eslint/no-host-metadata-property\n host: {\n class: 'oui-dialog-header',\n },\n})\nexport class OuiDialogHeader {\n constructor() {}\n}\n\n/**\n * Header Title of ui.\n */\n@Directive({\n selector: '[oui-dialog-header-title], [ouiDialogHeaderTitle]',\n exportAs: 'ouiDialogHeaderTitle',\n // eslint-disable-next-line @angular-eslint/no-host-metadata-property\n host: {\n class: 'oui-dialog-header-title',\n },\n})\nexport class OuiDialogHeaderTitle {\n constructor() {}\n}\n\n/**\n * Header Image of ui.\n */\n@Directive({\n selector: '[oui-dialog-header-image], [ouiDialogHeaderImage]',\n exportAs: 'ouiDialogHeaderImage',\n // eslint-disable-next-line @angular-eslint/no-host-metadata-property\n host: {\n class: 'oui-dialog-header-image',\n },\n})\nexport class OuiDialogHeaderImage {\n constructor() {}\n}\n\n/**\n * Header action area of dialog.\n */\n@Directive({\n selector: '[oui-dialog-header-action], [ouiDialogHeaderAction]',\n exportAs: 'ouiDialogHeaderAction',\n // eslint-disable-next-line @angular-eslint/no-host-metadata-property\n host: {\n class: 'oui-dialog-header-action',\n },\n})\nexport class OuiDialogHeaderAction {\n constructor() {}\n}\n\n/**\n * header action article.\n */\n@Component({\n // eslint-disable-next-line @angular-eslint/component-selector\n selector: '[oui-dialog-header-article], [ouiDialogHeaderArticle]',\n template: '',\n exportAs: 'ouiDialogHeaderArticle',\n // eslint-disable-next-line @angular-eslint/no-host-metadata-property\n host: {\n class: 'oui-dialog-header-article',\n },\n})\nexport class OuiDialogHeaderArticle implements OnDestroy {\n private _monitorSubscription: Subscription = Subscription.EMPTY;\n constructor(\n private ouiIconRegistry: OuiIconRegistry,\n private domSanitizer: DomSanitizer,\n protected elementRef: ElementRef,\n private _focusMonitor: FocusMonitor,\n private _ngZone: NgZone\n ) {\n this.ouiIconRegistry.addSvgIconLiteral(\n `article-icon`,\n this.domSanitizer.bypassSecurityTrustHtml(ICONS.ARTICLE_ICON)\n );\n this._monitorSubscription = this._focusMonitor\n .monitor(this.elementRef, true)\n .subscribe(() => this._ngZone.run(() => {}));\n }\n ngOnDestroy() {\n this._monitorSubscription.unsubscribe();\n }\n}\n\n/**\n * header action article.\n */\n@Component({\n // eslint-disable-next-line @angular-eslint/component-selector\n selector: '[oui-dialog-header-video], [ouiDialogHeaderVideo]',\n template: '',\n exportAs: 'ouiDialogHeaderVideo',\n // eslint-disable-next-line @angular-eslint/no-host-metadata-property\n host: {\n class: 'oui-dialog-header-video',\n },\n})\nexport class OuiDialogHeaderVideo implements OnDestroy {\n private _monitorSubscription: Subscription = Subscription.EMPTY;\n\n constructor(\n private ouiIconRegistry: OuiIconRegistry,\n private domSanitizer: DomSanitizer,\n protected elementRef: ElementRef,\n private _focusMonitor: FocusMonitor,\n private _ngZone: NgZone\n ) {\n this.ouiIconRegistry.addSvgIconLiteral(\n `video-icon`,\n this.domSanitizer.bypassSecurityTrustHtml(ICONS.VIDEO_ICON)\n );\n this._monitorSubscription = this._focusMonitor\n .monitor(this.elementRef, true)\n .subscribe(() => this._ngZone.run(() => {}));\n }\n ngOnDestroy() {\n this._monitorSubscription.unsubscribe();\n }\n}\n\n/**\n * header action close\n */\n@Component({\n // eslint-disable-next-line @angular-eslint/component-selector\n selector: '[oui-dialog-header-close], [ouiDialogHeaderClose]',\n template: '',\n exportAs: 'ouiDialogHeaderClose',\n // eslint-disable-next-line @angular-eslint/no-host-metadata-property\n host: {\n class: 'oui-dialog-header-close',\n '[attr.tabindex]': '0',\n },\n})\nexport class OuiDialogHeaderClose implements OnDestroy {\n private _monitorSubscription: Subscription = Subscription.EMPTY;\n constructor(\n private ouiIconRegistry: OuiIconRegistry,\n private domSanitizer: DomSanitizer,\n protected elementRef: ElementRef,\n private _focusMonitor: FocusMonitor,\n private _ngZone: NgZone\n ) {\n this.ouiIconRegistry.addSvgIconLiteral(\n `close-icon`,\n this.domSanitizer.bypassSecurityTrustHtml(ICONS.CLOSE_ICON)\n );\n this._monitorSubscription = this._focusMonitor\n .monitor(this.elementRef, true)\n .subscribe(() => this._ngZone.run(() => {}));\n }\n ngOnDestroy() {\n this._monitorSubscription.unsubscribe();\n }\n}\n\n/**\n * header action separator close\n */\n@Directive({\n selector: '[oui-dialog-header-separator], [ouiDialogHeaderSeparator]',\n exportAs: 'ouiDialogHeaderSeparator',\n // eslint-disable-next-line @angular-eslint/no-host-metadata-property\n host: {\n class: 'oui-dialog-header-separator',\n },\n})\nexport class OuiDialogHeaderSeparator {\n constructor() {}\n}\n\n/**\n * directive for close the current dialog.\n */\n@Directive({\n selector: `[oui-dialog-close], [ouiDialogClose]`,\n exportAs: 'ouiDialogClose',\n // eslint-disable-next-line @angular-eslint/no-host-metadata-property\n host: {\n '[class.cross-disabled]': 'dialogResult===false',\n '(click)': 'closeDialog()',\n '[attr.aria-label]': 'ariaLabel',\n '(keyup.space)': 'handleKeydown($event)',\n '(keydown.enter)': 'handleKeydown($event)',\n },\n})\nexport class OuiDialogClose implements OnInit, OnChanges {\n /** Screenreader label for the button. */\n @Input('aria-label')\n ariaLabel = 'Close dialog';\n\n /** Dialog close input. */\n @Input('oui-dialog-close')\n dialogResult: any;\n\n @Input('ouiDialogClose')\n _ouiDialogClose: any;\n\n constructor(\n @Optional() public dialogRef: OuiDialogRef,\n private _elementRef: ElementRef,\n private _dialog: OuiDialog\n ) {}\n\n /** Ensures the option is selected when activated from the keyboard. */\n handleKeydown(event: KeyboardEvent): void {\n this.closeDialog();\n event.preventDefault();\n }\n\n closeDialog() {\n if (this.dialogResult !== false) {\n this.dialogRef.close(this.dialogResult);\n }\n }\n\n ngOnInit() {\n if (!this.dialogRef) {\n // When this directive is included in a dialog via TemplateRef (rather than being\n // in a Component), the DialogRef isn't available via injection because embedded\n // views cannot be given a custom injector. Instead, we look up the DialogRef by\n // ID. This must occur in `onInit`, as the ID binding for the dialog container won't\n // be resolved at constructor time.\n this.dialogRef = getClosestDialog(\n this._elementRef,\n this._dialog.openDialogs\n )!;\n }\n }\n\n ngOnChanges(changes: SimpleChanges) {\n const proxiedChange =\n changes._ouiDialogClose || changes._ouiDialogCloseResult;\n if (proxiedChange) {\n this.dialogResult = proxiedChange.currentValue;\n }\n }\n}\n\n/**\n * Content section of dialog.\n */\n@Directive({\n selector: '[oui-dialog-content], [ouiDialogContent]',\n exportAs: 'ouiDialogContent',\n // eslint-disable-next-line @angular-eslint/no-host-metadata-property\n host: {\n class: 'oui-dialog-content',\n },\n})\nexport class OuiDialogContent implements OnInit {\n constructor(\n @Optional() public dialogRef: OuiDialogRef,\n private _elementRef: ElementRef,\n private _dialog: OuiDialog\n ) {}\n\n ngOnInit() {\n if (!this.dialogRef) {\n // When this directive is included in a dialog via TemplateRef (rather than being\n // in a Component), the DialogRef isn't available via injection because embedded\n // views cannot be given a custom injector. Instead, we look up the DialogRef by\n // ID. This must occur in `onInit`, as the ID binding for the dialog container won't\n // be resolved at constructor time.\n this.dialogRef = getClosestDialog(\n this._elementRef,\n this._dialog.openDialogs\n )!;\n }\n this._setContentHeight();\n }\n /* prevent content scroll in default scroll strategy **/\n private _setContentHeight() {\n if (!this.dialogRef.dialogConfig.scrollStrategy) {\n this._elementRef.nativeElement.style.maxHeight = 'none';\n this._elementRef.nativeElement.style.overflow = 'visible';\n }\n }\n}\n\n/**\n * Content section of dialog.\n */\n@Directive({\n selector: '[oui-dialog-footer], [ouiDialogFooter]',\n exportAs: 'ouiDialogFooter',\n // eslint-disable-next-line @angular-eslint/no-host-metadata-property\n host: {\n class: 'oui-dialog-footer',\n },\n})\nexport class OuiDialogFooter {\n @Input()\n id = `oui-dialog-footer-${dialogElementUid++}`;\n constructor() {}\n}\n\n/**\n * footer action left\n */\n@Directive({\n selector: '[oui-dialog-footer-action-left], [ouiDialogFooterActionLeft]',\n exportAs: 'ouiDialogFooterActionLeft',\n // eslint-disable-next-line @angular-eslint/no-host-metadata-property\n host: {\n class: 'oui-dialog-footer-action-left',\n },\n})\nexport class OuiDialogFooterActionLeft {\n constructor() {}\n}\n\n/**\n * footer action right\n */\n@Directive({\n selector: '[oui-dialog-footer-action-right], [ouiDialogFooterActionRight]',\n exportAs: 'ouiDialogFooterActionRight',\n // eslint-disable-next-line @angular-eslint/no-host-metadata-property\n host: {\n class: 'oui-dialog-footer-action-right',\n },\n})\nexport class OuiDialogFooterActionRight {\n constructor() {}\n}\n\n/**\n * Finds the closest MatDialogRef to an element by looking at the DOM.\n *\n * @param element Element relative to which to look for a dialog.\n * @param openDialogs References to the currently-open dialogs.\n */\nfunction getClosestDialog(\n element: ElementRef,\n openDialogs: OuiDialogRef[]\n) {\n let parent: HTMLElement | null = element.nativeElement.parentElement;\n\n while (parent && !parent.classList.contains('oui-dialog-container')) {\n parent = parent.parentElement;\n }\n\n return parent ? openDialogs.find((dialog) => dialog.id === parent!.id) : null;\n}\n", "selector": "[oui-dialog-header-title], [ouiDialogHeaderTitle]", "providers": [], + "exportAs": "ouiDialogHeaderTitle", + "hostDirectives": [], + "standalone": false, "inputsClass": [], "outputsClass": [], "deprecated": false, @@ -14328,6 +14488,7 @@ "hostListeners": [], "propertiesClass": [], "methodsClass": [], + "extends": [], "constructorObj": { "name": "constructor", "description": "", @@ -14347,6 +14508,8 @@ "sourceCode": "import { Directive, Input } from '@angular/core';\n\nlet nextUniqueId = 0;\n\n/** Single error message to be shown underneath the form field. */\n@Directive({\n // eslint-disable-next-line @angular-eslint/directive-selector\n selector: 'oui-error',\n // eslint-disable-next-line @angular-eslint/no-host-metadata-property\n host: {\n class: 'oui-error',\n role: 'alert',\n '[attr.id]': 'id',\n },\n})\nexport class OuiError {\n @Input() id = `oui-error-${nextUniqueId++}`;\n}\n", "selector": "oui-error", "providers": [], + "hostDirectives": [], + "standalone": false, "inputsClass": [ { "name": "id", @@ -14364,7 +14527,8 @@ "hostBindings": [], "hostListeners": [], "propertiesClass": [], - "methodsClass": [] + "methodsClass": [], + "extends": [] }, { "name": "OuiFooterCell", @@ -14376,6 +14540,8 @@ "sourceCode": "import { Directive, ElementRef, Input } from '@angular/core';\nimport {\n CdkCell,\n CdkCellDef,\n CdkColumnDef,\n CdkFooterCell,\n CdkFooterCellDef,\n CdkHeaderCell,\n CdkHeaderCellDef,\n} from '@angular/cdk/table';\n\n/**\n * Cell definition for the oui-table.\n * Captures the template of a column's data row cell as well as cell-specific properties.\n */\n@Directive({\n selector: '[ouiCellDef]',\n providers: [{ provide: CdkCellDef, useExisting: OuiCellDef }],\n})\nexport class OuiCellDef extends CdkCellDef {}\n\n/**\n * Header cell definition for the oui-table.\n * Captures the template of a column's header cell and as well as cell-specific properties.\n */\n@Directive({\n selector: '[ouiHeaderCellDef]',\n providers: [{ provide: CdkHeaderCellDef, useExisting: OuiHeaderCellDef }],\n})\nexport class OuiHeaderCellDef extends CdkHeaderCellDef {}\n\n/**\n * Footer cell definition for the oui-table.\n * Captures the template of a column's footer cell and as well as cell-specific properties.\n */\n@Directive({\n selector: '[ouiFooterCellDef]',\n providers: [{ provide: CdkFooterCellDef, useExisting: OuiFooterCellDef }],\n})\nexport class OuiFooterCellDef extends CdkFooterCellDef {}\n\n/**\n * Column definition for the oui-table.\n * Defines a set of cells available for a table column.\n */\n@Directive({\n selector: '[ouiColumnDef]',\n providers: [\n { provide: CdkColumnDef, useExisting: OuiColumnDef },\n { provide: 'OUI_SORT_HEADER_COLUMN_DEF', useExisting: OuiColumnDef },\n ],\n})\nexport class OuiColumnDef extends CdkColumnDef {\n /** Unique name for this column. */\n @Input('ouiColumnDef')\n get name(): string {\n return this._name;\n }\n set name(name: string) {\n this._setNameInput(name);\n }\n}\n\n/** Header cell template container that adds the right classes and role. */\n@Directive({\n // eslint-disable-next-line @angular-eslint/directive-selector\n selector: 'oui-header-cell, th[oui-header-cell]',\n // eslint-disable-next-line @angular-eslint/no-host-metadata-property\n host: {\n class: 'oui-header-cell',\n role: 'columnheader',\n },\n})\nexport class OuiHeaderCell extends CdkHeaderCell {\n constructor(columnDef: CdkColumnDef, elementRef: ElementRef) {\n super(columnDef, elementRef);\n elementRef.nativeElement.classList.add(\n `oui-column-${columnDef.cssClassFriendlyName}`\n );\n }\n}\n\n/** Footer cell template container that adds the right classes and role. */\n@Directive({\n // eslint-disable-next-line @angular-eslint/directive-selector\n selector: 'oui-footer-cell, td[oui-footer-cell]',\n // eslint-disable-next-line @angular-eslint/no-host-metadata-property\n host: {\n class: 'oui-footer-cell',\n role: 'gridcell',\n },\n})\nexport class OuiFooterCell extends CdkFooterCell {\n constructor(columnDef: CdkColumnDef, elementRef: ElementRef) {\n super(columnDef, elementRef);\n elementRef.nativeElement.classList.add(\n `oui-column-${columnDef.cssClassFriendlyName}`\n );\n }\n}\n\n/** Cell template container that adds the right classes and role. */\n@Directive({\n // eslint-disable-next-line @angular-eslint/directive-selector\n selector: 'oui-cell, td[oui-cell]',\n // eslint-disable-next-line @angular-eslint/no-host-metadata-property\n host: {\n class: 'oui-cell',\n role: 'gridcell',\n },\n})\nexport class OuiCell extends CdkCell {\n constructor(columnDef: CdkColumnDef, elementRef: ElementRef) {\n super(columnDef, elementRef);\n elementRef.nativeElement.classList.add(\n `oui-column-${columnDef.cssClassFriendlyName}`\n );\n }\n}\n", "selector": "oui-footer-cell, td[oui-footer-cell]", "providers": [], + "hostDirectives": [], + "standalone": false, "inputsClass": [], "outputsClass": [], "deprecated": false, @@ -14384,7 +14550,9 @@ "hostListeners": [], "propertiesClass": [], "methodsClass": [], - "extends": "CdkFooterCell", + "extends": [ + "CdkFooterCell" + ], "constructorObj": { "name": "constructor", "description": "", @@ -14441,6 +14609,8 @@ "name": "{ provide: CdkFooterCellDef, useExisting: OuiFooterCellDef }" } ], + "hostDirectives": [], + "standalone": false, "inputsClass": [], "outputsClass": [], "deprecated": false, @@ -14449,7 +14619,9 @@ "hostListeners": [], "propertiesClass": [], "methodsClass": [], - "extends": "CdkFooterCellDef" + "extends": [ + "CdkFooterCellDef" + ] }, { "name": "OuiFooterRowDef", @@ -14465,6 +14637,8 @@ "name": "{ provide: CdkFooterRowDef, useExisting: OuiFooterRowDef }" } ], + "hostDirectives": [], + "standalone": false, "inputsClass": [], "outputsClass": [], "deprecated": false, @@ -14473,7 +14647,9 @@ "hostListeners": [], "propertiesClass": [], "methodsClass": [], - "extends": "CdkFooterRowDef" + "extends": [ + "CdkFooterRowDef" + ] }, { "name": "OuiHeaderCell", @@ -14485,6 +14661,8 @@ "sourceCode": "import { Directive, ElementRef, Input } from '@angular/core';\nimport {\n CdkCell,\n CdkCellDef,\n CdkColumnDef,\n CdkFooterCell,\n CdkFooterCellDef,\n CdkHeaderCell,\n CdkHeaderCellDef,\n} from '@angular/cdk/table';\n\n/**\n * Cell definition for the oui-table.\n * Captures the template of a column's data row cell as well as cell-specific properties.\n */\n@Directive({\n selector: '[ouiCellDef]',\n providers: [{ provide: CdkCellDef, useExisting: OuiCellDef }],\n})\nexport class OuiCellDef extends CdkCellDef {}\n\n/**\n * Header cell definition for the oui-table.\n * Captures the template of a column's header cell and as well as cell-specific properties.\n */\n@Directive({\n selector: '[ouiHeaderCellDef]',\n providers: [{ provide: CdkHeaderCellDef, useExisting: OuiHeaderCellDef }],\n})\nexport class OuiHeaderCellDef extends CdkHeaderCellDef {}\n\n/**\n * Footer cell definition for the oui-table.\n * Captures the template of a column's footer cell and as well as cell-specific properties.\n */\n@Directive({\n selector: '[ouiFooterCellDef]',\n providers: [{ provide: CdkFooterCellDef, useExisting: OuiFooterCellDef }],\n})\nexport class OuiFooterCellDef extends CdkFooterCellDef {}\n\n/**\n * Column definition for the oui-table.\n * Defines a set of cells available for a table column.\n */\n@Directive({\n selector: '[ouiColumnDef]',\n providers: [\n { provide: CdkColumnDef, useExisting: OuiColumnDef },\n { provide: 'OUI_SORT_HEADER_COLUMN_DEF', useExisting: OuiColumnDef },\n ],\n})\nexport class OuiColumnDef extends CdkColumnDef {\n /** Unique name for this column. */\n @Input('ouiColumnDef')\n get name(): string {\n return this._name;\n }\n set name(name: string) {\n this._setNameInput(name);\n }\n}\n\n/** Header cell template container that adds the right classes and role. */\n@Directive({\n // eslint-disable-next-line @angular-eslint/directive-selector\n selector: 'oui-header-cell, th[oui-header-cell]',\n // eslint-disable-next-line @angular-eslint/no-host-metadata-property\n host: {\n class: 'oui-header-cell',\n role: 'columnheader',\n },\n})\nexport class OuiHeaderCell extends CdkHeaderCell {\n constructor(columnDef: CdkColumnDef, elementRef: ElementRef) {\n super(columnDef, elementRef);\n elementRef.nativeElement.classList.add(\n `oui-column-${columnDef.cssClassFriendlyName}`\n );\n }\n}\n\n/** Footer cell template container that adds the right classes and role. */\n@Directive({\n // eslint-disable-next-line @angular-eslint/directive-selector\n selector: 'oui-footer-cell, td[oui-footer-cell]',\n // eslint-disable-next-line @angular-eslint/no-host-metadata-property\n host: {\n class: 'oui-footer-cell',\n role: 'gridcell',\n },\n})\nexport class OuiFooterCell extends CdkFooterCell {\n constructor(columnDef: CdkColumnDef, elementRef: ElementRef) {\n super(columnDef, elementRef);\n elementRef.nativeElement.classList.add(\n `oui-column-${columnDef.cssClassFriendlyName}`\n );\n }\n}\n\n/** Cell template container that adds the right classes and role. */\n@Directive({\n // eslint-disable-next-line @angular-eslint/directive-selector\n selector: 'oui-cell, td[oui-cell]',\n // eslint-disable-next-line @angular-eslint/no-host-metadata-property\n host: {\n class: 'oui-cell',\n role: 'gridcell',\n },\n})\nexport class OuiCell extends CdkCell {\n constructor(columnDef: CdkColumnDef, elementRef: ElementRef) {\n super(columnDef, elementRef);\n elementRef.nativeElement.classList.add(\n `oui-column-${columnDef.cssClassFriendlyName}`\n );\n }\n}\n", "selector": "oui-header-cell, th[oui-header-cell]", "providers": [], + "hostDirectives": [], + "standalone": false, "inputsClass": [], "outputsClass": [], "deprecated": false, @@ -14493,7 +14671,9 @@ "hostListeners": [], "propertiesClass": [], "methodsClass": [], - "extends": "CdkHeaderCell", + "extends": [ + "CdkHeaderCell" + ], "constructorObj": { "name": "constructor", "description": "", @@ -14550,6 +14730,8 @@ "name": "{ provide: CdkHeaderCellDef, useExisting: OuiHeaderCellDef }" } ], + "hostDirectives": [], + "standalone": false, "inputsClass": [], "outputsClass": [], "deprecated": false, @@ -14558,7 +14740,9 @@ "hostListeners": [], "propertiesClass": [], "methodsClass": [], - "extends": "CdkHeaderCellDef" + "extends": [ + "CdkHeaderCellDef" + ] }, { "name": "OuiHeaderRowDef", @@ -14574,6 +14758,8 @@ "name": "{ provide: CdkHeaderRowDef, useExisting: OuiHeaderRowDef }" } ], + "hostDirectives": [], + "standalone": false, "inputsClass": [], "outputsClass": [], "deprecated": false, @@ -14582,7 +14768,9 @@ "hostListeners": [], "propertiesClass": [], "methodsClass": [], - "extends": "CdkHeaderRowDef" + "extends": [ + "CdkHeaderRowDef" + ] }, { "name": "OuiInput", @@ -14605,6 +14793,9 @@ "type": "directive" } ], + "exportAs": "ouiInput", + "hostDirectives": [], + "standalone": false, "inputsClass": [ { "name": "disabled", @@ -14614,17 +14805,17 @@ { "pos": 4784, "end": 4801, - "flags": 4227072, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 325, + "kind": 334, "tagName": { "pos": 4785, "end": 4797, - "flags": 4227072, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "docs-private" }, "comment": "" @@ -14654,17 +14845,17 @@ { "pos": 5410, "end": 5427, - "flags": 4227072, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 325, + "kind": 334, "tagName": { "pos": 5411, "end": 5423, - "flags": 4227072, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "docs-private" }, "comment": "" @@ -14684,17 +14875,17 @@ { "pos": 5643, "end": 5660, - "flags": 4227072, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 325, + "kind": 334, "tagName": { "pos": 5644, "end": 5656, - "flags": 4227072, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "docs-private" }, "comment": "" @@ -14724,17 +14915,17 @@ { "pos": 5763, "end": 5780, - "flags": 4227072, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 325, + "kind": 334, "tagName": { "pos": 5764, "end": 5776, - "flags": 4227072, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "docs-private" }, "comment": "" @@ -14764,17 +14955,17 @@ { "pos": 6819, "end": 6836, - "flags": 4227072, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 325, + "kind": 334, "tagName": { "pos": 6820, "end": 6832, - "flags": 4227072, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "docs-private" }, "comment": "" @@ -14813,7 +15004,7 @@ "description": "", "line": 189, "modifierKind": [ - 122 + 124 ] }, { @@ -14825,7 +15016,7 @@ "description": "", "line": 284, "modifierKind": [ - 123 + 125 ] }, { @@ -14837,7 +15028,7 @@ "description": "", "line": 203, "modifierKind": [ - 122 + 124 ] }, { @@ -14849,7 +15040,7 @@ "description": "", "line": 113, "modifierKind": [ - 121 + 123 ] }, { @@ -14884,7 +15075,7 @@ "description": "", "line": 274, "modifierKind": [ - 122 + 124 ] }, { @@ -14896,7 +15087,7 @@ "description": "", "line": 298, "modifierKind": [ - 123 + 125 ] }, { @@ -14908,7 +15099,7 @@ "description": "", "line": 299, "modifierKind": [ - 123 + 125 ] }, { @@ -14920,7 +15111,7 @@ "description": "", "line": 112, "modifierKind": [ - 122 + 124 ] }, { @@ -14933,7 +15124,7 @@ "description": "", "line": 272, "modifierKind": [ - 121 + 123 ] }, { @@ -14946,7 +15137,7 @@ "description": "", "line": 225, "modifierKind": [ - 122 + 124 ] }, { @@ -14959,7 +15150,7 @@ "description": "", "line": 243, "modifierKind": [ - 122 + 124 ] }, { @@ -14972,7 +15163,7 @@ "description": "", "line": 111, "modifierKind": [ - 122 + 124 ] }, { @@ -14989,17 +15180,17 @@ { "pos": 4676, "end": 4693, - "flags": 4227072, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 325, + "kind": 334, "tagName": { "pos": 4677, "end": 4689, - "flags": 4227072, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "docs-private" }, "comment": "" @@ -15030,17 +15221,17 @@ { "pos": 4484, "end": 4501, - "flags": 4227072, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 325, + "kind": 334, "tagName": { "pos": 4485, "end": 4497, - "flags": 4227072, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "docs-private" }, "comment": "" @@ -15061,17 +15252,17 @@ { "pos": 3696, "end": 3713, - "flags": 4227072, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 325, + "kind": 334, "tagName": { "pos": 3697, "end": 3709, - "flags": 4227072, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "docs-private" }, "comment": "" @@ -15092,17 +15283,17 @@ { "pos": 4153, "end": 4170, - "flags": 4227072, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 325, + "kind": 334, "tagName": { "pos": 4154, "end": 4166, - "flags": 4227072, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "docs-private" }, "comment": "" @@ -15129,23 +15320,25 @@ } ], "modifierKind": [ - 123 + 170, + 170, + 125 ], "jsdoctags": [ { "pos": 7645, "end": 7659, - "flags": 4194304, + "flags": 16777216, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 325, + "kind": 334, "tagName": { "pos": 7646, "end": 7658, - "flags": 4194304, + "flags": 16777216, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "docs-private" }, "comment": "" @@ -15163,23 +15356,23 @@ "line": 150, "rawdescription": "\n\nImplemented as part of OuiFormFieldControl.\n\n", "modifierKind": [ - 144 + 148 ], "jsdoctags": [ { "pos": 4336, "end": 4353, - "flags": 4227072, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 325, + "kind": 334, "tagName": { "pos": 4337, "end": 4349, - "flags": 4227072, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "docs-private" }, "comment": "" @@ -15200,7 +15393,7 @@ "rawdescription": "\nDoes some manual dirty checking on the native input `value` property.", "description": "

Does some manual dirty checking on the native input value property.

\n", "modifierKind": [ - 122 + 124 ] }, { @@ -15215,7 +15408,7 @@ "rawdescription": "\nChecks whether the input is invalid based on the native validation.", "description": "

Checks whether the input is invalid based on the native validation.

\n", "modifierKind": [ - 122 + 124 ] }, { @@ -15230,7 +15423,7 @@ "rawdescription": "\nChecks whether the input type is one of the types that are never empty.", "description": "

Checks whether the input type is one of the types that are never empty.

\n", "modifierKind": [ - 122 + 124 ] }, { @@ -15245,7 +15438,7 @@ "rawdescription": "\nDetermines if the component host is a textarea.", "description": "

Determines if the component host is a textarea.

\n", "modifierKind": [ - 122 + 124 ] }, { @@ -15270,7 +15463,7 @@ "rawdescription": "\nMake sure the input is a supported type.", "description": "

Make sure the input is a supported type.

\n", "modifierKind": [ - 122 + 124 ] }, { @@ -15285,7 +15478,7 @@ "rawdescription": "\nAdding class dynamically based of type", "description": "

Adding class dynamically based of type

\n", "modifierKind": [ - 122 + 124 ] }, { @@ -15428,7 +15621,9 @@ "deprecationMessage": "" } ], - "extends": "_OuiInputMixinBase", + "extends": [ + "_OuiInputMixinBase" + ], "implements": [ "OuiFormFieldControl", "OnChanges", @@ -15608,17 +15803,17 @@ { "pos": 4784, "end": 4801, - "flags": 4227072, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 325, + "kind": 334, "tagName": { "pos": 4785, "end": 4797, - "flags": 4227072, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "docs-private" }, "comment": "" @@ -15666,17 +15861,17 @@ { "pos": 5410, "end": 5427, - "flags": 4227072, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 325, + "kind": 334, "tagName": { "pos": 5411, "end": 5423, - "flags": 4227072, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "docs-private" }, "comment": "" @@ -15724,17 +15919,17 @@ { "pos": 5763, "end": 5780, - "flags": 4227072, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 325, + "kind": 334, "tagName": { "pos": 5764, "end": 5776, - "flags": 4227072, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "docs-private" }, "comment": "" @@ -15820,17 +16015,17 @@ { "pos": 6819, "end": 6836, - "flags": 4227072, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 325, + "kind": 334, "tagName": { "pos": 6820, "end": 6832, - "flags": 4227072, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "docs-private" }, "comment": "" @@ -15889,17 +16084,17 @@ { "pos": 11912, "end": 11929, - "flags": 4227072, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 325, + "kind": 334, "tagName": { "pos": 11913, "end": 11925, - "flags": 4227072, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "docs-private" }, "comment": "" @@ -15920,17 +16115,17 @@ { "pos": 12177, "end": 12194, - "flags": 4227072, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 325, + "kind": 334, "tagName": { "pos": 12178, "end": 12190, - "flags": 4227072, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "docs-private" }, "comment": "" @@ -15950,6 +16145,8 @@ "sourceCode": "import {\n Directive,\n TemplateRef,\n ComponentFactoryResolver,\n ApplicationRef,\n Injector,\n ViewContainerRef,\n Inject,\n OnDestroy,\n} from '@angular/core';\nimport { TemplatePortal, DomPortalOutlet } from '@angular/cdk/portal';\nimport { DOCUMENT } from '@angular/common';\nimport { Subject } from 'rxjs';\n\n/**\n * Menu content that will be rendered lazily once the menu is opened.\n */\n@Directive({\n selector: 'ng-template[ouiMenuContent]',\n})\nexport class OuiMenuContent implements OnDestroy {\n private _portal: TemplatePortal;\n private _outlet: DomPortalOutlet;\n\n /** Emits when the menu content has been attached. */\n _attached = new Subject();\n\n constructor(\n private _template: TemplateRef,\n private _componentFactoryResolver: ComponentFactoryResolver,\n private _appRef: ApplicationRef,\n private _injector: Injector,\n private _viewContainerRef: ViewContainerRef,\n @Inject(DOCUMENT) private _document: Document\n ) {}\n\n /**\n * Attaches the content with a particular context.\n */\n attach(context: any = {}) {\n if (!this._portal) {\n this._portal = new TemplatePortal(this._template, this._viewContainerRef);\n }\n\n this.detach();\n\n if (!this._outlet) {\n this._outlet = new DomPortalOutlet(\n this._document.createElement('div'),\n this._componentFactoryResolver,\n this._appRef,\n this._injector\n );\n }\n\n const element: HTMLElement = this._template.elementRef.nativeElement;\n\n // Because we support opening the same menu from different triggers (which in turn have their\n // own `OverlayRef` panel), we have to re-insert the host element every time, otherwise we\n // risk it staying attached to a pane that's no longer in the DOM.\n element.parentNode!.insertBefore(this._outlet.outletElement, element);\n this._portal.attach(this._outlet, context);\n this._attached.next();\n }\n\n /**\n * Detaches the content.\n */\n detach() {\n if (this._portal.isAttached) {\n this._portal.detach();\n }\n }\n\n ngOnDestroy() {\n if (this._outlet) {\n this._outlet.dispose();\n }\n }\n}\n", "selector": "ng-template[ouiMenuContent]", "providers": [], + "hostDirectives": [], + "standalone": false, "inputsClass": [], "outputsClass": [], "deprecated": false, @@ -15977,7 +16174,7 @@ "description": "", "line": 23, "modifierKind": [ - 121 + 123 ] }, { @@ -15989,7 +16186,7 @@ "description": "", "line": 22, "modifierKind": [ - 121 + 123 ] } ], @@ -16049,6 +16246,7 @@ "deprecationMessage": "" } ], + "extends": [], "implements": [ "OnDestroy" ], @@ -16164,6 +16362,9 @@ "sourceCode": "import {\n FocusMonitor,\n FocusOrigin,\n isFakeMousedownFromScreenReader,\n} from '@angular/cdk/a11y';\nimport { RIGHT_ARROW, SPACE } from '@angular/cdk/keycodes';\nimport {\n FlexibleConnectedPositionStrategy,\n HorizontalConnectionPos,\n Overlay,\n OverlayConfig,\n OverlayRef,\n VerticalConnectionPos,\n ScrollStrategy,\n} from '@angular/cdk/overlay';\nimport { TemplatePortal } from '@angular/cdk/portal';\nimport {\n AfterContentInit,\n Directive,\n ElementRef,\n EventEmitter,\n Inject,\n InjectionToken,\n Input,\n OnDestroy,\n Optional,\n Output,\n Self,\n ViewContainerRef,\n} from '@angular/core';\nimport { normalizePassiveListenerOptions } from '@angular/cdk/platform';\nimport {\n asapScheduler,\n merge,\n Observable,\n of as observableOf,\n Subscription,\n} from 'rxjs';\nimport { delay, filter } from 'rxjs/operators';\nimport { OuiMenu } from './menu-directive';\nimport { throwOuiMenuMissingError } from './menu-errors';\nimport { OuiMenuItem } from './menu-item';\nimport { OuiMenuPanel } from './menu-panel';\nimport { MenuPositionX, MenuPositionY } from './menu-positions';\n\n/** Injection token that determines the scroll handling while the menu is open. */\nexport const OUI_MENU_SCROLL_STRATEGY = new InjectionToken<\n () => ScrollStrategy\n>('oui-menu-scroll-strategy');\n\n/** @docs-private */\nexport function OUI_MENU_SCROLL_STRATEGY_FACTORY(\n overlay: Overlay\n): () => ScrollStrategy {\n return () => overlay.scrollStrategies.close();\n}\n\n/** @docs-private */\nexport const OUI_MENU_SCROLL_STRATEGY_FACTORY_PROVIDER = {\n provide: OUI_MENU_SCROLL_STRATEGY,\n deps: [Overlay],\n useFactory: OUI_MENU_SCROLL_STRATEGY_FACTORY,\n};\n\n/** Default top padding of the menu panel. */\nexport const MENU_PANEL_TOP_PADDING = 11;\n\n/** Default left padding of the menu panel */\nexport const MENU_PANEL_LEFT_PADDING = 2;\n\n/** Options for binding a passive event listener. */\nconst passiveEventListenerOptions = normalizePassiveListenerOptions({\n passive: true,\n});\n\n// TODO(andrewseguin): Remove the kebab versions in favor of camelCased attribute selectors\n\n/**\n * This directive is intended to be used in conjunction with an oui-menu tag. It is\n * responsible for toggling the display of the provided menu instance.\n */\n@Directive({\n selector: `[oui-menu-trigger-for], [ouiMenuTriggerFor]`,\n // eslint-disable-next-line @angular-eslint/no-host-metadata-property\n host: {\n 'aria-haspopup': 'true',\n '[attr.aria-expanded]': 'menuOpen || null',\n '(mousedown)': '_handleMousedown($event)',\n '(keydown)': '_handleKeydown($event)',\n '(click)': '_handleClick($event)',\n },\n exportAs: 'ouiMenuTrigger',\n})\nexport class OuiMenuTrigger implements AfterContentInit, OnDestroy {\n private _portal: TemplatePortal;\n private _overlayRef: OverlayRef | null = null;\n private _menuOpen = false;\n private _closeSubscription = Subscription.EMPTY;\n private _hoverSubscription = Subscription.EMPTY;\n private _menuCloseSubscription = Subscription.EMPTY;\n private _scrollStrategy: () => ScrollStrategy;\n private _openViaFocus = false;\n\n // Tracking input type is necessary so it's possible to only auto-focus\n // the first item of the list when the menu is opened via the keyboard\n _openedBy: 'mouse' | 'touch' | null = null;\n\n /** References the menu instance that the trigger is associated with. */\n @Input('ouiMenuTriggerFor')\n get menu() {\n return this._menu;\n }\n set menu(menu: OuiMenuPanel) {\n if (menu === this._menu) {\n return;\n }\n this._menu = menu;\n this._menuCloseSubscription.unsubscribe();\n\n if (menu) {\n this._menuCloseSubscription = menu.close\n .asObservable()\n .subscribe((event) => {\n this._destroyMenu(event);\n // If a click closed the menu, we should close the entire chain of nested menus.\n if ((event === 'click' || event === 'tab') && this._parentMenu) {\n this._parentMenu.closed.emit(event);\n }\n });\n }\n }\n private _menu: OuiMenuPanel;\n\n /** Data to be passed along to any lazily-rendered content. */\n\n // eslint-disable-next-line @angular-eslint/no-input-rename\n @Input('ouiMenuTriggerData')\n menuData: any;\n\n /** Event emitted when the associated menu is opened. */\n @Output()\n readonly menuOpened: EventEmitter = new EventEmitter();\n\n /** Event emitted when the associated menu is closed. */\n @Output()\n readonly menuClosed: EventEmitter = new EventEmitter();\n\n /**\n * Handles touch start events on the trigger.\n * Needs to be an arrow function so we can easily use addEventListener and removeEventListener.\n */\n private _handleTouchStart = () => (this._openedBy = 'touch');\n\n constructor(\n private _overlay: Overlay,\n private _element: ElementRef,\n private _viewContainerRef: ViewContainerRef,\n @Inject(OUI_MENU_SCROLL_STRATEGY) scrollStrategy: any,\n @Optional() private _parentMenu: OuiMenu,\n @Optional()\n @Self()\n private _menuItemInstance: OuiMenuItem,\n // TODO(crisbeto): make the _focusMonitor required when doing breaking changes.\n // @breaking-change 8.0.0\n private _focusMonitor?: FocusMonitor\n ) {\n _element.nativeElement.addEventListener(\n 'touchstart',\n this._handleTouchStart,\n passiveEventListenerOptions\n );\n\n if (_menuItemInstance) {\n _menuItemInstance._triggersSubmenu = this.triggersSubmenu();\n }\n\n this._scrollStrategy = scrollStrategy;\n }\n\n ngAfterContentInit() {\n this._checkMenu();\n this._handleHover();\n }\n\n ngOnDestroy() {\n if (this._overlayRef) {\n this._overlayRef.dispose();\n this._overlayRef = null;\n }\n\n this._element.nativeElement.removeEventListener(\n 'touchstart',\n this._handleTouchStart,\n passiveEventListenerOptions\n );\n\n this._cleanUpSubscriptions();\n }\n\n /** Whether the menu is open. */\n get menuOpen(): boolean {\n return this._menuOpen;\n }\n\n /** Whether the menu triggers a sub-menu or a top-level one. */\n triggersSubmenu(): boolean {\n return !!(this._menuItemInstance && this._parentMenu);\n }\n\n /** Toggles the menu between the open and closed states. */\n toggleMenu(): void {\n return this._menuOpen ? this.closeMenu() : this.openMenu();\n }\n\n /** Opens the menu. */\n openMenu(): void {\n if (this._menuOpen) {\n return;\n }\n\n this._checkMenu();\n\n const overlayRef = this._createOverlay();\n const overlayConfig = overlayRef.getConfig();\n\n this._setPosition(\n overlayConfig.positionStrategy as FlexibleConnectedPositionStrategy\n );\n overlayConfig.hasBackdrop =\n this.menu.hasBackdrop == null\n ? !this.triggersSubmenu()\n : this.menu.hasBackdrop;\n overlayRef.attach(this._getPortal());\n\n if (this.menu.lazyContent) {\n this.menu.lazyContent.attach(this.menuData);\n }\n\n this._closeSubscription = this._menuClosingActions().subscribe(() => {\n this.closeMenu();\n });\n this._initMenu();\n }\n\n /** Closes the menu. */\n closeMenu(event?: 'click' | 'keydown' | 'tab'): void {\n this.menu.close.emit(event);\n }\n\n /**\n * Focuses the menu trigger.\n *\n * @param origin Source of the menu trigger's focus.\n */\n focus(origin: FocusOrigin = 'program') {\n if (this._focusMonitor) {\n this._focusMonitor.focusVia(this._element.nativeElement, origin);\n } else {\n this._element.nativeElement.focus();\n }\n }\n\n /** Closes the menu and does the necessary cleanup. */\n private _destroyMenu(event) {\n // (TODO)\n if (!this._overlayRef || !this.menuOpen) {\n return;\n }\n\n const menu = this.menu;\n\n this._closeSubscription.unsubscribe();\n this._overlayRef.detach();\n this._resetMenu(event);\n\n if (!(menu instanceof OuiMenu) && menu.lazyContent) {\n menu.lazyContent.detach();\n }\n }\n\n /**\n * This method sets the menu state to open and focuses the first item if\n * the menu was opened via the keyboard.\n */\n private _initMenu(): void {\n this.menu.parentMenu = this.triggersSubmenu()\n ? this._parentMenu\n : undefined;\n this._setIsMenuOpen(true);\n this.menu.focusFirstItem(this._openedBy || 'program');\n }\n\n /**\n * This method resets the menu when it's closed, most importantly restoring\n * focus to the menu trigger if the menu was opened via the keyboard.\n */\n private _resetMenu(event): void {\n this._setIsMenuOpen(false);\n\n // We should reset focus if the user is navigating using a keyboard or\n // if we have a top-level trigger which might cause focus to be lost\n // when clicking on the backdrop.\n // Focus back to menu only when clicking outside of menu on window or ESC key pressed.\n if ((!event && !this.triggersSubmenu()) || event === 'keydown') {\n if (!this._openedBy) {\n // Note that the focus style will show up both for `program` and\n // `keyboard` so we don't have to specify which one it is.\n this.focus();\n } else if (!this.triggersSubmenu()) {\n this.focus(this._openedBy);\n }\n }\n this._openedBy = null;\n }\n\n // set state rather than toggle to support triggers sharing a menu\n private _setIsMenuOpen(isOpen: boolean): void {\n this._menuOpen = isOpen;\n this._menuOpen ? this.menuOpened.emit() : this.menuClosed.emit();\n\n if (this.triggersSubmenu()) {\n this._menuItemInstance._highlighted = isOpen;\n }\n }\n\n /**\n * This method checks that a valid instance of OuiMenu has been passed into\n * ouiMenuTriggerFor. If not, an exception is thrown.\n */\n private _checkMenu() {\n if (!this.menu) {\n throwOuiMenuMissingError();\n }\n }\n\n /**\n * This method creates the overlay from the provided menu's template and saves its\n * OverlayRef so that it can be attached to the DOM when openMenu is called.\n */\n private _createOverlay(): OverlayRef {\n if (!this._overlayRef) {\n const config = this._getOverlayConfig();\n this._subscribeToPositions(\n config.positionStrategy as FlexibleConnectedPositionStrategy\n );\n this._overlayRef = this._overlay.create(config);\n\n // Consume the `keydownEvents` in order to prevent them from going to another overlay.\n // Ideally we'd also have our keyboard event logic in here, however doing so will\n // break anybody that may have implemented the `OuiMenuPanel` themselves.\n this._overlayRef.keydownEvents().subscribe();\n }\n\n return this._overlayRef;\n }\n\n /**\n * This method builds the configuration object needed to create the overlay, the OverlayState.\n *\n * @returns OverlayConfig\n */\n private _getOverlayConfig(): OverlayConfig {\n return new OverlayConfig({\n positionStrategy: this._overlay\n .position()\n .flexibleConnectedTo(this._element)\n .withLockedPosition()\n .withTransformOriginOn('.oui-menu-panel'),\n backdropClass:\n this.menu.backdropClass || 'cdk-overlay-transparent-backdrop',\n scrollStrategy: this._scrollStrategy(),\n direction: 'ltr',\n });\n }\n\n /**\n * Listens to changes in the position of the overlay and sets the correct classes\n * on the menu based on the new position. This ensures the animation origin is always\n * correct, even if a fallback position is used for the overlay.\n */\n private _subscribeToPositions(\n position: FlexibleConnectedPositionStrategy\n ): void {\n if (this.menu.setPositionClasses) {\n position.positionChanges.subscribe((change) => {\n const posX: MenuPositionX =\n change.connectionPair.overlayX === 'start' ? 'after' : 'before';\n const posY: MenuPositionY =\n change.connectionPair.overlayY === 'top' ? 'below' : 'above';\n\n this.menu.setPositionClasses!(posX, posY);\n });\n }\n }\n\n /**\n * Sets the appropriate positions on a position strategy\n * so the overlay connects with the trigger correctly.\n *\n * @param positionStrategy Strategy whose position to update.\n */\n private _setPosition(positionStrategy: FlexibleConnectedPositionStrategy) {\n let [originX, originFallbackX]: HorizontalConnectionPos[] =\n this.menu.xPosition === 'before' ? ['end', 'start'] : ['start', 'end'];\n\n const [overlayY, overlayFallbackY]: VerticalConnectionPos[] =\n this.menu.yPosition === 'above' ? ['bottom', 'top'] : ['top', 'bottom'];\n\n let [originY, originFallbackY] = [overlayY, overlayFallbackY];\n let [overlayX, overlayFallbackX] = [originX, originFallbackX];\n let offsetY = 0;\n let offsetX = 0;\n\n if (this.triggersSubmenu()) {\n // When the menu is a sub-menu, it should always align itself\n // to the edges of the trigger, instead of overlapping it.\n overlayFallbackX = originX =\n this.menu.xPosition === 'before' ? 'start' : 'end';\n originFallbackX = overlayX = originX === 'end' ? 'start' : 'end';\n offsetY =\n overlayY === 'bottom'\n ? MENU_PANEL_TOP_PADDING\n : -MENU_PANEL_TOP_PADDING;\n\n offsetX =\n overlayX === 'start'\n ? MENU_PANEL_LEFT_PADDING\n : -MENU_PANEL_LEFT_PADDING;\n } else if (!this.menu.overlapTrigger) {\n originY = overlayY === 'top' ? 'bottom' : 'top';\n originFallbackY = overlayFallbackY === 'top' ? 'bottom' : 'top';\n }\n\n positionStrategy.withPositions([\n { originX, originY, overlayX, overlayY, offsetY, offsetX },\n {\n originX: originFallbackX,\n originY,\n overlayX: overlayFallbackX,\n overlayY,\n offsetY,\n offsetX,\n },\n {\n originX,\n originY: originFallbackY,\n overlayX,\n overlayY: overlayFallbackY,\n offsetY: -offsetY,\n offsetX,\n },\n {\n originX: originFallbackX,\n originY: originFallbackY,\n overlayX: overlayFallbackX,\n overlayY: overlayFallbackY,\n offsetY: -offsetY,\n offsetX: -offsetX,\n },\n ]);\n }\n\n /** Cleans up the active subscriptions. */\n private _cleanUpSubscriptions(): void {\n this._closeSubscription.unsubscribe();\n this._hoverSubscription.unsubscribe();\n }\n\n /** Returns a stream that emits whenever an action that should close the menu occurs. */\n private _menuClosingActions() {\n const backdrop = this._overlayRef!.backdropClick();\n const detachments = this._overlayRef!.detachments();\n const parentClose = this._parentMenu\n ? this._parentMenu.closed\n : observableOf();\n const hover = this._parentMenu\n ? this._parentMenu._hovered().pipe(\n filter((active) => active !== this._menuItemInstance),\n filter(() => this._menuOpen)\n )\n : observableOf();\n\n return merge(backdrop, parentClose as Observable, hover, detachments);\n }\n\n /** Handles mouse presses on the trigger. */\n _handleMousedown(event: MouseEvent): void {\n if (!isFakeMousedownFromScreenReader(event)) {\n // Since right or middle button clicks won't trigger the `click` event,\n // we shouldn't consider the menu as opened by mouse in those cases.\n this._openedBy = event.button === 0 ? 'mouse' : null;\n\n // Since clicking on the trigger won't close the menu if it opens a sub-menu,\n // we should prevent focus from moving onto it via click to avoid the\n // highlight from lingering on the menu item.\n if (this.triggersSubmenu()) {\n event.preventDefault();\n }\n }\n }\n\n /** Handles key presses on the trigger. */\n _handleKeydown(event: KeyboardEvent): void {\n const keyCode = event.keyCode;\n if (this.triggersSubmenu() && keyCode === RIGHT_ARROW) {\n this.openMenu();\n } else if (keyCode === SPACE) {\n this.openMenu();\n }\n }\n\n /** Handles click events on the trigger. */\n _handleClick(event: MouseEvent): void {\n if (this.triggersSubmenu()) {\n // Stop event propagation to avoid closing the parent menu.\n event.stopPropagation();\n this.openMenu();\n } else {\n this.toggleMenu();\n }\n }\n\n _handleFocus(): void {\n if (!this._openViaFocus) {\n this.toggleMenu();\n }\n this._openViaFocus = !this._openViaFocus;\n }\n\n /** Handles the cases where the user hovers over the trigger. */\n private _handleHover() {\n // Subscribe to changes in the hovered item in order to toggle the panel.\n if (!this.triggersSubmenu()) {\n return;\n }\n\n this._hoverSubscription = this._parentMenu\n ._hovered()\n // Since we might have multiple competing triggers for the same menu (e.g. a sub-menu\n // with different data and triggers), we have to delay it by a tick to ensure that\n // it won't be closed immediately after it is opened.\n .pipe(\n filter(\n (active) => active === this._menuItemInstance && !active.disabled\n ),\n delay(0, asapScheduler)\n )\n .subscribe(() => {\n this._openedBy = 'mouse';\n\n // If the same menu is used between multiple triggers, it might still be animating\n // while the new trigger tries to re-open it. Wait for the animation to finish\n // before doing so. Also interrupt if the user moves to another item.\n // (TODO)\n this.openMenu();\n });\n }\n\n /** Gets the portal that should be attached to the overlay. */\n private _getPortal(): TemplatePortal {\n // Note that we can avoid this check by keeping the portal on the menu panel.\n // While it would be cleaner, we'd have to introduce another required method on\n // `OuiMenuPanel`, making it harder to consume.\n if (!this._portal || this._portal.templateRef !== this.menu.templateRef) {\n this._portal = new TemplatePortal(\n this.menu.templateRef,\n this._viewContainerRef\n );\n }\n\n return this._portal;\n }\n}\n", "selector": "[oui-menu-trigger-for], [ouiMenuTriggerFor]", "providers": [], + "exportAs": "ouiMenuTrigger", + "hostDirectives": [], + "standalone": false, "inputsClass": [ { "name": "ouiMenuTriggerData", @@ -16223,7 +16424,7 @@ "description": "", "line": 98, "modifierKind": [ - 121 + 123 ] }, { @@ -16237,7 +16438,7 @@ "line": 152, "rawdescription": "\n\nHandles touch start events on the trigger.\nNeeds to be an arrow function so we can easily use addEventListener and removeEventListener.\n", "modifierKind": [ - 121 + 123 ] }, { @@ -16250,7 +16451,7 @@ "description": "", "line": 99, "modifierKind": [ - 121 + 123 ] }, { @@ -16262,7 +16463,7 @@ "description": "", "line": 132, "modifierKind": [ - 121 + 123 ] }, { @@ -16275,7 +16476,7 @@ "description": "", "line": 100, "modifierKind": [ - 121 + 123 ] }, { @@ -16288,7 +16489,7 @@ "description": "", "line": 97, "modifierKind": [ - 121 + 123 ] }, { @@ -16311,7 +16512,7 @@ "description": "", "line": 102, "modifierKind": [ - 121 + 123 ] }, { @@ -16324,7 +16525,7 @@ "description": "", "line": 96, "modifierKind": [ - 121 + 123 ] }, { @@ -16336,7 +16537,7 @@ "description": "", "line": 95, "modifierKind": [ - 121 + 123 ] }, { @@ -16348,7 +16549,7 @@ "description": "", "line": 101, "modifierKind": [ - 121 + 123 ] } ], @@ -16365,7 +16566,7 @@ "rawdescription": "\n\nThis method checks that a valid instance of OuiMenu has been passed into\nouiMenuTriggerFor. If not, an exception is thrown.\n", "description": "

This method checks that a valid instance of OuiMenu has been passed into\nouiMenuTriggerFor. If not, an exception is thrown.

\n", "modifierKind": [ - 121 + 123 ] }, { @@ -16380,7 +16581,7 @@ "rawdescription": "\nCleans up the active subscriptions.", "description": "

Cleans up the active subscriptions.

\n", "modifierKind": [ - 121 + 123 ] }, { @@ -16395,7 +16596,7 @@ "rawdescription": "\n\nThis method creates the overlay from the provided menu's template and saves its\nOverlayRef so that it can be attached to the DOM when openMenu is called.\n", "description": "

This method creates the overlay from the provided menu's template and saves its\nOverlayRef so that it can be attached to the DOM when openMenu is called.

\n", "modifierKind": [ - 121 + 123 ] }, { @@ -16417,7 +16618,7 @@ "rawdescription": "\nCloses the menu and does the necessary cleanup.", "description": "

Closes the menu and does the necessary cleanup.

\n", "modifierKind": [ - 121 + 123 ], "jsdoctags": [ { @@ -16443,17 +16644,17 @@ "rawdescription": "\n\nThis method builds the configuration object needed to create the overlay, the OverlayState.\n\n", "description": "

This method builds the configuration object needed to create the overlay, the OverlayState.

\n", "modifierKind": [ - 121 + 123 ], "jsdoctags": [ { "tagName": { "pos": 10499, "end": 10506, - "flags": 4227072, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "returns" }, "comment": "

OverlayConfig

\n" @@ -16472,7 +16673,7 @@ "rawdescription": "\nGets the portal that should be attached to the overlay.", "description": "

Gets the portal that should be attached to the overlay.

\n", "modifierKind": [ - 121 + 123 ] }, { @@ -16527,7 +16728,7 @@ "rawdescription": "\nHandles the cases where the user hovers over the trigger.", "description": "

Handles the cases where the user hovers over the trigger.

\n", "modifierKind": [ - 121 + 123 ] }, { @@ -16602,7 +16803,7 @@ "rawdescription": "\n\nThis method sets the menu state to open and focuses the first item if\nthe menu was opened via the keyboard.\n", "description": "

This method sets the menu state to open and focuses the first item if\nthe menu was opened via the keyboard.

\n", "modifierKind": [ - 121 + 123 ] }, { @@ -16617,7 +16818,7 @@ "rawdescription": "\nReturns a stream that emits whenever an action that should close the menu occurs.", "description": "

Returns a stream that emits whenever an action that should close the menu occurs.

\n", "modifierKind": [ - 121 + 123 ] }, { @@ -16639,7 +16840,7 @@ "rawdescription": "\n\nThis method resets the menu when it's closed, most importantly restoring\nfocus to the menu trigger if the menu was opened via the keyboard.\n", "description": "

This method resets the menu when it's closed, most importantly restoring\nfocus to the menu trigger if the menu was opened via the keyboard.

\n", "modifierKind": [ - 121 + 123 ], "jsdoctags": [ { @@ -16670,7 +16871,7 @@ "deprecated": false, "deprecationMessage": "", "modifierKind": [ - 121 + 123 ], "jsdoctags": [ { @@ -16703,17 +16904,17 @@ "rawdescription": "\n\nSets the appropriate positions on a position strategy\nso the overlay connects with the trigger correctly.\n\n", "description": "

Sets the appropriate positions on a position strategy\nso the overlay connects with the trigger correctly.

\n", "modifierKind": [ - 121 + 123 ], "jsdoctags": [ { "name": { "pos": 11833, "end": 11849, - "flags": 4227072, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "positionStrategy" }, "type": "FlexibleConnectedPositionStrategy", @@ -16722,10 +16923,10 @@ "tagName": { "pos": 11827, "end": 11832, - "flags": 4227072, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "param" }, "comment": "

Strategy whose position to update.

\n" @@ -16751,7 +16952,7 @@ "rawdescription": "\n\nListens to changes in the position of the overlay and sets the correct classes\non the menu based on the new position. This ensures the animation origin is always\ncorrect, even if a fallback position is used for the overlay.\n", "description": "

Listens to changes in the position of the overlay and sets the correct classes\non the menu based on the new position. This ensures the animation origin is always\ncorrect, even if a fallback position is used for the overlay.

\n", "modifierKind": [ - 121 + 123 ], "jsdoctags": [ { @@ -16821,10 +17022,10 @@ "name": { "pos": 7106, "end": 7112, - "flags": 4227072, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "origin" }, "type": "FocusOrigin", @@ -16834,10 +17035,10 @@ "tagName": { "pos": 7100, "end": 7105, - "flags": 4227072, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "param" }, "comment": "

Source of the menu trigger's focus.

\n" @@ -16901,6 +17102,7 @@ "description": "

Whether the menu triggers a sub-menu or a top-level one.

\n" } ], + "extends": [], "implements": [ "AfterContentInit", "OnDestroy" @@ -17077,13 +17279,15 @@ }, { "name": "OuiPaginatedTabHeader", - "id": "directive-OuiPaginatedTabHeader-243c2e04b569d5d305f92edec5d594922284a23fceec2d0d450e045571c53603ac34bdd32451c1fc5544bbbbfe6e2a0264043f07f4b1a67543e2ae7c2f067c02", + "id": "directive-OuiPaginatedTabHeader-215a951b97ba6dbc96bfb7df7a5fe507c4d67e32ac9ddb70f0ff477d7438f05881d5b603a1a3e7a9c78d1a658a254ca8fc9aa0f1282d867ad923d534f716177f", "file": "ui/src/components/tabs/paginated-tab-header.ts", "type": "directive", "description": "

Base class for a tab header that supported pagination.

\n", "rawdescription": "\n\nBase class for a tab header that supported pagination.\n", - "sourceCode": "import {\n ChangeDetectorRef,\n ElementRef,\n NgZone,\n Optional,\n QueryList,\n EventEmitter,\n AfterContentChecked,\n AfterContentInit,\n AfterViewInit,\n OnDestroy,\n Directive,\n Inject,\n Input,\n} from '@angular/core';\nimport { Direction, Directionality } from '@angular/cdk/bidi';\nimport {\n BooleanInput,\n coerceBooleanProperty,\n coerceNumberProperty,\n NumberInput,\n} from '@angular/cdk/coercion';\nimport { ViewportRuler } from '@angular/cdk/scrolling';\nimport { FocusKeyManager, FocusableOption } from '@angular/cdk/a11y';\nimport { ENTER, SPACE, hasModifierKey } from '@angular/cdk/keycodes';\nimport {\n merge,\n of as observableOf,\n Subject,\n EMPTY,\n Observer,\n Observable,\n timer,\n fromEvent,\n} from 'rxjs';\nimport {\n take,\n switchMap,\n startWith,\n skip,\n takeUntil,\n filter,\n} from 'rxjs/operators';\nimport {\n Platform,\n normalizePassiveListenerOptions,\n} from '@angular/cdk/platform';\nimport { ANIMATION_MODULE_TYPE } from '@angular/platform-browser/animations';\n\n/** Config used to bind passive event listeners */\nconst passiveEventListenerOptions = normalizePassiveListenerOptions({\n passive: true,\n}) as EventListenerOptions;\n\n/**\n * The directions that scrolling can go in when the header's tabs exceed the header width. 'After'\n * will scroll the header towards the end of the tabs list and 'before' will scroll towards the\n * beginning of the list.\n */\nexport type ScrollDirection = 'after' | 'before';\n\n/**\n * Amount of milliseconds to wait before starting to scroll the header automatically.\n * Set a little conservatively in order to handle fake events dispatched on touch devices.\n */\nconst HEADER_SCROLL_DELAY = 650;\n\n/**\n * Interval in milliseconds at which to scroll the header\n * while the user is holding their pointer.\n */\nconst HEADER_SCROLL_INTERVAL = 100;\n\n/** Item inside a paginated tab header. */\nexport type MatPaginatedTabHeaderItem = FocusableOption & {\n elementRef: ElementRef;\n};\n\n/**\n * Base class for a tab header that supported pagination.\n * @docs-private\n */\n@Directive()\nexport abstract class OuiPaginatedTabHeader\n implements AfterContentChecked, AfterContentInit, AfterViewInit, OnDestroy\n{\n abstract _items: QueryList;\n abstract _inkBar: {\n hide: () => void;\n alignToElement: (element: HTMLElement) => void;\n };\n abstract _tabListContainer: ElementRef;\n abstract _tabList: ElementRef;\n abstract _tabListInner: ElementRef;\n abstract _nextPaginator: ElementRef;\n abstract _previousPaginator: ElementRef;\n\n /** The distance in pixels that the tab labels should be translated to the left. */\n private _scrollDistance = 0;\n\n /** Whether the header should scroll to the selected index after the view has been checked. */\n private _selectedIndexChanged = false;\n\n /** Emits when the component is destroyed. */\n protected readonly _destroyed = new Subject();\n\n /** Whether the controls for pagination should be displayed */\n _showPaginationControls = false;\n\n /** Whether the tab list can be scrolled more towards the end of the tab label list. */\n _disableScrollAfter = true;\n\n /** Whether the tab list can be scrolled more towards the beginning of the tab label list. */\n _disableScrollBefore = true;\n\n /**\n * The number of tab labels that are displayed on the header. When this changes, the header\n * should re-evaluate the scroll position.\n */\n private _tabLabelCount: number;\n\n /** Whether the scroll distance has changed and should be applied after the view is checked. */\n private _scrollDistanceChanged: boolean;\n\n /** Used to manage focus between the tabs. */\n private _keyManager: FocusKeyManager;\n\n /** Cached text content of the header. */\n private _currentTextContent: string;\n\n /** Stream that will stop the automated scrolling. */\n private _stopScrolling = new Subject();\n\n /**\n * Whether pagination should be disabled. This can be used to avoid unnecessary\n * layout recalculations if it's known that pagination won't be required.\n */\n @Input()\n get disablePagination(): boolean {\n return this._disablePagination;\n }\n set disablePagination(value: BooleanInput) {\n this._disablePagination = coerceBooleanProperty(value);\n }\n private _disablePagination = false;\n\n /** The index of the active tab. */\n get selectedIndex(): number {\n return this._selectedIndex;\n }\n set selectedIndex(value: NumberInput) {\n value = coerceNumberProperty(value);\n\n if (this._selectedIndex != value) {\n this._selectedIndexChanged = true;\n this._selectedIndex = value;\n\n if (this._keyManager) {\n this._keyManager.updateActiveItem(value);\n }\n }\n }\n private _selectedIndex = 0;\n\n /** Event emitted when the option is selected. */\n readonly selectFocusedIndex: EventEmitter =\n new EventEmitter();\n\n /** Event emitted when a label is focused. */\n readonly indexFocused: EventEmitter = new EventEmitter();\n\n constructor(\n protected _elementRef: ElementRef,\n protected _changeDetectorRef: ChangeDetectorRef,\n private _viewportRuler: ViewportRuler,\n @Optional() private _dir: Directionality,\n private _ngZone: NgZone,\n private _platform: Platform,\n @Optional() @Inject(ANIMATION_MODULE_TYPE) public _animationMode?: string\n ) {\n // Bind the `mouseleave` event on the outside since it doesn't change anything in the view.\n _ngZone.runOutsideAngular(() => {\n fromEvent(_elementRef.nativeElement, 'mouseleave')\n .pipe(takeUntil(this._destroyed))\n .subscribe(() => {\n this._stopInterval();\n });\n });\n }\n\n /** Called when the user has selected an item via the keyboard. */\n protected abstract _itemSelected(event: KeyboardEvent): void;\n\n ngAfterViewInit() {\n // We need to handle these events manually, because we want to bind passive event listeners.\n fromEvent(\n this._previousPaginator.nativeElement,\n 'touchstart',\n passiveEventListenerOptions\n )\n .pipe(takeUntil(this._destroyed))\n .subscribe(() => {\n this._handlePaginatorPress('before');\n });\n\n fromEvent(\n this._nextPaginator.nativeElement,\n 'touchstart',\n passiveEventListenerOptions\n )\n .pipe(takeUntil(this._destroyed))\n .subscribe(() => {\n this._handlePaginatorPress('after');\n });\n }\n\n ngAfterContentInit() {\n const dirChange = this._dir ? this._dir.change : observableOf('ltr');\n const resize = this._viewportRuler.change(150);\n const realign = () => {\n this.updatePagination();\n this._alignInkBarToSelectedTab();\n };\n\n this._keyManager = new FocusKeyManager(\n this._items\n )\n .withHorizontalOrientation(this._getLayoutDirection())\n .withHomeAndEnd()\n .withWrap()\n // Allow focus to land on disabled tabs, as per https://w3c.github.io/aria-practices/#kbd_disabled_controls\n .skipPredicate(() => false);\n\n this._keyManager.updateActiveItem(this._selectedIndex);\n\n // Defer the first call in order to allow for slower browsers to lay out the elements.\n // This helps in cases where the user lands directly on a page with paginated tabs.\n // Note that we use `onStable` instead of `requestAnimationFrame`, because the latter\n // can hold up tests that are in a background tab.\n this._ngZone.onStable.pipe(take(1)).subscribe(realign);\n\n // On dir change or window resize, realign the ink bar and update the orientation of\n // the key manager if the direction has changed.\n merge(dirChange, resize, this._items.changes, this._itemsResized())\n .pipe(takeUntil(this._destroyed))\n .subscribe(() => {\n // We need to defer this to give the browser some time to recalculate\n // the element dimensions. The call has to be wrapped in `NgZone.run`,\n // because the viewport change handler runs outside of Angular.\n this._ngZone.run(() => {\n Promise.resolve().then(() => {\n // Clamp the scroll distance, because it can change with the number of tabs.\n this._scrollDistance = Math.max(\n 0,\n Math.min(this._getMaxScrollDistance(), this._scrollDistance)\n );\n realign();\n });\n });\n this._keyManager.withHorizontalOrientation(this._getLayoutDirection());\n });\n\n // If there is a change in the focus key manager we need to emit the `indexFocused`\n // event in order to provide a public event that notifies about focus changes. Also we realign\n // the tabs container by scrolling the new focused tab into the visible section.\n this._keyManager.change.subscribe((newFocusIndex) => {\n this.indexFocused.emit(newFocusIndex);\n this._setTabFocus(newFocusIndex);\n });\n }\n\n /** Sends any changes that could affect the layout of the items. */\n private _itemsResized(): Observable {\n if (typeof ResizeObserver !== 'function') {\n return EMPTY;\n }\n\n return this._items.changes.pipe(\n startWith(this._items),\n switchMap(\n (tabItems: QueryList) =>\n new Observable((observer: Observer) =>\n this._ngZone.runOutsideAngular(() => {\n const resizeObserver = new ResizeObserver((entries) =>\n observer.next(entries)\n );\n tabItems.forEach(\n (\n item // eslint-disable-next-line @typescript-eslint/no-unsafe-argument\n ) => resizeObserver.observe(item.elementRef.nativeElement)\n );\n return () => {\n resizeObserver.disconnect();\n };\n })\n )\n ),\n // Skip the first emit since the resize observer emits when an item\n // is observed for new items when the tab is already inserted\n skip(1),\n // Skip emissions where all the elements are invisible since we don't want\n // the header to try and re-render with invalid measurements. See #25574.\n filter((entries) =>\n entries.some((e) => e.contentRect.width > 0 && e.contentRect.height > 0)\n )\n );\n }\n\n ngAfterContentChecked(): void {\n // If the number of tab labels have changed, check if scrolling should be enabled\n if (this._tabLabelCount != this._items.length) {\n this.updatePagination();\n this._tabLabelCount = this._items.length;\n this._changeDetectorRef.markForCheck();\n }\n\n // If the selected index has changed, scroll to the label and check if the scrolling controls\n // should be disabled.\n if (this._selectedIndexChanged) {\n this._scrollToLabel(this._selectedIndex);\n this._checkScrollingControls();\n this._alignInkBarToSelectedTab();\n this._selectedIndexChanged = false;\n this._changeDetectorRef.markForCheck();\n }\n\n // If the scroll distance has been changed (tab selected, focused, scroll controls activated),\n // then translate the header to reflect this.\n if (this._scrollDistanceChanged) {\n this._updateTabScrollPosition();\n this._scrollDistanceChanged = false;\n this._changeDetectorRef.markForCheck();\n }\n }\n\n ngOnDestroy() {\n // this._keyManager?.destroy();\n this._destroyed.next();\n this._destroyed.complete();\n this._stopScrolling.complete();\n }\n\n /** Handles keyboard events on the header. */\n _handleKeydown(event: KeyboardEvent) {\n // We don't handle any key bindings with a modifier key.\n if (hasModifierKey(event)) {\n return;\n }\n\n switch (event.keyCode) {\n case ENTER:\n case SPACE:\n if (this.focusIndex !== this.selectedIndex) {\n const item = this._items.get(this.focusIndex);\n\n if (item && !item.disabled) {\n this.selectFocusedIndex.emit(this.focusIndex);\n this._itemSelected(event);\n }\n }\n break;\n default:\n this._keyManager.onKeydown(event);\n }\n }\n\n /**\n * Callback for when the MutationObserver detects that the content has changed.\n */\n _onContentChanges() {\n const textContent = this._elementRef.nativeElement.textContent;\n\n // We need to diff the text content of the header, because the MutationObserver callback\n // will fire even if the text content didn't change which is inefficient and is prone\n // to infinite loops if a poorly constructed expression is passed in (see #14249).\n if (textContent !== this._currentTextContent) {\n this._currentTextContent = textContent || '';\n\n // The content observer runs outside the `NgZone` by default, which\n // means that we need to bring the callback back in ourselves.\n this._ngZone.run(() => {\n this.updatePagination();\n this._alignInkBarToSelectedTab();\n this._changeDetectorRef.markForCheck();\n });\n }\n }\n\n /**\n * Updates the view whether pagination should be enabled or not.\n *\n * WARNING: Calling this method can be very costly in terms of performance. It should be called\n * as infrequently as possible from outside of the Tabs component as it causes a reflow of the\n * page.\n */\n updatePagination() {\n this._checkPaginationEnabled();\n this._checkScrollingControls();\n this._updateTabScrollPosition();\n }\n\n /** Tracks which element has focus; used for keyboard navigation */\n get focusIndex(): number {\n return this._keyManager ? this._keyManager.activeItemIndex! : 0;\n }\n\n /** When the focus index is set, we must manually send focus to the correct label */\n set focusIndex(value: number) {\n if (\n !this._isValidIndex(value) ||\n this.focusIndex === value ||\n !this._keyManager\n ) {\n return;\n }\n\n this._keyManager.setActiveItem(value);\n }\n\n /**\n * Determines if an index is valid. If the tabs are not ready yet, we assume that the user is\n * providing a valid index and return true.\n */\n _isValidIndex(index: number): boolean {\n return this._items ? !!this._items.toArray()[index] : true;\n }\n\n /**\n * Sets focus on the HTML element for the label wrapper and scrolls it into the view if\n * scrolling is enabled.\n */\n _setTabFocus(tabIndex: number) {\n if (this._showPaginationControls) {\n this._scrollToLabel(tabIndex);\n }\n\n if (this._items && this._items.length) {\n this._items.toArray()[tabIndex].focus();\n\n // Do not let the browser manage scrolling to focus the element, this will be handled\n // by using translation. In LTR, the scroll left should be 0. In RTL, the scroll width\n // should be the full width minus the offset width.\n const containerEl = this._tabListContainer.nativeElement;\n const dir = this._getLayoutDirection();\n\n if (dir == 'ltr') {\n containerEl.scrollLeft = 0;\n } else {\n containerEl.scrollLeft =\n containerEl.scrollWidth - containerEl.offsetWidth;\n }\n }\n }\n\n /** The layout direction of the containing app. */\n _getLayoutDirection(): Direction {\n return this._dir && this._dir.value === 'rtl' ? 'rtl' : 'ltr';\n }\n\n /** Performs the CSS transformation on the tab list that will cause the list to scroll. */\n _updateTabScrollPosition() {\n if (this.disablePagination) {\n return;\n }\n\n const scrollDistance = this.scrollDistance;\n const translateX =\n this._getLayoutDirection() === 'ltr' ? -scrollDistance : scrollDistance;\n\n // Don't use `translate3d` here because we don't want to create a new layer. A new layer\n // seems to cause flickering and overflow in Internet Explorer. For example, the ink bar\n // and ripples will exceed the boundaries of the visible tab bar.\n // See: https://github.com/angular/components/issues/10276\n // We round the `transform` here, because transforms with sub-pixel precision cause some\n // browsers to blur the content of the element.\n this._tabList.nativeElement.style.transform = `translateX(${Math.round(\n translateX\n )}px)`;\n\n // Setting the `transform` on IE will change the scroll offset of the parent, causing the\n // position to be thrown off in some cases. We have to reset it ourselves to ensure that\n // it doesn't get thrown off. Note that we scope it only to IE and Edge, because messing\n // with the scroll position throws off Chrome 71+ in RTL mode (see #14689).\n if (this._platform.TRIDENT || this._platform.EDGE) {\n this._tabListContainer.nativeElement.scrollLeft = 0;\n }\n }\n\n /** Sets the distance in pixels that the tab header should be transformed in the X-axis. */\n get scrollDistance(): number {\n return this._scrollDistance;\n }\n set scrollDistance(value: number) {\n this._scrollTo(value);\n }\n\n /**\n * Moves the tab list in the 'before' or 'after' direction (towards the beginning of the list or\n * the end of the list, respectively). The distance to scroll is computed to be a third of the\n * length of the tab list view window.\n *\n * This is an expensive call that forces a layout reflow to compute box and scroll metrics and\n * should be called sparingly.\n */\n _scrollHeader(direction: ScrollDirection) {\n const viewLength = this._tabListContainer.nativeElement.offsetWidth;\n\n // Move the scroll distance one-third the length of the tab list's viewport.\n const scrollAmount = ((direction == 'before' ? -1 : 1) * viewLength) / 3;\n\n return this._scrollTo(this._scrollDistance + scrollAmount);\n }\n\n /** Handles click events on the pagination arrows. */\n _handlePaginatorClick(direction: ScrollDirection) {\n this._stopInterval();\n this._scrollHeader(direction);\n }\n\n /**\n * Moves the tab list such that the desired tab label (marked by index) is moved into view.\n *\n * This is an expensive call that forces a layout reflow to compute box and scroll metrics and\n * should be called sparingly.\n */\n _scrollToLabel(labelIndex: number) {\n if (this.disablePagination) {\n return;\n }\n\n const selectedLabel = this._items\n ? this._items.toArray()[labelIndex]\n : null;\n\n if (!selectedLabel) {\n return;\n }\n\n // The view length is the visible width of the tab labels.\n const viewLength = this._tabListContainer.nativeElement.offsetWidth;\n const { offsetLeft, offsetWidth } = selectedLabel.elementRef.nativeElement;\n\n let labelBeforePos: number, labelAfterPos: number;\n if (this._getLayoutDirection() == 'ltr') {\n labelBeforePos = offsetLeft;\n // eslint-disable-next-line @typescript-eslint/restrict-plus-operands\n labelAfterPos = labelBeforePos + offsetWidth;\n } else {\n labelAfterPos = this._tabListInner.nativeElement.offsetWidth - offsetLeft;\n labelBeforePos = labelAfterPos - offsetWidth;\n }\n\n const beforeVisiblePos = this.scrollDistance;\n const afterVisiblePos = this.scrollDistance + viewLength;\n\n if (labelBeforePos < beforeVisiblePos) {\n // Scroll header to move label to the before direction\n this.scrollDistance -= beforeVisiblePos - labelBeforePos;\n } else if (labelAfterPos > afterVisiblePos) {\n // Scroll header to move label to the after direction\n this.scrollDistance += Math.min(\n labelAfterPos - afterVisiblePos,\n labelBeforePos - beforeVisiblePos\n );\n }\n }\n\n /**\n * Evaluate whether the pagination controls should be displayed. If the scroll width of the\n * tab list is wider than the size of the header container, then the pagination controls should\n * be shown.\n *\n * This is an expensive call that forces a layout reflow to compute box and scroll metrics and\n * should be called sparingly.\n */\n _checkPaginationEnabled() {\n if (this.disablePagination) {\n this._showPaginationControls = false;\n } else {\n const isEnabled =\n this._tabListInner.nativeElement.scrollWidth >\n this._elementRef.nativeElement.offsetWidth;\n\n if (!isEnabled) {\n this.scrollDistance = 0;\n }\n\n if (isEnabled !== this._showPaginationControls) {\n this._changeDetectorRef.markForCheck();\n }\n\n this._showPaginationControls = isEnabled;\n }\n }\n\n /**\n * Evaluate whether the before and after controls should be enabled or disabled.\n * If the header is at the beginning of the list (scroll distance is equal to 0) then disable the\n * before button. If the header is at the end of the list (scroll distance is equal to the\n * maximum distance we can scroll), then disable the after button.\n *\n * This is an expensive call that forces a layout reflow to compute box and scroll metrics and\n * should be called sparingly.\n */\n _checkScrollingControls() {\n if (this.disablePagination) {\n this._disableScrollAfter = this._disableScrollBefore = true;\n } else {\n // Check if the pagination arrows should be activated.\n this._disableScrollBefore = this.scrollDistance == 0;\n this._disableScrollAfter =\n this.scrollDistance == this._getMaxScrollDistance();\n this._changeDetectorRef.markForCheck();\n }\n }\n\n /**\n * Determines what is the maximum length in pixels that can be set for the scroll distance. This\n * is equal to the difference in width between the tab list container and tab header container.\n *\n * This is an expensive call that forces a layout reflow to compute box and scroll metrics and\n * should be called sparingly.\n */\n _getMaxScrollDistance(): number {\n const lengthOfTabList = this._tabListInner.nativeElement.scrollWidth;\n const viewLength = this._tabListContainer.nativeElement.offsetWidth;\n return lengthOfTabList - viewLength || 0;\n }\n\n /** Tells the ink-bar to align itself to the current label wrapper */\n _alignInkBarToSelectedTab(): void {\n const selectedItem =\n this._items && this._items.length\n ? this._items.toArray()[this.selectedIndex]\n : null;\n const selectedLabelWrapper = selectedItem\n ? selectedItem.elementRef.nativeElement\n : null;\n\n if (selectedLabelWrapper) {\n // eslint-disable-next-line @typescript-eslint/no-unsafe-argument\n this._inkBar.alignToElement(selectedLabelWrapper);\n } else {\n this._inkBar.hide();\n }\n }\n\n /** Stops the currently-running paginator interval. */\n _stopInterval() {\n this._stopScrolling.next();\n }\n\n /**\n * Handles the user pressing down on one of the paginators.\n * Starts scrolling the header after a certain amount of time.\n * @param direction In which direction the paginator should be scrolled.\n */\n _handlePaginatorPress(direction: ScrollDirection, mouseEvent?: MouseEvent) {\n // Don't start auto scrolling for right mouse button clicks. Note that we shouldn't have to\n // null check the `button`, but we do it so we don't break tests that use fake events.\n if (mouseEvent && mouseEvent.button != null && mouseEvent.button !== 0) {\n return;\n }\n\n // Avoid overlapping timers.\n this._stopInterval();\n\n // Start a timer after the delay and keep firing based on the interval.\n timer(HEADER_SCROLL_DELAY, HEADER_SCROLL_INTERVAL)\n // Keep the timer going until something tells it to stop or the component is destroyed.\n .pipe(takeUntil(merge(this._stopScrolling, this._destroyed)))\n .subscribe(() => {\n const { maxScrollDistance, distance } = this._scrollHeader(direction);\n\n // Stop the timer if we've reached the start or the end.\n if (distance === 0 || distance >= maxScrollDistance) {\n this._stopInterval();\n }\n });\n }\n\n /**\n * Scrolls the header to a given position.\n * @param position Position to which to scroll.\n * @returns Information on the current scroll distance and the maximum.\n */\n private _scrollTo(position: number) {\n if (this.disablePagination) {\n return { maxScrollDistance: 0, distance: 0 };\n }\n\n const maxScrollDistance = this._getMaxScrollDistance();\n this._scrollDistance = Math.max(0, Math.min(maxScrollDistance, position));\n\n // Mark that the scroll distance has changed so that after the view is checked, the CSS\n // transformation can move the header.\n this._scrollDistanceChanged = true;\n this._checkScrollingControls();\n\n return { maxScrollDistance, distance: this._scrollDistance };\n }\n}\n", + "sourceCode": "import {\r\n ChangeDetectorRef,\r\n ElementRef,\r\n NgZone,\r\n Optional,\r\n QueryList,\r\n EventEmitter,\r\n AfterContentChecked,\r\n AfterContentInit,\r\n AfterViewInit,\r\n OnDestroy,\r\n Directive,\r\n Inject,\r\n Input,\r\n} from '@angular/core';\r\nimport { Direction, Directionality } from '@angular/cdk/bidi';\r\nimport {\r\n BooleanInput,\r\n coerceBooleanProperty,\r\n coerceNumberProperty,\r\n NumberInput,\r\n} from '@angular/cdk/coercion';\r\nimport { ViewportRuler } from '@angular/cdk/scrolling';\r\nimport { FocusKeyManager, FocusableOption } from '@angular/cdk/a11y';\r\nimport { ENTER, SPACE, hasModifierKey } from '@angular/cdk/keycodes';\r\nimport {\r\n merge,\r\n of as observableOf,\r\n Subject,\r\n EMPTY,\r\n Observer,\r\n Observable,\r\n timer,\r\n fromEvent,\r\n} from 'rxjs';\r\nimport {\r\n take,\r\n switchMap,\r\n startWith,\r\n skip,\r\n takeUntil,\r\n filter,\r\n} from 'rxjs/operators';\r\nimport {\r\n Platform,\r\n normalizePassiveListenerOptions,\r\n} from '@angular/cdk/platform';\r\nimport { ANIMATION_MODULE_TYPE } from '@angular/platform-browser/animations';\r\n\r\n/** Config used to bind passive event listeners */\r\nconst passiveEventListenerOptions = normalizePassiveListenerOptions({\r\n passive: true,\r\n}) as EventListenerOptions;\r\n\r\n/**\r\n * The directions that scrolling can go in when the header's tabs exceed the header width. 'After'\r\n * will scroll the header towards the end of the tabs list and 'before' will scroll towards the\r\n * beginning of the list.\r\n */\r\nexport type ScrollDirection = 'after' | 'before';\r\n\r\n/**\r\n * Amount of milliseconds to wait before starting to scroll the header automatically.\r\n * Set a little conservatively in order to handle fake events dispatched on touch devices.\r\n */\r\nconst HEADER_SCROLL_DELAY = 650;\r\n\r\n/**\r\n * Interval in milliseconds at which to scroll the header\r\n * while the user is holding their pointer.\r\n */\r\nconst HEADER_SCROLL_INTERVAL = 100;\r\n\r\n/** Item inside a paginated tab header. */\r\nexport type MatPaginatedTabHeaderItem = FocusableOption & {\r\n elementRef: ElementRef;\r\n};\r\n\r\n/**\r\n * Base class for a tab header that supported pagination.\r\n * @docs-private\r\n */\r\n@Directive()\r\nexport abstract class OuiPaginatedTabHeader\r\n implements AfterContentChecked, AfterContentInit, AfterViewInit, OnDestroy\r\n{\r\n abstract _items: QueryList;\r\n abstract _inkBar: {\r\n hide: () => void;\r\n alignToElement: (element: HTMLElement) => void;\r\n };\r\n abstract _tabListContainer: ElementRef;\r\n abstract _tabList: ElementRef;\r\n abstract _tabListInner: ElementRef;\r\n abstract _nextPaginator: ElementRef;\r\n abstract _previousPaginator: ElementRef;\r\n\r\n /** The distance in pixels that the tab labels should be translated to the left. */\r\n private _scrollDistance = 0;\r\n\r\n /** Whether the header should scroll to the selected index after the view has been checked. */\r\n private _selectedIndexChanged = false;\r\n\r\n /** Emits when the component is destroyed. */\r\n protected readonly _destroyed = new Subject();\r\n\r\n /** Whether the controls for pagination should be displayed */\r\n _showPaginationControls = false;\r\n\r\n /** Whether the tab list can be scrolled more towards the end of the tab label list. */\r\n _disableScrollAfter = true;\r\n\r\n /** Whether the tab list can be scrolled more towards the beginning of the tab label list. */\r\n _disableScrollBefore = true;\r\n\r\n /**\r\n * The number of tab labels that are displayed on the header. When this changes, the header\r\n * should re-evaluate the scroll position.\r\n */\r\n private _tabLabelCount: number;\r\n\r\n /** Whether the scroll distance has changed and should be applied after the view is checked. */\r\n private _scrollDistanceChanged: boolean;\r\n\r\n /** Used to manage focus between the tabs. */\r\n private _keyManager: FocusKeyManager;\r\n\r\n /** Cached text content of the header. */\r\n private _currentTextContent: string;\r\n\r\n /** Stream that will stop the automated scrolling. */\r\n private _stopScrolling = new Subject();\r\n\r\n /**\r\n * Whether pagination should be disabled. This can be used to avoid unnecessary\r\n * layout recalculations if it's known that pagination won't be required.\r\n */\r\n @Input()\r\n get disablePagination(): boolean {\r\n return this._disablePagination;\r\n }\r\n set disablePagination(value: BooleanInput) {\r\n this._disablePagination = coerceBooleanProperty(value);\r\n }\r\n private _disablePagination = false;\r\n\r\n /** The index of the active tab. */\r\n get selectedIndex(): number {\r\n return this._selectedIndex;\r\n }\r\n set selectedIndex(value: NumberInput) {\r\n value = coerceNumberProperty(value);\r\n\r\n if (this._selectedIndex != value) {\r\n this._selectedIndexChanged = true;\r\n this._selectedIndex = value;\r\n\r\n if (this._keyManager) {\r\n this._keyManager.updateActiveItem(value);\r\n }\r\n }\r\n }\r\n private _selectedIndex = 0;\r\n\r\n /** Event emitted when the option is selected. */\r\n readonly selectFocusedIndex: EventEmitter =\r\n new EventEmitter();\r\n\r\n /** Event emitted when a label is focused. */\r\n readonly indexFocused: EventEmitter = new EventEmitter();\r\n\r\n constructor(\r\n protected _elementRef: ElementRef,\r\n protected _changeDetectorRef: ChangeDetectorRef,\r\n private _viewportRuler: ViewportRuler,\r\n @Optional() private _dir: Directionality,\r\n private _ngZone: NgZone,\r\n private _platform: Platform,\r\n @Optional() @Inject(ANIMATION_MODULE_TYPE) public _animationMode?: string\r\n ) {\r\n // Bind the `mouseleave` event on the outside since it doesn't change anything in the view.\r\n _ngZone.runOutsideAngular(() => {\r\n fromEvent(_elementRef.nativeElement, 'mouseleave')\r\n .pipe(takeUntil(this._destroyed))\r\n .subscribe(() => {\r\n this._stopInterval();\r\n });\r\n });\r\n }\r\n\r\n /** Called when the user has selected an item via the keyboard. */\r\n protected abstract _itemSelected(event: KeyboardEvent): void;\r\n\r\n ngAfterViewInit() {\r\n // We need to handle these events manually, because we want to bind passive event listeners.\r\n fromEvent(\r\n this._previousPaginator.nativeElement,\r\n 'touchstart',\r\n passiveEventListenerOptions\r\n )\r\n .pipe(takeUntil(this._destroyed))\r\n .subscribe(() => {\r\n this._handlePaginatorPress('before');\r\n });\r\n\r\n fromEvent(\r\n this._nextPaginator.nativeElement,\r\n 'touchstart',\r\n passiveEventListenerOptions\r\n )\r\n .pipe(takeUntil(this._destroyed))\r\n .subscribe(() => {\r\n this._handlePaginatorPress('after');\r\n });\r\n }\r\n\r\n ngAfterContentInit() {\r\n const dirChange = this._dir ? this._dir.change : observableOf('ltr');\r\n const resize = this._viewportRuler.change(150);\r\n const realign = () => {\r\n this.updatePagination();\r\n this._alignInkBarToSelectedTab();\r\n };\r\n\r\n this._keyManager = new FocusKeyManager(\r\n this._items\r\n )\r\n .withHorizontalOrientation(this._getLayoutDirection())\r\n .withHomeAndEnd()\r\n .withWrap()\r\n // Allow focus to land on disabled tabs, as per https://w3c.github.io/aria-practices/#kbd_disabled_controls\r\n .skipPredicate(() => false);\r\n\r\n this._keyManager.updateActiveItem(this._selectedIndex);\r\n\r\n // Defer the first call in order to allow for slower browsers to lay out the elements.\r\n // This helps in cases where the user lands directly on a page with paginated tabs.\r\n // Note that we use `onStable` instead of `requestAnimationFrame`, because the latter\r\n // can hold up tests that are in a background tab.\r\n this._ngZone.onStable.pipe(take(1)).subscribe(realign);\r\n\r\n // On dir change or window resize, realign the ink bar and update the orientation of\r\n // the key manager if the direction has changed.\r\n merge(dirChange, resize, this._items.changes, this._itemsResized())\r\n .pipe(takeUntil(this._destroyed))\r\n .subscribe(() => {\r\n // We need to defer this to give the browser some time to recalculate\r\n // the element dimensions. The call has to be wrapped in `NgZone.run`,\r\n // because the viewport change handler runs outside of Angular.\r\n this._ngZone.run(() => {\r\n Promise.resolve().then(() => {\r\n // Clamp the scroll distance, because it can change with the number of tabs.\r\n this._scrollDistance = Math.max(\r\n 0,\r\n Math.min(this._getMaxScrollDistance(), this._scrollDistance)\r\n );\r\n realign();\r\n });\r\n });\r\n this._keyManager.withHorizontalOrientation(this._getLayoutDirection());\r\n });\r\n\r\n // If there is a change in the focus key manager we need to emit the `indexFocused`\r\n // event in order to provide a public event that notifies about focus changes. Also we realign\r\n // the tabs container by scrolling the new focused tab into the visible section.\r\n this._keyManager.change.subscribe((newFocusIndex) => {\r\n this.indexFocused.emit(newFocusIndex);\r\n this._setTabFocus(newFocusIndex);\r\n });\r\n }\r\n\r\n /** Sends any changes that could affect the layout of the items. */\r\n private _itemsResized(): Observable {\r\n if (typeof ResizeObserver !== 'function') {\r\n return EMPTY;\r\n }\r\n\r\n return this._items.changes.pipe(\r\n startWith(this._items),\r\n switchMap(\r\n (tabItems: QueryList) =>\r\n new Observable((observer: Observer) =>\r\n this._ngZone.runOutsideAngular(() => {\r\n const resizeObserver = new ResizeObserver((entries) =>\r\n observer.next(entries)\r\n );\r\n tabItems.forEach(\r\n (\r\n item // eslint-disable-next-line @typescript-eslint/no-unsafe-argument\r\n ) => resizeObserver.observe(item.elementRef.nativeElement)\r\n );\r\n return () => {\r\n resizeObserver.disconnect();\r\n };\r\n })\r\n )\r\n ),\r\n // Skip the first emit since the resize observer emits when an item\r\n // is observed for new items when the tab is already inserted\r\n skip(1),\r\n // Skip emissions where all the elements are invisible since we don't want\r\n // the header to try and re-render with invalid measurements. See #25574.\r\n filter((entries) =>\r\n entries.some((e) => e.contentRect.width > 0 && e.contentRect.height > 0)\r\n )\r\n );\r\n }\r\n\r\n ngAfterContentChecked(): void {\r\n // If the number of tab labels have changed, check if scrolling should be enabled\r\n if (this._tabLabelCount != this._items.length) {\r\n this.updatePagination();\r\n this._tabLabelCount = this._items.length;\r\n this._changeDetectorRef.markForCheck();\r\n }\r\n\r\n // If the selected index has changed, scroll to the label and check if the scrolling controls\r\n // should be disabled.\r\n if (this._selectedIndexChanged) {\r\n this._scrollToLabel(this._selectedIndex);\r\n this._checkScrollingControls();\r\n this._alignInkBarToSelectedTab();\r\n this._selectedIndexChanged = false;\r\n this._changeDetectorRef.markForCheck();\r\n }\r\n\r\n // If the scroll distance has been changed (tab selected, focused, scroll controls activated),\r\n // then translate the header to reflect this.\r\n if (this._scrollDistanceChanged) {\r\n this._updateTabScrollPosition();\r\n this._scrollDistanceChanged = false;\r\n this._changeDetectorRef.markForCheck();\r\n }\r\n }\r\n\r\n ngOnDestroy() {\r\n // this._keyManager?.destroy();\r\n this._destroyed.next();\r\n this._destroyed.complete();\r\n this._stopScrolling.complete();\r\n }\r\n\r\n /** Handles keyboard events on the header. */\r\n _handleKeydown(event: KeyboardEvent) {\r\n // We don't handle any key bindings with a modifier key.\r\n if (hasModifierKey(event)) {\r\n return;\r\n }\r\n\r\n switch (event.keyCode) {\r\n case ENTER:\r\n case SPACE:\r\n if (this.focusIndex !== this.selectedIndex) {\r\n const item = this._items.get(this.focusIndex);\r\n\r\n if (item && !item.disabled) {\r\n this.selectFocusedIndex.emit(this.focusIndex);\r\n this._itemSelected(event);\r\n }\r\n }\r\n break;\r\n default:\r\n this._keyManager.onKeydown(event);\r\n }\r\n }\r\n\r\n /**\r\n * Callback for when the MutationObserver detects that the content has changed.\r\n */\r\n _onContentChanges() {\r\n const textContent = this._elementRef.nativeElement.textContent;\r\n\r\n // We need to diff the text content of the header, because the MutationObserver callback\r\n // will fire even if the text content didn't change which is inefficient and is prone\r\n // to infinite loops if a poorly constructed expression is passed in (see #14249).\r\n if (textContent !== this._currentTextContent) {\r\n this._currentTextContent = textContent || '';\r\n\r\n // The content observer runs outside the `NgZone` by default, which\r\n // means that we need to bring the callback back in ourselves.\r\n this._ngZone.run(() => {\r\n this.updatePagination();\r\n this._alignInkBarToSelectedTab();\r\n this._changeDetectorRef.markForCheck();\r\n });\r\n }\r\n }\r\n\r\n /**\r\n * Updates the view whether pagination should be enabled or not.\r\n *\r\n * WARNING: Calling this method can be very costly in terms of performance. It should be called\r\n * as infrequently as possible from outside of the Tabs component as it causes a reflow of the\r\n * page.\r\n */\r\n updatePagination() {\r\n this._checkPaginationEnabled();\r\n this._checkScrollingControls();\r\n this._updateTabScrollPosition();\r\n }\r\n\r\n /** Tracks which element has focus; used for keyboard navigation */\r\n get focusIndex(): number {\r\n return this._keyManager ? this._keyManager.activeItemIndex! : 0;\r\n }\r\n\r\n /** When the focus index is set, we must manually send focus to the correct label */\r\n set focusIndex(value: number) {\r\n if (\r\n !this._isValidIndex(value) ||\r\n this.focusIndex === value ||\r\n !this._keyManager\r\n ) {\r\n return;\r\n }\r\n\r\n this._keyManager.setActiveItem(value);\r\n }\r\n\r\n /**\r\n * Determines if an index is valid. If the tabs are not ready yet, we assume that the user is\r\n * providing a valid index and return true.\r\n */\r\n _isValidIndex(index: number): boolean {\r\n return this._items ? !!this._items.toArray()[index] : true;\r\n }\r\n\r\n /**\r\n * Sets focus on the HTML element for the label wrapper and scrolls it into the view if\r\n * scrolling is enabled.\r\n */\r\n _setTabFocus(tabIndex: number) {\r\n if (this._showPaginationControls) {\r\n this._scrollToLabel(tabIndex);\r\n }\r\n\r\n if (this._items && this._items.length) {\r\n this._items.toArray()[tabIndex].focus();\r\n\r\n // Do not let the browser manage scrolling to focus the element, this will be handled\r\n // by using translation. In LTR, the scroll left should be 0. In RTL, the scroll width\r\n // should be the full width minus the offset width.\r\n const containerEl = this._tabListContainer.nativeElement;\r\n const dir = this._getLayoutDirection();\r\n\r\n if (dir == 'ltr') {\r\n containerEl.scrollLeft = 0;\r\n } else {\r\n containerEl.scrollLeft =\r\n containerEl.scrollWidth - containerEl.offsetWidth;\r\n }\r\n }\r\n }\r\n\r\n /** The layout direction of the containing app. */\r\n _getLayoutDirection(): Direction {\r\n return this._dir && this._dir.value === 'rtl' ? 'rtl' : 'ltr';\r\n }\r\n\r\n /** Performs the CSS transformation on the tab list that will cause the list to scroll. */\r\n _updateTabScrollPosition() {\r\n if (this.disablePagination) {\r\n return;\r\n }\r\n\r\n const scrollDistance = this.scrollDistance;\r\n const translateX =\r\n this._getLayoutDirection() === 'ltr' ? -scrollDistance : scrollDistance;\r\n\r\n // Don't use `translate3d` here because we don't want to create a new layer. A new layer\r\n // seems to cause flickering and overflow in Internet Explorer. For example, the ink bar\r\n // and ripples will exceed the boundaries of the visible tab bar.\r\n // See: https://github.com/angular/components/issues/10276\r\n // We round the `transform` here, because transforms with sub-pixel precision cause some\r\n // browsers to blur the content of the element.\r\n this._tabList.nativeElement.style.transform = `translateX(${Math.round(\r\n translateX\r\n )}px)`;\r\n\r\n // Setting the `transform` on IE will change the scroll offset of the parent, causing the\r\n // position to be thrown off in some cases. We have to reset it ourselves to ensure that\r\n // it doesn't get thrown off. Note that we scope it only to IE and Edge, because messing\r\n // with the scroll position throws off Chrome 71+ in RTL mode (see #14689).\r\n if (this._platform.TRIDENT || this._platform.EDGE) {\r\n this._tabListContainer.nativeElement.scrollLeft = 0;\r\n }\r\n }\r\n\r\n /** Sets the distance in pixels that the tab header should be transformed in the X-axis. */\r\n get scrollDistance(): number {\r\n return this._scrollDistance;\r\n }\r\n set scrollDistance(value: number) {\r\n this._scrollTo(value);\r\n }\r\n\r\n /**\r\n * Moves the tab list in the 'before' or 'after' direction (towards the beginning of the list or\r\n * the end of the list, respectively). The distance to scroll is computed to be a third of the\r\n * length of the tab list view window.\r\n *\r\n * This is an expensive call that forces a layout reflow to compute box and scroll metrics and\r\n * should be called sparingly.\r\n */\r\n _scrollHeader(direction: ScrollDirection) {\r\n const viewLength = this._tabListContainer.nativeElement.offsetWidth;\r\n\r\n // Move the scroll distance one-third the length of the tab list's viewport.\r\n const scrollAmount = ((direction == 'before' ? -1 : 1) * viewLength) / 3;\r\n\r\n return this._scrollTo(this._scrollDistance + scrollAmount);\r\n }\r\n\r\n /** Handles click events on the pagination arrows. */\r\n _handlePaginatorClick(direction: ScrollDirection) {\r\n this._stopInterval();\r\n this._scrollHeader(direction);\r\n }\r\n\r\n /**\r\n * Moves the tab list such that the desired tab label (marked by index) is moved into view.\r\n *\r\n * This is an expensive call that forces a layout reflow to compute box and scroll metrics and\r\n * should be called sparingly.\r\n */\r\n _scrollToLabel(labelIndex: number) {\r\n if (this.disablePagination) {\r\n return;\r\n }\r\n\r\n const selectedLabel = this._items\r\n ? this._items.toArray()[labelIndex]\r\n : null;\r\n\r\n if (!selectedLabel) {\r\n return;\r\n }\r\n\r\n // The view length is the visible width of the tab labels.\r\n const viewLength = this._tabListContainer.nativeElement.offsetWidth;\r\n const { offsetLeft, offsetWidth } = selectedLabel.elementRef.nativeElement;\r\n\r\n let labelBeforePos: number, labelAfterPos: number;\r\n if (this._getLayoutDirection() == 'ltr') {\r\n labelBeforePos = offsetLeft;\r\n // eslint-disable-next-line @typescript-eslint/restrict-plus-operands\r\n labelAfterPos = labelBeforePos + offsetWidth;\r\n } else {\r\n labelAfterPos = this._tabListInner.nativeElement.offsetWidth - offsetLeft;\r\n labelBeforePos = labelAfterPos - offsetWidth;\r\n }\r\n\r\n const beforeVisiblePos = this.scrollDistance;\r\n const afterVisiblePos = this.scrollDistance + viewLength;\r\n\r\n if (labelBeforePos < beforeVisiblePos) {\r\n // Scroll header to move label to the before direction\r\n this.scrollDistance -= beforeVisiblePos - labelBeforePos;\r\n } else if (labelAfterPos > afterVisiblePos) {\r\n // Scroll header to move label to the after direction\r\n this.scrollDistance += Math.min(\r\n labelAfterPos - afterVisiblePos,\r\n labelBeforePos - beforeVisiblePos\r\n );\r\n }\r\n }\r\n\r\n /**\r\n * Evaluate whether the pagination controls should be displayed. If the scroll width of the\r\n * tab list is wider than the size of the header container, then the pagination controls should\r\n * be shown.\r\n *\r\n * This is an expensive call that forces a layout reflow to compute box and scroll metrics and\r\n * should be called sparingly.\r\n */\r\n _checkPaginationEnabled() {\r\n if (this.disablePagination) {\r\n this._showPaginationControls = false;\r\n } else {\r\n const isEnabled =\r\n this._tabListInner.nativeElement.scrollWidth >\r\n this._elementRef.nativeElement.offsetWidth;\r\n\r\n if (!isEnabled) {\r\n this.scrollDistance = 0;\r\n }\r\n\r\n if (isEnabled !== this._showPaginationControls) {\r\n this._changeDetectorRef.markForCheck();\r\n }\r\n\r\n this._showPaginationControls = isEnabled;\r\n }\r\n }\r\n\r\n /**\r\n * Evaluate whether the before and after controls should be enabled or disabled.\r\n * If the header is at the beginning of the list (scroll distance is equal to 0) then disable the\r\n * before button. If the header is at the end of the list (scroll distance is equal to the\r\n * maximum distance we can scroll), then disable the after button.\r\n *\r\n * This is an expensive call that forces a layout reflow to compute box and scroll metrics and\r\n * should be called sparingly.\r\n */\r\n _checkScrollingControls() {\r\n if (this.disablePagination) {\r\n this._disableScrollAfter = this._disableScrollBefore = true;\r\n } else {\r\n // Check if the pagination arrows should be activated.\r\n this._disableScrollBefore = this.scrollDistance == 0;\r\n this._disableScrollAfter =\r\n this.scrollDistance == this._getMaxScrollDistance();\r\n this._changeDetectorRef.markForCheck();\r\n }\r\n }\r\n\r\n /**\r\n * Determines what is the maximum length in pixels that can be set for the scroll distance. This\r\n * is equal to the difference in width between the tab list container and tab header container.\r\n *\r\n * This is an expensive call that forces a layout reflow to compute box and scroll metrics and\r\n * should be called sparingly.\r\n */\r\n _getMaxScrollDistance(): number {\r\n const lengthOfTabList = this._tabListInner.nativeElement.scrollWidth;\r\n const viewLength = this._tabListContainer.nativeElement.offsetWidth;\r\n return lengthOfTabList - viewLength || 0;\r\n }\r\n\r\n /** Tells the ink-bar to align itself to the current label wrapper */\r\n _alignInkBarToSelectedTab(): void {\r\n const selectedItem =\r\n this._items && this._items.length\r\n ? this._items.toArray()[this.selectedIndex]\r\n : null;\r\n const selectedLabelWrapper = selectedItem\r\n ? selectedItem.elementRef.nativeElement\r\n : null;\r\n\r\n if (selectedLabelWrapper) {\r\n // eslint-disable-next-line @typescript-eslint/no-unsafe-argument\r\n this._inkBar.alignToElement(selectedLabelWrapper);\r\n } else {\r\n this._inkBar.hide();\r\n }\r\n }\r\n\r\n /** Stops the currently-running paginator interval. */\r\n _stopInterval() {\r\n this._stopScrolling.next();\r\n }\r\n\r\n /**\r\n * Handles the user pressing down on one of the paginators.\r\n * Starts scrolling the header after a certain amount of time.\r\n * @param direction In which direction the paginator should be scrolled.\r\n */\r\n _handlePaginatorPress(direction: ScrollDirection, mouseEvent?: MouseEvent) {\r\n // Don't start auto scrolling for right mouse button clicks. Note that we shouldn't have to\r\n // null check the `button`, but we do it so we don't break tests that use fake events.\r\n if (mouseEvent && mouseEvent.button != null && mouseEvent.button !== 0) {\r\n return;\r\n }\r\n\r\n // Avoid overlapping timers.\r\n this._stopInterval();\r\n\r\n // Start a timer after the delay and keep firing based on the interval.\r\n timer(HEADER_SCROLL_DELAY, HEADER_SCROLL_INTERVAL)\r\n // Keep the timer going until something tells it to stop or the component is destroyed.\r\n .pipe(takeUntil(merge(this._stopScrolling, this._destroyed)))\r\n .subscribe(() => {\r\n const { maxScrollDistance, distance } = this._scrollHeader(direction);\r\n\r\n // Stop the timer if we've reached the start or the end.\r\n if (distance === 0 || distance >= maxScrollDistance) {\r\n this._stopInterval();\r\n }\r\n });\r\n }\r\n\r\n /**\r\n * Scrolls the header to a given position.\r\n * @param position Position to which to scroll.\r\n * @returns Information on the current scroll distance and the maximum.\r\n */\r\n private _scrollTo(position: number) {\r\n if (this.disablePagination) {\r\n return { maxScrollDistance: 0, distance: 0 };\r\n }\r\n\r\n const maxScrollDistance = this._getMaxScrollDistance();\r\n this._scrollDistance = Math.max(0, Math.min(maxScrollDistance, position));\r\n\r\n // Mark that the scroll distance has changed so that after the view is checked, the CSS\r\n // transformation can move the header.\r\n this._scrollDistanceChanged = true;\r\n this._checkScrollingControls();\r\n\r\n return { maxScrollDistance, distance: this._scrollDistance };\r\n }\r\n}\r\n", "providers": [], + "hostDirectives": [], + "standalone": false, "inputsClass": [ { "name": "disablePagination", @@ -17121,7 +17325,9 @@ } ], "modifierKind": [ - 123 + 170, + 170, + 125 ] }, { @@ -17134,7 +17340,7 @@ "line": 137, "rawdescription": "\nCached text content of the header.", "modifierKind": [ - 121 + 123 ] }, { @@ -17148,8 +17354,8 @@ "line": 113, "rawdescription": "\nEmits when the component is destroyed.", "modifierKind": [ - 122, - 144 + 124, + 148 ] }, { @@ -17162,7 +17368,7 @@ "description": "", "line": 153, "modifierKind": [ - 121 + 123 ] }, { @@ -17196,7 +17402,7 @@ "description": "", "line": 96, "modifierKind": [ - 126 + 128 ] }, { @@ -17208,7 +17414,7 @@ "description": "", "line": 95, "modifierKind": [ - 126 + 128 ] }, { @@ -17221,7 +17427,7 @@ "line": 134, "rawdescription": "\nUsed to manage focus between the tabs.", "modifierKind": [ - 121 + 123 ] }, { @@ -17233,7 +17439,7 @@ "description": "", "line": 103, "modifierKind": [ - 126 + 128 ] }, { @@ -17245,7 +17451,7 @@ "description": "", "line": 104, "modifierKind": [ - 126 + 128 ] }, { @@ -17259,7 +17465,7 @@ "line": 107, "rawdescription": "\nThe distance in pixels that the tab labels should be translated to the left.", "modifierKind": [ - 121 + 123 ] }, { @@ -17272,7 +17478,7 @@ "line": 131, "rawdescription": "\nWhether the scroll distance has changed and should be applied after the view is checked.", "modifierKind": [ - 121 + 123 ] }, { @@ -17285,7 +17491,7 @@ "description": "", "line": 171, "modifierKind": [ - 121 + 123 ] }, { @@ -17299,7 +17505,7 @@ "line": 110, "rawdescription": "\nWhether the header should scroll to the selected index after the view has been checked.", "modifierKind": [ - 121 + 123 ] }, { @@ -17324,7 +17530,7 @@ "line": 140, "rawdescription": "\nStream that will stop the automated scrolling.", "modifierKind": [ - 121 + 123 ] }, { @@ -17337,7 +17543,7 @@ "line": 128, "rawdescription": "\n\nThe number of tab labels that are displayed on the header. When this changes, the header\nshould re-evaluate the scroll position.\n", "modifierKind": [ - 121 + 123 ] }, { @@ -17349,7 +17555,7 @@ "description": "", "line": 101, "modifierKind": [ - 126 + 128 ] }, { @@ -17361,7 +17567,7 @@ "description": "", "line": 100, "modifierKind": [ - 126 + 128 ] }, { @@ -17373,7 +17579,7 @@ "description": "", "line": 102, "modifierKind": [ - 126 + 128 ] }, { @@ -17387,7 +17593,7 @@ "line": 178, "rawdescription": "\nEvent emitted when a label is focused.", "modifierKind": [ - 144 + 148 ] }, { @@ -17401,7 +17607,7 @@ "line": 174, "rawdescription": "\nEvent emitted when the option is selected.", "modifierKind": [ - 144 + 148 ] } ], @@ -17554,24 +17760,24 @@ "jsdoctags": [ { "name": { - "pos": 22708, - "end": 22717, - "flags": 4227072, + "pos": 23371, + "end": 23380, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "direction" }, "type": "ScrollDirection", "deprecated": false, "deprecationMessage": "", "tagName": { - "pos": 22702, - "end": 22707, - "flags": 4227072, + "pos": 23365, + "end": 23370, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "param" }, "comment": "

In which direction the paginator should be scrolled.

\n" @@ -17637,8 +17843,8 @@ "rawdescription": "\nCalled when the user has selected an item via the keyboard.", "description": "

Called when the user has selected an item via the keyboard.

\n", "modifierKind": [ - 122, - 126 + 124, + 128 ], "jsdoctags": [ { @@ -17664,7 +17870,7 @@ "rawdescription": "\nSends any changes that could affect the layout of the items.", "description": "

Sends any changes that could affect the layout of the items.

\n", "modifierKind": [ - 121 + 123 ] }, { @@ -17728,41 +17934,41 @@ "rawdescription": "\n\nScrolls the header to a given position.\n", "description": "

Scrolls the header to a given position.

\n", "modifierKind": [ - 121 + 123 ], "jsdoctags": [ { "name": { - "pos": 23848, - "end": 23856, - "flags": 4227072, + "pos": 24539, + "end": 24547, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "position" }, "type": "number", "deprecated": false, "deprecationMessage": "", "tagName": { - "pos": 23842, - "end": 23847, - "flags": 4227072, + "pos": 24533, + "end": 24538, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "param" }, "comment": "

Position to which to scroll.

\n" }, { "tagName": { - "pos": 23892, - "end": 23899, - "flags": 4227072, + "pos": 24584, + "end": 24591, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "returns" }, "comment": "

Information on the current scroll distance and the maximum.

\n" @@ -17906,6 +18112,7 @@ "description": "

Updates the view whether pagination should be enabled or not.

\n

WARNING: Calling this method can be very costly in terms of performance. It should be called\nas infrequently as possible from outside of the Tabs component as it causes a reflow of the\npage.

\n" } ], + "extends": [], "implements": [ "AfterContentChecked", "AfterContentInit", @@ -18197,6 +18404,8 @@ "sourceCode": "import {\n Directive,\n TemplateRef,\n ComponentFactoryResolver,\n ApplicationRef,\n Injector,\n ViewContainerRef,\n Inject,\n OnDestroy,\n} from '@angular/core';\nimport { TemplatePortal, DomPortalOutlet } from '@angular/cdk/portal';\nimport { DOCUMENT } from '@angular/common';\nimport { Subject } from 'rxjs';\n\n/**\n * Panel content that will be rendered lazily once the panel is opened.\n */\n@Directive({\n selector: 'ng-template[ouiPanelContent]',\n})\nexport class OuiPanelContent implements OnDestroy {\n private _portal: TemplatePortal;\n private _outlet: DomPortalOutlet;\n\n /** Emits when the panel content has been attached. */\n _attached = new Subject();\n\n constructor(\n private _template: TemplateRef,\n private _componentFactoryResolver: ComponentFactoryResolver,\n private _appRef: ApplicationRef,\n private _injector: Injector,\n private _viewContainerRef: ViewContainerRef,\n @Inject(DOCUMENT) private _document: Document\n ) {}\n\n /**\n * Attaches the content with a particular context.\n */\n attach(context: any = {}) {\n if (!this._portal) {\n this._portal = new TemplatePortal(this._template, this._viewContainerRef);\n }\n\n this.detach();\n\n if (!this._outlet) {\n this._outlet = new DomPortalOutlet(\n this._document.createElement('div'),\n this._componentFactoryResolver,\n this._appRef,\n this._injector\n );\n }\n\n const element: HTMLElement = this._template.elementRef.nativeElement;\n\n // Because we support opening the same menu from different triggers (which in turn have their\n // own `OverlayRef` panel), we have to re-insert the host element every time, otherwise we\n // risk it staying attached to a pane that's no longer in the DOM.\n element.parentNode!.insertBefore(this._outlet.outletElement, element);\n this._portal.attach(this._outlet, context);\n this._attached.next();\n }\n\n /**\n * Detaches the content.\n */\n detach() {\n if (this._portal.isAttached) {\n this._portal.detach();\n }\n }\n\n ngOnDestroy() {\n if (this._outlet) {\n this._outlet.dispose();\n }\n }\n}\n", "selector": "ng-template[ouiPanelContent]", "providers": [], + "hostDirectives": [], + "standalone": false, "inputsClass": [], "outputsClass": [], "deprecated": false, @@ -18224,7 +18433,7 @@ "description": "", "line": 23, "modifierKind": [ - 121 + 123 ] }, { @@ -18236,7 +18445,7 @@ "description": "", "line": 22, "modifierKind": [ - 121 + 123 ] } ], @@ -18296,6 +18505,7 @@ "deprecationMessage": "" } ], + "extends": [], "implements": [ "OnDestroy" ], @@ -18403,14 +18613,17 @@ }, { "name": "OuiPanelTrigger", - "id": "directive-OuiPanelTrigger-917ed27a5eec90a7d92ed4c032cc1d1ea4d9e33b91f5447e8ff55302e0120c996222257a518f3e07b157d8564c97f0122cd6c6f4cf50ae23971ee90fd66686d2", + "id": "directive-OuiPanelTrigger-6f1fb3e0e0bb5b386c23c6c8cf2d965fbc76f5026dbd9ec534e8ce7279c52941431b43316d79f4428028b9392eaf96907b1a0359547ac852d83c5a69a7e68e95", "file": "ui/src/components/panel/panel-trigger.ts", "type": "directive", "description": "

This directive is intended to be used in conjunction with an oui-panel tag. It is\nresponsible for toggling the display of the provided panel instance.

\n", "rawdescription": "\n\nThis directive is intended to be used in conjunction with an oui-panel tag. It is\nresponsible for toggling the display of the provided panel instance.\n", - "sourceCode": "import {\n InjectionToken,\n Directive,\n OnDestroy,\n Input,\n Output,\n EventEmitter,\n ElementRef,\n ViewContainerRef,\n Inject,\n} from '@angular/core';\nimport {\n ScrollStrategy,\n Overlay,\n OverlayRef,\n FlexibleConnectedPositionStrategy,\n OverlayConfig,\n} from '@angular/cdk/overlay';\nimport { Subscription, Observable, Subject } from 'rxjs';\nimport { TemplatePortal } from '@angular/cdk/portal';\nimport { OuiPanelOverlay } from './panel-overlay';\nimport {\n PanelPositionY,\n PanelPositionX,\n PanelFlexiblePosition,\n} from './panel-positions';\nimport { merge } from 'rxjs';\nimport { debounceTime, filter } from 'rxjs/operators';\nimport { SPACE } from '@angular/cdk/keycodes';\nimport { FocusTrap, ConfigurableFocusTrapFactory } from '@angular/cdk/a11y';\n\n/** Injection token that determines the scroll handling while the panel-overlay is open. */\nexport const OUI_PANEL_SCROLL_STRATEGY = new InjectionToken<\n () => ScrollStrategy\n>('oui-panel-scroll-strategy');\n\n/** @docs-private */\nexport function OUI_PANEL_SCROLL_STRATEGY_FACTORY(\n overlay: Overlay\n): () => ScrollStrategy {\n return () => overlay.scrollStrategies.close();\n}\n\n/** @docs-private */\nexport const OUI_PANEL_SCROLL_STRATEGY_FACTORY_PROVIDER = {\n provide: OUI_PANEL_SCROLL_STRATEGY,\n deps: [Overlay],\n useFactory: OUI_PANEL_SCROLL_STRATEGY_FACTORY,\n};\n\n/**\n * This directive is intended to be used in conjunction with an oui-panel tag. It is\n * responsible for toggling the display of the provided panel instance.\n */\n@Directive({\n selector: `[oui-panel-trigger-for], [ouiPanelTriggerFor]`,\n // eslint-disable-next-line @angular-eslint/no-host-metadata-property\n host: {\n 'aria-haspopup': 'true',\n '[attr.aria-expanded]': 'panelOpen || null',\n '(mouseenter)': '_handleMouseEnter($event)',\n '(mouseleave)': '_handelMouseLeave($event)',\n '(keydown)': '_handleKeydown($event)',\n },\n exportAs: 'ouiPanelTrigger',\n})\nexport class OuiPanelTrigger implements OnDestroy {\n private _portal: TemplatePortal;\n private _overlayRef: OverlayRef | null = null;\n private _panelOpen = false;\n private _closeSubscription = Subscription.EMPTY;\n private _hoverSubscription = Subscription.EMPTY;\n private _keyboardEventSubscription: Subscription = Subscription.EMPTY;\n private _escapeEventSubscription: Subscription = Subscription.EMPTY;\n private _panelCloseSubscription = Subscription.EMPTY;\n private _mouseLeave: Subject = new Subject();\n private _mouseEnter: Subject = new Subject();\n private _scrollStrategy: () => ScrollStrategy;\n\n /** The class that traps and manages focus within the panel. */\n private _focusTrap: FocusTrap;\n\n /** Element that was focused before the panel was opened. Save this to restore upon close. */\n private _currentFocusElement: HTMLElement = null;\n\n /** References the panel instance that the trigger is associated with. */\n @Input('ouiPanelTriggerFor')\n get panel() {\n return this._panel;\n }\n set panel(panel: OuiPanelOverlay) {\n if (panel === this._panel) {\n return;\n }\n this._panel = panel;\n this._panelCloseSubscription.unsubscribe();\n\n if (panel) {\n this._panelCloseSubscription = panel.closed\n .asObservable()\n .subscribe(() => {\n this._destroyPanel();\n });\n this._escapeEventSubscription = this.panel.escapeEvent.subscribe(() => {\n this.closePanel();\n });\n }\n }\n private _panel: OuiPanelOverlay;\n\n /** Event emitted when the associated panel is opened. */\n @Output()\n readonly panelOpened: EventEmitter = new EventEmitter();\n\n /** Event emitted when the associated panel is closed. */\n @Output()\n readonly panelClosed: EventEmitter = new EventEmitter();\n\n constructor(\n private _overlay: Overlay,\n private _element: ElementRef,\n private _viewContainerRef: ViewContainerRef,\n private _focusTrapFactory: ConfigurableFocusTrapFactory,\n @Inject(OUI_PANEL_SCROLL_STRATEGY) scrollStrategy: any\n ) {\n this._scrollStrategy = scrollStrategy;\n }\n\n /** Whether the panel is open. */\n get panelOpen(): boolean {\n return this._panelOpen;\n }\n\n /** Toggles the panel between the open and closed states. */\n togglePanel(): void {\n return this._panelOpen ? this.closePanel() : this.openPanel();\n }\n\n /** Ensures the option is selected when activated from the keyboard. */\n _handleKeydown(event: KeyboardEvent): void {\n const keyCode = event.keyCode;\n if (keyCode === SPACE) {\n this.openPanel();\n this._trapFocus();\n event.preventDefault();\n // On tab it will focus on the element itself\n this._currentFocusElement = event.target as HTMLElement;\n }\n }\n\n /** Opens The Panel */\n openPanel(): void {\n if (this._panelOpen) {\n return;\n }\n const overlayRef = this._createOverlay();\n const overlayConfig = overlayRef.getConfig();\n\n this._setPosition(\n overlayConfig.positionStrategy as FlexibleConnectedPositionStrategy\n );\n // overlayConfig.hasBackdrop = true;\n overlayRef.attach(this._getPortal());\n this._setLargeWidth();\n this._closeSubscription = this._panelClosingActions().subscribe(() => {\n this.closePanel('mouserHover');\n });\n this._setIsPanelOpen(true);\n }\n\n // set state rather than toggle to support triggers sharing a panel\n private _setIsPanelOpen(isOpen: boolean): void {\n this._panelOpen = isOpen;\n this._panelOpen ? this.panelOpened.emit() : this.panelClosed.emit();\n }\n\n /**\n * This method creates the overlay from the provided panel's template and saves its\n * OverlayRef so that it can be attached to the DOM when openPanel is called.\n */\n private _createOverlay(): OverlayRef {\n if (document.querySelector('.oui-panel')) {\n document.querySelector('.oui-panel').remove();\n }\n if (!this._overlayRef) {\n const config = this._getOverlayConfig();\n this._subscribeToPositions(\n config.positionStrategy as FlexibleConnectedPositionStrategy\n );\n this._overlayRef = this._overlay.create(config);\n\n // Consume the `keydownEvents` in order to prevent them from going to another overlay.\n // Ideally we'd also have our keyboard event logic in here, however doing so will\n // break anybody that may have implemented the `OuiPanelOverlay` themselves.\n this._keyboardEventSubscription = this._overlayRef\n .keydownEvents()\n .pipe(filter((event) => event.key === 'Escape'))\n .subscribe(() => this.closePanel());\n }\n return this._overlayRef;\n }\n\n /**\n * This method builds the configuration object needed to create the overlay, the OverlayState.\n *\n * @returns OverlayConfig\n */\n private _getOverlayConfig(): OverlayConfig {\n return new OverlayConfig({\n positionStrategy: this._overlay\n .position()\n .flexibleConnectedTo(this._element)\n .withLockedPosition()\n .withTransformOriginOn('.oui-panel-overlay'),\n backdropClass: 'cdk-overlay-transparent-backdrop',\n scrollStrategy: this._scrollStrategy(),\n direction: 'ltr',\n });\n }\n\n /**\n * Listens to changes in the position of the overlay and sets the correct classes\n * on the menu based on the new position. This ensures the animation origin is always\n * correct, even if a fallback position is used for the overlay.\n */\n private _subscribeToPositions(\n position: FlexibleConnectedPositionStrategy\n ): void {\n if (this.panel.setPositionClasses) {\n position.positionChanges.subscribe((change) => {\n const posX: PanelPositionX =\n change.connectionPair.overlayX === 'start' ? 'after' : 'before';\n const posY: PanelPositionY =\n change.connectionPair.overlayY === 'top' ? 'below' : 'above';\n\n this.panel.setPositionClasses!(posX, posY);\n });\n }\n }\n\n /**\n * Sets the appropriate positions on a position strategy\n * so the overlay connects with the trigger correctly.\n *\n * @param positionStrategy Strategy whose position to update.\n */\n private _setPosition(positionStrategy: FlexibleConnectedPositionStrategy) {\n const panelPositions = new PanelFlexiblePosition(\n this.panel.xPosition,\n this.panel.yPosition\n );\n positionStrategy.withPositions(panelPositions.getPosition());\n }\n /** assign large width if overlay element contains img tag */\n private _setLargeWidth() {\n const imageTag = this._overlayRef.overlayElement.querySelector('img');\n if (imageTag) {\n const content: HTMLDivElement =\n this._overlayRef.overlayElement.querySelector('.oui-panel-content');\n content.classList.add('oui-panel-content-large');\n }\n }\n\n /** Cleans up the active subscriptions. */\n private _cleanUpSubscriptions(): void {\n this._closeSubscription.unsubscribe();\n this._hoverSubscription.unsubscribe();\n this._escapeEventSubscription.unsubscribe();\n this._keyboardEventSubscription.unsubscribe();\n }\n\n /** Closes the menu and does the necessary cleanup. */\n private _destroyPanel() {\n if (!this._overlayRef || !this.panelOpen) {\n return;\n }\n this._setIsPanelOpen(false);\n const panel = this.panel;\n\n this._closeSubscription.unsubscribe();\n this._overlayRef.detach();\n\n if (panel.lazyContent) {\n panel.lazyContent.detach();\n }\n }\n\n /** Closes The Panel */\n closePanel(hoverType?) {\n this.panel.closed.emit();\n if (!hoverType) {\n this._restoreFocus();\n }\n }\n\n /** Moves the focus inside the focus trap. */\n public _trapFocus() {\n const element: HTMLDivElement =\n this._overlayRef.overlayElement.querySelector('.oui-panel-content');\n\n if (!this._focusTrap) {\n this._focusTrap = this._focusTrapFactory.create(element);\n }\n element.focus();\n }\n\n /** Restores focus to the element that was focused before the panel opened. */\n public _restoreFocus() {\n const toFocus = this._currentFocusElement;\n // We need the extra check, because IE can set the `activeElement` to null in some cases.\n if (toFocus && typeof toFocus.focus === 'function') {\n toFocus.focus();\n }\n\n if (this._focusTrap) {\n this._focusTrap = null;\n }\n }\n\n /** Gets the portal that should be attached to the overlay. */\n private _getPortal(): TemplatePortal {\n // Note that we can avoid this check by keeping the portal on the menu panel.\n // While it would be cleaner, we'd have to introduce another required method on\n // `OuiPanelOverlay`, making it harder to consume.\n if (!this._portal || this._portal.templateRef !== this.panel.templateRef) {\n this._portal = new TemplatePortal(\n this.panel.templateRef,\n this._viewContainerRef\n );\n }\n return this._portal;\n }\n\n public _handleMouseEnter(event: MouseEvent): void {\n // On hover it will focus on the element itself\n const focusElement = event.target as HTMLElement;\n this._currentFocusElement = focusElement.querySelector('oui-icon');\n this._mouseEnter.next(event);\n this.openPanel();\n event.stopImmediatePropagation();\n }\n\n public _handelMouseLeave(event: MouseEvent): void {\n this._mouseLeave.next(event);\n event.stopImmediatePropagation();\n }\n\n /** Returns a stream that emits whenever an action that should close the panel occurs. */\n private _panelClosingActions(): Observable {\n const detachments = this._overlayRef!.detachments();\n const mouseLeave = merge(\n this._mouseLeave.asObservable(),\n this._mouseEnter.asObservable(),\n this.panel.mouseLeave,\n this.panel.mouseEnter\n ).pipe(\n debounceTime(200),\n filter((event) => event.type === 'mouseleave')\n );\n return merge(detachments, mouseLeave);\n }\n\n ngOnDestroy() {\n if (this._overlayRef) {\n this._overlayRef.dispose();\n this._overlayRef = null;\n }\n this._cleanUpSubscriptions();\n }\n}\n", + "sourceCode": "import {\r\n InjectionToken,\r\n Directive,\r\n OnDestroy,\r\n Input,\r\n Output,\r\n EventEmitter,\r\n ElementRef,\r\n ViewContainerRef,\r\n Inject,\r\n} from '@angular/core';\r\nimport {\r\n ScrollStrategy,\r\n Overlay,\r\n OverlayRef,\r\n FlexibleConnectedPositionStrategy,\r\n OverlayConfig,\r\n} from '@angular/cdk/overlay';\r\nimport { Subscription, Observable, Subject } from 'rxjs';\r\nimport { TemplatePortal } from '@angular/cdk/portal';\r\nimport { OuiPanelOverlay } from './panel-overlay';\r\nimport {\r\n PanelPositionY,\r\n PanelPositionX,\r\n PanelFlexiblePosition,\r\n} from './panel-positions';\r\nimport { merge } from 'rxjs';\r\nimport { debounceTime, filter } from 'rxjs/operators';\r\nimport { SPACE } from '@angular/cdk/keycodes';\r\nimport { FocusTrap, ConfigurableFocusTrapFactory } from '@angular/cdk/a11y';\r\n\r\n/** Injection token that determines the scroll handling while the panel-overlay is open. */\r\nexport const OUI_PANEL_SCROLL_STRATEGY = new InjectionToken<\r\n () => ScrollStrategy\r\n>('oui-panel-scroll-strategy');\r\n\r\n/** @docs-private */\r\nexport function OUI_PANEL_SCROLL_STRATEGY_FACTORY(\r\n overlay: Overlay\r\n): () => ScrollStrategy {\r\n return () => overlay.scrollStrategies.close();\r\n}\r\n\r\n/** @docs-private */\r\nexport const OUI_PANEL_SCROLL_STRATEGY_FACTORY_PROVIDER = {\r\n provide: OUI_PANEL_SCROLL_STRATEGY,\r\n deps: [Overlay],\r\n useFactory: OUI_PANEL_SCROLL_STRATEGY_FACTORY,\r\n};\r\n\r\n/**\r\n * This directive is intended to be used in conjunction with an oui-panel tag. It is\r\n * responsible for toggling the display of the provided panel instance.\r\n */\r\n@Directive({\r\n selector: `[oui-panel-trigger-for], [ouiPanelTriggerFor]`,\r\n // eslint-disable-next-line @angular-eslint/no-host-metadata-property\r\n host: {\r\n 'aria-haspopup': 'true',\r\n '[attr.aria-expanded]': 'panelOpen || null',\r\n '(mouseenter)': '_handleMouseEnter($event)',\r\n '(mouseleave)': '_handelMouseLeave($event)',\r\n '(keydown)': '_handleKeydown($event)',\r\n },\r\n exportAs: 'ouiPanelTrigger',\r\n})\r\nexport class OuiPanelTrigger implements OnDestroy {\r\n private _portal: TemplatePortal;\r\n private _overlayRef: OverlayRef | null = null;\r\n private _panelOpen = false;\r\n private _closeSubscription = Subscription.EMPTY;\r\n private _hoverSubscription = Subscription.EMPTY;\r\n private _keyboardEventSubscription: Subscription = Subscription.EMPTY;\r\n private _escapeEventSubscription: Subscription = Subscription.EMPTY;\r\n private _panelCloseSubscription = Subscription.EMPTY;\r\n private _mouseLeave: Subject = new Subject();\r\n private _mouseEnter: Subject = new Subject();\r\n private _scrollStrategy: () => ScrollStrategy;\r\n\r\n /** The class that traps and manages focus within the panel. */\r\n private _focusTrap: FocusTrap;\r\n\r\n /** Element that was focused before the panel was opened. Save this to restore upon close. */\r\n private _currentFocusElement: HTMLElement = null;\r\n\r\n /** References the panel instance that the trigger is associated with. */\r\n @Input('ouiPanelTriggerFor')\r\n get panel() {\r\n return this._panel;\r\n }\r\n set panel(panel: OuiPanelOverlay) {\r\n if (panel === this._panel) {\r\n return;\r\n }\r\n this._panel = panel;\r\n this._panelCloseSubscription.unsubscribe();\r\n\r\n if (panel) {\r\n this._panelCloseSubscription = panel.closed\r\n .asObservable()\r\n .subscribe(() => {\r\n this._destroyPanel();\r\n });\r\n this._escapeEventSubscription = this.panel.escapeEvent.subscribe(() => {\r\n this.closePanel();\r\n });\r\n }\r\n }\r\n private _panel: OuiPanelOverlay;\r\n\r\n /** Event emitted when the associated panel is opened. */\r\n @Output()\r\n readonly panelOpened: EventEmitter = new EventEmitter();\r\n\r\n /** Event emitted when the associated panel is closed. */\r\n @Output()\r\n readonly panelClosed: EventEmitter = new EventEmitter();\r\n\r\n constructor(\r\n private _overlay: Overlay,\r\n private _element: ElementRef,\r\n private _viewContainerRef: ViewContainerRef,\r\n private _focusTrapFactory: ConfigurableFocusTrapFactory,\r\n @Inject(OUI_PANEL_SCROLL_STRATEGY) scrollStrategy: any\r\n ) {\r\n this._scrollStrategy = scrollStrategy;\r\n }\r\n\r\n /** Whether the panel is open. */\r\n get panelOpen(): boolean {\r\n return this._panelOpen;\r\n }\r\n\r\n /** Toggles the panel between the open and closed states. */\r\n togglePanel(): void {\r\n return this._panelOpen ? this.closePanel() : this.openPanel();\r\n }\r\n\r\n /** Ensures the option is selected when activated from the keyboard. */\r\n _handleKeydown(event: KeyboardEvent): void {\r\n const keyCode = event.keyCode;\r\n if (keyCode === SPACE) {\r\n this.openPanel();\r\n this._trapFocus();\r\n event.preventDefault();\r\n // On tab it will focus on the element itself\r\n this._currentFocusElement = event.target as HTMLElement;\r\n }\r\n }\r\n\r\n /** Opens The Panel */\r\n openPanel(): void {\r\n if (this._panelOpen) {\r\n return;\r\n }\r\n const overlayRef = this._createOverlay();\r\n const overlayConfig = overlayRef.getConfig();\r\n\r\n this._setPosition(\r\n overlayConfig.positionStrategy as FlexibleConnectedPositionStrategy\r\n );\r\n // overlayConfig.hasBackdrop = true;\r\n overlayRef.attach(this._getPortal());\r\n this._setLargeWidth();\r\n this._closeSubscription = this._panelClosingActions().subscribe(() => {\r\n this.closePanel('mouserHover');\r\n });\r\n this._setIsPanelOpen(true);\r\n }\r\n\r\n // set state rather than toggle to support triggers sharing a panel\r\n private _setIsPanelOpen(isOpen: boolean): void {\r\n this._panelOpen = isOpen;\r\n this._panelOpen ? this.panelOpened.emit() : this.panelClosed.emit();\r\n }\r\n\r\n /**\r\n * This method creates the overlay from the provided panel's template and saves its\r\n * OverlayRef so that it can be attached to the DOM when openPanel is called.\r\n */\r\n private _createOverlay(): OverlayRef {\r\n if (document.querySelector('.oui-panel')) {\r\n document.querySelector('.oui-panel').remove();\r\n }\r\n if (!this._overlayRef) {\r\n const config = this._getOverlayConfig();\r\n this._subscribeToPositions(\r\n config.positionStrategy as FlexibleConnectedPositionStrategy\r\n );\r\n this._overlayRef = this._overlay.create(config);\r\n\r\n // Consume the `keydownEvents` in order to prevent them from going to another overlay.\r\n // Ideally we'd also have our keyboard event logic in here, however doing so will\r\n // break anybody that may have implemented the `OuiPanelOverlay` themselves.\r\n this._keyboardEventSubscription = this._overlayRef\r\n .keydownEvents()\r\n .pipe(filter((event) => event.key === 'Escape'))\r\n .subscribe(() => this.closePanel());\r\n }\r\n return this._overlayRef;\r\n }\r\n\r\n /**\r\n * This method builds the configuration object needed to create the overlay, the OverlayState.\r\n *\r\n * @returns OverlayConfig\r\n */\r\n private _getOverlayConfig(): OverlayConfig {\r\n return new OverlayConfig({\r\n positionStrategy: this._overlay\r\n .position()\r\n .flexibleConnectedTo(this._element)\r\n .withLockedPosition()\r\n .withTransformOriginOn('.oui-panel-overlay'),\r\n backdropClass: 'cdk-overlay-transparent-backdrop',\r\n scrollStrategy: this._scrollStrategy(),\r\n direction: 'ltr',\r\n });\r\n }\r\n\r\n /**\r\n * Listens to changes in the position of the overlay and sets the correct classes\r\n * on the menu based on the new position. This ensures the animation origin is always\r\n * correct, even if a fallback position is used for the overlay.\r\n */\r\n private _subscribeToPositions(\r\n position: FlexibleConnectedPositionStrategy\r\n ): void {\r\n if (this.panel.setPositionClasses) {\r\n position.positionChanges.subscribe((change) => {\r\n const posX: PanelPositionX =\r\n change.connectionPair.overlayX === 'start' ? 'after' : 'before';\r\n const posY: PanelPositionY =\r\n change.connectionPair.overlayY === 'top' ? 'below' : 'above';\r\n\r\n this.panel.setPositionClasses!(posX, posY);\r\n });\r\n }\r\n }\r\n\r\n /**\r\n * Sets the appropriate positions on a position strategy\r\n * so the overlay connects with the trigger correctly.\r\n *\r\n * @param positionStrategy Strategy whose position to update.\r\n */\r\n private _setPosition(positionStrategy: FlexibleConnectedPositionStrategy) {\r\n const panelPositions = new PanelFlexiblePosition(\r\n this.panel.xPosition,\r\n this.panel.yPosition\r\n );\r\n positionStrategy.withPositions(panelPositions.getPosition());\r\n }\r\n /** assign large width if overlay element contains img tag */\r\n private _setLargeWidth() {\r\n const imageTag = this._overlayRef.overlayElement.querySelector('img');\r\n if (imageTag) {\r\n const content: HTMLDivElement =\r\n this._overlayRef.overlayElement.querySelector('.oui-panel-content');\r\n content.classList.add('oui-panel-content-large');\r\n }\r\n }\r\n\r\n /** Cleans up the active subscriptions. */\r\n private _cleanUpSubscriptions(): void {\r\n this._closeSubscription.unsubscribe();\r\n this._hoverSubscription.unsubscribe();\r\n this._escapeEventSubscription.unsubscribe();\r\n this._keyboardEventSubscription.unsubscribe();\r\n }\r\n\r\n /** Closes the menu and does the necessary cleanup. */\r\n private _destroyPanel() {\r\n if (!this._overlayRef || !this.panelOpen) {\r\n return;\r\n }\r\n this._setIsPanelOpen(false);\r\n const panel = this.panel;\r\n\r\n this._closeSubscription.unsubscribe();\r\n this._overlayRef.detach();\r\n\r\n if (panel.lazyContent) {\r\n panel.lazyContent.detach();\r\n }\r\n }\r\n\r\n /** Closes The Panel */\r\n closePanel(hoverType?) {\r\n this.panel.closed.emit();\r\n if (!hoverType) {\r\n this._restoreFocus();\r\n }\r\n }\r\n\r\n /** Moves the focus inside the focus trap. */\r\n public _trapFocus() {\r\n const element: HTMLDivElement =\r\n this._overlayRef.overlayElement.querySelector('.oui-panel-content');\r\n\r\n if (!this._focusTrap) {\r\n this._focusTrap = this._focusTrapFactory.create(element);\r\n }\r\n element.focus();\r\n }\r\n\r\n /** Restores focus to the element that was focused before the panel opened. */\r\n public _restoreFocus() {\r\n const toFocus = this._currentFocusElement;\r\n // We need the extra check, because IE can set the `activeElement` to null in some cases.\r\n if (toFocus && typeof toFocus.focus === 'function') {\r\n toFocus.focus();\r\n }\r\n\r\n if (this._focusTrap) {\r\n this._focusTrap = null;\r\n }\r\n }\r\n\r\n /** Gets the portal that should be attached to the overlay. */\r\n private _getPortal(): TemplatePortal {\r\n // Note that we can avoid this check by keeping the portal on the menu panel.\r\n // While it would be cleaner, we'd have to introduce another required method on\r\n // `OuiPanelOverlay`, making it harder to consume.\r\n if (!this._portal || this._portal.templateRef !== this.panel.templateRef) {\r\n this._portal = new TemplatePortal(\r\n this.panel.templateRef,\r\n this._viewContainerRef\r\n );\r\n }\r\n return this._portal;\r\n }\r\n\r\n public _handleMouseEnter(event: MouseEvent): void {\r\n // On hover it will focus on the element itself\r\n const focusElement = event.target as HTMLElement;\r\n this._currentFocusElement = focusElement.querySelector('oui-icon');\r\n this._mouseEnter.next(event);\r\n this.openPanel();\r\n event.stopImmediatePropagation();\r\n }\r\n\r\n public _handelMouseLeave(event: MouseEvent): void {\r\n this._mouseLeave.next(event);\r\n event.stopImmediatePropagation();\r\n }\r\n\r\n /** Returns a stream that emits whenever an action that should close the panel occurs. */\r\n private _panelClosingActions(): Observable {\r\n const detachments = this._overlayRef!.detachments();\r\n const mouseLeave = merge(\r\n this._mouseLeave.asObservable(),\r\n this._mouseEnter.asObservable(),\r\n this.panel.mouseLeave,\r\n this.panel.mouseEnter\r\n ).pipe(\r\n debounceTime(200),\r\n filter((event) => event.type === 'mouseleave')\r\n );\r\n return merge(detachments, mouseLeave);\r\n }\r\n\r\n ngOnDestroy() {\r\n if (this._overlayRef) {\r\n this._overlayRef.dispose();\r\n this._overlayRef = null;\r\n }\r\n this._cleanUpSubscriptions();\r\n }\r\n}\r\n", "selector": "[oui-panel-trigger-for], [ouiPanelTriggerFor]", "providers": [], + "exportAs": "ouiPanelTrigger", + "hostDirectives": [], + "standalone": false, "inputsClass": [ { "name": "ouiPanelTriggerFor", @@ -18460,7 +18673,7 @@ "description": "", "line": 71, "modifierKind": [ - 121 + 123 ] }, { @@ -18474,7 +18687,7 @@ "line": 84, "rawdescription": "\nElement that was focused before the panel was opened. Save this to restore upon close.", "modifierKind": [ - 121 + 123 ] }, { @@ -18487,7 +18700,7 @@ "description": "", "line": 74, "modifierKind": [ - 121 + 123 ] }, { @@ -18500,7 +18713,7 @@ "line": 81, "rawdescription": "\nThe class that traps and manages focus within the panel.", "modifierKind": [ - 121 + 123 ] }, { @@ -18513,7 +18726,7 @@ "description": "", "line": 72, "modifierKind": [ - 121 + 123 ] }, { @@ -18526,7 +18739,7 @@ "description": "", "line": 73, "modifierKind": [ - 121 + 123 ] }, { @@ -18539,7 +18752,7 @@ "description": "", "line": 77, "modifierKind": [ - 121 + 123 ] }, { @@ -18552,7 +18765,7 @@ "description": "", "line": 76, "modifierKind": [ - 121 + 123 ] }, { @@ -18565,7 +18778,7 @@ "description": "", "line": 69, "modifierKind": [ - 121 + 123 ] }, { @@ -18577,7 +18790,7 @@ "description": "", "line": 109, "modifierKind": [ - 121 + 123 ] }, { @@ -18590,7 +18803,7 @@ "description": "", "line": 75, "modifierKind": [ - 121 + 123 ] }, { @@ -18603,7 +18816,7 @@ "description": "", "line": 70, "modifierKind": [ - 121 + 123 ] }, { @@ -18615,7 +18828,7 @@ "description": "", "line": 68, "modifierKind": [ - 121 + 123 ] }, { @@ -18627,7 +18840,7 @@ "description": "", "line": 78, "modifierKind": [ - 121 + 123 ] } ], @@ -18644,7 +18857,7 @@ "rawdescription": "\nCleans up the active subscriptions.", "description": "

Cleans up the active subscriptions.

\n", "modifierKind": [ - 121 + 123 ] }, { @@ -18659,7 +18872,7 @@ "rawdescription": "\n\nThis method creates the overlay from the provided panel's template and saves its\nOverlayRef so that it can be attached to the DOM when openPanel is called.\n", "description": "

This method creates the overlay from the provided panel's template and saves its\nOverlayRef so that it can be attached to the DOM when openPanel is called.

\n", "modifierKind": [ - 121 + 123 ] }, { @@ -18674,7 +18887,7 @@ "rawdescription": "\nCloses the menu and does the necessary cleanup.", "description": "

Closes the menu and does the necessary cleanup.

\n", "modifierKind": [ - 121 + 123 ] }, { @@ -18689,17 +18902,17 @@ "rawdescription": "\n\nThis method builds the configuration object needed to create the overlay, the OverlayState.\n\n", "description": "

This method builds the configuration object needed to create the overlay, the OverlayState.

\n", "modifierKind": [ - 121 + 123 ], "jsdoctags": [ { "tagName": { - "pos": 6680, - "end": 6687, - "flags": 4227072, + "pos": 6885, + "end": 6892, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "returns" }, "comment": "

OverlayConfig

\n" @@ -18718,7 +18931,7 @@ "rawdescription": "\nGets the portal that should be attached to the overlay.", "description": "

Gets the portal that should be attached to the overlay.

\n", "modifierKind": [ - 121 + 123 ] }, { @@ -18738,7 +18951,7 @@ "deprecated": false, "deprecationMessage": "", "modifierKind": [ - 123 + 125 ], "jsdoctags": [ { @@ -18799,7 +19012,7 @@ "deprecated": false, "deprecationMessage": "", "modifierKind": [ - 123 + 125 ], "jsdoctags": [ { @@ -18825,7 +19038,7 @@ "rawdescription": "\nReturns a stream that emits whenever an action that should close the panel occurs.", "description": "

Returns a stream that emits whenever an action that should close the panel occurs.

\n", "modifierKind": [ - 121 + 123 ] }, { @@ -18840,7 +19053,7 @@ "rawdescription": "\nRestores focus to the element that was focused before the panel opened.", "description": "

Restores focus to the element that was focused before the panel opened.

\n", "modifierKind": [ - 123 + 125 ] }, { @@ -18860,7 +19073,7 @@ "deprecated": false, "deprecationMessage": "", "modifierKind": [ - 121 + 123 ], "jsdoctags": [ { @@ -18886,7 +19099,7 @@ "rawdescription": "\nassign large width if overlay element contains img tag", "description": "

assign large width if overlay element contains img tag

\n", "modifierKind": [ - 121 + 123 ] }, { @@ -18908,29 +19121,29 @@ "rawdescription": "\n\nSets the appropriate positions on a position strategy\nso the overlay connects with the trigger correctly.\n\n", "description": "

Sets the appropriate positions on a position strategy\nso the overlay connects with the trigger correctly.

\n", "modifierKind": [ - 121 + 123 ], "jsdoctags": [ { "name": { - "pos": 7986, - "end": 8002, - "flags": 4227072, + "pos": 8230, + "end": 8246, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "positionStrategy" }, "type": "FlexibleConnectedPositionStrategy", "deprecated": false, "deprecationMessage": "", "tagName": { - "pos": 7980, - "end": 7985, - "flags": 4227072, + "pos": 8224, + "end": 8229, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "param" }, "comment": "

Strategy whose position to update.

\n" @@ -18956,7 +19169,7 @@ "rawdescription": "\n\nListens to changes in the position of the overlay and sets the correct classes\non the menu based on the new position. This ensures the animation origin is always\ncorrect, even if a fallback position is used for the overlay.\n", "description": "

Listens to changes in the position of the overlay and sets the correct classes\non the menu based on the new position. This ensures the animation origin is always\ncorrect, even if a fallback position is used for the overlay.

\n", "modifierKind": [ - 121 + 123 ], "jsdoctags": [ { @@ -18982,7 +19195,7 @@ "rawdescription": "\nMoves the focus inside the focus trap.", "description": "

Moves the focus inside the focus trap.

\n", "modifierKind": [ - 123 + 125 ] }, { @@ -19052,6 +19265,7 @@ "description": "

Toggles the panel between the open and closed states.

\n" } ], + "extends": [], "implements": [ "OnDestroy" ], @@ -19207,6 +19421,8 @@ "name": "{ provide: CdkRowDef, useExisting: OuiRowDef }" } ], + "hostDirectives": [], + "standalone": false, "inputsClass": [], "outputsClass": [], "deprecated": false, @@ -19215,18 +19431,22 @@ "hostListeners": [], "propertiesClass": [], "methodsClass": [], - "extends": "CdkRowDef" + "extends": [ + "CdkRowDef" + ] }, { "name": "OuiSelectTrigger", - "id": "component-OuiSelect-d85db46eab36d315c1fdcd891bdac570b57a0ccdc711e79255f204f23073d94dc6b0707254460df0585b83b8338fb5a5a8a9bcb9d49bc6bf529c53c663cbdac2", + "id": "directive-OuiSelectTrigger-69627b742fec8101b0c412f353bb903b4d499f0f8291080ef1d6ac0c418484f2235fec3981e84104b948fe2f242b0a29fea2c39687b9ed9b01e6aa4fcda7ba37", "file": "ui/src/components/select/select.component.ts", - "type": "component", + "type": "directive", "description": "

Allows the user to customize the trigger that is displayed when the select has a value.

\n", "rawdescription": "\n\nAllows the user to customize the trigger that is displayed when the select has a value.\n", - "sourceCode": "import { ActiveDescendantKeyManager, FocusMonitor } from '@angular/cdk/a11y';\nimport { Directionality } from '@angular/cdk/bidi';\nimport { coerceBooleanProperty } from '@angular/cdk/coercion';\nimport { SelectionModel } from '@angular/cdk/collections';\nimport {\n A,\n DOWN_ARROW,\n END,\n ENTER,\n HOME,\n LEFT_ARROW,\n RIGHT_ARROW,\n SPACE,\n UP_ARROW,\n hasModifierKey,\n TAB,\n} from '@angular/cdk/keycodes';\nimport { CdkConnectedOverlay } from '@angular/cdk/overlay';\nimport {\n AfterContentInit,\n Attribute,\n ChangeDetectionStrategy,\n ChangeDetectorRef,\n Component,\n ContentChild,\n ContentChildren,\n Directive,\n DoCheck,\n ElementRef,\n EventEmitter,\n Input,\n isDevMode,\n NgZone,\n OnChanges,\n OnDestroy,\n OnInit,\n Optional,\n Output,\n QueryList,\n Self,\n SimpleChanges,\n ViewChild,\n ViewEncapsulation,\n Inject,\n} from '@angular/core';\nimport {\n ControlValueAccessor,\n FormGroupDirective,\n NgControl,\n NgForm,\n} from '@angular/forms';\nimport {\n _countGroupLabelsBeforeOption,\n _getOptionScrollPosition,\n CanDisable,\n CanDisableCtor,\n CanUpdateErrorState,\n CanUpdateErrorStateCtor,\n HasTabIndex,\n HasTabIndexCtor,\n OuiOptionSelectionChange,\n mixinErrorState,\n mixinTabIndex,\n mixinDisabled,\n} from '../core';\nimport { OuiFormField, OuiFormFieldControl } from '../form-field/public-api';\nimport { DOCUMENT } from '@angular/common';\nimport { OUI_OPTION_PARENT_COMPONENT, OuiOption } from '../core/option/option';\nimport { OuiOptgroup } from '../core/option/optgroup';\nimport { ErrorStateMatcher } from '../core/error/error-options';\nimport { defer, merge, Observable, Subject } from 'rxjs';\nimport {\n distinctUntilChanged,\n filter,\n map,\n startWith,\n switchMap,\n take,\n takeUntil,\n} from 'rxjs/operators';\nimport {\n getOuiSelectDynamicMultipleError,\n getOuiSelectNonArrayValueError,\n getOuiSelectNonFunctionValueError,\n} from './select-errors';\nimport { OuiIconRegistry } from '../icon/icon-registery';\nimport { DomSanitizer } from '@angular/platform-browser';\nimport { ICONS } from '../core/shared/icons';\n\nlet nextUniqueId = 0;\n\n/**\n * The following style constants are necessary to save here in order\n * to properly calculate the alignment of the selected option over\n * the trigger element.\n */\n\n/** The height of each select option. */\nexport const SELECT_OPTION_HEIGHT = 40;\n\n/** The panel's padding on the x-axis */\nexport const SELECT_PANEL_PADDING_X = 16;\n\n/** The panel's x axis padding if it is indented (e.g. there is an option group). */\nexport const SELECT_PANEL_INDENT_PADDING_X = SELECT_PANEL_PADDING_X * 2;\n\n/** The height of the select items in `em` units. */\nexport const SELECT_ITEM_HEIGHT_EM = 3;\n\n/** The total height of the select panel. */\nexport const SELECT_PANEL_HEIGHT = 200;\n\n// TODO(josephperrott): Revert to a constant after 2018 spec updates are fully merged.\n/**\n * Distance between the panel edge and the option text in\n * multi-selection mode.\n *\n * Calculated as:\n * (SELECT_PANEL_PADDING_X * 1.5) + 20 = 44\n * The padding is multiplied by 1.5 because the checkbox's margin is half the padding.\n * The checkbox width is 16px.\n */\nexport let SELECT_MULTIPLE_PANEL_PADDING_X = 0;\n\n/**\n * The select panel will only \"fit\" inside the viewport if it is positioned at\n * this value or more away from the viewport boundary.\n */\nexport const SELECT_PANEL_VIEWPORT_PADDING = 8;\n\n/** Change event object that is emitted when the select value has changed. */\nexport class OuiSelectChange {\n constructor(\n /** Reference to the select that emitted the change event. */\n public source: OuiSelect,\n /** Current value of the select that emitted the event. */\n public value: any\n ) {}\n}\n\n// Boilerplate for applying mixins to OuiSelect.\n/** @docs-private */\nexport class OuiSelectBase {\n constructor(\n public _elementRef: ElementRef,\n public _defaultErrorStateMatcher: ErrorStateMatcher,\n public _parentForm: NgForm,\n public _parentFormGroup: FormGroupDirective,\n public ngControl: NgControl\n ) {}\n}\n\nexport const _OuiSelectMixinBase: CanDisableCtor &\n HasTabIndexCtor &\n CanUpdateErrorStateCtor &\n typeof OuiSelectBase = mixinTabIndex(\n mixinDisabled(mixinErrorState(OuiSelectBase))\n);\n\n/**\n * Allows the user to customize the trigger that is displayed when the select has a value.\n */\n@Directive({\n // eslint-disable-next-line @angular-eslint/directive-selector\n selector: 'oui-select-trigger',\n})\nexport class OuiSelectTrigger {}\n\n@Component({\n selector: 'oui-select',\n exportAs: 'ouiSelect',\n templateUrl: 'select.html',\n styleUrls: ['select.scss'],\n // eslint-disable-next-line @angular-eslint/no-inputs-metadata-property\n inputs: ['disabled', 'tabIndex'],\n encapsulation: ViewEncapsulation.None,\n changeDetection: ChangeDetectionStrategy.OnPush,\n // eslint-disable-next-line @angular-eslint/no-host-metadata-property\n host: {\n role: 'listbox',\n '[attr.id]': 'id',\n '[attr.tabindex]': 'tabIndex',\n '[attr.aria-label]': '_getAriaLabel()',\n '[attr.aria-labelledby]': '_getAriaLabelledby()',\n '[attr.aria-required]': 'required.toString()',\n '[attr.aria-disabled]': 'disabled.toString()',\n '[attr.aria-invalid]': 'errorState',\n '[attr.aria-owns]': 'panelOpen ? _optionIds : null',\n '[attr.aria-multiselectable]': 'multiple',\n '[attr.aria-describedby]': '_ariaDescribedby || null',\n '[attr.aria-activedescendant]': '_getAriaActiveDescendant()',\n '[class.oui-select-disabled]': 'disabled',\n '[class.oui-select-invalid]': 'errorState',\n '[class.oui-select-required]': 'required',\n '[class.oui-select-empty]': 'empty',\n class: 'oui-select oui-input',\n '(keydown)': '_handleKeydown($event)',\n '(focus)': '_onFocus()',\n '(blur)': '_onBlur()',\n },\n providers: [\n { provide: OuiFormFieldControl, useExisting: OuiSelect },\n { provide: OUI_OPTION_PARENT_COMPONENT, useExisting: OuiSelect },\n ],\n})\nexport class OuiSelect\n extends _OuiSelectMixinBase\n implements\n AfterContentInit,\n OnChanges,\n OnDestroy,\n OnInit,\n DoCheck,\n ControlValueAccessor,\n CanDisable,\n HasTabIndex,\n OuiFormFieldControl,\n CanUpdateErrorState\n{\n /**Holds selected values after done */\n @Input() savedValues = [];\n /**Done button disabled until dropdown is dirty */\n disableDoneButton = true;\n /** Whether or not the overlay panel is open. */\n private _panelOpen = false;\n\n /** Whether filling out the select is required in the form. */\n private _required = false;\n\n /** Whether filling out the select is required in the form. */\n private _actionItems = false;\n\n /** The scroll position of the overlay panel, calculated to center the selected option. */\n private _scrollTop = 0;\n\n /** The placeholder displayed in the trigger of the select. */\n private _placeholder: string;\n\n /** Whether the component is in multiple selection mode. */\n private _multiple = false;\n\n /** Search input field **/\n isSearchFieldPresent: boolean;\n\n /** Unique id for this input. */\n private _uid = `oui-select-${nextUniqueId++}`;\n\n /** The last measured value for the trigger's client bounding rect. */\n _triggerRect: ClientRect;\n\n /** The aria-describedby attribute on the select for improved a11y. */\n _ariaDescribedby: string;\n\n /** The cached font-size of the trigger element. */\n _triggerFontSize = 0;\n\n /** Deals with the selection logic. */\n _selectionModel: SelectionModel;\n\n /** Manages keyboard events for options in the panel. */\n _keyManager: ActiveDescendantKeyManager;\n\n /** The IDs of child options to be passed to the aria-owns attribute. */\n _optionIds = '';\n\n /** The value of the select panel's transform-origin property. */\n _transformOrigin = 'top';\n\n /** If there is search input field a class is added dynamically to the perfect scrollbar **/\n ouiSelectInputOuterClassName: string;\n\n /** Adding top class to overlay panel */\n cdkConnectionOverlayPanel = '';\n\n /**\n * The y-offset of the overlay panel in relation to the trigger's top start corner.\n * This must be adjusted to align the selected option text over the trigger text.\n * when the panel opens. Will change based on the y-position of the selected option.\n */\n _offsetY = 0;\n\n /**\n * This position config ensures that the top \"start\" corner of the overlay\n * is aligned with with the top \"start\" of the origin by default (overlapping\n * the trigger completely). If the panel cannot fit below the trigger, it\n * will fall back to a position above the trigger.\n */\n _positions = [\n {\n originX: 'start',\n originY: 'top',\n overlayX: 'start',\n overlayY: 'top',\n },\n {\n originX: 'start',\n originY: 'bottom',\n overlayX: 'start',\n overlayY: 'bottom',\n },\n ];\n /** Emits whenever the component is destroyed. */\n private readonly _destroy = new Subject();\n\n /** Whether the component is disabling centering of the active option over the trigger. */\n private _disableOptionCentering = false;\n\n private _focused = false;\n\n /** A name for this control that can be used by `oui-form-field`. */\n controlType = 'oui-select';\n\n /** Trigger that opens the select. */\n @ViewChild('trigger') trigger: ElementRef;\n\n /** Trigger that opens the select. */\n @ViewChild('ddCancelButton', { read: ElementRef }) ddCancelButton: ElementRef;\n\n /** Trigger that opens the select. */\n @ViewChild('ddDoneButton', { read: ElementRef }) ddDoneButton: ElementRef;\n\n /** Panel containing the select options. */\n @ViewChild('panel', { read: ElementRef }) panel: ElementRef;\n\n private _value: any;\n\n /**\n * Function used to sort the values in a select in multiple mode.\n * Follows the same logic as `Array.prototype.sort`.\n */\n @Input() sortComparator: (\n a: OuiOption,\n b: OuiOption,\n options: OuiOption[]\n ) => number;\n\n /** Aria label of the select. If not specified, the placeholder will be used as label. */\n @Input('aria-label') ariaLabel = '';\n\n /** Input that can be used to specify the `aria-labelledby` attribute. */\n @Input('aria-labelledby') ariaLabelledby: string;\n private _large = false;\n _monitorSubscription: any;\n\n /** Whether the oui-select is of large size. */\n @Input()\n get large(): boolean {\n return this._large;\n }\n set large(value) {\n this._large = coerceBooleanProperty(value);\n this._changeDetectorRef.markForCheck();\n }\n\n private _id: string;\n\n /** Event emitted when the select panel has been toggled. */\n @Output()\n readonly openedChange: EventEmitter = new EventEmitter();\n\n /** Combined stream of all of the child options' change events. */\n readonly optionSelectionChanges: Observable = defer(\n (): Observable => {\n if (this.options) {\n return merge(...this.options.map((option) => option.onSelectionChange));\n }\n\n return this._ngZone.onStable.asObservable().pipe(\n take(1),\n switchMap(() => this.optionSelectionChanges)\n );\n }\n );\n\n /**\n * Event that emits whenever the raw value of the select changes. This is here primarily\n * to facilitate the two-way binding for the `value` input.\n *\n * @docs-private\n */\n @Output() readonly valueChange: EventEmitter = new EventEmitter();\n\n /** Object used to control when error messages are shown. */\n @Input() errorStateMatcher: ErrorStateMatcher;\n\n /** All of the defined select options. */\n @ContentChildren(OuiOption, { descendants: true })\n options: QueryList;\n\n /** Event emitted when the select has been opened. */\n // eslint-disable-next-line @angular-eslint/no-output-rename\n @Output('opened')\n readonly _openedStream: Observable = this.openedChange.pipe(\n filter((o) => o),\n map(() => {})\n );\n\n /** Event emitted when the select has been closed. */\n // eslint-disable-next-line @angular-eslint/no-output-rename\n @Output('closed')\n readonly _closedStream: Observable = this.openedChange.pipe(\n filter((o) => !o),\n map(() => {\n this.isSearchFieldPresent = false;\n })\n );\n\n /** Event emitted when the selected value has been changed by the user. */\n @Output()\n readonly selectionChange: EventEmitter =\n new EventEmitter();\n\n /** Event emitted when the selected value has been changed and saved by the user. */\n @Output()\n readonly saveSelectionChange: EventEmitter =\n new EventEmitter();\n\n /** All of the defined groups of options. */\n @ContentChildren(OuiOptgroup) optionGroups: QueryList;\n\n /** User-supplied override of the trigger element. */\n @ContentChild(OuiSelectTrigger)\n customTrigger: OuiSelectTrigger;\n\n /** Classes to be passed to the select panel. Supports the same syntax as `ngClass`. */\n @Input() panelClass: string | string[] | Set | { [key: string]: any };\n\n /** Overlay pane containing the options. */\n @ViewChild(CdkConnectedOverlay)\n overlayDir: CdkConnectedOverlay;\n\n /** Emits when the panel element is finished transforming in. */\n _panelDoneAnimatingStream = new Subject();\n\n /** Comparison function to specify which option is displayed. Defaults to object equality. */\n private _compareWith = (o1: any, o2: any) => o1 === o2;\n\n /** Whether the select is focused. */\n get focused(): boolean {\n return this._focused || this._panelOpen;\n }\n /**\n * @deprecated Setter to be removed as this property is intended to be readonly.\n */\n set focused(value: boolean) {\n this._focused = value;\n }\n /** `View -> model callback called when value changes` */\n _onChange: (value: any) => void = () => {};\n\n /** `View -> model callback called when select has been touched` */\n _onTouched = () => {};\n\n /** Placeholder to be shown if no value has been selected. */\n @Input()\n get placeholder(): string {\n return this._placeholder;\n }\n set placeholder(value: string) {\n this._placeholder = value;\n this.stateChanges.next();\n }\n\n /** Whether the component is required. */\n @Input()\n get required(): boolean {\n return this._required;\n }\n set required(value: boolean) {\n this._required = coerceBooleanProperty(value);\n this.stateChanges.next();\n }\n\n /** Whether the user should be allowed to select multiple options. */\n @Input()\n get multiple(): boolean {\n return this._multiple;\n }\n set multiple(value: boolean) {\n if (this._selectionModel) {\n throw getOuiSelectDynamicMultipleError();\n }\n\n this._multiple = coerceBooleanProperty(value);\n }\n\n /** Whether the action items are required and use saveSelectionChange instead of selectionChange. */\n @Input()\n get actionItems(): boolean {\n return this._actionItems;\n }\n set actionItems(value: boolean) {\n if (this._multiple) {\n this._actionItems = coerceBooleanProperty(value);\n this.stateChanges.next();\n }\n }\n\n /** Whether to center the active option over the trigger. */\n @Input()\n get disableOptionCentering(): boolean {\n return this._disableOptionCentering;\n }\n set disableOptionCentering(value: boolean) {\n this._disableOptionCentering = coerceBooleanProperty(value);\n }\n\n /**\n * Function to compare the option values with the selected values. The first argument\n * is a value from an option. The second is a value from the selection. A boolean\n * should be returned.\n */\n @Input()\n get compareWith() {\n return this._compareWith;\n }\n set compareWith(fn: (o1: any, o2: any) => boolean) {\n if (typeof fn !== 'function') {\n throw getOuiSelectNonFunctionValueError();\n }\n this._compareWith = fn;\n if (this._selectionModel) {\n // A different comparator means the selection could change.\n this._initializeSelection();\n }\n }\n\n /** Value of the select control. */\n @Input()\n get value(): any {\n return this._value;\n }\n set value(newValue: any) {\n if (newValue !== this._value) {\n this.writeValue(newValue);\n this._value = newValue;\n }\n }\n\n /** Unique id of the element. */\n @Input()\n get id(): string {\n return this._id;\n }\n set id(value: string) {\n this._id = value || this._uid;\n this.stateChanges.next();\n }\n\n constructor(\n private _changeDetectorRef: ChangeDetectorRef,\n private _ngZone: NgZone,\n _defaultErrorStateMatcher: ErrorStateMatcher,\n elementRef: ElementRef,\n private _focusMonitor: FocusMonitor,\n @Optional() private _dir: Directionality,\n @Optional() _parentForm: NgForm,\n @Optional() _parentFormGroup: FormGroupDirective,\n @Optional() private _parentFormField: OuiFormField,\n @Self() @Optional() public ngControl: NgControl,\n @Attribute('tabindex') tabIndex: string,\n @Optional() @Inject(DOCUMENT) private _document: any,\n public _elementRef: ElementRef,\n public _ouiIconRegistry: OuiIconRegistry,\n private _domSanitizer: DomSanitizer\n ) {\n super(\n elementRef,\n _defaultErrorStateMatcher,\n _parentForm,\n _parentFormGroup,\n ngControl\n );\n this._monitorSubscription = this._focusMonitor\n .monitor(this._elementRef, true)\n .subscribe(() => this._ngZone.run(() => {}));\n this._ouiIconRegistry.addSvgIconLiteral(\n `select-arrow-icon`,\n this._domSanitizer.bypassSecurityTrustHtml(ICONS.SELECT_ARROW_ICON)\n );\n\n if (this.ngControl) {\n // Note: we provide the value accessor through here, instead of\n // the `providers` to avoid running into a circular import.\n this.ngControl.valueAccessor = this;\n }\n\n this.tabIndex = parseInt(tabIndex, 10) || 0;\n\n // Force setter to be called in case id was not specified.\n this.id = this.id;\n }\n\n ngOnInit() {\n this._selectionModel = new SelectionModel(this.multiple);\n this.stateChanges.next();\n\n // We need `distinctUntilChanged` here, because some browsers will\n // fire the animation end event twice for the same animation. See:\n // https://github.com/angular/angular/issues/24084\n this._panelDoneAnimatingStream\n .pipe(distinctUntilChanged(), takeUntil(this._destroy))\n .subscribe(() => {\n if (this.panelOpen) {\n this._scrollTop = 0;\n this.openedChange.emit(true);\n } else {\n this.openedChange.emit(false);\n this.overlayDir.offsetX = 0;\n this._changeDetectorRef.markForCheck();\n }\n });\n }\n\n ngAfterContentInit() {\n this._initKeyManager();\n\n this._selectionModel.changed\n .pipe(takeUntil(this._destroy))\n .subscribe((event) => {\n event.added.forEach((option) => option.select());\n event.removed.forEach((option) => option.deselect());\n });\n\n this.options.changes\n .pipe(startWith(null), takeUntil(this._destroy))\n .subscribe(() => {\n this._resetOptions();\n this._initializeSelection();\n });\n }\n\n ngDoCheck() {\n if (this.ngControl) {\n this.updateErrorState();\n }\n }\n\n ngOnChanges(changes: SimpleChanges) {\n // Updating the disabled state is handled by `mixinDisabled`, but we need to additionally let\n // the parent form field know to run change detection when the disabled state changes.\n if (changes.disabled) {\n this.stateChanges.next();\n }\n }\n\n ngOnDestroy() {\n this._monitorSubscription.unsubscribe();\n this._focusMonitor.stopMonitoring(this._elementRef);\n this._destroy.next();\n this._destroy.complete();\n this.stateChanges.complete();\n }\n\n /** Toggles the overlay panel open or closed. */\n toggle(): void {\n this.panelOpen ? this.close() : this.open();\n }\n\n /** Opens the overlay panel. */\n open(): void {\n if (\n this.disabled ||\n !this.options ||\n !this.options.length ||\n this._panelOpen\n ) {\n return;\n }\n\n this._triggerRect = this.trigger.nativeElement.getBoundingClientRect();\n\n this._panelOpen = true;\n this._keyManager.withHorizontalOrientation(null);\n\n this._highlightCorrectOption();\n this._changeDetectorRef.markForCheck();\n this.openedChange.emit(true);\n this._elementRef.nativeElement.classList.add(\n 'oui-select-list-options-opened'\n );\n }\n\n /** Closes the overlay panel and focuses the host element. */\n close(): void {\n if (this._panelOpen) {\n this._panelOpen = false;\n this._keyManager.withHorizontalOrientation(this._isRtl() ? 'rtl' : 'ltr');\n this._changeDetectorRef.markForCheck();\n this._onTouched();\n this.openedChange.emit(false);\n this._elementRef.nativeElement.classList.remove(\n 'oui-select-list-options-opened'\n );\n setTimeout((_) => this._document.activeElement.blur());\n }\n }\n\n /**\n * Sets the select's value. Part of the ControlValueAccessor interface\n * required to integrate with Angular's core forms API.\n *\n * @param value New value to be written to the model.\n */\n writeValue(value: any): void {\n if (this.options) {\n this._setSelectionByValue(value);\n }\n }\n\n /**\n * Saves a callback function to be invoked when the select's value\n * changes from user input. Part of the ControlValueAccessor interface\n * required to integrate with Angular's core forms API.\n *\n * @param fn Callback to be triggered when the value changes.\n */\n registerOnChange(fn: (value: any) => void): void {\n this._onChange = fn;\n }\n\n /**\n * Saves a callback function to be invoked when the select is blurred\n * by the user. Part of the ControlValueAccessor interface required\n * to integrate with Angular's core forms API.\n *\n * @param fn Callback to be triggered when the component has been touched.\n */\n registerOnTouched(fn: () => {}): void {\n this._onTouched = fn;\n }\n\n /**\n * Disables the select. Part of the ControlValueAccessor interface required\n * to integrate with Angular's core forms API.\n *\n * @param isDisabled Sets whether the component is disabled.\n */\n setDisabledState(isDisabled: boolean): void {\n this.disabled = isDisabled;\n this._changeDetectorRef.markForCheck();\n this.stateChanges.next();\n }\n\n /** Whether or not the overlay panel is open. */\n get panelOpen(): boolean {\n return this._panelOpen;\n }\n\n /** The currently selected option. */\n get selected(): OuiOption | OuiOption[] {\n return this.multiple\n ? this._selectionModel.selected\n : this._selectionModel.selected[0];\n }\n\n /** The value displayed in the trigger. */\n get triggerValue(): string {\n if (this.empty) {\n return '';\n }\n if (this._multiple) {\n const selectedOptions = this._selectionModel.selected.map(\n (option) => option.viewValueForSelect\n );\n\n if (this._isRtl()) {\n selectedOptions.reverse();\n }\n return selectedOptions.join(', ');\n }\n return this._selectionModel.selected[0].viewValueForSelect;\n }\n\n /** Whether the element is in RTL mode. */\n _isRtl(): boolean {\n return this._dir ? this._dir.value === 'rtl' : false;\n }\n\n /** Handles all keydown events on the select. */\n _handleKeydown(event: KeyboardEvent): void {\n if (!this.disabled) {\n this.panelOpen\n ? this._handleOpenKeydown(event)\n : this._handleClosedKeydown(event);\n }\n }\n\n /** Handles keyboard events while the select is closed. */\n private _handleClosedKeydown(event: KeyboardEvent): void {\n const keyCode = event.keyCode;\n const isArrowKey =\n keyCode === DOWN_ARROW ||\n keyCode === UP_ARROW ||\n keyCode === LEFT_ARROW ||\n keyCode === RIGHT_ARROW;\n const isOpenKey = keyCode === ENTER || keyCode === SPACE;\n const manager = this._keyManager;\n\n // Open the select on ALT + arrow key to match the native \n event.preventDefault();\n this.close();\n } else if (\n (keyCode === ENTER || keyCode === SPACE) &&\n manager.activeItem &&\n !hasModifierKey(event)\n ) {\n event.preventDefault();\n manager.activeItem._selectViaInteraction();\n } else if (this._multiple && keyCode === A && event.ctrlKey) {\n event.preventDefault();\n this.handleCtrlKey();\n } else if (normalNavigationCheck) {\n // Check for non multiple select dropdown that the key pressed is not Tab, Space, Enter\n if (!this.isSearchFieldPresent) this.focus();\n this.handleScrolling(manager, event, isArrowKey, keyCode);\n }\n }\n\n /**\n * Handle ctrl key\n */\n private handleCtrlKey() {\n const hasDeselectedOptions = this.options.some(\n (opt) => !opt.disabled && !opt.selected\n );\n\n this.options.forEach((option) => {\n if (!option.disabled) {\n hasDeselectedOptions ? option.select() : option.deselect();\n }\n });\n }\n\n /**\n * @param manager\n * @param event\n * @param isArrowKey\n * @param keyCode\n */\n private handleScrolling(\n manager: ActiveDescendantKeyManager,\n event: KeyboardEvent,\n isArrowKey: boolean,\n keyCode: number\n ) {\n const previouslyFocusedIndex = manager.activeItemIndex;\n\n manager.onKeydown(event);\n\n if (\n this._multiple &&\n isArrowKey &&\n event.shiftKey &&\n manager.activeItem &&\n manager.activeItemIndex !== previouslyFocusedIndex\n ) {\n manager.activeItem._selectViaInteraction();\n }\n if (isArrowKey && manager.activeItemIndex !== previouslyFocusedIndex) {\n this._scrollToOption();\n } else {\n // First or last\n if (keyCode === DOWN_ARROW) {\n manager.setFirstItemActive();\n this._setScrollTop(0);\n }\n if (keyCode === UP_ARROW) {\n manager.setLastItemActive();\n this._scrollToOption();\n }\n }\n }\n\n _onFocus() {\n if (!this.disabled) {\n this._focused = true;\n this.stateChanges.next();\n }\n }\n\n /**\n * Calls the touched callback only if the panel is closed. Otherwise, the trigger will\n * \"blur\" to the panel when it opens, causing a false positive.\n */\n _onBlur() {\n this._focused = false;\n // this.isSearchFieldPresent = false;\n\n if (!this.disabled && !this.panelOpen) {\n this._onTouched();\n this._changeDetectorRef.markForCheck();\n this.stateChanges.next();\n }\n }\n\n /**\n * Callback that is invoked when the overlay panel has been attached.\n */\n _onAttached(): void {\n this.overlayDir.positionChange.pipe(take(1)).subscribe(() => {\n this._setPseudoCheckboxPaddingSize();\n this._changeDetectorRef.detectChanges();\n this.panel.nativeElement.scrollTop = this._scrollTop;\n });\n }\n\n /** Returns the theme to be used on the panel. */\n _getPanelTheme(): string {\n return this._parentFormField ? `oui-${this._parentFormField.color}` : '';\n }\n\n // TODO(josephperrott): Remove after 2018 spec updates are fully merged.\n /** Sets the pseudo checkbox padding size based on the width of the pseudo checkbox. */\n private _setPseudoCheckboxPaddingSize() {\n if (!SELECT_MULTIPLE_PANEL_PADDING_X && this.multiple) {\n const pseudoCheckbox = this.panel.nativeElement.querySelector(\n '.oui-pseudo-checkbox'\n );\n if (pseudoCheckbox) {\n SELECT_MULTIPLE_PANEL_PADDING_X =\n SELECT_PANEL_PADDING_X * 1.5 + pseudoCheckbox.offsetWidth;\n }\n }\n }\n\n /** Whether the select has a value. */\n get empty(): boolean {\n return !this._selectionModel || this._selectionModel.isEmpty();\n }\n\n private _initializeSelection(): void {\n // Defer setting the value in order to avoid the \"Expression\n // has changed after it was checked\" errors from Angular.\n Promise.resolve().then(() => {\n this._setSelectionByValue(\n this.ngControl ? this.ngControl.value : this._value\n );\n this.savedValues = this.ngControl ? this.ngControl.value : this._value;\n if (this.multiple) {\n this._highlightFirstFilteredOption();\n }\n });\n }\n\n /**\n * Sets the selected option based on a value. If no option can be\n * found with the designated value, the select trigger is cleared.\n */\n private _setSelectionByValue(value: any | any[]): void {\n if (this.multiple && value) {\n if (!Array.isArray(value)) {\n throw getOuiSelectNonArrayValueError();\n }\n\n this._selectionModel.clear();\n value.forEach((currentValue: any) => this._selectValue(currentValue));\n this._sortValues();\n } else {\n this._selectionModel.clear();\n const correspondingOption = this._selectValue(value);\n // Shift focus to the active item. Note that we shouldn't do this in multiple\n // mode, because we don't know what option the user interacted with last.\n if (correspondingOption) {\n this._keyManager.setActiveItem(correspondingOption);\n }\n }\n this._changeDetectorRef.markForCheck();\n }\n\n /**\n * Finds and selects and option based on its value.\n *\n * @returns Option that has the corresponding value.\n */\n private _selectValue(value: any): OuiOption | undefined {\n const correspondingOption = this.options.find((option: OuiOption) => {\n try {\n // Treat null as a special reset value.\n return option.value != null && this._compareWith(option.value, value);\n } catch (error) {\n if (isDevMode()) {\n // Notify developers of errors in their comparator.\n console.warn(error);\n }\n return false;\n }\n });\n\n if (correspondingOption) {\n this._selectionModel.select(correspondingOption);\n }\n\n return correspondingOption;\n }\n\n /** Sets up a key manager to listen to keyboard events on the overlay panel. */\n private _initKeyManager() {\n this._keyManager = new ActiveDescendantKeyManager(this.options)\n .withTypeAhead()\n .withVerticalOrientation()\n .withHorizontalOrientation(this._isRtl() ? 'rtl' : 'ltr')\n .withAllowedModifierKeys(['shiftKey']);\n\n this._keyManager.tabOut.pipe(takeUntil(this._destroy)).subscribe(() => {\n // Restore focus to the trigger before closing. Ensures that the focus\n // position won't be lost if the user got focus into the overlay.\n this.focus();\n this.close();\n });\n\n this._keyManager.change.pipe(takeUntil(this._destroy)).subscribe(() => {\n if (this._panelOpen && this.panel) {\n // Panel is opened\n // Need not to scroll\n } else if (\n !this._panelOpen &&\n !this.multiple &&\n this._keyManager.activeItem\n ) {\n this._keyManager.activeItem._selectViaInteraction();\n }\n });\n }\n\n /** Drops current option subscriptions and IDs and resets from scratch. */\n private _resetOptions(): void {\n const changedOrDestroyed = merge(this.options.changes, this._destroy);\n\n this.optionSelectionChanges\n .pipe(takeUntil(changedOrDestroyed))\n .subscribe((event) => {\n this._onSelect(event.source, event.isUserInput);\n\n if (event.isUserInput && !this.multiple && this._panelOpen) {\n this.close();\n this.focus();\n }\n });\n\n // Listen to changes in the internal state of the options and react accordingly.\n // Handles cases like the labels of the selected options changing.\n merge(...this.options.map((option) => option._stateChanges))\n .pipe(takeUntil(changedOrDestroyed))\n .subscribe(() => {\n this._changeDetectorRef.markForCheck();\n this.stateChanges.next();\n });\n\n this._setOptionIds();\n }\n\n /** Invoked when an option is clicked. */\n private _onSelect(option: OuiOption, isUserInput: boolean): void {\n const wasSelected = this._selectionModel.isSelected(option);\n\n if (option.value == null && !this._multiple) {\n option.deselect();\n this._selectionModel.clear();\n this._propagateChanges(option.value);\n } else {\n option.selected\n ? this._selectionModel.select(option)\n : this._selectionModel.deselect(option);\n\n if (isUserInput) {\n this._keyManager.setActiveItem(option);\n }\n\n if (this.multiple) {\n this._sortValues();\n\n if (isUserInput) {\n // In case the user selected the option with their mouse, we\n // want to restore focus back to the trigger, in order to\n // prevent the select keyboard controls from clashing with\n // the ones from `oui-option`.\n this.focus();\n }\n }\n }\n\n if (wasSelected !== this._selectionModel.isSelected(option)) {\n this._propagateChanges();\n }\n this.disableDoneButton = false;\n this.stateChanges.next();\n }\n discardRecentChanges() {\n this.value = this.savedValues;\n this._setSelectionByValue(this.value);\n this.disableDoneButton = true;\n this.close();\n }\n doneRecentChanges() {\n this.savedValues = this.value;\n this.disableDoneButton = true;\n this.saveSelectionChange.emit(new OuiSelectChange(this, this.value));\n this.close();\n }\n /** Sorts the selected values in the selected based on their order in the panel. */\n private _sortValues() {\n if (this.multiple) {\n const options = this.options.toArray();\n\n this._selectionModel.sort((a, b) =>\n this.sortComparator\n ? this.sortComparator(a, b, options)\n : options.indexOf(a) - options.indexOf(b)\n );\n this.stateChanges.next();\n }\n }\n\n /** Emits change event to set the model value. */\n private _propagateChanges(fallbackValue?: any): void {\n let valueToEmit: any = null;\n\n if (this.multiple) {\n valueToEmit = (this.selected as OuiOption[]).map(\n (option) => option.value\n );\n } else {\n valueToEmit = this.selected\n ? (this.selected as OuiOption).value\n : fallbackValue;\n }\n\n this._value = valueToEmit;\n this.valueChange.emit(valueToEmit);\n this._onChange(valueToEmit);\n this.selectionChange.emit(new OuiSelectChange(this, valueToEmit));\n this._changeDetectorRef.markForCheck();\n }\n\n /** Records option IDs to pass to the aria-owns property. */\n private _setOptionIds() {\n this._optionIds = this.options.map((option) => option.id).join(' ');\n }\n\n /**\n * Highlights the selected item. If no option is selected, it will highlight\n * the first item instead.\n */\n private _highlightCorrectOption(): void {\n if (this.multiple) {\n this._highlightFirstFilteredOption();\n } else if (this._keyManager) {\n if (this.empty) {\n this._keyManager.setFirstItemActive();\n } else {\n this._keyManager.setActiveItem(this._selectionModel.selected[0]);\n }\n }\n }\n\n /**\n * Highlights the first of the filtered options if no element is currently highlighted\n */\n private _highlightFirstFilteredOption(): void {\n if (this._keyManager) {\n const activeElement = this._keyManager.activeItem?._getHostElement();\n // activeElement is not part of DOM if there is no parent element\n if (!activeElement || !activeElement.parentElement) {\n // highlight first element if there is no active element or active element is not part of DOM\n this._keyManager.setFirstItemActive();\n }\n }\n }\n\n /** Focuses the select element. */\n focus(): void {\n this._elementRef.nativeElement.focus();\n }\n\n /** Returns the aria-label of the select component. */\n _getAriaLabel(): string | null {\n // If an ariaLabelledby value has been set by the consumer, the select should not overwrite the\n // `aria-labelledby` value by setting the ariaLabel to the placeholder.\n return this.ariaLabelledby ? null : this.ariaLabel || this.placeholder;\n }\n\n /** Returns the aria-labelledby of the select component. */\n _getAriaLabelledby(): string | null {\n if (this.ariaLabelledby) {\n return this.ariaLabelledby;\n }\n\n return null;\n }\n\n /** Determines the `aria-activedescendant` to be set on the host. */\n _getAriaActiveDescendant(): string | null {\n if (this.panelOpen && this._keyManager && this._keyManager.activeItem) {\n return this._keyManager.activeItem.id;\n }\n\n return null;\n }\n\n /**\n * Implemented as part of OuiFormFieldControl.\n *\n * @docs-private\n */\n setDescribedByIds(ids: string[]) {\n this._ariaDescribedby = ids.join(' ');\n }\n\n /**\n * Implemented as part of OuiFormFieldControl.\n *\n * @docs-private\n */\n onContainerClick() {\n this.focus();\n this.open();\n }\n\n /**\n * Implemented as part of OuiFormFieldControl.\n *\n * @docs-private\n */\n get shouldLabelFloat(): boolean {\n return this._panelOpen || !this.empty;\n }\n\n /**\n * Add outer class to perfect scrollbar\n * This is added only when there is a search field\n */\n ouiSelectInputOuter() {\n this.ouiSelectInputOuterClassName = 'oui-select-input-outer';\n }\n\n /**\n * Custom overlay class for cdk overlay container\n */\n openCdk() {\n this.overlayDir.positionChange.pipe(take(1)).subscribe((e) => {\n this.cdkConnectionOverlayPanel = '';\n if (e.connectionPair.originY === 'top') {\n this.cdkConnectionOverlayPanel = 'select-overlay-top';\n }\n this._changeDetectorRef.detectChanges();\n setTimeout((_) => this._scrollToOption());\n });\n\n const cdkOverLayContainer = this._document.querySelector(\n '.cdk-overlay-container'\n );\n const ouiSelectPanel = this._document.querySelector('.oui-select-panel');\n cdkOverLayContainer.classList.add('oui-select-overlay-container');\n const containerWidth = this._elementRef.nativeElement.offsetWidth;\n ouiSelectPanel.style.width = `${containerWidth}px`;\n const searchQueryString = '.oui-select-search-inner';\n if (this._document.querySelector(searchQueryString)) {\n this.scrollCalc(searchQueryString);\n this.isSearchFieldPresent = true;\n }\n }\n scrollCalc(selectQueryString: string) {\n const searchInput = this._document.querySelector(selectQueryString);\n const outter = this._document.querySelector('.oui-select-panel');\n let inner = this._document.querySelector('.oui-option');\n if (inner === null) {\n inner = 0;\n }\n const scrollbarWidth = outter.offsetWidth - inner.offsetWidth;\n if (scrollbarWidth > 5) {\n searchInput.style.width = `${inner.offsetWidth}px`;\n } else {\n searchInput.style.width = `calc(100% + 8px)`;\n }\n }\n\n /**\n * Given that we are not actually focusing active options, we must manually adjust scroll\n * to reveal options below the fold. First, we find the offset of the option from the top\n * of the panel. If that offset is below the fold, the new scrollTop will be the offset -\n * the panel height + the option height, so the active option will be just visible at the\n * bottom of the panel. If that offset is above the top of the visible panel, the new scrollTop\n * will become the offset. If that offset is visible within the panel already, the scrollTop is\n * not adjusted.\n */\n private _scrollToOption(): void {\n const manager = this._keyManager;\n const index = manager.activeItemIndex || 0;\n const labelCount = _countGroupLabelsBeforeOption(\n index,\n this.options,\n this.optionGroups\n );\n const scrollTop = this._getScrollTop();\n const newScrollPosition = _getOptionScrollPosition(\n index + labelCount,\n SELECT_OPTION_HEIGHT,\n scrollTop,\n this.actionItems && this.isSearchFieldPresent && labelCount\n ? SELECT_PANEL_HEIGHT - (50 + labelCount * 19)\n : (this.actionItems && this.isSearchFieldPresent && !labelCount) ||\n (this.actionItems && !this.isSearchFieldPresent && labelCount) ||\n (!this.actionItems && this.isSearchFieldPresent && labelCount)\n ? SELECT_PANEL_HEIGHT - 50\n : SELECT_PANEL_HEIGHT\n );\n this._setScrollTop(newScrollPosition);\n }\n\n /**\n * Sets the panel scrollTop. This allows us to manually scroll to display options\n * above or below the fold, as they are not actually being focused when active.\n */\n _setScrollTop(scrollTop: number): void {\n if (this.panel) {\n this.panel.nativeElement.querySelector('.oui-select-options').scrollTop =\n scrollTop;\n }\n }\n\n /** Returns the panel's scrollTop. */\n _getScrollTop(): number {\n return this.panel ? this.panel.nativeElement.scrollTop : 0;\n }\n}\n", + "sourceCode": "import { ActiveDescendantKeyManager, FocusMonitor } from '@angular/cdk/a11y';\r\nimport { Directionality } from '@angular/cdk/bidi';\r\nimport { coerceBooleanProperty } from '@angular/cdk/coercion';\r\nimport { SelectionModel } from '@angular/cdk/collections';\r\nimport {\r\n A,\r\n DOWN_ARROW,\r\n END,\r\n ENTER,\r\n HOME,\r\n LEFT_ARROW,\r\n RIGHT_ARROW,\r\n SPACE,\r\n UP_ARROW,\r\n hasModifierKey,\r\n TAB,\r\n} from '@angular/cdk/keycodes';\r\nimport { CdkConnectedOverlay } from '@angular/cdk/overlay';\r\nimport {\r\n AfterContentInit,\r\n Attribute,\r\n ChangeDetectionStrategy,\r\n ChangeDetectorRef,\r\n Component,\r\n ContentChild,\r\n ContentChildren,\r\n Directive,\r\n DoCheck,\r\n ElementRef,\r\n EventEmitter,\r\n Input,\r\n isDevMode,\r\n NgZone,\r\n OnChanges,\r\n OnDestroy,\r\n OnInit,\r\n Optional,\r\n Output,\r\n QueryList,\r\n Self,\r\n SimpleChanges,\r\n ViewChild,\r\n ViewEncapsulation,\r\n Inject,\r\n} from '@angular/core';\r\nimport {\r\n ControlValueAccessor,\r\n FormGroupDirective,\r\n NgControl,\r\n NgForm,\r\n} from '@angular/forms';\r\nimport {\r\n _countGroupLabelsBeforeOption,\r\n _getOptionScrollPosition,\r\n CanDisable,\r\n CanDisableCtor,\r\n CanUpdateErrorState,\r\n CanUpdateErrorStateCtor,\r\n HasTabIndex,\r\n HasTabIndexCtor,\r\n OuiOptionSelectionChange,\r\n mixinErrorState,\r\n mixinTabIndex,\r\n mixinDisabled,\r\n} from '../core';\r\nimport { OuiFormField, OuiFormFieldControl } from '../form-field/public-api';\r\nimport { DOCUMENT } from '@angular/common';\r\nimport { OUI_OPTION_PARENT_COMPONENT, OuiOption } from '../core/option/option';\r\nimport { OuiOptgroup } from '../core/option/optgroup';\r\nimport { ErrorStateMatcher } from '../core/error/error-options';\r\nimport { defer, merge, Observable, Subject } from 'rxjs';\r\nimport {\r\n distinctUntilChanged,\r\n filter,\r\n map,\r\n startWith,\r\n switchMap,\r\n take,\r\n takeUntil,\r\n} from 'rxjs/operators';\r\nimport {\r\n getOuiSelectDynamicMultipleError,\r\n getOuiSelectNonArrayValueError,\r\n getOuiSelectNonFunctionValueError,\r\n} from './select-errors';\r\nimport { OuiIconRegistry } from '../icon/icon-registery';\r\nimport { DomSanitizer } from '@angular/platform-browser';\r\nimport { ICONS } from '../core/shared/icons';\r\n\r\nlet nextUniqueId = 0;\r\n\r\n/**\r\n * The following style constants are necessary to save here in order\r\n * to properly calculate the alignment of the selected option over\r\n * the trigger element.\r\n */\r\n\r\n/** The height of each select option. */\r\nexport const SELECT_OPTION_HEIGHT = 40;\r\n\r\n/** The panel's padding on the x-axis */\r\nexport const SELECT_PANEL_PADDING_X = 16;\r\n\r\n/** The panel's x axis padding if it is indented (e.g. there is an option group). */\r\nexport const SELECT_PANEL_INDENT_PADDING_X = SELECT_PANEL_PADDING_X * 2;\r\n\r\n/** The height of the select items in `em` units. */\r\nexport const SELECT_ITEM_HEIGHT_EM = 3;\r\n\r\n/** The total height of the select panel. */\r\nexport const SELECT_PANEL_HEIGHT = 200;\r\n\r\n// TODO(josephperrott): Revert to a constant after 2018 spec updates are fully merged.\r\n/**\r\n * Distance between the panel edge and the option text in\r\n * multi-selection mode.\r\n *\r\n * Calculated as:\r\n * (SELECT_PANEL_PADDING_X * 1.5) + 20 = 44\r\n * The padding is multiplied by 1.5 because the checkbox's margin is half the padding.\r\n * The checkbox width is 16px.\r\n */\r\nexport let SELECT_MULTIPLE_PANEL_PADDING_X = 0;\r\n\r\n/**\r\n * The select panel will only \"fit\" inside the viewport if it is positioned at\r\n * this value or more away from the viewport boundary.\r\n */\r\nexport const SELECT_PANEL_VIEWPORT_PADDING = 8;\r\n\r\n/** Change event object that is emitted when the select value has changed. */\r\nexport class OuiSelectChange {\r\n constructor(\r\n /** Reference to the select that emitted the change event. */\r\n public source: OuiSelect,\r\n /** Current value of the select that emitted the event. */\r\n public value: any\r\n ) {}\r\n}\r\n\r\n// Boilerplate for applying mixins to OuiSelect.\r\n/** @docs-private */\r\nexport class OuiSelectBase {\r\n constructor(\r\n public _elementRef: ElementRef,\r\n public _defaultErrorStateMatcher: ErrorStateMatcher,\r\n public _parentForm: NgForm,\r\n public _parentFormGroup: FormGroupDirective,\r\n public ngControl: NgControl\r\n ) {}\r\n}\r\n\r\nexport const _OuiSelectMixinBase: CanDisableCtor &\r\n HasTabIndexCtor &\r\n CanUpdateErrorStateCtor &\r\n typeof OuiSelectBase = mixinTabIndex(\r\n mixinDisabled(mixinErrorState(OuiSelectBase))\r\n);\r\n\r\n/**\r\n * Allows the user to customize the trigger that is displayed when the select has a value.\r\n */\r\n@Directive({\r\n // eslint-disable-next-line @angular-eslint/directive-selector\r\n selector: 'oui-select-trigger',\r\n})\r\nexport class OuiSelectTrigger {}\r\n\r\n@Component({\r\n selector: 'oui-select',\r\n exportAs: 'ouiSelect',\r\n templateUrl: 'select.html',\r\n styleUrls: ['select.scss'],\r\n // eslint-disable-next-line @angular-eslint/no-inputs-metadata-property\r\n inputs: ['disabled', 'tabIndex'],\r\n encapsulation: ViewEncapsulation.None,\r\n changeDetection: ChangeDetectionStrategy.OnPush,\r\n // eslint-disable-next-line @angular-eslint/no-host-metadata-property\r\n host: {\r\n role: 'listbox',\r\n '[attr.id]': 'id',\r\n '[attr.tabindex]': 'tabIndex',\r\n '[attr.aria-label]': '_getAriaLabel()',\r\n '[attr.aria-labelledby]': '_getAriaLabelledby()',\r\n '[attr.aria-required]': 'required.toString()',\r\n '[attr.aria-disabled]': 'disabled.toString()',\r\n '[attr.aria-invalid]': 'errorState',\r\n '[attr.aria-owns]': 'panelOpen ? _optionIds : null',\r\n '[attr.aria-multiselectable]': 'multiple',\r\n '[attr.aria-describedby]': '_ariaDescribedby || null',\r\n '[attr.aria-activedescendant]': '_getAriaActiveDescendant()',\r\n '[class.oui-select-disabled]': 'disabled',\r\n '[class.oui-select-invalid]': 'errorState',\r\n '[class.oui-select-required]': 'required',\r\n '[class.oui-select-empty]': 'empty',\r\n class: 'oui-select oui-input',\r\n '(keydown)': '_handleKeydown($event)',\r\n '(focus)': '_onFocus()',\r\n '(blur)': '_onBlur()',\r\n },\r\n providers: [\r\n { provide: OuiFormFieldControl, useExisting: OuiSelect },\r\n { provide: OUI_OPTION_PARENT_COMPONENT, useExisting: OuiSelect },\r\n ],\r\n})\r\nexport class OuiSelect\r\n extends _OuiSelectMixinBase\r\n implements\r\n AfterContentInit,\r\n OnChanges,\r\n OnDestroy,\r\n OnInit,\r\n DoCheck,\r\n ControlValueAccessor,\r\n CanDisable,\r\n HasTabIndex,\r\n OuiFormFieldControl,\r\n CanUpdateErrorState\r\n{\r\n /**Holds selected values after done */\r\n @Input() savedValues = [];\r\n /**Done button disabled until dropdown is dirty */\r\n disableDoneButton = true;\r\n /** Whether or not the overlay panel is open. */\r\n private _panelOpen = false;\r\n\r\n /** Whether filling out the select is required in the form. */\r\n private _required = false;\r\n\r\n /** Whether filling out the select is required in the form. */\r\n private _actionItems = false;\r\n\r\n /** The scroll position of the overlay panel, calculated to center the selected option. */\r\n private _scrollTop = 0;\r\n\r\n /** The placeholder displayed in the trigger of the select. */\r\n private _placeholder: string;\r\n\r\n /** Whether the component is in multiple selection mode. */\r\n private _multiple = false;\r\n\r\n /** Search input field **/\r\n isSearchFieldPresent: boolean;\r\n\r\n /** Unique id for this input. */\r\n private _uid = `oui-select-${nextUniqueId++}`;\r\n\r\n /** The last measured value for the trigger's client bounding rect. */\r\n _triggerRect: ClientRect;\r\n\r\n /** The aria-describedby attribute on the select for improved a11y. */\r\n _ariaDescribedby: string;\r\n\r\n /** The cached font-size of the trigger element. */\r\n _triggerFontSize = 0;\r\n\r\n /** Deals with the selection logic. */\r\n _selectionModel: SelectionModel;\r\n\r\n /** Manages keyboard events for options in the panel. */\r\n _keyManager: ActiveDescendantKeyManager;\r\n\r\n /** The IDs of child options to be passed to the aria-owns attribute. */\r\n _optionIds = '';\r\n\r\n /** The value of the select panel's transform-origin property. */\r\n _transformOrigin = 'top';\r\n\r\n /** If there is search input field a class is added dynamically to the perfect scrollbar **/\r\n ouiSelectInputOuterClassName: string;\r\n\r\n /** Adding top class to overlay panel */\r\n cdkConnectionOverlayPanel = '';\r\n\r\n /**\r\n * The y-offset of the overlay panel in relation to the trigger's top start corner.\r\n * This must be adjusted to align the selected option text over the trigger text.\r\n * when the panel opens. Will change based on the y-position of the selected option.\r\n */\r\n _offsetY = 0;\r\n\r\n /**\r\n * This position config ensures that the top \"start\" corner of the overlay\r\n * is aligned with with the top \"start\" of the origin by default (overlapping\r\n * the trigger completely). If the panel cannot fit below the trigger, it\r\n * will fall back to a position above the trigger.\r\n */\r\n _positions = [\r\n {\r\n originX: 'start',\r\n originY: 'top',\r\n overlayX: 'start',\r\n overlayY: 'top',\r\n },\r\n {\r\n originX: 'start',\r\n originY: 'bottom',\r\n overlayX: 'start',\r\n overlayY: 'bottom',\r\n },\r\n ];\r\n /** Emits whenever the component is destroyed. */\r\n private readonly _destroy = new Subject();\r\n\r\n /** Whether the component is disabling centering of the active option over the trigger. */\r\n private _disableOptionCentering = false;\r\n\r\n private _focused = false;\r\n\r\n /** A name for this control that can be used by `oui-form-field`. */\r\n controlType = 'oui-select';\r\n\r\n /** Trigger that opens the select. */\r\n @ViewChild('trigger') trigger: ElementRef;\r\n\r\n /** Trigger that opens the select. */\r\n @ViewChild('ddCancelButton', { read: ElementRef }) ddCancelButton: ElementRef;\r\n\r\n /** Trigger that opens the select. */\r\n @ViewChild('ddDoneButton', { read: ElementRef }) ddDoneButton: ElementRef;\r\n\r\n /** Panel containing the select options. */\r\n @ViewChild('panel', { read: ElementRef }) panel: ElementRef;\r\n\r\n private _value: any;\r\n\r\n /**\r\n * Function used to sort the values in a select in multiple mode.\r\n * Follows the same logic as `Array.prototype.sort`.\r\n */\r\n @Input() sortComparator: (\r\n a: OuiOption,\r\n b: OuiOption,\r\n options: OuiOption[]\r\n ) => number;\r\n\r\n /** Aria label of the select. If not specified, the placeholder will be used as label. */\r\n @Input('aria-label') ariaLabel = '';\r\n\r\n /** Input that can be used to specify the `aria-labelledby` attribute. */\r\n @Input('aria-labelledby') ariaLabelledby: string;\r\n private _large = false;\r\n _monitorSubscription: any;\r\n\r\n /** Whether the oui-select is of large size. */\r\n @Input()\r\n get large(): boolean {\r\n return this._large;\r\n }\r\n set large(value) {\r\n this._large = coerceBooleanProperty(value);\r\n this._changeDetectorRef.markForCheck();\r\n }\r\n\r\n private _id: string;\r\n\r\n /** Event emitted when the select panel has been toggled. */\r\n @Output()\r\n readonly openedChange: EventEmitter = new EventEmitter();\r\n\r\n /** Combined stream of all of the child options' change events. */\r\n readonly optionSelectionChanges: Observable = defer(\r\n (): Observable => {\r\n if (this.options) {\r\n return merge(...this.options.map((option) => option.onSelectionChange));\r\n }\r\n\r\n return this._ngZone.onStable.asObservable().pipe(\r\n take(1),\r\n switchMap(() => this.optionSelectionChanges)\r\n );\r\n }\r\n );\r\n\r\n /**\r\n * Event that emits whenever the raw value of the select changes. This is here primarily\r\n * to facilitate the two-way binding for the `value` input.\r\n *\r\n * @docs-private\r\n */\r\n @Output() readonly valueChange: EventEmitter = new EventEmitter();\r\n\r\n /** Object used to control when error messages are shown. */\r\n @Input() errorStateMatcher: ErrorStateMatcher;\r\n\r\n /** All of the defined select options. */\r\n @ContentChildren(OuiOption, { descendants: true })\r\n options: QueryList;\r\n\r\n /** Event emitted when the select has been opened. */\r\n // eslint-disable-next-line @angular-eslint/no-output-rename\r\n @Output('opened')\r\n readonly _openedStream: Observable = this.openedChange.pipe(\r\n filter((o) => o),\r\n map(() => {})\r\n );\r\n\r\n /** Event emitted when the select has been closed. */\r\n // eslint-disable-next-line @angular-eslint/no-output-rename\r\n @Output('closed')\r\n readonly _closedStream: Observable = this.openedChange.pipe(\r\n filter((o) => !o),\r\n map(() => {\r\n this.isSearchFieldPresent = false;\r\n })\r\n );\r\n\r\n /** Event emitted when the selected value has been changed by the user. */\r\n @Output()\r\n readonly selectionChange: EventEmitter =\r\n new EventEmitter();\r\n\r\n /** Event emitted when the selected value has been changed and saved by the user. */\r\n @Output()\r\n readonly saveSelectionChange: EventEmitter =\r\n new EventEmitter();\r\n\r\n /** All of the defined groups of options. */\r\n @ContentChildren(OuiOptgroup) optionGroups: QueryList;\r\n\r\n /** User-supplied override of the trigger element. */\r\n @ContentChild(OuiSelectTrigger)\r\n customTrigger: OuiSelectTrigger;\r\n\r\n /** Classes to be passed to the select panel. Supports the same syntax as `ngClass`. */\r\n @Input() panelClass: string | string[] | Set | { [key: string]: any };\r\n\r\n /** Overlay pane containing the options. */\r\n @ViewChild(CdkConnectedOverlay)\r\n overlayDir: CdkConnectedOverlay;\r\n\r\n /** Emits when the panel element is finished transforming in. */\r\n _panelDoneAnimatingStream = new Subject();\r\n\r\n /** Comparison function to specify which option is displayed. Defaults to object equality. */\r\n private _compareWith = (o1: any, o2: any) => o1 === o2;\r\n\r\n /** Whether the select is focused. */\r\n get focused(): boolean {\r\n return this._focused || this._panelOpen;\r\n }\r\n /**\r\n * @deprecated Setter to be removed as this property is intended to be readonly.\r\n */\r\n set focused(value: boolean) {\r\n this._focused = value;\r\n }\r\n /** `View -> model callback called when value changes` */\r\n _onChange: (value: any) => void = () => {};\r\n\r\n /** `View -> model callback called when select has been touched` */\r\n _onTouched = () => {};\r\n\r\n /** Placeholder to be shown if no value has been selected. */\r\n @Input()\r\n get placeholder(): string {\r\n return this._placeholder;\r\n }\r\n set placeholder(value: string) {\r\n this._placeholder = value;\r\n this.stateChanges.next();\r\n }\r\n\r\n /** Whether the component is required. */\r\n @Input()\r\n get required(): boolean {\r\n return this._required;\r\n }\r\n set required(value: boolean) {\r\n this._required = coerceBooleanProperty(value);\r\n this.stateChanges.next();\r\n }\r\n\r\n /** Whether the user should be allowed to select multiple options. */\r\n @Input()\r\n get multiple(): boolean {\r\n return this._multiple;\r\n }\r\n set multiple(value: boolean) {\r\n if (this._selectionModel) {\r\n throw getOuiSelectDynamicMultipleError();\r\n }\r\n\r\n this._multiple = coerceBooleanProperty(value);\r\n }\r\n\r\n /** Whether the action items are required and use saveSelectionChange instead of selectionChange. */\r\n @Input()\r\n get actionItems(): boolean {\r\n return this._actionItems;\r\n }\r\n set actionItems(value: boolean) {\r\n if (this._multiple) {\r\n this._actionItems = coerceBooleanProperty(value);\r\n this.stateChanges.next();\r\n }\r\n }\r\n\r\n /** Whether to center the active option over the trigger. */\r\n @Input()\r\n get disableOptionCentering(): boolean {\r\n return this._disableOptionCentering;\r\n }\r\n set disableOptionCentering(value: boolean) {\r\n this._disableOptionCentering = coerceBooleanProperty(value);\r\n }\r\n\r\n /**\r\n * Function to compare the option values with the selected values. The first argument\r\n * is a value from an option. The second is a value from the selection. A boolean\r\n * should be returned.\r\n */\r\n @Input()\r\n get compareWith() {\r\n return this._compareWith;\r\n }\r\n set compareWith(fn: (o1: any, o2: any) => boolean) {\r\n if (typeof fn !== 'function') {\r\n throw getOuiSelectNonFunctionValueError();\r\n }\r\n this._compareWith = fn;\r\n if (this._selectionModel) {\r\n // A different comparator means the selection could change.\r\n this._initializeSelection();\r\n }\r\n }\r\n\r\n /** Value of the select control. */\r\n @Input()\r\n get value(): any {\r\n return this._value;\r\n }\r\n set value(newValue: any) {\r\n if (newValue !== this._value) {\r\n this.writeValue(newValue);\r\n this._value = newValue;\r\n }\r\n }\r\n\r\n /** Unique id of the element. */\r\n @Input()\r\n get id(): string {\r\n return this._id;\r\n }\r\n set id(value: string) {\r\n this._id = value || this._uid;\r\n this.stateChanges.next();\r\n }\r\n\r\n constructor(\r\n private _changeDetectorRef: ChangeDetectorRef,\r\n private _ngZone: NgZone,\r\n _defaultErrorStateMatcher: ErrorStateMatcher,\r\n elementRef: ElementRef,\r\n private _focusMonitor: FocusMonitor,\r\n @Optional() private _dir: Directionality,\r\n @Optional() _parentForm: NgForm,\r\n @Optional() _parentFormGroup: FormGroupDirective,\r\n @Optional() private _parentFormField: OuiFormField,\r\n @Self() @Optional() public ngControl: NgControl,\r\n @Attribute('tabindex') tabIndex: string,\r\n @Optional() @Inject(DOCUMENT) private _document: any,\r\n public _elementRef: ElementRef,\r\n public _ouiIconRegistry: OuiIconRegistry,\r\n private _domSanitizer: DomSanitizer\r\n ) {\r\n super(\r\n elementRef,\r\n _defaultErrorStateMatcher,\r\n _parentForm,\r\n _parentFormGroup,\r\n ngControl\r\n );\r\n this._monitorSubscription = this._focusMonitor\r\n .monitor(this._elementRef, true)\r\n .subscribe(() => this._ngZone.run(() => {}));\r\n this._ouiIconRegistry.addSvgIconLiteral(\r\n `select-arrow-icon`,\r\n this._domSanitizer.bypassSecurityTrustHtml(ICONS.SELECT_ARROW_ICON)\r\n );\r\n\r\n if (this.ngControl) {\r\n // Note: we provide the value accessor through here, instead of\r\n // the `providers` to avoid running into a circular import.\r\n this.ngControl.valueAccessor = this;\r\n }\r\n\r\n this.tabIndex = parseInt(tabIndex, 10) || 0;\r\n\r\n // Force setter to be called in case id was not specified.\r\n this.id = this.id;\r\n }\r\n\r\n ngOnInit() {\r\n this._selectionModel = new SelectionModel(this.multiple);\r\n this.stateChanges.next();\r\n\r\n // We need `distinctUntilChanged` here, because some browsers will\r\n // fire the animation end event twice for the same animation. See:\r\n // https://github.com/angular/angular/issues/24084\r\n this._panelDoneAnimatingStream\r\n .pipe(distinctUntilChanged(), takeUntil(this._destroy))\r\n .subscribe(() => {\r\n if (this.panelOpen) {\r\n this._scrollTop = 0;\r\n this.openedChange.emit(true);\r\n } else {\r\n this.openedChange.emit(false);\r\n this.overlayDir.offsetX = 0;\r\n this._changeDetectorRef.markForCheck();\r\n }\r\n });\r\n }\r\n\r\n ngAfterContentInit() {\r\n this._initKeyManager();\r\n\r\n this._selectionModel.changed\r\n .pipe(takeUntil(this._destroy))\r\n .subscribe((event) => {\r\n event.added.forEach((option) => option.select());\r\n event.removed.forEach((option) => option.deselect());\r\n });\r\n\r\n this.options.changes\r\n .pipe(startWith(null), takeUntil(this._destroy))\r\n .subscribe(() => {\r\n this._resetOptions();\r\n this._initializeSelection();\r\n });\r\n }\r\n\r\n ngDoCheck() {\r\n if (this.ngControl) {\r\n this.updateErrorState();\r\n }\r\n }\r\n\r\n ngOnChanges(changes: SimpleChanges) {\r\n // Updating the disabled state is handled by `mixinDisabled`, but we need to additionally let\r\n // the parent form field know to run change detection when the disabled state changes.\r\n if (changes.disabled) {\r\n this.stateChanges.next();\r\n }\r\n }\r\n\r\n ngOnDestroy() {\r\n this._monitorSubscription.unsubscribe();\r\n this._focusMonitor.stopMonitoring(this._elementRef);\r\n this._destroy.next();\r\n this._destroy.complete();\r\n this.stateChanges.complete();\r\n }\r\n\r\n /** Toggles the overlay panel open or closed. */\r\n toggle(): void {\r\n this.panelOpen ? this.close() : this.open();\r\n }\r\n\r\n /** Opens the overlay panel. */\r\n open(): void {\r\n if (\r\n this.disabled ||\r\n !this.options ||\r\n !this.options.length ||\r\n this._panelOpen\r\n ) {\r\n return;\r\n }\r\n\r\n this._triggerRect = this.trigger.nativeElement.getBoundingClientRect();\r\n\r\n this._panelOpen = true;\r\n this._keyManager.withHorizontalOrientation(null);\r\n\r\n this._highlightCorrectOption();\r\n this._changeDetectorRef.markForCheck();\r\n this.openedChange.emit(true);\r\n this._elementRef.nativeElement.classList.add(\r\n 'oui-select-list-options-opened'\r\n );\r\n }\r\n\r\n /** Closes the overlay panel and focuses the host element. */\r\n close(): void {\r\n if (this._panelOpen) {\r\n this._panelOpen = false;\r\n this._keyManager.withHorizontalOrientation(this._isRtl() ? 'rtl' : 'ltr');\r\n this._changeDetectorRef.markForCheck();\r\n this._onTouched();\r\n this.openedChange.emit(false);\r\n this._elementRef.nativeElement.classList.remove(\r\n 'oui-select-list-options-opened'\r\n );\r\n setTimeout((_) => this._document.activeElement.blur());\r\n }\r\n }\r\n\r\n /**\r\n * Sets the select's value. Part of the ControlValueAccessor interface\r\n * required to integrate with Angular's core forms API.\r\n *\r\n * @param value New value to be written to the model.\r\n */\r\n writeValue(value: any): void {\r\n if (this.options) {\r\n this._setSelectionByValue(value);\r\n }\r\n }\r\n\r\n /**\r\n * Saves a callback function to be invoked when the select's value\r\n * changes from user input. Part of the ControlValueAccessor interface\r\n * required to integrate with Angular's core forms API.\r\n *\r\n * @param fn Callback to be triggered when the value changes.\r\n */\r\n registerOnChange(fn: (value: any) => void): void {\r\n this._onChange = fn;\r\n }\r\n\r\n /**\r\n * Saves a callback function to be invoked when the select is blurred\r\n * by the user. Part of the ControlValueAccessor interface required\r\n * to integrate with Angular's core forms API.\r\n *\r\n * @param fn Callback to be triggered when the component has been touched.\r\n */\r\n registerOnTouched(fn: () => {}): void {\r\n this._onTouched = fn;\r\n }\r\n\r\n /**\r\n * Disables the select. Part of the ControlValueAccessor interface required\r\n * to integrate with Angular's core forms API.\r\n *\r\n * @param isDisabled Sets whether the component is disabled.\r\n */\r\n setDisabledState(isDisabled: boolean): void {\r\n this.disabled = isDisabled;\r\n this._changeDetectorRef.markForCheck();\r\n this.stateChanges.next();\r\n }\r\n\r\n /** Whether or not the overlay panel is open. */\r\n get panelOpen(): boolean {\r\n return this._panelOpen;\r\n }\r\n\r\n /** The currently selected option. */\r\n get selected(): OuiOption | OuiOption[] {\r\n return this.multiple\r\n ? this._selectionModel.selected\r\n : this._selectionModel.selected[0];\r\n }\r\n\r\n /** The value displayed in the trigger. */\r\n get triggerValue(): string {\r\n if (this.empty) {\r\n return '';\r\n }\r\n if (this._multiple) {\r\n const selectedOptions = this._selectionModel.selected.map(\r\n (option) => option.viewValueForSelect\r\n );\r\n\r\n if (this._isRtl()) {\r\n selectedOptions.reverse();\r\n }\r\n return selectedOptions.join(', ');\r\n }\r\n return this._selectionModel.selected[0].viewValueForSelect;\r\n }\r\n\r\n /** Whether the element is in RTL mode. */\r\n _isRtl(): boolean {\r\n return this._dir ? this._dir.value === 'rtl' : false;\r\n }\r\n\r\n /** Handles all keydown events on the select. */\r\n _handleKeydown(event: KeyboardEvent): void {\r\n if (!this.disabled) {\r\n this.panelOpen\r\n ? this._handleOpenKeydown(event)\r\n : this._handleClosedKeydown(event);\r\n }\r\n }\r\n\r\n /** Handles keyboard events while the select is closed. */\r\n private _handleClosedKeydown(event: KeyboardEvent): void {\r\n const keyCode = event.keyCode;\r\n const isArrowKey =\r\n keyCode === DOWN_ARROW ||\r\n keyCode === UP_ARROW ||\r\n keyCode === LEFT_ARROW ||\r\n keyCode === RIGHT_ARROW;\r\n const isOpenKey = keyCode === ENTER || keyCode === SPACE;\r\n const manager = this._keyManager;\r\n\r\n // Open the select on ALT + arrow key to match the native \r\n event.preventDefault();\r\n this.close();\r\n } else if (\r\n (keyCode === ENTER || keyCode === SPACE) &&\r\n manager.activeItem &&\r\n !hasModifierKey(event)\r\n ) {\r\n event.preventDefault();\r\n manager.activeItem._selectViaInteraction();\r\n } else if (this._multiple && keyCode === A && event.ctrlKey) {\r\n event.preventDefault();\r\n this.handleCtrlKey();\r\n } else if (normalNavigationCheck) {\r\n // Check for non multiple select dropdown that the key pressed is not Tab, Space, Enter\r\n if (!this.isSearchFieldPresent) this.focus();\r\n this.handleScrolling(manager, event, isArrowKey, keyCode);\r\n }\r\n }\r\n\r\n /**\r\n * Handle ctrl key\r\n */\r\n private handleCtrlKey() {\r\n const hasDeselectedOptions = this.options.some(\r\n (opt) => !opt.disabled && !opt.selected\r\n );\r\n\r\n this.options.forEach((option) => {\r\n if (!option.disabled) {\r\n hasDeselectedOptions ? option.select() : option.deselect();\r\n }\r\n });\r\n }\r\n\r\n /**\r\n * @param manager\r\n * @param event\r\n * @param isArrowKey\r\n * @param keyCode\r\n */\r\n private handleScrolling(\r\n manager: ActiveDescendantKeyManager,\r\n event: KeyboardEvent,\r\n isArrowKey: boolean,\r\n keyCode: number\r\n ) {\r\n const previouslyFocusedIndex = manager.activeItemIndex;\r\n\r\n manager.onKeydown(event);\r\n\r\n if (\r\n this._multiple &&\r\n isArrowKey &&\r\n event.shiftKey &&\r\n manager.activeItem &&\r\n manager.activeItemIndex !== previouslyFocusedIndex\r\n ) {\r\n manager.activeItem._selectViaInteraction();\r\n }\r\n if (isArrowKey && manager.activeItemIndex !== previouslyFocusedIndex) {\r\n this._scrollToOption();\r\n } else {\r\n // First or last\r\n if (keyCode === DOWN_ARROW) {\r\n manager.setFirstItemActive();\r\n this._setScrollTop(0);\r\n }\r\n if (keyCode === UP_ARROW) {\r\n manager.setLastItemActive();\r\n this._scrollToOption();\r\n }\r\n }\r\n }\r\n\r\n _onFocus() {\r\n if (!this.disabled) {\r\n this._focused = true;\r\n this.stateChanges.next();\r\n }\r\n }\r\n\r\n /**\r\n * Calls the touched callback only if the panel is closed. Otherwise, the trigger will\r\n * \"blur\" to the panel when it opens, causing a false positive.\r\n */\r\n _onBlur() {\r\n this._focused = false;\r\n // this.isSearchFieldPresent = false;\r\n\r\n if (!this.disabled && !this.panelOpen) {\r\n this._onTouched();\r\n this._changeDetectorRef.markForCheck();\r\n this.stateChanges.next();\r\n }\r\n }\r\n\r\n /**\r\n * Callback that is invoked when the overlay panel has been attached.\r\n */\r\n _onAttached(): void {\r\n this.overlayDir.positionChange.pipe(take(1)).subscribe(() => {\r\n this._setPseudoCheckboxPaddingSize();\r\n this._changeDetectorRef.detectChanges();\r\n this.panel.nativeElement.scrollTop = this._scrollTop;\r\n });\r\n }\r\n\r\n /** Returns the theme to be used on the panel. */\r\n _getPanelTheme(): string {\r\n return this._parentFormField ? `oui-${this._parentFormField.color}` : '';\r\n }\r\n\r\n // TODO(josephperrott): Remove after 2018 spec updates are fully merged.\r\n /** Sets the pseudo checkbox padding size based on the width of the pseudo checkbox. */\r\n private _setPseudoCheckboxPaddingSize() {\r\n if (!SELECT_MULTIPLE_PANEL_PADDING_X && this.multiple) {\r\n const pseudoCheckbox = this.panel.nativeElement.querySelector(\r\n '.oui-pseudo-checkbox'\r\n );\r\n if (pseudoCheckbox) {\r\n SELECT_MULTIPLE_PANEL_PADDING_X =\r\n SELECT_PANEL_PADDING_X * 1.5 + pseudoCheckbox.offsetWidth;\r\n }\r\n }\r\n }\r\n\r\n /** Whether the select has a value. */\r\n get empty(): boolean {\r\n return !this._selectionModel || this._selectionModel.isEmpty();\r\n }\r\n\r\n private _initializeSelection(): void {\r\n // Defer setting the value in order to avoid the \"Expression\r\n // has changed after it was checked\" errors from Angular.\r\n Promise.resolve().then(() => {\r\n this._setSelectionByValue(\r\n this.ngControl ? this.ngControl.value : this._value\r\n );\r\n this.savedValues = this.ngControl ? this.ngControl.value : this._value;\r\n if (this.multiple) {\r\n this._highlightFirstFilteredOption();\r\n }\r\n });\r\n }\r\n\r\n /**\r\n * Sets the selected option based on a value. If no option can be\r\n * found with the designated value, the select trigger is cleared.\r\n */\r\n private _setSelectionByValue(value: any | any[]): void {\r\n if (this.multiple && value) {\r\n if (!Array.isArray(value)) {\r\n throw getOuiSelectNonArrayValueError();\r\n }\r\n\r\n this._selectionModel.clear();\r\n value.forEach((currentValue: any) => this._selectValue(currentValue));\r\n this._sortValues();\r\n } else {\r\n this._selectionModel.clear();\r\n const correspondingOption = this._selectValue(value);\r\n // Shift focus to the active item. Note that we shouldn't do this in multiple\r\n // mode, because we don't know what option the user interacted with last.\r\n if (correspondingOption) {\r\n this._keyManager.setActiveItem(correspondingOption);\r\n }\r\n }\r\n this._changeDetectorRef.markForCheck();\r\n }\r\n\r\n /**\r\n * Finds and selects and option based on its value.\r\n *\r\n * @returns Option that has the corresponding value.\r\n */\r\n private _selectValue(value: any): OuiOption | undefined {\r\n const correspondingOption = this.options.find((option: OuiOption) => {\r\n try {\r\n // Treat null as a special reset value.\r\n return option.value != null && this._compareWith(option.value, value);\r\n } catch (error) {\r\n if (isDevMode()) {\r\n // Notify developers of errors in their comparator.\r\n console.warn(error);\r\n }\r\n return false;\r\n }\r\n });\r\n\r\n if (correspondingOption) {\r\n this._selectionModel.select(correspondingOption);\r\n }\r\n\r\n return correspondingOption;\r\n }\r\n\r\n /** Sets up a key manager to listen to keyboard events on the overlay panel. */\r\n private _initKeyManager() {\r\n this._keyManager = new ActiveDescendantKeyManager(this.options)\r\n .withTypeAhead()\r\n .withVerticalOrientation()\r\n .withHorizontalOrientation(this._isRtl() ? 'rtl' : 'ltr')\r\n .withAllowedModifierKeys(['shiftKey']);\r\n\r\n this._keyManager.tabOut.pipe(takeUntil(this._destroy)).subscribe(() => {\r\n // Restore focus to the trigger before closing. Ensures that the focus\r\n // position won't be lost if the user got focus into the overlay.\r\n this.focus();\r\n this.close();\r\n });\r\n\r\n this._keyManager.change.pipe(takeUntil(this._destroy)).subscribe(() => {\r\n if (this._panelOpen && this.panel) {\r\n // Panel is opened\r\n // Need not to scroll\r\n } else if (\r\n !this._panelOpen &&\r\n !this.multiple &&\r\n this._keyManager.activeItem\r\n ) {\r\n this._keyManager.activeItem._selectViaInteraction();\r\n }\r\n });\r\n }\r\n\r\n /** Drops current option subscriptions and IDs and resets from scratch. */\r\n private _resetOptions(): void {\r\n const changedOrDestroyed = merge(this.options.changes, this._destroy);\r\n\r\n this.optionSelectionChanges\r\n .pipe(takeUntil(changedOrDestroyed))\r\n .subscribe((event) => {\r\n this._onSelect(event.source, event.isUserInput);\r\n\r\n if (event.isUserInput && !this.multiple && this._panelOpen) {\r\n this.close();\r\n this.focus();\r\n }\r\n });\r\n\r\n // Listen to changes in the internal state of the options and react accordingly.\r\n // Handles cases like the labels of the selected options changing.\r\n merge(...this.options.map((option) => option._stateChanges))\r\n .pipe(takeUntil(changedOrDestroyed))\r\n .subscribe(() => {\r\n this._changeDetectorRef.markForCheck();\r\n this.stateChanges.next();\r\n });\r\n\r\n this._setOptionIds();\r\n }\r\n\r\n /** Invoked when an option is clicked. */\r\n private _onSelect(option: OuiOption, isUserInput: boolean): void {\r\n const wasSelected = this._selectionModel.isSelected(option);\r\n\r\n if (option.value == null && !this._multiple) {\r\n option.deselect();\r\n this._selectionModel.clear();\r\n this._propagateChanges(option.value);\r\n } else {\r\n option.selected\r\n ? this._selectionModel.select(option)\r\n : this._selectionModel.deselect(option);\r\n\r\n if (isUserInput) {\r\n this._keyManager.setActiveItem(option);\r\n }\r\n\r\n if (this.multiple) {\r\n this._sortValues();\r\n\r\n if (isUserInput) {\r\n // In case the user selected the option with their mouse, we\r\n // want to restore focus back to the trigger, in order to\r\n // prevent the select keyboard controls from clashing with\r\n // the ones from `oui-option`.\r\n this.focus();\r\n }\r\n }\r\n }\r\n\r\n if (wasSelected !== this._selectionModel.isSelected(option)) {\r\n this._propagateChanges();\r\n }\r\n this.disableDoneButton = false;\r\n this.stateChanges.next();\r\n }\r\n discardRecentChanges() {\r\n this.value = this.savedValues;\r\n this._setSelectionByValue(this.value);\r\n this.disableDoneButton = true;\r\n this.close();\r\n }\r\n doneRecentChanges() {\r\n this.savedValues = this.value;\r\n this.disableDoneButton = true;\r\n this.saveSelectionChange.emit(new OuiSelectChange(this, this.value));\r\n this.close();\r\n }\r\n /** Sorts the selected values in the selected based on their order in the panel. */\r\n private _sortValues() {\r\n if (this.multiple) {\r\n const options = this.options.toArray();\r\n\r\n this._selectionModel.sort((a, b) =>\r\n this.sortComparator\r\n ? this.sortComparator(a, b, options)\r\n : options.indexOf(a) - options.indexOf(b)\r\n );\r\n this.stateChanges.next();\r\n }\r\n }\r\n\r\n /** Emits change event to set the model value. */\r\n private _propagateChanges(fallbackValue?: any): void {\r\n let valueToEmit: any = null;\r\n\r\n if (this.multiple) {\r\n valueToEmit = (this.selected as OuiOption[]).map(\r\n (option) => option.value\r\n );\r\n } else {\r\n valueToEmit = this.selected\r\n ? (this.selected as OuiOption).value\r\n : fallbackValue;\r\n }\r\n\r\n this._value = valueToEmit;\r\n this.valueChange.emit(valueToEmit);\r\n this._onChange(valueToEmit);\r\n this.selectionChange.emit(new OuiSelectChange(this, valueToEmit));\r\n this._changeDetectorRef.markForCheck();\r\n }\r\n\r\n /** Records option IDs to pass to the aria-owns property. */\r\n private _setOptionIds() {\r\n this._optionIds = this.options.map((option) => option.id).join(' ');\r\n }\r\n\r\n /**\r\n * Highlights the selected item. If no option is selected, it will highlight\r\n * the first item instead.\r\n */\r\n private _highlightCorrectOption(): void {\r\n if (this.multiple) {\r\n this._highlightFirstFilteredOption();\r\n } else if (this._keyManager) {\r\n if (this.empty) {\r\n this._keyManager.setFirstItemActive();\r\n } else {\r\n this._keyManager.setActiveItem(this._selectionModel.selected[0]);\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * Highlights the first of the filtered options if no element is currently highlighted\r\n */\r\n private _highlightFirstFilteredOption(): void {\r\n if (this._keyManager) {\r\n const activeElement = this._keyManager.activeItem?._getHostElement();\r\n // activeElement is not part of DOM if there is no parent element\r\n if (!activeElement || !activeElement.parentElement) {\r\n // highlight first element if there is no active element or active element is not part of DOM\r\n this._keyManager.setFirstItemActive();\r\n }\r\n }\r\n }\r\n\r\n /** Focuses the select element. */\r\n focus(): void {\r\n this._elementRef.nativeElement.focus();\r\n }\r\n\r\n /** Returns the aria-label of the select component. */\r\n _getAriaLabel(): string | null {\r\n // If an ariaLabelledby value has been set by the consumer, the select should not overwrite the\r\n // `aria-labelledby` value by setting the ariaLabel to the placeholder.\r\n return this.ariaLabelledby ? null : this.ariaLabel || this.placeholder;\r\n }\r\n\r\n /** Returns the aria-labelledby of the select component. */\r\n _getAriaLabelledby(): string | null {\r\n if (this.ariaLabelledby) {\r\n return this.ariaLabelledby;\r\n }\r\n\r\n return null;\r\n }\r\n\r\n /** Determines the `aria-activedescendant` to be set on the host. */\r\n _getAriaActiveDescendant(): string | null {\r\n if (this.panelOpen && this._keyManager && this._keyManager.activeItem) {\r\n return this._keyManager.activeItem.id;\r\n }\r\n\r\n return null;\r\n }\r\n\r\n /**\r\n * Implemented as part of OuiFormFieldControl.\r\n *\r\n * @docs-private\r\n */\r\n setDescribedByIds(ids: string[]) {\r\n this._ariaDescribedby = ids.join(' ');\r\n }\r\n\r\n /**\r\n * Implemented as part of OuiFormFieldControl.\r\n *\r\n * @docs-private\r\n */\r\n onContainerClick() {\r\n this.focus();\r\n this.open();\r\n }\r\n\r\n /**\r\n * Implemented as part of OuiFormFieldControl.\r\n *\r\n * @docs-private\r\n */\r\n get shouldLabelFloat(): boolean {\r\n return this._panelOpen || !this.empty;\r\n }\r\n\r\n /**\r\n * Add outer class to perfect scrollbar\r\n * This is added only when there is a search field\r\n */\r\n ouiSelectInputOuter() {\r\n this.ouiSelectInputOuterClassName = 'oui-select-input-outer';\r\n }\r\n\r\n /**\r\n * Custom overlay class for cdk overlay container\r\n */\r\n openCdk() {\r\n this.overlayDir.positionChange.pipe(take(1)).subscribe((e) => {\r\n this.cdkConnectionOverlayPanel = '';\r\n if (e.connectionPair.originY === 'top') {\r\n this.cdkConnectionOverlayPanel = 'select-overlay-top';\r\n }\r\n this._changeDetectorRef.detectChanges();\r\n setTimeout((_) => this._scrollToOption());\r\n });\r\n\r\n const cdkOverLayContainer = this._document.querySelector(\r\n '.cdk-overlay-container'\r\n );\r\n const ouiSelectPanel = this._document.querySelector('.oui-select-panel');\r\n cdkOverLayContainer.classList.add('oui-select-overlay-container');\r\n const containerWidth = this._elementRef.nativeElement.offsetWidth;\r\n ouiSelectPanel.style.width = `${containerWidth}px`;\r\n const searchQueryString = '.oui-select-search-inner';\r\n if (this._document.querySelector(searchQueryString)) {\r\n this.scrollCalc(searchQueryString);\r\n }\r\n const actionItemsQueryString = '.oui-select-action-items';\r\n if (this._document.querySelector(actionItemsQueryString)) {\r\n this.scrollCalc(actionItemsQueryString);\r\n }\r\n }\r\n scrollCalc(selectQueryString: string) {\r\n const searchInput = this._document.querySelector(selectQueryString);\r\n const outter = this._document.querySelector('.oui-select-panel');\r\n let inner = this._document.querySelector('.oui-option');\r\n if (inner === null) {\r\n inner = 0;\r\n }\r\n const scrollbarWidth = outter.offsetWidth - inner.offsetWidth;\r\n if (scrollbarWidth > 5) {\r\n searchInput.style.width = `${inner.offsetWidth}px`;\r\n } else {\r\n searchInput.style.width = `calc(100% + 8px)`;\r\n }\r\n }\r\n\r\n /**\r\n * Given that we are not actually focusing active options, we must manually adjust scroll\r\n * to reveal options below the fold. First, we find the offset of the option from the top\r\n * of the panel. If that offset is below the fold, the new scrollTop will be the offset -\r\n * the panel height + the option height, so the active option will be just visible at the\r\n * bottom of the panel. If that offset is above the top of the visible panel, the new scrollTop\r\n * will become the offset. If that offset is visible within the panel already, the scrollTop is\r\n * not adjusted.\r\n */\r\n private _scrollToOption(): void {\r\n const manager = this._keyManager;\r\n const index = manager.activeItemIndex || 0;\r\n const labelCount = _countGroupLabelsBeforeOption(\r\n index,\r\n this.options,\r\n this.optionGroups\r\n );\r\n const scrollTop = this._getScrollTop();\r\n const newScrollPosition = _getOptionScrollPosition(\r\n index + labelCount,\r\n SELECT_OPTION_HEIGHT,\r\n scrollTop,\r\n SELECT_PANEL_HEIGHT\r\n );\r\n this._setScrollTop(newScrollPosition);\r\n }\r\n\r\n /**\r\n * Sets the panel scrollTop. This allows us to manually scroll to display options\r\n * above or below the fold, as they are not actually being focused when active.\r\n */\r\n _setScrollTop(scrollTop: number): void {\r\n if (this.panel) {\r\n this.panel.nativeElement.scrollTop = scrollTop;\r\n }\r\n }\r\n\r\n /** Returns the panel's scrollTop. */\r\n _getScrollTop(): number {\r\n return this.panel ? this.panel.nativeElement.scrollTop : 0;\r\n }\r\n}\r\n", "selector": "oui-select-trigger", "providers": [], + "hostDirectives": [], + "standalone": false, "inputsClass": [], "outputsClass": [], "deprecated": false, @@ -19234,7 +19454,8 @@ "hostBindings": [], "hostListeners": [], "propertiesClass": [], - "methodsClass": [] + "methodsClass": [], + "extends": [] }, { "name": "OuiSort", @@ -19246,6 +19467,9 @@ "sourceCode": "import { coerceBooleanProperty } from '@angular/cdk/coercion';\nimport {\n Directive,\n EventEmitter,\n Input,\n isDevMode,\n OnChanges,\n OnDestroy,\n OnInit,\n Output,\n} from '@angular/core';\nimport {\n CanDisable,\n CanDisableCtor,\n HasInitialized,\n HasInitializedCtor,\n mixinDisabled,\n mixinInitialized,\n} from '../core';\nimport { Subject } from 'rxjs';\nimport { SortDirection } from './sort-direction';\nimport {\n getSortDuplicateSortableIdError,\n getSortHeaderMissingIdError,\n getSortInvalidDirectionError,\n} from './sort-errors';\n\n/** Interface for a directive that holds sorting state consumed by `OuiSortHeader`. */\nexport interface OuiSortable {\n /** The id of the column being sorted. */\n id: string;\n\n /** Starting sort direction. */\n start: 'asc' | 'desc';\n\n /** Whether to disable clearing the sorting state. */\n disableClear: boolean;\n}\n\n/** The current sort state. */\nexport interface Sort {\n /** The id of the column being sorted. */\n active: string;\n\n /** The sort direction. */\n direction: SortDirection;\n}\n\n// Boilerplate for applying mixins to OuiSort.\n/** @docs-private */\nexport class OuiSortBase {}\nexport const _OuiSortMixinBase: HasInitializedCtor &\n CanDisableCtor &\n typeof OuiSortBase = mixinInitialized(mixinDisabled(OuiSortBase));\n\n/** Container for OuiSortables to manage the sort state and provide default sort parameters. */\n@Directive({\n selector: '[ouiSort]',\n exportAs: 'ouiSort',\n // eslint-disable-next-line @angular-eslint/no-inputs-metadata-property\n inputs: ['disabled: ouiSortDisabled'],\n})\nexport class OuiSort\n extends _OuiSortMixinBase\n implements CanDisable, HasInitialized, OnChanges, OnDestroy, OnInit\n{\n /** Collection of all registered sortables that this directive manages. */\n sortables = new Map();\n\n /** Used to notify any child components listening to state changes. */\n readonly _stateChanges = new Subject();\n\n /** The id of the most recently sorted OuiSortable. */\n // eslint-disable-next-line @angular-eslint/no-input-rename\n @Input('ouiSortActive') active: string;\n\n /**\n * The direction to set when an OuiSortable is initially sorted.\n * May be overriden by the OuiSortable's sort start.\n */\n // eslint-disable-next-line @angular-eslint/no-input-rename\n @Input('ouiSortStart') start: 'asc' | 'desc' = 'asc';\n\n /** The sort direction of the currently active OuiSortable. */\n @Input('ouiSortDirection')\n get direction(): SortDirection {\n return this._direction;\n }\n set direction(direction: SortDirection) {\n if (\n isDevMode() &&\n direction &&\n direction !== 'asc' &&\n direction !== 'desc'\n ) {\n throw getSortInvalidDirectionError(direction);\n }\n this._direction = direction;\n }\n private _direction: SortDirection = '';\n\n /**\n * Whether to disable the user from clearing the sort by finishing the sort direction cycle.\n * May be overriden by the OuiSortable's disable clear input.\n */\n @Input('ouiSortDisableClear')\n get disableClear(): boolean {\n return this._disableClear;\n }\n set disableClear(v: boolean) {\n this._disableClear = coerceBooleanProperty(v);\n }\n private _disableClear: boolean;\n\n /** Event emitted when the user changes either the active sort or sort direction. */\n // eslint-disable-next-line @angular-eslint/no-output-rename\n @Output('ouiSortChange')\n readonly sortChange: EventEmitter = new EventEmitter();\n\n /**\n * Register function to be used by the contained OuiSortables. Adds the OuiSortable to the\n * collection of OuiSortables.\n */\n register(sortable: OuiSortable): void {\n if (!sortable.id) {\n throw getSortHeaderMissingIdError();\n }\n\n if (this.sortables.has(sortable.id)) {\n throw getSortDuplicateSortableIdError(sortable.id);\n }\n this.sortables.set(sortable.id, sortable);\n }\n\n /**\n * Unregister function to be used by the contained OuiSortables. Removes the OuiSortable from the\n * collection of contained OuiSortables.\n */\n deregister(sortable: OuiSortable): void {\n this.sortables.delete(sortable.id);\n }\n\n /** Sets the active sort id and determines the new sort direction. */\n sort(sortable: OuiSortable): void {\n if (this.active !== sortable.id) {\n this.active = sortable.id;\n this.direction = sortable.start ? sortable.start : this.start;\n } else {\n this.direction = this.getNextSortDirection(sortable);\n }\n\n this.sortChange.emit({ active: this.active, direction: this.direction });\n }\n\n /** Returns the next sort direction of the active sortable, checking for potential overrides. */\n getNextSortDirection(sortable: OuiSortable): SortDirection {\n if (!sortable) {\n return '';\n }\n\n const sortDirectionCycle = getSortDirectionCycle(\n sortable.start || this.start\n );\n\n // Get and return the next direction in the cycle\n let nextDirectionIndex = sortDirectionCycle.indexOf(this.direction) + 1;\n if (nextDirectionIndex >= sortDirectionCycle.length) {\n nextDirectionIndex = 0;\n }\n return sortDirectionCycle[nextDirectionIndex];\n }\n\n ngOnInit() {\n this._markInitialized();\n }\n\n ngOnChanges() {\n this._stateChanges.next();\n }\n\n ngOnDestroy() {\n this._stateChanges.complete();\n }\n}\n\n/** Returns the sort direction cycle to use given the provided parameters of order and clear. */\nfunction getSortDirectionCycle(start: 'asc' | 'desc'): SortDirection[] {\n const sortOrder: SortDirection[] = ['asc', 'desc'];\n if (start === 'desc') {\n sortOrder.reverse();\n }\n\n return sortOrder;\n}\n", "selector": "[ouiSort]", "providers": [], + "exportAs": "ouiSort", + "hostDirectives": [], + "standalone": false, "inputsClass": [ { "name": "ouiSortActive", @@ -19316,7 +19540,7 @@ "description": "", "line": 100, "modifierKind": [ - 121 + 123 ] }, { @@ -19328,7 +19552,7 @@ "description": "", "line": 113, "modifierKind": [ - 121 + 123 ] }, { @@ -19342,7 +19566,7 @@ "line": 71, "rawdescription": "\nUsed to notify any child components listening to state changes.", "modifierKind": [ - 144 + 148 ] }, { @@ -19509,7 +19733,9 @@ ] } ], - "extends": "_OuiSortMixinBase", + "extends": [ + "_OuiSortMixinBase" + ], "implements": [ "CanDisable", "HasInitialized", @@ -19598,14 +19824,16 @@ }, { "name": "OuiTabBodyPortal", - "id": "directive-OuiTabBodyPortal-d9aba0e7f5c272163d8a1fcdea5954740c5bac6598de09205831a017a4275c387861d98bd5093d058798cb1713335c4f3d57c032469562999ee21727593e8750", + "id": "directive-OuiTabBodyPortal-35910442aae2ae956d9d640aaca92c9ecb135a5b0cac0d799979fba8976ff19c4489f5f438564beb0bb143fbe9b12783c9ba692171c5c13d4e4497c1d052be96", "file": "ui/src/components/tabs/tab-body.ts", "type": "directive", "description": "

The portal host directive for the contents of the tab.

\n", "rawdescription": "\n\nThe portal host directive for the contents of the tab.\n", - "sourceCode": "import {\n ChangeDetectionStrategy,\n ChangeDetectorRef,\n Component,\n ComponentFactoryResolver,\n Directive,\n ElementRef,\n EventEmitter,\n // forwardRef,\n Inject,\n Input,\n OnDestroy,\n OnInit,\n Optional,\n Output,\n ViewChild,\n ViewContainerRef,\n ViewEncapsulation,\n} from '@angular/core';\nimport { CdkPortalOutlet } from '@angular/cdk/portal';\nimport { Direction, Directionality } from '@angular/cdk/bidi';\nimport { DOCUMENT } from '@angular/common';\nimport { Subject, Subscription } from 'rxjs';\nimport {\n distinctUntilChanged,\n // startWith\n} from 'rxjs/operators';\nimport { AnimationEvent } from '@angular/animations';\nimport { ouiTabsAnimations } from './tabs-animations';\n\n/**\n * The portal host directive for the contents of the tab.\n * @docs-private\n */\n\n@Directive({\n // eslint-disable-next-line @angular-eslint/directive-selector\n selector: `OuiTabBodyHost`,\n})\nexport class OuiTabBodyPortal\n extends CdkPortalOutlet\n implements OnInit, OnDestroy\n{\n /** Subscription to events for when the tab body begins centering. */\n private _centeringSub = Subscription.EMPTY;\n /** Subscription to events for when the tab body finishes leaving from center position. */\n private _leavingSub = Subscription.EMPTY;\n\n constructor(\n componentFactoryResolver: ComponentFactoryResolver,\n viewContainerRef: ViewContainerRef,\n // @Inject(forwardRef(() => OuiTabBody)) private _host: OuiTabBody,\n @Inject(DOCUMENT) _document: any\n ) {\n super(componentFactoryResolver, viewContainerRef, _document);\n }\n\n /** Set initial visibility or set up subscription for changing visibility. */\n override ngOnInit(): void {\n super.ngOnInit();\n }\n\n /** Clean up centering subscription. */\n override ngOnDestroy(): void {\n super.ngOnDestroy();\n this._centeringSub.unsubscribe();\n this._leavingSub.unsubscribe();\n }\n}\n\n/**\n * These position states are used internally as animation states for the tab body. Setting the\n * position state to left, right, or center will transition the tab body from its current\n * position to its respective state. If there is not current position (void, in the case of a new\n * tab body), then there will be no transition animation to its state.\n *\n * In the case of a new tab body that should immediately be centered with an animating transition,\n * then left-origin-center or right-origin-center can be used, which will use left or right as its\n * pseudo-prior state.\n */\nexport type OuiTabBodyPositionState =\n | 'left'\n | 'center'\n | 'right'\n | 'left-origin-center'\n | 'right-origin-center';\n\n/**\n * Wrapper for the contents of a tab.\n * @docs-private\n */\n@Component({\n selector: 'oui-tab-body',\n templateUrl: 'tab-body.html',\n // styleUrls: ['tab-body.css'],\n encapsulation: ViewEncapsulation.None,\n // tslint:disable-next-line:validate-decorators\n changeDetection: ChangeDetectionStrategy.Default,\n animations: [ouiTabsAnimations.translateTab],\n // eslint-disable-next-line @angular-eslint/no-host-metadata-property\n host: {\n class: 'oui-mdc-tab-body',\n },\n})\nexport class OuiTabBody implements OnInit, OnDestroy {\n /** Current position of the tab-body in the tab-group. Zero means that the tab is visible. */\n private _positionIndex: number;\n\n /** Subscription to the directionality change observable. */\n private _dirChangeSubscription = Subscription.EMPTY;\n\n /** Tab body position state. Used by the animation trigger for the current state. */\n _position: OuiTabBodyPositionState;\n\n /** Emits when an animation on the tab is complete. */\n readonly _translateTabComplete = new Subject();\n\n /** Event emitted when the tab begins to animate towards the center as the active tab. */\n @Output() readonly _onCentering: EventEmitter =\n new EventEmitter();\n\n /** Event emitted before the centering of the tab begins. */\n @Output() readonly _beforeCentering: EventEmitter =\n new EventEmitter();\n\n /** Event emitted before the centering of the tab begins. */\n @Output() readonly _afterLeavingCenter: EventEmitter =\n new EventEmitter();\n\n /** Event emitted when the tab completes its animation towards the center. */\n @Output() readonly _onCentered: EventEmitter = new EventEmitter(\n true\n );\n\n /** The portal host inside of this container into which the tab body content will be loaded. */\n @ViewChild(CdkPortalOutlet) _portalHost: CdkPortalOutlet;\n\n /** The tab body content to display. */\n @Input('content') _content: any;\n\n /** Position that will be used when the tab is immediately becoming visible after creation. */\n @Input() origin: number | null;\n\n // Note that the default value will always be overwritten by `OuiTabBody`, but we need one\n // anyway to prevent the animations module from throwing an error if the body is used on its own.\n /** Duration for the tab's animation. */\n @Input() animationDuration = '0';\n\n /** Whether the tab's content should be kept in the DOM while it's off-screen. */\n @Input() preserveContent = false;\n _innerContent: any;\n\n /** The shifted index position of the tab body, where zero represents the active center tab. */\n @Input()\n set position(position: number) {\n this._positionIndex = position;\n this._computePositionAnimationState();\n }\n\n constructor(\n private _elementRef: ElementRef,\n @Optional() private _dir: Directionality,\n changeDetectorRef: ChangeDetectorRef\n ) {\n if (_dir) {\n this._dirChangeSubscription = _dir.change.subscribe((dir: Direction) => {\n this._computePositionAnimationState(dir);\n changeDetectorRef.markForCheck();\n });\n }\n\n // Ensure that we get unique animation events, because the `.done` callback can get\n // invoked twice in some browsers. See https://github.com/angular/angular/issues/24084.\n this._translateTabComplete\n .pipe(\n distinctUntilChanged((x, y) => {\n return x.fromState === y.fromState && x.toState === y.toState;\n })\n )\n .subscribe((event) => {\n // If the transition to the center is complete, emit an event.\n if (\n this._isCenterPosition(event.toState) &&\n this._isCenterPosition(this._position)\n ) {\n this._onCentered.emit();\n }\n\n if (\n this._isCenterPosition(event.fromState) &&\n !this._isCenterPosition(this._position)\n ) {\n this._afterLeavingCenter.emit();\n }\n });\n }\n\n /**\n * After initialized, check if the content is centered and has an origin. If so, set the\n * special position states that transition the tab from the left or right before centering.\n */\n ngOnInit() {\n if (this._position == 'center' && this.origin != null) {\n this._position = this._computePositionFromOrigin(this.origin);\n }\n this._innerContent = this._content ? this._content : '';\n }\n\n ngOnDestroy() {\n this._dirChangeSubscription.unsubscribe();\n this._translateTabComplete.complete();\n }\n\n _onTranslateTabStarted(event: AnimationEvent): void {\n const isCentering = this._isCenterPosition(event.toState);\n this._beforeCentering.emit(isCentering);\n if (isCentering) {\n this._onCentering.emit(this._elementRef.nativeElement.clientHeight);\n }\n }\n\n /** The text direction of the containing app. */\n _getLayoutDirection(): Direction {\n return this._dir && this._dir.value === 'rtl' ? 'rtl' : 'ltr';\n }\n\n /** Whether the provided position state is considered center, regardless of origin. */\n _isCenterPosition(position: OuiTabBodyPositionState | string): boolean {\n return (\n position == 'center' ||\n position == 'left-origin-center' ||\n position == 'right-origin-center'\n );\n }\n\n /** Computes the position state that will be used for the tab-body animation trigger. */\n private _computePositionAnimationState(\n dir: Direction = this._getLayoutDirection()\n ) {\n if (this._positionIndex < 0) {\n this._position = dir == 'ltr' ? 'left' : 'right';\n } else if (this._positionIndex > 0) {\n this._position = dir == 'ltr' ? 'right' : 'left';\n } else {\n this._position = 'center';\n }\n }\n\n /**\n * Computes the position state based on the specified origin position. This is used if the\n * tab is becoming visible immediately after creation.\n */\n private _computePositionFromOrigin(origin: number): OuiTabBodyPositionState {\n const dir = this._getLayoutDirection();\n\n if ((dir == 'ltr' && origin <= 0) || (dir == 'rtl' && origin > 0)) {\n return 'left-origin-center';\n }\n\n return 'right-origin-center';\n }\n}\n\n/**\n * The origin state is an internally used state that is set on a new tab body indicating if it\n * began to the left or right of the prior selected index. For example, if the selected index was\n * set to 1, and a new tab is created and selected at index 2, then the tab body would have an\n * origin of right because its index was greater than the prior selected index.\n */\nexport type OuiTabBodyOriginState = 'left' | 'right';\n", + "sourceCode": "import {\r\n ChangeDetectionStrategy,\r\n ChangeDetectorRef,\r\n Component,\r\n ComponentFactoryResolver,\r\n Directive,\r\n ElementRef,\r\n EventEmitter,\r\n // forwardRef,\r\n Inject,\r\n Input,\r\n OnDestroy,\r\n OnInit,\r\n Optional,\r\n Output,\r\n ViewChild,\r\n ViewContainerRef,\r\n ViewEncapsulation,\r\n} from '@angular/core';\r\nimport { CdkPortalOutlet } from '@angular/cdk/portal';\r\nimport { Direction, Directionality } from '@angular/cdk/bidi';\r\nimport { DOCUMENT } from '@angular/common';\r\nimport { Subject, Subscription } from 'rxjs';\r\nimport {\r\n distinctUntilChanged,\r\n // startWith\r\n} from 'rxjs/operators';\r\nimport { AnimationEvent } from '@angular/animations';\r\nimport { ouiTabsAnimations } from './tabs-animations';\r\n\r\n/**\r\n * The portal host directive for the contents of the tab.\r\n * @docs-private\r\n */\r\n\r\n@Directive({\r\n // eslint-disable-next-line @angular-eslint/directive-selector\r\n selector: `OuiTabBodyHost`,\r\n})\r\nexport class OuiTabBodyPortal\r\n extends CdkPortalOutlet\r\n implements OnInit, OnDestroy\r\n{\r\n /** Subscription to events for when the tab body begins centering. */\r\n private _centeringSub = Subscription.EMPTY;\r\n /** Subscription to events for when the tab body finishes leaving from center position. */\r\n private _leavingSub = Subscription.EMPTY;\r\n\r\n constructor(\r\n componentFactoryResolver: ComponentFactoryResolver,\r\n viewContainerRef: ViewContainerRef,\r\n // @Inject(forwardRef(() => OuiTabBody)) private _host: OuiTabBody,\r\n @Inject(DOCUMENT) _document: any\r\n ) {\r\n super(componentFactoryResolver, viewContainerRef, _document);\r\n }\r\n\r\n /** Set initial visibility or set up subscription for changing visibility. */\r\n override ngOnInit(): void {\r\n super.ngOnInit();\r\n }\r\n\r\n /** Clean up centering subscription. */\r\n override ngOnDestroy(): void {\r\n super.ngOnDestroy();\r\n this._centeringSub.unsubscribe();\r\n this._leavingSub.unsubscribe();\r\n }\r\n}\r\n\r\n/**\r\n * These position states are used internally as animation states for the tab body. Setting the\r\n * position state to left, right, or center will transition the tab body from its current\r\n * position to its respective state. If there is not current position (void, in the case of a new\r\n * tab body), then there will be no transition animation to its state.\r\n *\r\n * In the case of a new tab body that should immediately be centered with an animating transition,\r\n * then left-origin-center or right-origin-center can be used, which will use left or right as its\r\n * pseudo-prior state.\r\n */\r\nexport type OuiTabBodyPositionState =\r\n | 'left'\r\n | 'center'\r\n | 'right'\r\n | 'left-origin-center'\r\n | 'right-origin-center';\r\n\r\n/**\r\n * Wrapper for the contents of a tab.\r\n * @docs-private\r\n */\r\n@Component({\r\n selector: 'oui-tab-body',\r\n templateUrl: 'tab-body.html',\r\n // styleUrls: ['tab-body.css'],\r\n encapsulation: ViewEncapsulation.None,\r\n // tslint:disable-next-line:validate-decorators\r\n changeDetection: ChangeDetectionStrategy.Default,\r\n animations: [ouiTabsAnimations.translateTab],\r\n // eslint-disable-next-line @angular-eslint/no-host-metadata-property\r\n host: {\r\n class: 'oui-mdc-tab-body',\r\n },\r\n})\r\nexport class OuiTabBody implements OnInit, OnDestroy {\r\n /** Current position of the tab-body in the tab-group. Zero means that the tab is visible. */\r\n private _positionIndex: number;\r\n\r\n /** Subscription to the directionality change observable. */\r\n private _dirChangeSubscription = Subscription.EMPTY;\r\n\r\n /** Tab body position state. Used by the animation trigger for the current state. */\r\n _position: OuiTabBodyPositionState;\r\n\r\n /** Emits when an animation on the tab is complete. */\r\n readonly _translateTabComplete = new Subject();\r\n\r\n /** Event emitted when the tab begins to animate towards the center as the active tab. */\r\n @Output() readonly _onCentering: EventEmitter =\r\n new EventEmitter();\r\n\r\n /** Event emitted before the centering of the tab begins. */\r\n @Output() readonly _beforeCentering: EventEmitter =\r\n new EventEmitter();\r\n\r\n /** Event emitted before the centering of the tab begins. */\r\n @Output() readonly _afterLeavingCenter: EventEmitter =\r\n new EventEmitter();\r\n\r\n /** Event emitted when the tab completes its animation towards the center. */\r\n @Output() readonly _onCentered: EventEmitter = new EventEmitter(\r\n true\r\n );\r\n\r\n /** The portal host inside of this container into which the tab body content will be loaded. */\r\n @ViewChild(CdkPortalOutlet) _portalHost: CdkPortalOutlet;\r\n\r\n /** The tab body content to display. */\r\n @Input('content') _content: any;\r\n\r\n /** Position that will be used when the tab is immediately becoming visible after creation. */\r\n @Input() origin: number | null;\r\n\r\n // Note that the default value will always be overwritten by `OuiTabBody`, but we need one\r\n // anyway to prevent the animations module from throwing an error if the body is used on its own.\r\n /** Duration for the tab's animation. */\r\n @Input() animationDuration = '0';\r\n\r\n /** Whether the tab's content should be kept in the DOM while it's off-screen. */\r\n @Input() preserveContent = false;\r\n _innerContent: any;\r\n\r\n /** The shifted index position of the tab body, where zero represents the active center tab. */\r\n @Input()\r\n set position(position: number) {\r\n this._positionIndex = position;\r\n this._computePositionAnimationState();\r\n }\r\n\r\n constructor(\r\n private _elementRef: ElementRef,\r\n @Optional() private _dir: Directionality,\r\n changeDetectorRef: ChangeDetectorRef\r\n ) {\r\n if (_dir) {\r\n this._dirChangeSubscription = _dir.change.subscribe((dir: Direction) => {\r\n this._computePositionAnimationState(dir);\r\n changeDetectorRef.markForCheck();\r\n });\r\n }\r\n\r\n // Ensure that we get unique animation events, because the `.done` callback can get\r\n // invoked twice in some browsers. See https://github.com/angular/angular/issues/24084.\r\n this._translateTabComplete\r\n .pipe(\r\n distinctUntilChanged((x, y) => {\r\n return x.fromState === y.fromState && x.toState === y.toState;\r\n })\r\n )\r\n .subscribe((event) => {\r\n // If the transition to the center is complete, emit an event.\r\n if (\r\n this._isCenterPosition(event.toState) &&\r\n this._isCenterPosition(this._position)\r\n ) {\r\n this._onCentered.emit();\r\n }\r\n\r\n if (\r\n this._isCenterPosition(event.fromState) &&\r\n !this._isCenterPosition(this._position)\r\n ) {\r\n this._afterLeavingCenter.emit();\r\n }\r\n });\r\n }\r\n\r\n /**\r\n * After initialized, check if the content is centered and has an origin. If so, set the\r\n * special position states that transition the tab from the left or right before centering.\r\n */\r\n ngOnInit() {\r\n if (this._position == 'center' && this.origin != null) {\r\n this._position = this._computePositionFromOrigin(this.origin);\r\n }\r\n this._innerContent = this._content ? this._content : '';\r\n }\r\n\r\n ngOnDestroy() {\r\n this._dirChangeSubscription.unsubscribe();\r\n this._translateTabComplete.complete();\r\n }\r\n\r\n _onTranslateTabStarted(event: AnimationEvent): void {\r\n const isCentering = this._isCenterPosition(event.toState);\r\n this._beforeCentering.emit(isCentering);\r\n if (isCentering) {\r\n this._onCentering.emit(this._elementRef.nativeElement.clientHeight);\r\n }\r\n }\r\n\r\n /** The text direction of the containing app. */\r\n _getLayoutDirection(): Direction {\r\n return this._dir && this._dir.value === 'rtl' ? 'rtl' : 'ltr';\r\n }\r\n\r\n /** Whether the provided position state is considered center, regardless of origin. */\r\n _isCenterPosition(position: OuiTabBodyPositionState | string): boolean {\r\n return (\r\n position == 'center' ||\r\n position == 'left-origin-center' ||\r\n position == 'right-origin-center'\r\n );\r\n }\r\n\r\n /** Computes the position state that will be used for the tab-body animation trigger. */\r\n private _computePositionAnimationState(\r\n dir: Direction = this._getLayoutDirection()\r\n ) {\r\n if (this._positionIndex < 0) {\r\n this._position = dir == 'ltr' ? 'left' : 'right';\r\n } else if (this._positionIndex > 0) {\r\n this._position = dir == 'ltr' ? 'right' : 'left';\r\n } else {\r\n this._position = 'center';\r\n }\r\n }\r\n\r\n /**\r\n * Computes the position state based on the specified origin position. This is used if the\r\n * tab is becoming visible immediately after creation.\r\n */\r\n private _computePositionFromOrigin(origin: number): OuiTabBodyPositionState {\r\n const dir = this._getLayoutDirection();\r\n\r\n if ((dir == 'ltr' && origin <= 0) || (dir == 'rtl' && origin > 0)) {\r\n return 'left-origin-center';\r\n }\r\n\r\n return 'right-origin-center';\r\n }\r\n}\r\n\r\n/**\r\n * The origin state is an internally used state that is set on a new tab body indicating if it\r\n * began to the left or right of the prior selected index. For example, if the selected index was\r\n * set to 1, and a new tab is created and selected at index 2, then the tab body would have an\r\n * origin of right because its index was greater than the prior selected index.\r\n */\r\nexport type OuiTabBodyOriginState = 'left' | 'right';\r\n", "selector": "OuiTabBodyHost", "providers": [], + "hostDirectives": [], + "standalone": false, "inputsClass": [], "outputsClass": [], "deprecated": false, @@ -19624,7 +19852,7 @@ "line": 53, "rawdescription": "\nSubscription to events for when the tab body begins centering.", "modifierKind": [ - 121 + 123 ] }, { @@ -19638,7 +19866,7 @@ "line": 55, "rawdescription": "\nSubscription to events for when the tab body finishes leaving from center position.", "modifierKind": [ - 121 + 123 ] } ], @@ -19655,7 +19883,7 @@ "rawdescription": "\nClean up centering subscription.", "description": "

Clean up centering subscription.

\n", "modifierKind": [ - 158 + 164 ] }, { @@ -19670,11 +19898,13 @@ "rawdescription": "\nSet initial visibility or set up subscription for changing visibility.", "description": "

Set initial visibility or set up subscription for changing visibility.

\n", "modifierKind": [ - 158 + 164 ] } ], - "extends": "CdkPortalOutlet", + "extends": [ + "CdkPortalOutlet" + ], "implements": [ "OnInit", "OnDestroy" @@ -19738,18 +19968,20 @@ }, { "name": "OuiTabContent", - "id": "directive-OuiTabContent-e3691c333f63b4c362db06374f029c5706f6d523069071c3b7d33a0504cc699f5efedfb762e924b8ee679cda55eb3d5b6c40939fba7c7c796d8e7fbe6e59c779", + "id": "directive-OuiTabContent-b65da5c32e4f035a7b8d83f50cd7b6ff20be1b4708c0961689a65bebcbdc20d0b042047289ddf9884062cf425e1d05cb48a95e891417153373ea260a1a1e2604", "file": "ui/src/components/tabs/tab-content.ts", "type": "directive", "description": "

Decorates the ng-template tags and reads out the template from it.

\n", "rawdescription": "\nDecorates the `ng-template` tags and reads out the template from it.", - "sourceCode": "import { Directive, InjectionToken, TemplateRef } from '@angular/core';\n\n/**\n * Injection token that can be used to reference instances of `OuiTabContent`. It serves as\n * alternative token to the actual `OuiTabContent` class which could cause unnecessary\n * retention of the class and its directive metadata.\n */\nexport const OUI_TAB_CONTENT = new InjectionToken(\n 'OuiTabContent'\n);\n\n/** Decorates the `ng-template` tags and reads out the template from it. */\n@Directive({\n // eslint-disable-next-line @angular-eslint/directive-selector\n selector: '[OuiTabContent]',\n providers: [{ provide: OUI_TAB_CONTENT, useExisting: OuiTabContent }],\n})\nexport class OuiTabContent {\n constructor(/** Content for the tab. */ public template: TemplateRef) {}\n}\n", + "sourceCode": "import { Directive, InjectionToken, TemplateRef } from '@angular/core';\r\n\r\n/**\r\n * Injection token that can be used to reference instances of `OuiTabContent`. It serves as\r\n * alternative token to the actual `OuiTabContent` class which could cause unnecessary\r\n * retention of the class and its directive metadata.\r\n */\r\nexport const OUI_TAB_CONTENT = new InjectionToken(\r\n 'OuiTabContent'\r\n);\r\n\r\n/** Decorates the `ng-template` tags and reads out the template from it. */\r\n@Directive({\r\n // eslint-disable-next-line @angular-eslint/directive-selector\r\n selector: '[OuiTabContent]',\r\n providers: [{ provide: OUI_TAB_CONTENT, useExisting: OuiTabContent }],\r\n})\r\nexport class OuiTabContent {\r\n constructor(/** Content for the tab. */ public template: TemplateRef) {}\r\n}\r\n", "selector": "[OuiTabContent]", "providers": [ { "name": "{ provide: OUI_TAB_CONTENT, useExisting: OuiTabContent }" } ], + "hostDirectives": [], + "standalone": false, "inputsClass": [], "outputsClass": [], "deprecated": false, @@ -19767,11 +19999,12 @@ "line": 27, "rawdescription": "\n", "modifierKind": [ - 123 + 125 ] } ], "methodsClass": [], + "extends": [], "constructorObj": { "name": "constructor", "description": "", @@ -19801,18 +20034,20 @@ }, { "name": "OuiTabLabel", - "id": "directive-OuiTabLabel-cebb207555e4a38e6ea726f0d32c6698784059e11bba685a8fa9cd2171e4ef12b91d8284e5d780bfa1a0312c7507722587390be5e68c8331ccb842f699d20e19", + "id": "directive-OuiTabLabel-dccf6d94f02aac877fee777437c9fe03332635546d4e6d487228c5d45cc3aafe7c681d53c345ba635d51fad7d85a6672dfd69a6f7e5898924e8ed0be80ccb5e4", "file": "ui/src/components/tabs/tab-label.ts", "type": "directive", "description": "

Used to flag tab labels for use with the portal directive

\n", "rawdescription": "\nUsed to flag tab labels for use with the portal directive", - "sourceCode": "import {\n Directive,\n Inject,\n InjectionToken,\n Optional,\n TemplateRef,\n ViewContainerRef,\n} from '@angular/core';\nimport { CdkPortal } from '@angular/cdk/portal';\n\n/**\n * Injection token that can be used to reference instances of `OuiTabLabel`. It serves as\n * alternative token to the actual `OuiTabLabel` class which could cause unnecessary\n * retention of the class and its directive metadata.\n */\nexport const OUI_TAB_LABEL = new InjectionToken('OuiTabLabel');\n\n/**\n * Used to provide a tab label to a tab without causing a circular dependency.\n * @docs-private\n */\nexport const OUI_TAB = new InjectionToken('OUI_TAB');\n\n/** Used to flag tab labels for use with the portal directive */\n@Directive({\n selector: '[oui-tab-label], [OuiTabLabel]',\n providers: [{ provide: OUI_TAB_LABEL, useExisting: OuiTabLabel }],\n})\nexport class OuiTabLabel extends CdkPortal {\n constructor(\n templateRef: TemplateRef,\n viewContainerRef: ViewContainerRef,\n @Inject(OUI_TAB) @Optional() public _closestTab: any\n ) {\n super(templateRef, viewContainerRef);\n }\n}\n", + "sourceCode": "import {\r\n Directive,\r\n Inject,\r\n InjectionToken,\r\n Optional,\r\n TemplateRef,\r\n ViewContainerRef,\r\n} from '@angular/core';\r\nimport { CdkPortal } from '@angular/cdk/portal';\r\n\r\n/**\r\n * Injection token that can be used to reference instances of `OuiTabLabel`. It serves as\r\n * alternative token to the actual `OuiTabLabel` class which could cause unnecessary\r\n * retention of the class and its directive metadata.\r\n */\r\nexport const OUI_TAB_LABEL = new InjectionToken('OuiTabLabel');\r\n\r\n/**\r\n * Used to provide a tab label to a tab without causing a circular dependency.\r\n * @docs-private\r\n */\r\nexport const OUI_TAB = new InjectionToken('OUI_TAB');\r\n\r\n/** Used to flag tab labels for use with the portal directive */\r\n@Directive({\r\n selector: '[oui-tab-label], [OuiTabLabel]',\r\n providers: [{ provide: OUI_TAB_LABEL, useExisting: OuiTabLabel }],\r\n})\r\nexport class OuiTabLabel extends CdkPortal {\r\n constructor(\r\n templateRef: TemplateRef,\r\n viewContainerRef: ViewContainerRef,\r\n @Inject(OUI_TAB) @Optional() public _closestTab: any\r\n ) {\r\n super(templateRef, viewContainerRef);\r\n }\r\n}\r\n", "selector": "[oui-tab-label], [OuiTabLabel]", "providers": [ { "name": "{ provide: OUI_TAB_LABEL, useExisting: OuiTabLabel }" } ], + "hostDirectives": [], + "standalone": false, "inputsClass": [], "outputsClass": [], "deprecated": false, @@ -19839,12 +20074,16 @@ } ], "modifierKind": [ - 123 + 170, + 170, + 125 ] } ], "methodsClass": [], - "extends": "CdkPortal", + "extends": [ + "CdkPortal" + ], "constructorObj": { "name": "constructor", "description": "", @@ -19904,14 +20143,16 @@ }, { "name": "ouiTabLabelWrapper", - "id": "directive-ouiTabLabelWrapper-39eb023c2112987017621fbbab375ce632805d98b8060632114adbea3034f30a90ad85fea34756375ba235f08f50eb3af92f8d077e147c1eecc3dcb2759e9a28", + "id": "directive-ouiTabLabelWrapper-7e5d80ee640d0ea8999c77f7abcf384cf88e8e4e67e791d0966c3609d1ff326d98422cc0dafafc97745258d5d98bc78d166bed692c9aa7340871a5cfec7ea12b", "file": "ui/src/components/tabs/tab-label-wrapper.ts", "type": "directive", "description": "

Used in the oui-tab-group view to display tab labels.

\n", "rawdescription": "\n\nUsed in the `oui-tab-group` view to display tab labels.\n", - "sourceCode": "import { Directive, ElementRef } from '@angular/core';\nimport { mixinInkBarItem } from './ink-bar';\nimport { CanDisable, mixinDisabled } from '../core';\n\n// Boilerplate for applying mixins to ouiTabLabelWrapper.\n/** @docs-private */\nconst _OuiTabLabelWrapperMixinBase = mixinInkBarItem(\n mixinDisabled(\n class {\n elementRef: ElementRef;\n }\n )\n);\n\n/**\n * Used in the `oui-tab-group` view to display tab labels.\n * @docs-private\n */\n@Directive({\n selector: '[ouiTabLabelWrapper]',\n // eslint-disable-next-line @angular-eslint/no-inputs-metadata-property\n inputs: ['disabled', 'fitInkBarToContent'],\n // eslint-disable-next-line @angular-eslint/no-host-metadata-property\n host: {\n '[class.oui-mdc-tab-disabled]': 'disabled',\n '[attr.aria-disabled]': '!!disabled',\n },\n})\nexport class ouiTabLabelWrapper\n extends _OuiTabLabelWrapperMixinBase\n implements CanDisable\n{\n constructor(override elementRef: ElementRef) {\n super();\n }\n\n /** Sets focus on the wrapper element */\n focus(): void {\n this.elementRef.nativeElement.focus();\n }\n\n getOffsetLeft(): number {\n return this.elementRef.nativeElement.offsetLeft;\n }\n\n getOffsetWidth(): number {\n return this.elementRef.nativeElement.offsetWidth;\n }\n}\n", + "sourceCode": "import { Directive, ElementRef } from '@angular/core';\r\nimport { mixinInkBarItem } from './ink-bar';\r\nimport { CanDisable, mixinDisabled } from '../core';\r\n\r\n// Boilerplate for applying mixins to ouiTabLabelWrapper.\r\n/** @docs-private */\r\nconst _OuiTabLabelWrapperMixinBase = mixinInkBarItem(\r\n mixinDisabled(\r\n class {\r\n elementRef: ElementRef;\r\n }\r\n )\r\n);\r\n\r\n/**\r\n * Used in the `oui-tab-group` view to display tab labels.\r\n * @docs-private\r\n */\r\n@Directive({\r\n selector: '[ouiTabLabelWrapper]',\r\n // eslint-disable-next-line @angular-eslint/no-inputs-metadata-property\r\n inputs: ['disabled', 'fitInkBarToContent'],\r\n // eslint-disable-next-line @angular-eslint/no-host-metadata-property\r\n host: {\r\n '[class.oui-mdc-tab-disabled]': 'disabled',\r\n '[attr.aria-disabled]': '!!disabled',\r\n },\r\n})\r\nexport class ouiTabLabelWrapper\r\n extends _OuiTabLabelWrapperMixinBase\r\n implements CanDisable\r\n{\r\n constructor(override elementRef: ElementRef) {\r\n super();\r\n }\r\n\r\n /** Sets focus on the wrapper element */\r\n focus(): void {\r\n this.elementRef.nativeElement.focus();\r\n }\r\n\r\n getOffsetLeft(): number {\r\n return this.elementRef.nativeElement.offsetLeft;\r\n }\r\n\r\n getOffsetWidth(): number {\r\n return this.elementRef.nativeElement.offsetWidth;\r\n }\r\n}\r\n", "selector": "[ouiTabLabelWrapper]", "providers": [], + "hostDirectives": [], + "standalone": false, "inputsClass": [], "outputsClass": [], "deprecated": false, @@ -19953,7 +20194,9 @@ "deprecationMessage": "" } ], - "extends": "_OuiTabLabelWrapperMixinBase", + "extends": [ + "_OuiTabLabelWrapperMixinBase" + ], "implements": [ "CanDisable" ], @@ -19994,6 +20237,9 @@ "sourceCode": "import { AnimationEvent } from '@angular/animations';\nimport { AriaDescriber, FocusMonitor } from '@angular/cdk/a11y';\nimport { Directionality } from '@angular/cdk/bidi';\nimport { coerceBooleanProperty } from '@angular/cdk/coercion';\nimport {\n BreakpointObserver,\n Breakpoints,\n BreakpointState,\n} from '@angular/cdk/layout';\nimport {\n FlexibleConnectedPositionStrategy,\n HorizontalConnectionPos,\n OriginConnectionPosition,\n Overlay,\n OverlayConnectionPosition,\n OverlayRef,\n VerticalConnectionPos,\n ScrollStrategy,\n} from '@angular/cdk/overlay';\nimport { ScrollDispatcher } from '@angular/cdk/scrolling';\nimport { Platform } from '@angular/cdk/platform';\nimport { ComponentPortal } from '@angular/cdk/portal';\nimport { take, takeUntil } from 'rxjs/operators';\nimport {\n ChangeDetectionStrategy,\n ChangeDetectorRef,\n Component,\n Directive,\n ElementRef,\n Inject,\n InjectionToken,\n Input,\n NgZone,\n OnDestroy,\n Optional,\n ViewContainerRef,\n ViewEncapsulation,\n} from '@angular/core';\nimport { Subject, Observable } from 'rxjs';\nimport { ouiTooltipAnimations } from './tooltip-animations';\nimport { CanDisable } from '../core';\n\nexport type TooltipPosition = 'left' | 'right' | 'above' | 'below';\n\n/** Time in ms to throttle repositioning after scroll events. */\nexport const SCROLL_THROTTLE_MS = 20;\n\n/** CSS class that will be attached to the overlay panel. */\nexport const TOOLTIP_PANEL_CLASS = 'oui-tooltip-panel';\n\n/**\n * Creates an error to be thrown if the user supplied an invalid tooltip position.\n *\n * @docs-private\n */\nexport function getOuiTooltipInvalidPositionError(position: string) {\n return Error(`Tooltip position \"${position}\" is invalid.`);\n}\n\n/** Injection token that determines the scroll handling while a tooltip is visible. */\nexport const OUI_TOOLTIP_SCROLL_STRATEGY = new InjectionToken<\n () => ScrollStrategy\n>('oui-tooltip-scroll-strategy');\n\n/** @docs-private */\nexport function OUI_TOOLTIP_SCROLL_STRATEGY_FACTORY(\n overlay: Overlay\n): () => ScrollStrategy {\n return () =>\n overlay.scrollStrategies.reposition({ scrollThrottle: SCROLL_THROTTLE_MS });\n}\n\n/** @docs-private */\nexport const OUI_TOOLTIP_SCROLL_STRATEGY_FACTORY_PROVIDER = {\n provide: OUI_TOOLTIP_SCROLL_STRATEGY,\n deps: [Overlay],\n useFactory: OUI_TOOLTIP_SCROLL_STRATEGY_FACTORY,\n};\n\n/** Default `ouiTooltip` options that can be overridden. */\nexport interface OuiTooltipDefaultOptions {\n showDelay: number;\n hideDelay: number;\n touchendHideDelay: number;\n}\n\nexport interface NewCSSStyleDeclaration extends CSSStyleDeclaration {\n msUserSelect: string;\n}\n\n/** Injection token to be used to override the default options for `ouiTooltip`. */\nexport const OUI_TOOLTIP_DEFAULT_OPTIONS =\n new InjectionToken('oui-tooltip-default-options', {\n providedIn: 'root',\n factory: OUI_TOOLTIP_DEFAULT_OPTIONS_FACTORY,\n });\n\n/** @docs-private */\nexport function OUI_TOOLTIP_DEFAULT_OPTIONS_FACTORY(): OuiTooltipDefaultOptions {\n return {\n showDelay: 0,\n hideDelay: 0,\n touchendHideDelay: 1500,\n };\n}\n\nexport type TooltipVisibility = 'initial' | 'visible' | 'hidden';\n\n/**\n * Internal component that wraps the tooltip's content.\n *\n * @docs-private\n */\n@Component({\n selector: 'oui-tooltip-component',\n templateUrl: 'tooltip.html',\n styleUrls: ['tooltip.scss'],\n encapsulation: ViewEncapsulation.None,\n changeDetection: ChangeDetectionStrategy.OnPush,\n animations: [ouiTooltipAnimations.tooltipState],\n // eslint-disable-next-line @angular-eslint/no-host-metadata-property\n host: {\n // Forces the element to have a layout in IE and Edge. This fixes issues where the element\n // won't be rendered if the animations are disabled or there is no web animations polyfill.\n '[style.zoom]': '_visibility === \"visible\" ? 1 : null',\n '(body:click)': 'this._handleBodyInteraction()',\n 'aria-hidden': 'true',\n },\n})\nexport class TooltipComponent {\n /** Message to display in the tooltip */\n message: string;\n /** Classes to be added to the tooltip. Supports the same syntax as `ngClass`. */\n tooltipClass: string | string[] | Set | { [key: string]: any };\n\n /** The timeout ID of any current timer set to show the tooltip */\n _showTimeoutId: number | null;\n\n /** The timeout ID of any current timer set to hide the tooltip */\n _hideTimeoutId: number | null;\n\n /** Property watched by the animation framework to show or hide the tooltip */\n _visibility: TooltipVisibility = 'initial';\n\n /** Whether interactions on the page should close the tooltip */\n private _closeOnInteraction = false;\n\n /** Subject for notifying that the tooltip has been hidden from the view */\n private readonly _onHide: Subject = new Subject();\n\n /** Stream that emits whether the user has a handset-sized display. */\n _isHandset: Observable = this._breakpointObserver.observe(\n Breakpoints.Handset\n );\n\n constructor(\n private _changeDetectorRef: ChangeDetectorRef,\n private _breakpointObserver: BreakpointObserver\n ) {}\n\n /**\n * Shows the tooltip with an animation originating from the provided origin\n *\n * @param delay Amount of milliseconds to the delay showing the tooltip.\n */\n show(): void {\n // Cancel the delayed hide if it is scheduled\n if (this._hideTimeoutId) {\n clearTimeout(this._hideTimeoutId);\n this._hideTimeoutId = null;\n }\n\n // Body interactions should cancel the tooltip if there is a delay in showing.\n this._closeOnInteraction = true;\n setTimeout(() => {\n this._visibility = 'visible';\n this._showTimeoutId = null;\n\n // Mark for check so if any parent component has set the\n // ChangeDetectionStrategy to OnPush it will be checked anyways\n this._markForCheck();\n }, 0);\n }\n\n /**\n * Begins the animation to hide the tooltip after the provided delay in ms.\n *\n * @param delay Amount of milliseconds to delay showing the tooltip.\n */\n hide(): void {\n // Cancel the delayed show if it is scheduled\n if (this._showTimeoutId) {\n clearTimeout(this._showTimeoutId);\n this._showTimeoutId = null;\n }\n setTimeout(() => {\n this._visibility = 'hidden';\n this._hideTimeoutId = null;\n // Mark for check so if any parent component has set the\n // ChangeDetectionStrategy to OnPush it will be checked anyways\n this._markForCheck();\n }, 0);\n }\n\n /** Returns an observable that notifies when the tooltip has been hidden from view. */\n afterHidden(): Observable {\n return this._onHide.asObservable();\n }\n\n /** Whether the tooltip is being displayed. */\n isVisible(): boolean {\n return this._visibility === 'visible';\n }\n\n _animationStart() {\n this._closeOnInteraction = false;\n }\n\n _animationDone(event: AnimationEvent): void {\n const toState = event.toState as TooltipVisibility;\n\n if (toState === 'hidden' && !this.isVisible()) {\n this._onHide.next();\n }\n\n if (toState === 'visible' || toState === 'hidden') {\n this._closeOnInteraction = true;\n }\n }\n\n /**\n * Interactions on the HTML body should close the tooltip immediately\n */\n _handleBodyInteraction(): void {\n if (this._closeOnInteraction) {\n this.hide();\n }\n }\n\n /**\n * Marks that the tooltip needs to be checked in the next change detection run.\n * Mainly used for rendering the initial text before positioning a tooltip, which\n * can be problematic in components with OnPush change detection.\n */\n _markForCheck(): void {\n this._changeDetectorRef.markForCheck();\n }\n}\n\n/**\n * Directive that attaches a tooltip to the host element. Animates the showing and\n * hiding of a tooltip provided position (defaults to below the element).\n */\n@Directive({\n selector: '[ouiTooltip]',\n exportAs: 'ouiTooltip',\n // eslint-disable-next-line @angular-eslint/no-host-metadata-property\n host: {\n '(longpress)': 'show()',\n '(keydown)': '_handleKeydown($event)',\n '(touchend)': '_handleTouchend()',\n '[attr.tabindex]': 'disabled ? -1 : 0',\n '[attr.aria-hidden]': 'false',\n },\n})\nexport class OuiTooltip implements OnDestroy, CanDisable {\n _overlayRef: OverlayRef | null;\n _tooltipInstance: TooltipComponent | null;\n\n private _portal: ComponentPortal;\n private _position: TooltipPosition = 'below';\n private _disabled = false;\n private _tooltipClass:\n | string\n | string[]\n | Set\n | { [key: string]: any };\n private _scrollStrategy: () => ScrollStrategy;\n\n /** Allows the user to define the position of the tooltip relative to the parent element */\n @Input('ouiTooltipPosition')\n get position(): TooltipPosition {\n return this._position;\n }\n set position(value: TooltipPosition) {\n if (value !== this._position) {\n this._position = value;\n if (this._overlayRef) {\n this._updatePosition();\n\n if (this._tooltipInstance) {\n this._tooltipInstance!.show();\n }\n\n this._overlayRef.updatePosition();\n }\n }\n }\n\n /** Disables the display of the tooltip. */\n @Input('ouiTooltipDisabled')\n get disabled(): boolean {\n return this._disabled;\n }\n set disabled(value) {\n this._disabled = coerceBooleanProperty(value);\n\n // If tooltip is disabled, hide immediately.\n if (this._disabled) {\n this.hide();\n }\n }\n\n private _message = '';\n\n /** The message to be displayed in the tooltip */\n @Input('ouiTooltip')\n get message() {\n return this._message;\n }\n set message(value: string) {\n this._ariaDescriber.removeDescription(\n this._elementRef.nativeElement,\n this._message\n );\n\n // If the message is not a string (e.g. number), convert it to a string and trim it.\n this._message = value != null ? `${value}`.trim() : '';\n\n if (!this._message && this._isTooltipVisible()) {\n this.hide();\n } else {\n this._updateTooltipMessage();\n this._ariaDescriber.describe(\n this._elementRef.nativeElement,\n this.message\n );\n }\n }\n\n /** Classes to be passed to the tooltip. Supports the same syntax as `ngClass`. */\n @Input('ouiTooltipClass')\n get tooltipClass() {\n return this._tooltipClass;\n }\n set tooltipClass(\n value: string | string[] | Set | { [key: string]: any }\n ) {\n this._tooltipClass = value;\n if (this._tooltipInstance) {\n this._tooltipInstance._markForCheck();\n this._setTooltipClass(this._tooltipClass);\n }\n }\n\n private _manualListeners = new Map<\n string,\n EventListenerOrEventListenerObject\n >();\n\n /** Emits when the component is destroyed. */\n private readonly _destroyed = new Subject();\n\n constructor(\n private _overlay: Overlay,\n private _elementRef: ElementRef,\n private _scrollDispatcher: ScrollDispatcher,\n private _viewContainerRef: ViewContainerRef,\n private _ngZone: NgZone,\n platform: Platform,\n private _ariaDescriber: AriaDescriber,\n private _focusMonitor: FocusMonitor,\n @Inject(OUI_TOOLTIP_SCROLL_STRATEGY) scrollStrategy: any,\n @Optional() private _dir: Directionality\n ) {\n this._scrollStrategy = scrollStrategy;\n const element: HTMLElement = _elementRef.nativeElement;\n const elementStyle = element.style as NewCSSStyleDeclaration & {\n webkitUserDrag: string;\n };\n const hasGestures = typeof window === 'undefined' || (window as any).Hammer;\n\n // The mouse events shouldn't be bound on mobile devices, because they can prevent the\n // first tap from firing its click event or can cause the tooltip to open for clicks.\n if (!platform.IOS && !platform.ANDROID) {\n this._manualListeners\n .set('mouseenter', () => this.show())\n .set('mouseleave', () => this.hide());\n } else if (!hasGestures) {\n // there's no way for the user to trigger the tooltip on a touch device.\n this._manualListeners.set('touchstart', () => this.show());\n }\n\n this._manualListeners.forEach((listener, event) =>\n element.addEventListener(event, listener)\n );\n\n if (element.nodeName === 'INPUT' || element.nodeName === 'TEXTAREA') {\n elementStyle.webkitUserSelect =\n elementStyle.userSelect =\n elementStyle.msUserSelect =\n '';\n }\n\n // Hammer applies `-webkit-user-drag: none` on all elements by default,\n // which breaks the native drag&drop. If the consumer explicitly made\n // the element draggable, clear the `-webkit-user-drag`.\n if (element.draggable && elementStyle.webkitUserDrag === 'none') {\n elementStyle.webkitUserDrag = '';\n }\n\n _focusMonitor\n .monitor(_elementRef)\n .pipe(takeUntil(this._destroyed))\n .subscribe((origin) => {\n // Note that the focus monitor runs outside the Angular zone.\n if (!origin) {\n _ngZone.run(() => this.hide());\n } else if (origin === 'keyboard') {\n _ngZone.run(() => this.show());\n }\n });\n }\n\n /**\n * Dispose the tooltip when destroyed.\n */\n ngOnDestroy() {\n if (this._overlayRef) {\n this._overlayRef.dispose();\n this._tooltipInstance = null;\n }\n\n // Clean up the event listeners set in the constructor\n this._manualListeners.forEach((listener, event) => {\n this._elementRef.nativeElement.removeEventListener(event, listener);\n });\n this._manualListeners.clear();\n\n this._destroyed.next();\n this._destroyed.complete();\n\n this._ariaDescriber.removeDescription(\n this._elementRef.nativeElement,\n this.message\n );\n this._focusMonitor.stopMonitoring(this._elementRef);\n }\n\n /** Shows the tooltip after the delay in ms, defaults to tooltip-delay-show or 0ms if no input */\n show(): void {\n if (\n this.disabled ||\n !this.message ||\n (this._isTooltipVisible() &&\n !this._tooltipInstance!._showTimeoutId &&\n !this._tooltipInstance!._hideTimeoutId)\n ) {\n return;\n }\n\n const overlayRef = this._createOverlay();\n\n this._detach();\n this._portal =\n this._portal ||\n new ComponentPortal(TooltipComponent, this._viewContainerRef);\n this._tooltipInstance = overlayRef.attach(this._portal).instance;\n this._tooltipInstance\n .afterHidden()\n .pipe(takeUntil(this._destroyed))\n .subscribe(() => this._detach());\n this._setTooltipClass(this._tooltipClass);\n this._updateTooltipMessage();\n this._tooltipInstance!.show();\n }\n\n /** Hides the tooltip after the delay in ms, defaults to tooltip-delay-hide or 0ms if no input */\n hide(): void {\n if (this._tooltipInstance) {\n this._tooltipInstance.hide();\n }\n }\n\n /** Shows/hides the tooltip */\n toggle(): void {\n this._isTooltipVisible() ? this.hide() : this.show();\n }\n\n /** Returns true if the tooltip is currently visible to the user */\n _isTooltipVisible(): boolean {\n return !!this._tooltipInstance && this._tooltipInstance.isVisible();\n }\n\n /** Handles the keydown events on the host element. */\n _handleKeydown(e: KeyboardEvent) {\n if (this._isTooltipVisible() && e.key === 'Escape') {\n e.stopPropagation();\n this.hide();\n }\n }\n\n /** Handles the touchend events on the host element. */\n _handleTouchend() {\n this.hide();\n }\n\n /** Create the overlay config and position strategy */\n private _createOverlay(): OverlayRef {\n if (this._overlayRef) {\n return this._overlayRef;\n }\n\n // Create connected position strategy that listens for scroll events to reposition.\n const strategy = this._overlay\n .position()\n .flexibleConnectedTo(this._elementRef)\n .withTransformOriginOn('.oui-tooltip')\n .withFlexibleDimensions(false)\n .withViewportMargin(8);\n\n const scrollableAncestors =\n this._scrollDispatcher.getAncestorScrollContainers(this._elementRef);\n\n strategy.withScrollableContainers(scrollableAncestors);\n\n strategy.positionChanges\n .pipe(takeUntil(this._destroyed))\n .subscribe((change) => {\n if (this._tooltipInstance) {\n if (\n change.scrollableViewProperties.isOverlayClipped &&\n this._tooltipInstance.isVisible()\n ) {\n // After position changes occur and the overlay is clipped by\n // a parent scrollable then close the tooltip.\n this._ngZone.run(() => this.hide());\n }\n }\n });\n\n this._overlayRef = this._overlay.create({\n direction: this._dir,\n positionStrategy: strategy,\n panelClass: TOOLTIP_PANEL_CLASS,\n scrollStrategy: this._scrollStrategy(),\n });\n\n this._updatePosition();\n\n this._overlayRef\n .detachments()\n .pipe(takeUntil(this._destroyed))\n .subscribe(() => this._detach());\n\n return this._overlayRef;\n }\n\n /** Detaches the currently-attached tooltip. */\n private _detach() {\n if (this._overlayRef && this._overlayRef.hasAttached()) {\n this._overlayRef.detach();\n }\n\n this._tooltipInstance = null;\n }\n\n /** Updates the position of the current tooltip. */\n private _updatePosition() {\n const position = this._overlayRef!.getConfig()\n .positionStrategy as FlexibleConnectedPositionStrategy;\n const origin = this._getOrigin();\n const overlay = this._getOverlayPosition();\n\n position.withPositions([\n { ...origin.main, ...overlay.main },\n { ...origin.fallback, ...overlay.fallback },\n ]);\n }\n\n /**\n * Returns the origin position and a fallback position based on the user's position preference.\n * The fallback position is the inverse of the origin (e.g. `'below' -> 'above'`).\n */\n _getOrigin(): {\n main: OriginConnectionPosition;\n fallback: OriginConnectionPosition;\n } {\n const isLtr = !this._dir || this._dir.value === 'ltr';\n const position = this.position;\n let originPosition: OriginConnectionPosition;\n\n if (position === 'above' || position === 'below') {\n originPosition = {\n originX: 'center',\n originY: position === 'above' ? 'top' : 'bottom',\n };\n } else if (\n (position === 'left' && isLtr) ||\n (position === 'right' && !isLtr)\n ) {\n originPosition = { originX: 'start', originY: 'center' };\n } else if (\n (position === 'right' && isLtr) ||\n (position === 'left' && !isLtr)\n ) {\n originPosition = { originX: 'end', originY: 'center' };\n } else {\n throw getOuiTooltipInvalidPositionError(position);\n }\n\n const { x, y } = this._invertPosition(\n originPosition.originX,\n originPosition.originY\n );\n\n return {\n main: originPosition,\n fallback: { originX: x, originY: y },\n };\n }\n\n /** Returns the overlay position and a fallback position based on the user's preference */\n _getOverlayPosition(): {\n main: OverlayConnectionPosition;\n fallback: OverlayConnectionPosition;\n } {\n const isLtr = !this._dir || this._dir.value === 'ltr';\n const position = this.position;\n let overlayPosition: OverlayConnectionPosition;\n\n if (position === 'above') {\n overlayPosition = { overlayX: 'center', overlayY: 'bottom' };\n } else if (position === 'below') {\n overlayPosition = { overlayX: 'center', overlayY: 'top' };\n } else if (\n (position === 'left' && isLtr) ||\n (position === 'right' && !isLtr)\n ) {\n overlayPosition = { overlayX: 'end', overlayY: 'center' };\n } else if (\n (position === 'right' && isLtr) ||\n (position === 'left' && !isLtr)\n ) {\n overlayPosition = { overlayX: 'start', overlayY: 'center' };\n } else {\n throw getOuiTooltipInvalidPositionError(position);\n }\n\n const { x, y } = this._invertPosition(\n overlayPosition.overlayX,\n overlayPosition.overlayY\n );\n\n return {\n main: overlayPosition,\n fallback: { overlayX: x, overlayY: y },\n };\n }\n\n /** Updates the tooltip message and repositions the overlay according to the new message length */\n private _updateTooltipMessage() {\n // Must wait for the message to be painted to the tooltip so that the overlay can properly\n // calculate the correct positioning based on the size of the text.\n if (this._tooltipInstance) {\n this._tooltipInstance.message = this.message;\n this._tooltipInstance._markForCheck();\n\n this._ngZone.onMicrotaskEmpty\n .asObservable()\n .pipe(take(1), takeUntil(this._destroyed))\n .subscribe(() => {\n if (this._tooltipInstance) {\n this._overlayRef!.updatePosition();\n }\n });\n }\n }\n\n /** Updates the tooltip class */\n private _setTooltipClass(\n tooltipClass: string | string[] | Set | { [key: string]: any }\n ) {\n if (this._tooltipInstance) {\n this._tooltipInstance.tooltipClass = tooltipClass;\n this._tooltipInstance._markForCheck();\n }\n }\n\n /** Inverts an overlay position. */\n private _invertPosition(\n x: HorizontalConnectionPos,\n y: VerticalConnectionPos\n ) {\n if (this.position === 'above' || this.position === 'below') {\n if (y === 'top') {\n y = 'bottom';\n } else if (y === 'bottom') {\n y = 'top';\n }\n } else {\n if (x === 'end') {\n x = 'start';\n } else if (x === 'start') {\n x = 'end';\n }\n }\n\n return { x, y };\n }\n}\n", "selector": "[ouiTooltip]", "providers": [], + "exportAs": "ouiTooltip", + "hostDirectives": [], + "standalone": false, "inputsClass": [ { "name": "ouiTooltip", @@ -20053,8 +20299,8 @@ "line": 362, "rawdescription": "\nEmits when the component is destroyed.", "modifierKind": [ - 121, - 144 + 123, + 148 ] }, { @@ -20067,7 +20313,7 @@ "description": "", "line": 272, "modifierKind": [ - 121 + 123 ] }, { @@ -20080,7 +20326,7 @@ "description": "", "line": 356, "modifierKind": [ - 121 + 123 ] }, { @@ -20093,7 +20339,7 @@ "description": "", "line": 314, "modifierKind": [ - 121 + 123 ] }, { @@ -20114,7 +20360,7 @@ "description": "", "line": 270, "modifierKind": [ - 121 + 123 ] }, { @@ -20127,7 +20373,7 @@ "description": "", "line": 271, "modifierKind": [ - 121 + 123 ] }, { @@ -20139,7 +20385,7 @@ "description": "", "line": 278, "modifierKind": [ - 121 + 123 ] }, { @@ -20151,7 +20397,7 @@ "description": "", "line": 273, "modifierKind": [ - 121 + 123 ] }, { @@ -20177,7 +20423,7 @@ "rawdescription": "\nCreate the overlay config and position strategy", "description": "

Create the overlay config and position strategy

\n", "modifierKind": [ - 121 + 123 ] }, { @@ -20192,7 +20438,7 @@ "rawdescription": "\nDetaches the currently-attached tooltip.", "description": "

Detaches the currently-attached tooltip.

\n", "modifierKind": [ - 121 + 123 ] }, { @@ -20286,7 +20532,7 @@ "rawdescription": "\nInverts an overlay position.", "description": "

Inverts an overlay position.

\n", "modifierKind": [ - 121 + 123 ], "jsdoctags": [ { @@ -20340,7 +20586,7 @@ "rawdescription": "\nUpdates the tooltip class", "description": "

Updates the tooltip class

\n", "modifierKind": [ - 121 + 123 ], "jsdoctags": [ { @@ -20366,7 +20612,7 @@ "rawdescription": "\nUpdates the position of the current tooltip.", "description": "

Updates the position of the current tooltip.

\n", "modifierKind": [ - 121 + 123 ] }, { @@ -20381,7 +20627,7 @@ "rawdescription": "\nUpdates the tooltip message and repositions the overlay according to the new message length", "description": "

Updates the tooltip message and repositions the overlay according to the new message length

\n", "modifierKind": [ - 121 + 123 ] }, { @@ -20433,6 +20679,7 @@ "description": "

Shows/hides the tooltip

\n" } ], + "extends": [], "implements": [ "OnDestroy", "CanDisable" @@ -20785,6 +21032,7 @@ "./checkbox.html" ], "viewProviders": [], + "hostDirectives": [], "inputsClass": [ { "name": "aria-label", @@ -20901,7 +21149,7 @@ "description": "", "line": 170, "modifierKind": [ - 121 + 123 ] }, { @@ -20914,7 +21162,7 @@ "description": "", "line": 333, "modifierKind": [ - 121 + 123 ] }, { @@ -20927,7 +21175,7 @@ "description": "", "line": 192, "modifierKind": [ - 121 + 123 ] }, { @@ -20940,7 +21188,7 @@ "description": "", "line": 191, "modifierKind": [ - 121 + 123 ] }, { @@ -20953,7 +21201,7 @@ "description": "", "line": 190, "modifierKind": [ - 121 + 123 ] }, { @@ -20965,7 +21213,7 @@ "description": "", "line": 200, "modifierKind": [ - 123 + 125 ] }, { @@ -20982,6 +21230,9 @@ "name": "ViewChild", "stringifiedArguments": "'input'" } + ], + "modifierKind": [ + 170 ] }, { @@ -20995,7 +21246,7 @@ "line": 113, "rawdescription": "\nA unique id for the checkbox input. If none is supplied, it will be auto-generated.", "modifierKind": [ - 121 + 123 ] }, { @@ -21012,17 +21263,17 @@ { "pos": 9868, "end": 9885, - "flags": 4227072, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 325, + "kind": 334, "tagName": { "pos": 9869, "end": 9881, - "flags": 4227072, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "docs-private" }, "comment": "" @@ -21038,7 +21289,7 @@ "description": "", "line": 133, "modifierKind": [ - 121 + 123 ] }, { @@ -21051,7 +21302,7 @@ "description": "", "line": 109, "modifierKind": [ - 121 + 123 ] }, { @@ -21087,7 +21338,7 @@ "deprecated": false, "deprecationMessage": "", "modifierKind": [ - 121 + 123 ] }, { @@ -21113,7 +21364,7 @@ "deprecated": false, "deprecationMessage": "", "modifierKind": [ - 121 + 123 ], "jsdoctags": [ { @@ -21169,10 +21420,10 @@ "name": { "pos": 6607, "end": 6612, - "flags": 4227072, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "event" }, "type": "Event", @@ -21181,10 +21432,10 @@ "tagName": { "pos": 6601, "end": 6606, - "flags": 4227072, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "param" }, "comment": "" @@ -21236,7 +21487,7 @@ "deprecated": false, "deprecationMessage": "", "modifierKind": [ - 121 + 123 ], "jsdoctags": [ { @@ -21417,6 +21668,8 @@ "deprecationMessage": "", "hostBindings": [], "hostListeners": [], + "standalone": false, + "imports": [], "description": "

Supports all of the functionality of an HTML5 checkbox,\nand exposes a similar API. A MatCheckbox can be either checked, unchecked, or\ndisabled. Note that all additional accessibility attributes are taken care of by the component,\nso there is no need to provide them yourself. However, if you want to omit a label and still\nhave the checkbox be accessible, you may supply an [aria-label] input.\nSee: https://github.com/scheduleonce/once-ui/tree/master/ui/src/components/checkbox/README.md

\n", "rawdescription": "\n\nSupports all of the functionality of an HTML5 checkbox,\nand exposes a similar API. A MatCheckbox can be either checked, unchecked, or\ndisabled. Note that all additional accessibility attributes are taken care of by the component,\nso there is no need to provide them yourself. However, if you want to omit a label and still\nhave the checkbox be accessible, you may supply an [aria-label] input.\nSee: https://github.com/scheduleonce/once-ui/tree/master/ui/src/components/checkbox/README.md\n", "type": "component", @@ -21515,7 +21768,9 @@ } ] }, - "extends": "OuiCheckboxMixinBase", + "extends": [ + "OuiCheckboxMixinBase" + ], "implements": [ "ControlValueAccessor", "HasTabIndex", @@ -21674,6 +21929,7 @@ "template": "", "templateUrl": [], "viewProviders": [], + "hostDirectives": [], "inputsClass": [ { "name": "inline", @@ -21717,7 +21973,7 @@ "description": "", "line": 120, "modifierKind": [ - 123 + 125 ] }, { @@ -21730,7 +21986,7 @@ "description": "", "line": 104, "modifierKind": [ - 121 + 123 ] }, { @@ -21752,7 +22008,7 @@ "description": "", "line": 121, "modifierKind": [ - 123 + 125 ] } ], @@ -21767,7 +22023,7 @@ "deprecated": false, "deprecationMessage": "", "modifierKind": [ - 121 + 123 ] }, { @@ -21787,7 +22043,7 @@ "deprecated": false, "deprecationMessage": "", "modifierKind": [ - 121 + 123 ], "jsdoctags": [ { @@ -21816,6 +22072,8 @@ "deprecationMessage": "", "hostBindings": [], "hostListeners": [], + "standalone": false, + "imports": [], "description": "

oui-icon makes it easier to use vector-based icons in your app. This directive supports only SVG icons.\nTo associate a name with an icon URL, use the addSvgIcon. The methods of OuiIconRegistry. After registering an icon, it\ncan be displayed by setting the svgIcon input. For an icon in the default namespace, use the name directly.\nComponent to display an icon. It can be used in the following ways:

\n
    \n
  • Specify the svgIcon input to load an SVG icon from a URL previously registered with the addSvgIcon, addSvgIconSet.\nExamples:\n
  • \n
  • Use a font ligature as an icon by putting the ligature text in the content of the component.\nExample: home sun
  • \n
\n", "rawdescription": "\n\noui-icon makes it easier to use vector-based icons in your app. This directive supports only SVG icons.\nTo associate a name with an icon URL, use the addSvgIcon. The methods of OuiIconRegistry. After registering an icon, it\ncan be displayed by setting the svgIcon input. For an icon in the default namespace, use the name directly.\nComponent to display an icon. It can be used in the following ways:\n- Specify the svgIcon input to load an SVG icon from a URL previously registered with the addSvgIcon, addSvgIconSet.\n Examples:\n \n- Use a font ligature as an icon by putting the ligature text in the content of the component.\n Example: home sun\n", "type": "component", @@ -21899,7 +22157,9 @@ } ] }, - "extends": "OuiIconMixinBase", + "extends": [ + "OuiIconMixinBase" + ], "implements": [ "OnInit", "CanColor" @@ -21971,6 +22231,7 @@ "button.html" ], "viewProviders": [], + "hostDirectives": [], "inputsClass": [ { "name": "tabIndex", @@ -21994,7 +22255,7 @@ "description": "", "line": 78, "modifierKind": [ - 123 + 125 ], "inheritance": { "file": "OuiButton" @@ -22010,7 +22271,7 @@ "description": "", "line": 74, "modifierKind": [ - 121 + 123 ], "inheritance": { "file": "OuiButton" @@ -22056,7 +22317,7 @@ "deprecated": false, "deprecationMessage": "", "modifierKind": [ - 122 + 124 ], "inheritance": { "file": "OuiButton" @@ -22143,6 +22404,8 @@ "deprecationMessage": "", "hostBindings": [], "hostListeners": [], + "standalone": false, + "imports": [], "description": "

Once UI anchor.

\n", "rawdescription": "\n\nOnce UI anchor.\n", "type": "component", @@ -22226,7 +22489,9 @@ } ] }, - "extends": "OuiButton", + "extends": [ + "OuiButton" + ], "templateData": "\n" }, { @@ -22257,6 +22522,7 @@ "autocomplete.html" ], "viewProviders": [], + "hostDirectives": [], "inputsClass": [ { "name": "autoActiveFirstOption", @@ -22342,7 +22608,7 @@ "description": "", "line": 122, "modifierKind": [ - 121 + 123 ] }, { @@ -22401,21 +22667,24 @@ "stringifiedArguments": "OuiOptgroup" } ], + "modifierKind": [ + 170 + ], "jsdoctags": [ { "pos": 3111, "end": 3125, - "flags": 4227072, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 325, + "kind": 334, "tagName": { "pos": 3112, "end": 3124, - "flags": 4227072, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "docs-private" }, "comment": "" @@ -22437,21 +22706,24 @@ "stringifiedArguments": "OuiOption, {descendants: true}" } ], + "modifierKind": [ + 170 + ], "jsdoctags": [ { "pos": 3001, "end": 3015, - "flags": 4227072, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 325, + "kind": 334, "tagName": { "pos": 3002, "end": 3014, - "flags": 4227072, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "docs-private" }, "comment": "" @@ -22472,6 +22744,9 @@ "name": "ViewChild", "stringifiedArguments": "'panel'" } + ], + "modifierKind": [ + 170 ] }, { @@ -22500,21 +22775,24 @@ "stringifiedArguments": "TemplateRef" } ], + "modifierKind": [ + 170 + ], "jsdoctags": [ { "pos": 2809, "end": 2823, - "flags": 4227072, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 325, + "kind": 334, "tagName": { "pos": 2810, "end": 2822, - "flags": 4227072, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "docs-private" }, "comment": "" @@ -22622,6 +22900,8 @@ "deprecationMessage": "", "hostBindings": [], "hostListeners": [], + "standalone": false, + "imports": [], "description": "", "rawdescription": "\n", "type": "component", @@ -22690,6 +22970,7 @@ } ] }, + "extends": [], "implements": [ "AfterContentInit" ], @@ -22780,7 +23061,7 @@ }, { "name": "OuiAutocompleteGroupStorybook", - "id": "component-OuiAutocompleteGroupStorybook-a05c014d2972db1c12417e8b91b83e9c05e198f5aefa128642f94d6c8f39f1743944bff24abcb101f17049bff0df923723ca6efcd8edcabf932a36d0e252b563", + "id": "component-OuiAutocompleteGroupStorybook-a7c3a42dc260f97f48099129f3271decd60a827448988b8e399989f849989a0745c120e669504c278a5df2bf0c7aa7d074d5b69fefc6e004ad3a5a3600023dd0", "file": "ui/src/stories/autocomplete/autocomplete.component.ts", "encapsulation": [], "entryComponents": [], @@ -22793,6 +23074,7 @@ "template": "\n \n \n \n \n {{ name }}\n \n \n \n\n", "templateUrl": [], "viewProviders": [], + "hostDirectives": [], "inputsClass": [ { "name": "disabled", @@ -22815,7 +23097,7 @@ "propertiesClass": [ { "name": "stateForm", - "defaultValue": "this.fb.group({\n stateGroup: '',\n })", + "defaultValue": "this.fb.group({\r\n stateGroup: '',\r\n })", "deprecated": false, "deprecationMessage": "", "type": "UntypedFormGroup", @@ -22851,7 +23133,7 @@ "deprecated": false, "deprecationMessage": "", "modifierKind": [ - 121 + 123 ], "jsdoctags": [ { @@ -22880,10 +23162,12 @@ "deprecationMessage": "", "hostBindings": [], "hostListeners": [], + "standalone": false, + "imports": [], "description": "", "rawdescription": "\n", "type": "component", - "sourceCode": "import { Input, Component, OnInit } from '@angular/core';\nimport { Observable } from 'rxjs';\nimport {\n UntypedFormControl,\n UntypedFormBuilder,\n UntypedFormGroup,\n} from '@angular/forms';\nimport { startWith, map } from 'rxjs/operators';\n\nexport interface StateGroup {\n letter: string;\n names: string[];\n}\nexport const _filter = (opt: string[], value: string): string[] => {\n const filterValue = value.toLowerCase();\n\n return opt.filter((item) => item.toLowerCase().indexOf(filterValue) === 0);\n};\n\n@Component({\n selector: 'oui-autocomplete-storybook',\n template: `\n \n \n \n \n \n {{ option }}\n \n \n `,\n})\nexport class OuiAutocompleteStorybook implements OnInit {\n filteredOptions: Observable;\n myControl = new UntypedFormControl();\n @Input() options: any[];\n @Input()\n set disabled(value: boolean) {\n if (value) {\n this.myControl.disable();\n } else {\n this.myControl.enable();\n }\n }\n ngOnInit() {\n this.filteredOptions = this.myControl.valueChanges.pipe(\n startWith(''),\n map((value) => (typeof value === 'string' ? value : value)),\n map((option) => (option ? this._filter(option) : this.options.slice()))\n );\n }\n private _filter(option): string[] {\n const filterValue = option.toLowerCase();\n\n return this.options.filter(\n // eslint-disable-next-line no-shadow\n (option) => option.toLowerCase().indexOf(filterValue) === 0\n );\n }\n}\n\n@Component({\n selector: 'oui-autocomplete-group-storybook',\n template: `\n \n \n \n \n \n {{ name }}\n \n \n \n \n `,\n})\nexport class OuiAutocompleteGroupStorybook implements OnInit {\n @Input() stateGroups: StateGroup[];\n @Input()\n set disabled(value: boolean) {\n if (value) {\n this.stateForm.get('stateGroup')!.disable();\n } else {\n this.stateForm.get('stateGroup')!.enable();\n }\n }\n stateForm: UntypedFormGroup = this.fb.group({\n stateGroup: '',\n });\n stateGroupOptions: Observable;\n\n constructor(private fb: UntypedFormBuilder) {}\n ngOnInit() {\n this.stateGroupOptions = this.stateForm\n .get('stateGroup')!\n .valueChanges.pipe(\n startWith(''),\n map((value: string) => this._filterGroup(value))\n );\n }\n\n private _filterGroup(value: string): StateGroup[] {\n if (value) {\n return this.stateGroups\n .map((group) => ({\n letter: group.letter,\n names: _filter(group.names, value),\n }))\n .filter((group) => group.names.length > 0);\n }\n\n return this.stateGroups;\n }\n}\n", + "sourceCode": "import { Input, Component, OnInit } from '@angular/core';\r\nimport { Observable } from 'rxjs';\r\nimport {\r\n UntypedFormControl,\r\n UntypedFormBuilder,\r\n UntypedFormGroup,\r\n} from '@angular/forms';\r\nimport { startWith, map } from 'rxjs/operators';\r\n\r\nexport interface StateGroup {\r\n letter: string;\r\n names: string[];\r\n}\r\nexport const _filter = (opt: string[], value: string): string[] => {\r\n const filterValue = value.toLowerCase();\r\n\r\n return opt.filter((item) => item.toLowerCase().indexOf(filterValue) === 0);\r\n};\r\n\r\n@Component({\r\n selector: 'oui-autocomplete-storybook',\r\n template: `\r\n \r\n \r\n \r\n \r\n \r\n {{ option }}\r\n \r\n \r\n `,\r\n})\r\nexport class OuiAutocompleteStorybook implements OnInit {\r\n filteredOptions: Observable;\r\n myControl = new UntypedFormControl();\r\n @Input() options: any[];\r\n @Input()\r\n set disabled(value: boolean) {\r\n if (value) {\r\n this.myControl.disable();\r\n } else {\r\n this.myControl.enable();\r\n }\r\n }\r\n ngOnInit() {\r\n this.filteredOptions = this.myControl.valueChanges.pipe(\r\n startWith(''),\r\n map((value) => (typeof value === 'string' ? value : value)),\r\n map((option) => (option ? this._filter(option) : this.options.slice()))\r\n );\r\n }\r\n private _filter(option): string[] {\r\n const filterValue = option.toLowerCase();\r\n\r\n return this.options.filter(\r\n // eslint-disable-next-line no-shadow\r\n (option) => option.toLowerCase().indexOf(filterValue) === 0\r\n );\r\n }\r\n}\r\n\r\n@Component({\r\n selector: 'oui-autocomplete-group-storybook',\r\n template: `\r\n \r\n \r\n \r\n \r\n \r\n {{ name }}\r\n \r\n \r\n \r\n \r\n `,\r\n})\r\nexport class OuiAutocompleteGroupStorybook implements OnInit {\r\n @Input() stateGroups: StateGroup[];\r\n @Input()\r\n set disabled(value: boolean) {\r\n if (value) {\r\n this.stateForm.get('stateGroup')!.disable();\r\n } else {\r\n this.stateForm.get('stateGroup')!.enable();\r\n }\r\n }\r\n stateForm: UntypedFormGroup = this.fb.group({\r\n stateGroup: '',\r\n });\r\n stateGroupOptions: Observable;\r\n\r\n constructor(private fb: UntypedFormBuilder) {}\r\n ngOnInit() {\r\n this.stateGroupOptions = this.stateForm\r\n .get('stateGroup')!\r\n .valueChanges.pipe(\r\n startWith(''),\r\n map((value: string) => this._filterGroup(value))\r\n );\r\n }\r\n\r\n private _filterGroup(value: string): StateGroup[] {\r\n if (value) {\r\n return this.stateGroups\r\n .map((group) => ({\r\n letter: group.letter,\r\n names: _filter(group.names, value),\r\n }))\r\n .filter((group) => group.names.length > 0);\r\n }\r\n\r\n return this.stateGroups;\r\n }\r\n}\r\n", "assetsDirs": [], "styleUrlsData": "", "stylesData": "", @@ -22913,6 +23197,7 @@ } ] }, + "extends": [], "implements": [ "OnInit" ], @@ -22951,7 +23236,7 @@ }, { "name": "OuiAutocompleteStorybook", - "id": "component-OuiAutocompleteStorybook-a05c014d2972db1c12417e8b91b83e9c05e198f5aefa128642f94d6c8f39f1743944bff24abcb101f17049bff0df923723ca6efcd8edcabf932a36d0e252b563", + "id": "component-OuiAutocompleteStorybook-a7c3a42dc260f97f48099129f3271decd60a827448988b8e399989f849989a0745c120e669504c278a5df2bf0c7aa7d074d5b69fefc6e004ad3a5a3600023dd0", "file": "ui/src/stories/autocomplete/autocomplete.component.ts", "encapsulation": [], "entryComponents": [], @@ -22964,6 +23249,7 @@ "template": "\n \n\n\n \n {{ option }}\n \n\n", "templateUrl": [], "viewProviders": [], + "hostDirectives": [], "inputsClass": [ { "name": "disabled", @@ -23022,7 +23308,7 @@ "deprecated": false, "deprecationMessage": "", "modifierKind": [ - 121 + 123 ], "jsdoctags": [ { @@ -23051,13 +23337,16 @@ "deprecationMessage": "", "hostBindings": [], "hostListeners": [], + "standalone": false, + "imports": [], "description": "", "rawdescription": "\n", "type": "component", - "sourceCode": "import { Input, Component, OnInit } from '@angular/core';\nimport { Observable } from 'rxjs';\nimport {\n UntypedFormControl,\n UntypedFormBuilder,\n UntypedFormGroup,\n} from '@angular/forms';\nimport { startWith, map } from 'rxjs/operators';\n\nexport interface StateGroup {\n letter: string;\n names: string[];\n}\nexport const _filter = (opt: string[], value: string): string[] => {\n const filterValue = value.toLowerCase();\n\n return opt.filter((item) => item.toLowerCase().indexOf(filterValue) === 0);\n};\n\n@Component({\n selector: 'oui-autocomplete-storybook',\n template: `\n \n \n \n \n \n {{ option }}\n \n \n `,\n})\nexport class OuiAutocompleteStorybook implements OnInit {\n filteredOptions: Observable;\n myControl = new UntypedFormControl();\n @Input() options: any[];\n @Input()\n set disabled(value: boolean) {\n if (value) {\n this.myControl.disable();\n } else {\n this.myControl.enable();\n }\n }\n ngOnInit() {\n this.filteredOptions = this.myControl.valueChanges.pipe(\n startWith(''),\n map((value) => (typeof value === 'string' ? value : value)),\n map((option) => (option ? this._filter(option) : this.options.slice()))\n );\n }\n private _filter(option): string[] {\n const filterValue = option.toLowerCase();\n\n return this.options.filter(\n // eslint-disable-next-line no-shadow\n (option) => option.toLowerCase().indexOf(filterValue) === 0\n );\n }\n}\n\n@Component({\n selector: 'oui-autocomplete-group-storybook',\n template: `\n \n \n \n \n \n {{ name }}\n \n \n \n \n `,\n})\nexport class OuiAutocompleteGroupStorybook implements OnInit {\n @Input() stateGroups: StateGroup[];\n @Input()\n set disabled(value: boolean) {\n if (value) {\n this.stateForm.get('stateGroup')!.disable();\n } else {\n this.stateForm.get('stateGroup')!.enable();\n }\n }\n stateForm: UntypedFormGroup = this.fb.group({\n stateGroup: '',\n });\n stateGroupOptions: Observable;\n\n constructor(private fb: UntypedFormBuilder) {}\n ngOnInit() {\n this.stateGroupOptions = this.stateForm\n .get('stateGroup')!\n .valueChanges.pipe(\n startWith(''),\n map((value: string) => this._filterGroup(value))\n );\n }\n\n private _filterGroup(value: string): StateGroup[] {\n if (value) {\n return this.stateGroups\n .map((group) => ({\n letter: group.letter,\n names: _filter(group.names, value),\n }))\n .filter((group) => group.names.length > 0);\n }\n\n return this.stateGroups;\n }\n}\n", + "sourceCode": "import { Input, Component, OnInit } from '@angular/core';\r\nimport { Observable } from 'rxjs';\r\nimport {\r\n UntypedFormControl,\r\n UntypedFormBuilder,\r\n UntypedFormGroup,\r\n} from '@angular/forms';\r\nimport { startWith, map } from 'rxjs/operators';\r\n\r\nexport interface StateGroup {\r\n letter: string;\r\n names: string[];\r\n}\r\nexport const _filter = (opt: string[], value: string): string[] => {\r\n const filterValue = value.toLowerCase();\r\n\r\n return opt.filter((item) => item.toLowerCase().indexOf(filterValue) === 0);\r\n};\r\n\r\n@Component({\r\n selector: 'oui-autocomplete-storybook',\r\n template: `\r\n \r\n \r\n \r\n \r\n \r\n {{ option }}\r\n \r\n \r\n `,\r\n})\r\nexport class OuiAutocompleteStorybook implements OnInit {\r\n filteredOptions: Observable;\r\n myControl = new UntypedFormControl();\r\n @Input() options: any[];\r\n @Input()\r\n set disabled(value: boolean) {\r\n if (value) {\r\n this.myControl.disable();\r\n } else {\r\n this.myControl.enable();\r\n }\r\n }\r\n ngOnInit() {\r\n this.filteredOptions = this.myControl.valueChanges.pipe(\r\n startWith(''),\r\n map((value) => (typeof value === 'string' ? value : value)),\r\n map((option) => (option ? this._filter(option) : this.options.slice()))\r\n );\r\n }\r\n private _filter(option): string[] {\r\n const filterValue = option.toLowerCase();\r\n\r\n return this.options.filter(\r\n // eslint-disable-next-line no-shadow\r\n (option) => option.toLowerCase().indexOf(filterValue) === 0\r\n );\r\n }\r\n}\r\n\r\n@Component({\r\n selector: 'oui-autocomplete-group-storybook',\r\n template: `\r\n \r\n \r\n \r\n \r\n \r\n {{ name }}\r\n \r\n \r\n \r\n \r\n `,\r\n})\r\nexport class OuiAutocompleteGroupStorybook implements OnInit {\r\n @Input() stateGroups: StateGroup[];\r\n @Input()\r\n set disabled(value: boolean) {\r\n if (value) {\r\n this.stateForm.get('stateGroup')!.disable();\r\n } else {\r\n this.stateForm.get('stateGroup')!.enable();\r\n }\r\n }\r\n stateForm: UntypedFormGroup = this.fb.group({\r\n stateGroup: '',\r\n });\r\n stateGroupOptions: Observable;\r\n\r\n constructor(private fb: UntypedFormBuilder) {}\r\n ngOnInit() {\r\n this.stateGroupOptions = this.stateForm\r\n .get('stateGroup')!\r\n .valueChanges.pipe(\r\n startWith(''),\r\n map((value: string) => this._filterGroup(value))\r\n );\r\n }\r\n\r\n private _filterGroup(value: string): StateGroup[] {\r\n if (value) {\r\n return this.stateGroups\r\n .map((group) => ({\r\n letter: group.letter,\r\n names: _filter(group.names, value),\r\n }))\r\n .filter((group) => group.names.length > 0);\r\n }\r\n\r\n return this.stateGroups;\r\n }\r\n}\r\n", "assetsDirs": [], "styleUrlsData": "", "stylesData": "", + "extends": [], "implements": [ "OnInit" ], @@ -23122,6 +23411,7 @@ "button.html" ], "viewProviders": [], + "hostDirectives": [], "inputsClass": [], "outputsClass": [], "propertiesClass": [ @@ -23134,7 +23424,7 @@ "description": "", "line": 78, "modifierKind": [ - 123 + 125 ] }, { @@ -23147,7 +23437,7 @@ "description": "", "line": 74, "modifierKind": [ - 121 + 123 ] } ], @@ -23162,7 +23452,7 @@ "deprecated": false, "deprecationMessage": "", "modifierKind": [ - 122 + 124 ] }, { @@ -23234,6 +23524,8 @@ "deprecationMessage": "", "hostBindings": [], "hostListeners": [], + "standalone": false, + "imports": [], "description": "

Once Ui button.

\n", "rawdescription": "\n\nOnce Ui button.\n", "type": "component", @@ -23317,7 +23609,9 @@ } ] }, - "extends": "OuiButtonMixinBase", + "extends": [ + "OuiButtonMixinBase" + ], "implements": [ "OnDestroy", "CanDisable", @@ -23349,6 +23643,7 @@ "calendar.html" ], "viewProviders": [], + "hostDirectives": [], "inputsClass": [ { "name": "dateClass", @@ -23494,7 +23789,7 @@ "description": "", "line": 172, "modifierKind": [ - 121 + 123 ] }, { @@ -23506,7 +23801,7 @@ "description": "", "line": 182, "modifierKind": [ - 121 + 123 ] }, { @@ -23518,7 +23813,7 @@ "description": "", "line": 62, "modifierKind": [ - 121 + 123 ] }, { @@ -23530,7 +23825,7 @@ "description": "", "line": 120, "modifierKind": [ - 121 + 123 ] }, { @@ -23542,7 +23837,7 @@ "description": "", "line": 108, "modifierKind": [ - 121 + 123 ] }, { @@ -23556,7 +23851,7 @@ "line": 69, "rawdescription": "\n\nUsed for scheduling that focus should be moved to the active cell on the next tick.\nWe need to schedule it, rather than do it immediately, because we have to wait\nfor Angular to re-evaluate the view children.\n", "modifierKind": [ - 121 + 123 ] }, { @@ -23568,7 +23863,7 @@ "description": "", "line": 96, "modifierKind": [ - 121 + 123 ] }, { @@ -23580,7 +23875,7 @@ "description": "", "line": 81, "modifierKind": [ - 121 + 123 ] }, { @@ -23597,6 +23892,9 @@ "name": "ViewChild", "stringifiedArguments": "OuiMonthView" } + ], + "modifierKind": [ + 170 ] }, { @@ -23613,6 +23911,9 @@ "name": "ViewChild", "stringifiedArguments": "OuiMultiYearView" } + ], + "modifierKind": [ + 170 ] }, { @@ -23640,6 +23941,9 @@ "name": "ViewChild", "stringifiedArguments": "OuiYearView" } + ], + "modifierKind": [ + 170 ] } ], @@ -23686,7 +23990,7 @@ "rawdescription": "\nReturns the component instance that corresponds to the current calendar view.", "description": "

Returns the component instance that corresponds to the current calendar view.

\n", "modifierKind": [ - 121 + 123 ] }, { @@ -23708,17 +24012,17 @@ "rawdescription": "\n\n", "description": "", "modifierKind": [ - 121 + 123 ], "jsdoctags": [ { "name": { "pos": 8352, "end": 8355, - "flags": 4227072, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "obj" }, "type": "any", @@ -23727,10 +24031,10 @@ "tagName": { "pos": 8346, "end": 8351, - "flags": 4227072, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "param" }, "comment": "

The object to check.

\n" @@ -23739,10 +24043,10 @@ "tagName": { "pos": 8383, "end": 8390, - "flags": 4227072, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "returns" }, "comment": "

The given object if it is both a date instance and valid, otherwise null.

\n" @@ -23949,6 +24253,8 @@ "deprecationMessage": "", "hostBindings": [], "hostListeners": [], + "standalone": false, + "imports": [], "description": "

A calendar that is used as part of the datepicker.

\n", "rawdescription": "\n\nA calendar that is used as part of the datepicker.\n", "type": "component", @@ -24032,6 +24338,7 @@ } ] }, + "extends": [], "implements": [ "AfterContentInit", "AfterViewChecked", @@ -24293,6 +24600,7 @@ "calendar-body.html" ], "viewProviders": [], + "hostDirectives": [], "inputsClass": [ { "name": "activeCell", @@ -24539,6 +24847,8 @@ "deprecationMessage": "", "hostBindings": [], "hostListeners": [], + "standalone": false, + "imports": [], "description": "

An internal component used to display calendar data in a table.

\n", "rawdescription": "\n\nAn internal component used to display calendar data in a table.\n", "type": "component", @@ -24592,6 +24902,7 @@ } ] }, + "extends": [], "implements": [ "OnChanges" ], @@ -24617,6 +24928,7 @@ "calendar-header.html" ], "viewProviders": [], + "hostDirectives": [], "inputsClass": [], "outputsClass": [], "propertiesClass": [ @@ -24635,7 +24947,8 @@ } ], "modifierKind": [ - 123 + 170, + 125 ] } ], @@ -24665,7 +24978,7 @@ "rawdescription": "\nWhether the two dates represent the same view in the current view mode (month or year).", "description": "

Whether the two dates represent the same view in the current view mode (month or year).

\n", "modifierKind": [ - 121 + 123 ], "jsdoctags": [ { @@ -24753,6 +25066,8 @@ "deprecationMessage": "", "hostBindings": [], "hostListeners": [], + "standalone": false, + "imports": [], "description": "

Default header for OuiCalendar

\n", "rawdescription": "\nDefault header for OuiCalendar", "type": "component", @@ -24861,6 +25176,7 @@ } ] }, + "extends": [], "accessors": { "periodButtonText": { "name": "periodButtonText", @@ -24927,6 +25243,7 @@ "template": "", "templateUrl": [], "viewProviders": [], + "hostDirectives": [], "inputsClass": [ { "name": "calendarHeaderComponent", @@ -25073,7 +25390,7 @@ "line": 274, "rawdescription": "\nA portal containing the calendar for this datepicker.", "modifierKind": [ - 121 + 123 ] }, { @@ -25105,7 +25422,7 @@ "line": 271, "rawdescription": "\nA reference to the dialog when the calendar is opened as a dialog.", "modifierKind": [ - 121 + 123 ] }, { @@ -25118,7 +25435,7 @@ "description": "", "line": 203, "modifierKind": [ - 121 + 123 ] }, { @@ -25132,7 +25449,7 @@ "line": 289, "rawdescription": "\nEmits when the datepicker is disabled.", "modifierKind": [ - 144 + 148 ] }, { @@ -25146,7 +25463,7 @@ "line": 280, "rawdescription": "\nThe element that was focused before the datepicker was opened.", "modifierKind": [ - 121 + 123 ] }, { @@ -25160,7 +25477,7 @@ "line": 283, "rawdescription": "\nSubscription to value changes in the associated input element.", "modifierKind": [ - 121 + 123 ] }, { @@ -25173,7 +25490,7 @@ "description": "", "line": 293, "modifierKind": [ - 121 + 123 ] }, { @@ -25186,7 +25503,7 @@ "description": "", "line": 239, "modifierKind": [ - 121 + 123 ] }, { @@ -25199,7 +25516,7 @@ "line": 277, "rawdescription": "\nReference to the component instantiated in popup mode.", "modifierKind": [ - 121 + 123 ] }, { @@ -25221,7 +25538,7 @@ "description": "", "line": 134, "modifierKind": [ - 121 + 123 ] }, { @@ -25235,7 +25552,7 @@ "line": 292, "rawdescription": "\nEmits new selected date when selected date changes.", "modifierKind": [ - 144 + 148 ] }, { @@ -25247,7 +25564,7 @@ "description": "", "line": 154, "modifierKind": [ - 121 + 123 ] }, { @@ -25260,7 +25577,7 @@ "description": "", "line": 185, "modifierKind": [ - 121 + 123 ] }, { @@ -25273,7 +25590,7 @@ "description": "", "line": 251, "modifierKind": [ - 121 + 123 ] }, { @@ -25301,7 +25618,7 @@ "rawdescription": "\nCreate the popup.", "description": "

Create the popup.

\n", "modifierKind": [ - 121 + 123 ] }, { @@ -25316,7 +25633,7 @@ "rawdescription": "\nCreate the popup PositionStrategy.", "description": "

Create the popup PositionStrategy.

\n", "modifierKind": [ - 121 + 123 ] }, { @@ -25338,17 +25655,17 @@ "rawdescription": "\n\n", "description": "", "modifierKind": [ - 121 + 123 ], "jsdoctags": [ { "name": { "pos": 17260, "end": 17263, - "flags": 4227072, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "obj" }, "type": "any", @@ -25357,10 +25674,10 @@ "tagName": { "pos": 17254, "end": 17259, - "flags": 4227072, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "param" }, "comment": "

The object to check.

\n" @@ -25369,10 +25686,10 @@ "tagName": { "pos": 17291, "end": 17298, - "flags": 4227072, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "returns" }, "comment": "

The given object if it is both a date instance and valid, otherwise null.

\n" @@ -25391,7 +25708,7 @@ "rawdescription": "\nOpen the calendar as a dialog.", "description": "

Open the calendar as a dialog.

\n", "modifierKind": [ - 121 + 123 ] }, { @@ -25406,7 +25723,7 @@ "rawdescription": "\nOpen the calendar as a popup.", "description": "

Open the calendar as a popup.

\n", "modifierKind": [ - 121 + 123 ] }, { @@ -25432,10 +25749,10 @@ "name": { "pos": 11329, "end": 11334, - "flags": 4227072, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "input" }, "type": "OuiDatepickerInput", @@ -25444,10 +25761,10 @@ "tagName": { "pos": 11323, "end": 11328, - "flags": 4227072, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "param" }, "comment": "

The datepicker input to register with this datepicker.

\n" @@ -25526,7 +25843,7 @@ "rawdescription": "\nPasses the current theme color along to the calendar overlay.", "description": "

Passes the current theme color along to the calendar overlay.

\n", "modifierKind": [ - 121 + 123 ] }, { @@ -25598,6 +25915,8 @@ "deprecationMessage": "", "hostBindings": [], "hostListeners": [], + "standalone": false, + "imports": [], "description": "

Component responsible for managing the datepicker popup/dialog.

\n", "rawdescription": "\nComponent responsible for managing the datepicker popup/dialog.", "type": "component", @@ -25766,6 +26085,7 @@ } ] }, + "extends": [], "implements": [ "OnDestroy", "CanColor" @@ -26057,6 +26377,7 @@ "datepicker-content.html" ], "viewProviders": [], + "hostDirectives": [], "inputsClass": [], "outputsClass": [], "propertiesClass": [ @@ -26074,6 +26395,9 @@ "name": "ViewChild", "stringifiedArguments": "OuiCalendar" } + ], + "modifierKind": [ + 170 ] }, { @@ -26113,6 +26437,8 @@ "deprecationMessage": "", "hostBindings": [], "hostListeners": [], + "standalone": false, + "imports": [], "description": "

Component used as the content for the datepicker dialog and popup. We use this instead of using\nOuiCalendar directly as the content so we can control the initial focus. This also gives us a\nplace to put additional features of the popup that are not part of the calendar itself in the\nfuture. (e.g. confirmation buttons).

\n", "rawdescription": "\n\nComponent used as the content for the datepicker dialog and popup. We use this instead of using\nOuiCalendar directly as the content so we can control the initial focus. This also gives us a\nplace to put additional features of the popup that are not part of the calendar itself in the\nfuture. (e.g. confirmation buttons).\n", "type": "component", @@ -26151,7 +26477,9 @@ } ] }, - "extends": "_OuiDatepickerContentMixinBase", + "extends": [ + "_OuiDatepickerContentMixinBase" + ], "implements": [ "AfterViewInit", "CanColor" @@ -26160,7 +26488,7 @@ }, { "name": "OuiDatepickerCustomStorybook", - "id": "component-OuiDatepickerCustomStorybook-ee54a56052b533f2afecd75c86b7766455aa487816a793e90aed32c3634b3048e6887c00be3d271dd0c63475c19e24be5d624030ad4aba05a137c4ae8e04bcec", + "id": "component-OuiDatepickerCustomStorybook-6df087d8c9d348ec38ff08538f8e33e41f2a1a7288d6a727c2955e792cade68d8483e2a1cbcc3b46fc2b31288ab49914c7e9412d25ce5d9f51d8a751ff8f75ac", "file": "ui/src/stories/datepicker/datepicker.component.ts", "encapsulation": [], "entryComponents": [], @@ -26177,6 +26505,7 @@ "template": "
\n \n \n \n \n \n
\n", "templateUrl": [], "viewProviders": [], + "hostDirectives": [], "inputsClass": [ { "name": "appearance", @@ -26491,10 +26820,12 @@ "deprecationMessage": "", "hostBindings": [], "hostListeners": [], + "standalone": false, + "imports": [], "description": "", "rawdescription": "\n", "type": "component", - "sourceCode": "import {\n Component,\n Output,\n EventEmitter,\n Input,\n OnChanges,\n} from '@angular/core';\nimport { OuiDatepickerInputEvent } from '../../components/datepicker';\nimport { OuiDateFormats, OUI_DATE_FORMATS } from '../../components';\n\nexport const OUI_CUSTOM_DATE_FORMATS: OuiDateFormats = {\n parse: {\n dateInput: null,\n },\n display: {\n dateInput: {\n year: 'numeric',\n day: '2-digit',\n month: '2-digit',\n },\n monthYearLabel: { year: 'numeric', month: 'short' },\n dateA11yLabel: { year: 'numeric', month: 'long', day: 'numeric' },\n monthYearA11yLabel: { year: 'numeric', month: 'long' },\n },\n};\n\n@Component({\n selector: 'oui-datepicker-storybook',\n template: `\n
\n \n \n \n \n \n
\n `,\n})\nexport class OuiDatepickerStorybook implements OnChanges {\n @Input() appearance = 'standard';\n @Input() color = 'primary';\n @Input() startView = ['month', 'year', 'multi-year'];\n @Input() opened = false;\n @Input() disabled = false;\n @Input() mindate: Date = new Date();\n minDate: Date = new Date();\n @Input() value: Date = new Date();\n _value: Date = new Date();\n @Input() maxdate: Date = new Date();\n maxDate: Date = new Date();\n @Output()\n readonly _closed: EventEmitter = new EventEmitter();\n @Output()\n readonly _monthSelected: EventEmitter = new EventEmitter();\n @Output()\n readonly _opened: EventEmitter = new EventEmitter();\n @Output()\n readonly _yearSelected: EventEmitter = new EventEmitter();\n @Output()\n readonly _dateChange: EventEmitter = new EventEmitter();\n constructor() {}\n ngOnChanges() {\n this.minDate = new Date(this.mindate);\n this.maxDate = new Date(this.maxdate);\n this._value = new Date(this.value);\n if (this.opened) {\n (document.querySelector('.oui-datepicker-toggle') as HTMLElement).focus();\n }\n }\n\n closed(e?: string) {\n this._closed.emit(e);\n }\n monthSelected(e?: string) {\n this._monthSelected.emit(e);\n }\n datepickeropened(e?: string) {\n this._opened.emit(e);\n }\n yearSelected(e?: string) {\n this._yearSelected.emit(e);\n }\n dateChange(e?: string) {\n this._dateChange.emit(e);\n }\n}\n\n@Component({\n selector: 'oui-datepicker-custom-storybook',\n template: `\n
\n \n \n \n \n \n
\n `,\n providers: [{ provide: OUI_DATE_FORMATS, useValue: OUI_CUSTOM_DATE_FORMATS }],\n})\nexport class OuiDatepickerCustomStorybook implements OnChanges {\n @Input() appearance = 'standard';\n @Input() color = 'primary';\n @Input() startView = ['month', 'year', 'multi-year'];\n @Input() opened = false;\n @Input() disabled = false;\n @Input() mindate: Date = new Date();\n minDate: Date = new Date();\n @Input() value: Date = new Date();\n _value: Date = new Date();\n @Input() maxdate: Date = new Date();\n maxDate: Date = new Date();\n @Output()\n readonly _closed: EventEmitter = new EventEmitter();\n @Output()\n readonly _monthSelected: EventEmitter = new EventEmitter();\n @Output()\n readonly _opened: EventEmitter = new EventEmitter();\n @Output()\n readonly _yearSelected: EventEmitter = new EventEmitter();\n @Output()\n readonly _dateChange: EventEmitter = new EventEmitter();\n constructor() {}\n ngOnChanges() {\n this.minDate = new Date(this.mindate);\n this.maxDate = new Date(this.maxdate);\n this._value = new Date(this.value);\n if (this.opened) {\n (document.querySelector('.oui-datepicker-toggle') as HTMLElement).focus();\n }\n }\n closed(e?: string) {\n this._closed.emit(e);\n }\n monthSelected(e?: string) {\n this._monthSelected.emit(e);\n }\n datepickeropened(e?: string) {\n this._opened.emit(e);\n }\n yearSelected(e?: string) {\n this._yearSelected.emit(e);\n }\n dateChange(e?: string) {\n this._dateChange.emit(e);\n }\n}\n\n@Component({\n selector: 'oui-daterangepicker-storybook',\n template: `\n
\n
\n \n \n \n \n \n
\n
\n \n \n \n \n \n
\n
\n `,\n})\nexport class OuiDaterangepickerStorybook implements OnChanges {\n @Input() appearance = 'standard';\n @Input() color = 'primary';\n @Input() startView = 'primary';\n @Input() opened = false;\n @Input() disabled = false;\n @Input() mindate: Date;\n minDate: Date = new Date();\n minRangeDate: Date;\n @Input() maxdate: Date;\n maxRangeDate: Date;\n maxDate: Date;\n @Output()\n readonly _dateChange: EventEmitter<{}> = new EventEmitter<{}>();\n constructor() {}\n ngOnChanges() {\n this.minRangeDate = new Date(this.mindate);\n this.maxRangeDate = new Date(this.maxdate);\n }\n mindateChange(e: OuiDatepickerInputEvent) {\n this.minDate = new Date(e.value);\n if (this.maxDate) {\n this._dateChange.emit({\n min: this.minDate,\n max: this.maxDate,\n });\n }\n // this._dateChange.emit(e);\n }\n maxdateChange(e: OuiDatepickerInputEvent) {\n this.maxDate = new Date(e.value);\n if (this.minDate) {\n this._dateChange.emit({\n min: this.minDate,\n max: this.maxDate,\n });\n }\n // this._dateChange.emit(e);\n }\n}\n", + "sourceCode": "import {\r\n Component,\r\n Output,\r\n EventEmitter,\r\n Input,\r\n OnChanges,\r\n} from '@angular/core';\r\nimport { OuiDatepickerInputEvent } from '../../components/datepicker';\r\nimport { OuiDateFormats, OUI_DATE_FORMATS } from '../../components';\r\n\r\nexport const OUI_CUSTOM_DATE_FORMATS: OuiDateFormats = {\r\n parse: {\r\n dateInput: null,\r\n },\r\n display: {\r\n dateInput: {\r\n year: 'numeric',\r\n day: '2-digit',\r\n month: '2-digit',\r\n },\r\n monthYearLabel: { year: 'numeric', month: 'short' },\r\n dateA11yLabel: { year: 'numeric', month: 'long', day: 'numeric' },\r\n monthYearA11yLabel: { year: 'numeric', month: 'long' },\r\n },\r\n};\r\n\r\n@Component({\r\n selector: 'oui-datepicker-storybook',\r\n template: `\r\n
\r\n \r\n \r\n \r\n \r\n \r\n
\r\n `,\r\n})\r\nexport class OuiDatepickerStorybook implements OnChanges {\r\n @Input() appearance = 'standard';\r\n @Input() color = 'primary';\r\n @Input() startView = ['month', 'year', 'multi-year'];\r\n @Input() opened = false;\r\n @Input() disabled = false;\r\n @Input() mindate: Date = new Date();\r\n minDate: Date = new Date();\r\n @Input() value: Date = new Date();\r\n _value: Date = new Date();\r\n @Input() maxdate: Date = new Date();\r\n maxDate: Date = new Date();\r\n @Output()\r\n readonly _closed: EventEmitter = new EventEmitter();\r\n @Output()\r\n readonly _monthSelected: EventEmitter = new EventEmitter();\r\n @Output()\r\n readonly _opened: EventEmitter = new EventEmitter();\r\n @Output()\r\n readonly _yearSelected: EventEmitter = new EventEmitter();\r\n @Output()\r\n readonly _dateChange: EventEmitter = new EventEmitter();\r\n constructor() {}\r\n ngOnChanges() {\r\n this.minDate = new Date(this.mindate);\r\n this.maxDate = new Date(this.maxdate);\r\n this._value = new Date(this.value);\r\n if (this.opened) {\r\n (document.querySelector('.oui-datepicker-toggle') as HTMLElement).focus();\r\n }\r\n }\r\n\r\n closed(e?: string) {\r\n this._closed.emit(e);\r\n }\r\n monthSelected(e?: string) {\r\n this._monthSelected.emit(e);\r\n }\r\n datepickeropened(e?: string) {\r\n this._opened.emit(e);\r\n }\r\n yearSelected(e?: string) {\r\n this._yearSelected.emit(e);\r\n }\r\n dateChange(e?: string) {\r\n this._dateChange.emit(e);\r\n }\r\n}\r\n\r\n@Component({\r\n selector: 'oui-datepicker-custom-storybook',\r\n template: `\r\n
\r\n \r\n \r\n \r\n \r\n \r\n
\r\n `,\r\n providers: [{ provide: OUI_DATE_FORMATS, useValue: OUI_CUSTOM_DATE_FORMATS }],\r\n})\r\nexport class OuiDatepickerCustomStorybook implements OnChanges {\r\n @Input() appearance = 'standard';\r\n @Input() color = 'primary';\r\n @Input() startView = ['month', 'year', 'multi-year'];\r\n @Input() opened = false;\r\n @Input() disabled = false;\r\n @Input() mindate: Date = new Date();\r\n minDate: Date = new Date();\r\n @Input() value: Date = new Date();\r\n _value: Date = new Date();\r\n @Input() maxdate: Date = new Date();\r\n maxDate: Date = new Date();\r\n @Output()\r\n readonly _closed: EventEmitter = new EventEmitter();\r\n @Output()\r\n readonly _monthSelected: EventEmitter = new EventEmitter();\r\n @Output()\r\n readonly _opened: EventEmitter = new EventEmitter();\r\n @Output()\r\n readonly _yearSelected: EventEmitter = new EventEmitter();\r\n @Output()\r\n readonly _dateChange: EventEmitter = new EventEmitter();\r\n constructor() {}\r\n ngOnChanges() {\r\n this.minDate = new Date(this.mindate);\r\n this.maxDate = new Date(this.maxdate);\r\n this._value = new Date(this.value);\r\n if (this.opened) {\r\n (document.querySelector('.oui-datepicker-toggle') as HTMLElement).focus();\r\n }\r\n }\r\n closed(e?: string) {\r\n this._closed.emit(e);\r\n }\r\n monthSelected(e?: string) {\r\n this._monthSelected.emit(e);\r\n }\r\n datepickeropened(e?: string) {\r\n this._opened.emit(e);\r\n }\r\n yearSelected(e?: string) {\r\n this._yearSelected.emit(e);\r\n }\r\n dateChange(e?: string) {\r\n this._dateChange.emit(e);\r\n }\r\n}\r\n\r\n@Component({\r\n selector: 'oui-daterangepicker-storybook',\r\n template: `\r\n
\r\n
\r\n \r\n \r\n \r\n \r\n \r\n
\r\n
\r\n \r\n \r\n \r\n \r\n \r\n
\r\n
\r\n `,\r\n})\r\nexport class OuiDaterangepickerStorybook implements OnChanges {\r\n @Input() appearance = 'standard';\r\n @Input() color = 'primary';\r\n @Input() startView = 'primary';\r\n @Input() opened = false;\r\n @Input() disabled = false;\r\n @Input() mindate: Date;\r\n minDate: Date = new Date();\r\n minRangeDate: Date;\r\n @Input() maxdate: Date;\r\n maxRangeDate: Date;\r\n maxDate: Date;\r\n @Output()\r\n readonly _dateChange: EventEmitter<{}> = new EventEmitter<{}>();\r\n constructor() {}\r\n ngOnChanges() {\r\n this.minRangeDate = new Date(this.mindate);\r\n this.maxRangeDate = new Date(this.maxdate);\r\n }\r\n mindateChange(e: OuiDatepickerInputEvent) {\r\n this.minDate = new Date(e.value);\r\n if (this.maxDate) {\r\n this._dateChange.emit({\r\n min: this.minDate,\r\n max: this.maxDate,\r\n });\r\n }\r\n // this._dateChange.emit(e);\r\n }\r\n maxdateChange(e: OuiDatepickerInputEvent) {\r\n this.maxDate = new Date(e.value);\r\n if (this.minDate) {\r\n this._dateChange.emit({\r\n min: this.minDate,\r\n max: this.maxDate,\r\n });\r\n }\r\n // this._dateChange.emit(e);\r\n }\r\n}\r\n", "assetsDirs": [], "styleUrlsData": "", "stylesData": "", @@ -26506,13 +26837,14 @@ "args": [], "line": 158 }, + "extends": [], "implements": [ "OnChanges" ] }, { "name": "OuiDatepickerStorybook", - "id": "component-OuiDatepickerStorybook-ee54a56052b533f2afecd75c86b7766455aa487816a793e90aed32c3634b3048e6887c00be3d271dd0c63475c19e24be5d624030ad4aba05a137c4ae8e04bcec", + "id": "component-OuiDatepickerStorybook-6df087d8c9d348ec38ff08538f8e33e41f2a1a7288d6a727c2955e792cade68d8483e2a1cbcc3b46fc2b31288ab49914c7e9412d25ce5d9f51d8a751ff8f75ac", "file": "ui/src/stories/datepicker/datepicker.component.ts", "encapsulation": [], "entryComponents": [], @@ -26525,6 +26857,7 @@ "template": "
\n \n \n \n \n \n
\n", "templateUrl": [], "viewProviders": [], + "hostDirectives": [], "inputsClass": [ { "name": "appearance", @@ -26839,10 +27172,12 @@ "deprecationMessage": "", "hostBindings": [], "hostListeners": [], + "standalone": false, + "imports": [], "description": "", "rawdescription": "\n", "type": "component", - "sourceCode": "import {\n Component,\n Output,\n EventEmitter,\n Input,\n OnChanges,\n} from '@angular/core';\nimport { OuiDatepickerInputEvent } from '../../components/datepicker';\nimport { OuiDateFormats, OUI_DATE_FORMATS } from '../../components';\n\nexport const OUI_CUSTOM_DATE_FORMATS: OuiDateFormats = {\n parse: {\n dateInput: null,\n },\n display: {\n dateInput: {\n year: 'numeric',\n day: '2-digit',\n month: '2-digit',\n },\n monthYearLabel: { year: 'numeric', month: 'short' },\n dateA11yLabel: { year: 'numeric', month: 'long', day: 'numeric' },\n monthYearA11yLabel: { year: 'numeric', month: 'long' },\n },\n};\n\n@Component({\n selector: 'oui-datepicker-storybook',\n template: `\n
\n \n \n \n \n \n
\n `,\n})\nexport class OuiDatepickerStorybook implements OnChanges {\n @Input() appearance = 'standard';\n @Input() color = 'primary';\n @Input() startView = ['month', 'year', 'multi-year'];\n @Input() opened = false;\n @Input() disabled = false;\n @Input() mindate: Date = new Date();\n minDate: Date = new Date();\n @Input() value: Date = new Date();\n _value: Date = new Date();\n @Input() maxdate: Date = new Date();\n maxDate: Date = new Date();\n @Output()\n readonly _closed: EventEmitter = new EventEmitter();\n @Output()\n readonly _monthSelected: EventEmitter = new EventEmitter();\n @Output()\n readonly _opened: EventEmitter = new EventEmitter();\n @Output()\n readonly _yearSelected: EventEmitter = new EventEmitter();\n @Output()\n readonly _dateChange: EventEmitter = new EventEmitter();\n constructor() {}\n ngOnChanges() {\n this.minDate = new Date(this.mindate);\n this.maxDate = new Date(this.maxdate);\n this._value = new Date(this.value);\n if (this.opened) {\n (document.querySelector('.oui-datepicker-toggle') as HTMLElement).focus();\n }\n }\n\n closed(e?: string) {\n this._closed.emit(e);\n }\n monthSelected(e?: string) {\n this._monthSelected.emit(e);\n }\n datepickeropened(e?: string) {\n this._opened.emit(e);\n }\n yearSelected(e?: string) {\n this._yearSelected.emit(e);\n }\n dateChange(e?: string) {\n this._dateChange.emit(e);\n }\n}\n\n@Component({\n selector: 'oui-datepicker-custom-storybook',\n template: `\n
\n \n \n \n \n \n
\n `,\n providers: [{ provide: OUI_DATE_FORMATS, useValue: OUI_CUSTOM_DATE_FORMATS }],\n})\nexport class OuiDatepickerCustomStorybook implements OnChanges {\n @Input() appearance = 'standard';\n @Input() color = 'primary';\n @Input() startView = ['month', 'year', 'multi-year'];\n @Input() opened = false;\n @Input() disabled = false;\n @Input() mindate: Date = new Date();\n minDate: Date = new Date();\n @Input() value: Date = new Date();\n _value: Date = new Date();\n @Input() maxdate: Date = new Date();\n maxDate: Date = new Date();\n @Output()\n readonly _closed: EventEmitter = new EventEmitter();\n @Output()\n readonly _monthSelected: EventEmitter = new EventEmitter();\n @Output()\n readonly _opened: EventEmitter = new EventEmitter();\n @Output()\n readonly _yearSelected: EventEmitter = new EventEmitter();\n @Output()\n readonly _dateChange: EventEmitter = new EventEmitter();\n constructor() {}\n ngOnChanges() {\n this.minDate = new Date(this.mindate);\n this.maxDate = new Date(this.maxdate);\n this._value = new Date(this.value);\n if (this.opened) {\n (document.querySelector('.oui-datepicker-toggle') as HTMLElement).focus();\n }\n }\n closed(e?: string) {\n this._closed.emit(e);\n }\n monthSelected(e?: string) {\n this._monthSelected.emit(e);\n }\n datepickeropened(e?: string) {\n this._opened.emit(e);\n }\n yearSelected(e?: string) {\n this._yearSelected.emit(e);\n }\n dateChange(e?: string) {\n this._dateChange.emit(e);\n }\n}\n\n@Component({\n selector: 'oui-daterangepicker-storybook',\n template: `\n
\n
\n \n \n \n \n \n
\n
\n \n \n \n \n \n
\n
\n `,\n})\nexport class OuiDaterangepickerStorybook implements OnChanges {\n @Input() appearance = 'standard';\n @Input() color = 'primary';\n @Input() startView = 'primary';\n @Input() opened = false;\n @Input() disabled = false;\n @Input() mindate: Date;\n minDate: Date = new Date();\n minRangeDate: Date;\n @Input() maxdate: Date;\n maxRangeDate: Date;\n maxDate: Date;\n @Output()\n readonly _dateChange: EventEmitter<{}> = new EventEmitter<{}>();\n constructor() {}\n ngOnChanges() {\n this.minRangeDate = new Date(this.mindate);\n this.maxRangeDate = new Date(this.maxdate);\n }\n mindateChange(e: OuiDatepickerInputEvent) {\n this.minDate = new Date(e.value);\n if (this.maxDate) {\n this._dateChange.emit({\n min: this.minDate,\n max: this.maxDate,\n });\n }\n // this._dateChange.emit(e);\n }\n maxdateChange(e: OuiDatepickerInputEvent) {\n this.maxDate = new Date(e.value);\n if (this.minDate) {\n this._dateChange.emit({\n min: this.minDate,\n max: this.maxDate,\n });\n }\n // this._dateChange.emit(e);\n }\n}\n", + "sourceCode": "import {\r\n Component,\r\n Output,\r\n EventEmitter,\r\n Input,\r\n OnChanges,\r\n} from '@angular/core';\r\nimport { OuiDatepickerInputEvent } from '../../components/datepicker';\r\nimport { OuiDateFormats, OUI_DATE_FORMATS } from '../../components';\r\n\r\nexport const OUI_CUSTOM_DATE_FORMATS: OuiDateFormats = {\r\n parse: {\r\n dateInput: null,\r\n },\r\n display: {\r\n dateInput: {\r\n year: 'numeric',\r\n day: '2-digit',\r\n month: '2-digit',\r\n },\r\n monthYearLabel: { year: 'numeric', month: 'short' },\r\n dateA11yLabel: { year: 'numeric', month: 'long', day: 'numeric' },\r\n monthYearA11yLabel: { year: 'numeric', month: 'long' },\r\n },\r\n};\r\n\r\n@Component({\r\n selector: 'oui-datepicker-storybook',\r\n template: `\r\n
\r\n \r\n \r\n \r\n \r\n \r\n
\r\n `,\r\n})\r\nexport class OuiDatepickerStorybook implements OnChanges {\r\n @Input() appearance = 'standard';\r\n @Input() color = 'primary';\r\n @Input() startView = ['month', 'year', 'multi-year'];\r\n @Input() opened = false;\r\n @Input() disabled = false;\r\n @Input() mindate: Date = new Date();\r\n minDate: Date = new Date();\r\n @Input() value: Date = new Date();\r\n _value: Date = new Date();\r\n @Input() maxdate: Date = new Date();\r\n maxDate: Date = new Date();\r\n @Output()\r\n readonly _closed: EventEmitter = new EventEmitter();\r\n @Output()\r\n readonly _monthSelected: EventEmitter = new EventEmitter();\r\n @Output()\r\n readonly _opened: EventEmitter = new EventEmitter();\r\n @Output()\r\n readonly _yearSelected: EventEmitter = new EventEmitter();\r\n @Output()\r\n readonly _dateChange: EventEmitter = new EventEmitter();\r\n constructor() {}\r\n ngOnChanges() {\r\n this.minDate = new Date(this.mindate);\r\n this.maxDate = new Date(this.maxdate);\r\n this._value = new Date(this.value);\r\n if (this.opened) {\r\n (document.querySelector('.oui-datepicker-toggle') as HTMLElement).focus();\r\n }\r\n }\r\n\r\n closed(e?: string) {\r\n this._closed.emit(e);\r\n }\r\n monthSelected(e?: string) {\r\n this._monthSelected.emit(e);\r\n }\r\n datepickeropened(e?: string) {\r\n this._opened.emit(e);\r\n }\r\n yearSelected(e?: string) {\r\n this._yearSelected.emit(e);\r\n }\r\n dateChange(e?: string) {\r\n this._dateChange.emit(e);\r\n }\r\n}\r\n\r\n@Component({\r\n selector: 'oui-datepicker-custom-storybook',\r\n template: `\r\n
\r\n \r\n \r\n \r\n \r\n \r\n
\r\n `,\r\n providers: [{ provide: OUI_DATE_FORMATS, useValue: OUI_CUSTOM_DATE_FORMATS }],\r\n})\r\nexport class OuiDatepickerCustomStorybook implements OnChanges {\r\n @Input() appearance = 'standard';\r\n @Input() color = 'primary';\r\n @Input() startView = ['month', 'year', 'multi-year'];\r\n @Input() opened = false;\r\n @Input() disabled = false;\r\n @Input() mindate: Date = new Date();\r\n minDate: Date = new Date();\r\n @Input() value: Date = new Date();\r\n _value: Date = new Date();\r\n @Input() maxdate: Date = new Date();\r\n maxDate: Date = new Date();\r\n @Output()\r\n readonly _closed: EventEmitter = new EventEmitter();\r\n @Output()\r\n readonly _monthSelected: EventEmitter = new EventEmitter();\r\n @Output()\r\n readonly _opened: EventEmitter = new EventEmitter();\r\n @Output()\r\n readonly _yearSelected: EventEmitter = new EventEmitter();\r\n @Output()\r\n readonly _dateChange: EventEmitter = new EventEmitter();\r\n constructor() {}\r\n ngOnChanges() {\r\n this.minDate = new Date(this.mindate);\r\n this.maxDate = new Date(this.maxdate);\r\n this._value = new Date(this.value);\r\n if (this.opened) {\r\n (document.querySelector('.oui-datepicker-toggle') as HTMLElement).focus();\r\n }\r\n }\r\n closed(e?: string) {\r\n this._closed.emit(e);\r\n }\r\n monthSelected(e?: string) {\r\n this._monthSelected.emit(e);\r\n }\r\n datepickeropened(e?: string) {\r\n this._opened.emit(e);\r\n }\r\n yearSelected(e?: string) {\r\n this._yearSelected.emit(e);\r\n }\r\n dateChange(e?: string) {\r\n this._dateChange.emit(e);\r\n }\r\n}\r\n\r\n@Component({\r\n selector: 'oui-daterangepicker-storybook',\r\n template: `\r\n
\r\n
\r\n \r\n \r\n \r\n \r\n \r\n
\r\n
\r\n \r\n \r\n \r\n \r\n \r\n
\r\n
\r\n `,\r\n})\r\nexport class OuiDaterangepickerStorybook implements OnChanges {\r\n @Input() appearance = 'standard';\r\n @Input() color = 'primary';\r\n @Input() startView = 'primary';\r\n @Input() opened = false;\r\n @Input() disabled = false;\r\n @Input() mindate: Date;\r\n minDate: Date = new Date();\r\n minRangeDate: Date;\r\n @Input() maxdate: Date;\r\n maxRangeDate: Date;\r\n maxDate: Date;\r\n @Output()\r\n readonly _dateChange: EventEmitter<{}> = new EventEmitter<{}>();\r\n constructor() {}\r\n ngOnChanges() {\r\n this.minRangeDate = new Date(this.mindate);\r\n this.maxRangeDate = new Date(this.maxdate);\r\n }\r\n mindateChange(e: OuiDatepickerInputEvent) {\r\n this.minDate = new Date(e.value);\r\n if (this.maxDate) {\r\n this._dateChange.emit({\r\n min: this.minDate,\r\n max: this.maxDate,\r\n });\r\n }\r\n // this._dateChange.emit(e);\r\n }\r\n maxdateChange(e: OuiDatepickerInputEvent) {\r\n this.maxDate = new Date(e.value);\r\n if (this.minDate) {\r\n this._dateChange.emit({\r\n min: this.minDate,\r\n max: this.maxDate,\r\n });\r\n }\r\n // this._dateChange.emit(e);\r\n }\r\n}\r\n", "assetsDirs": [], "styleUrlsData": "", "stylesData": "", @@ -26854,6 +27189,7 @@ "args": [], "line": 78 }, + "extends": [], "implements": [ "OnChanges" ] @@ -26881,6 +27217,7 @@ "datepicker-toggle.html" ], "viewProviders": [], + "hostDirectives": [], "inputsClass": [ { "name": "disabled", @@ -26929,6 +27266,9 @@ "name": "ViewChild", "stringifiedArguments": "'button'" } + ], + "modifierKind": [ + 170 ] }, { @@ -26945,6 +27285,9 @@ "name": "ContentChild", "stringifiedArguments": "OuiDatepickerToggleIcon" } + ], + "modifierKind": [ + 170 ] }, { @@ -26956,7 +27299,7 @@ "description": "", "line": 70, "modifierKind": [ - 121 + 123 ] }, { @@ -26968,7 +27311,7 @@ "description": "", "line": 80, "modifierKind": [ - 123 + 125 ] }, { @@ -26981,7 +27324,7 @@ "description": "", "line": 51, "modifierKind": [ - 121 + 123 ] } ], @@ -27024,7 +27367,7 @@ "deprecated": false, "deprecationMessage": "", "modifierKind": [ - 121 + 123 ] }, { @@ -27080,6 +27423,8 @@ "deprecationMessage": "", "hostBindings": [], "hostListeners": [], + "standalone": false, + "imports": [], "description": "", "rawdescription": "\n", "type": "component", @@ -27148,6 +27493,7 @@ } ] }, + "extends": [], "implements": [ "AfterContentInit", "OnChanges", @@ -27197,7 +27543,7 @@ }, { "name": "OuiDaterangepickerStorybook", - "id": "component-OuiDaterangepickerStorybook-ee54a56052b533f2afecd75c86b7766455aa487816a793e90aed32c3634b3048e6887c00be3d271dd0c63475c19e24be5d624030ad4aba05a137c4ae8e04bcec", + "id": "component-OuiDaterangepickerStorybook-6df087d8c9d348ec38ff08538f8e33e41f2a1a7288d6a727c2955e792cade68d8483e2a1cbcc3b46fc2b31288ab49914c7e9412d25ce5d9f51d8a751ff8f75ac", "file": "ui/src/stories/datepicker/datepicker.component.ts", "encapsulation": [], "entryComponents": [], @@ -27210,6 +27556,7 @@ "template": "
\n
\n \n \n \n \n \n
\n
\n \n \n \n \n \n
\n
\n", "templateUrl": [], "viewProviders": [], + "hostDirectives": [], "inputsClass": [ { "name": "appearance", @@ -27394,10 +27741,12 @@ "deprecationMessage": "", "hostBindings": [], "hostListeners": [], + "standalone": false, + "imports": [], "description": "", "rawdescription": "\n", "type": "component", - "sourceCode": "import {\n Component,\n Output,\n EventEmitter,\n Input,\n OnChanges,\n} from '@angular/core';\nimport { OuiDatepickerInputEvent } from '../../components/datepicker';\nimport { OuiDateFormats, OUI_DATE_FORMATS } from '../../components';\n\nexport const OUI_CUSTOM_DATE_FORMATS: OuiDateFormats = {\n parse: {\n dateInput: null,\n },\n display: {\n dateInput: {\n year: 'numeric',\n day: '2-digit',\n month: '2-digit',\n },\n monthYearLabel: { year: 'numeric', month: 'short' },\n dateA11yLabel: { year: 'numeric', month: 'long', day: 'numeric' },\n monthYearA11yLabel: { year: 'numeric', month: 'long' },\n },\n};\n\n@Component({\n selector: 'oui-datepicker-storybook',\n template: `\n
\n \n \n \n \n \n
\n `,\n})\nexport class OuiDatepickerStorybook implements OnChanges {\n @Input() appearance = 'standard';\n @Input() color = 'primary';\n @Input() startView = ['month', 'year', 'multi-year'];\n @Input() opened = false;\n @Input() disabled = false;\n @Input() mindate: Date = new Date();\n minDate: Date = new Date();\n @Input() value: Date = new Date();\n _value: Date = new Date();\n @Input() maxdate: Date = new Date();\n maxDate: Date = new Date();\n @Output()\n readonly _closed: EventEmitter = new EventEmitter();\n @Output()\n readonly _monthSelected: EventEmitter = new EventEmitter();\n @Output()\n readonly _opened: EventEmitter = new EventEmitter();\n @Output()\n readonly _yearSelected: EventEmitter = new EventEmitter();\n @Output()\n readonly _dateChange: EventEmitter = new EventEmitter();\n constructor() {}\n ngOnChanges() {\n this.minDate = new Date(this.mindate);\n this.maxDate = new Date(this.maxdate);\n this._value = new Date(this.value);\n if (this.opened) {\n (document.querySelector('.oui-datepicker-toggle') as HTMLElement).focus();\n }\n }\n\n closed(e?: string) {\n this._closed.emit(e);\n }\n monthSelected(e?: string) {\n this._monthSelected.emit(e);\n }\n datepickeropened(e?: string) {\n this._opened.emit(e);\n }\n yearSelected(e?: string) {\n this._yearSelected.emit(e);\n }\n dateChange(e?: string) {\n this._dateChange.emit(e);\n }\n}\n\n@Component({\n selector: 'oui-datepicker-custom-storybook',\n template: `\n
\n \n \n \n \n \n
\n `,\n providers: [{ provide: OUI_DATE_FORMATS, useValue: OUI_CUSTOM_DATE_FORMATS }],\n})\nexport class OuiDatepickerCustomStorybook implements OnChanges {\n @Input() appearance = 'standard';\n @Input() color = 'primary';\n @Input() startView = ['month', 'year', 'multi-year'];\n @Input() opened = false;\n @Input() disabled = false;\n @Input() mindate: Date = new Date();\n minDate: Date = new Date();\n @Input() value: Date = new Date();\n _value: Date = new Date();\n @Input() maxdate: Date = new Date();\n maxDate: Date = new Date();\n @Output()\n readonly _closed: EventEmitter = new EventEmitter();\n @Output()\n readonly _monthSelected: EventEmitter = new EventEmitter();\n @Output()\n readonly _opened: EventEmitter = new EventEmitter();\n @Output()\n readonly _yearSelected: EventEmitter = new EventEmitter();\n @Output()\n readonly _dateChange: EventEmitter = new EventEmitter();\n constructor() {}\n ngOnChanges() {\n this.minDate = new Date(this.mindate);\n this.maxDate = new Date(this.maxdate);\n this._value = new Date(this.value);\n if (this.opened) {\n (document.querySelector('.oui-datepicker-toggle') as HTMLElement).focus();\n }\n }\n closed(e?: string) {\n this._closed.emit(e);\n }\n monthSelected(e?: string) {\n this._monthSelected.emit(e);\n }\n datepickeropened(e?: string) {\n this._opened.emit(e);\n }\n yearSelected(e?: string) {\n this._yearSelected.emit(e);\n }\n dateChange(e?: string) {\n this._dateChange.emit(e);\n }\n}\n\n@Component({\n selector: 'oui-daterangepicker-storybook',\n template: `\n
\n
\n \n \n \n \n \n
\n
\n \n \n \n \n \n
\n
\n `,\n})\nexport class OuiDaterangepickerStorybook implements OnChanges {\n @Input() appearance = 'standard';\n @Input() color = 'primary';\n @Input() startView = 'primary';\n @Input() opened = false;\n @Input() disabled = false;\n @Input() mindate: Date;\n minDate: Date = new Date();\n minRangeDate: Date;\n @Input() maxdate: Date;\n maxRangeDate: Date;\n maxDate: Date;\n @Output()\n readonly _dateChange: EventEmitter<{}> = new EventEmitter<{}>();\n constructor() {}\n ngOnChanges() {\n this.minRangeDate = new Date(this.mindate);\n this.maxRangeDate = new Date(this.maxdate);\n }\n mindateChange(e: OuiDatepickerInputEvent) {\n this.minDate = new Date(e.value);\n if (this.maxDate) {\n this._dateChange.emit({\n min: this.minDate,\n max: this.maxDate,\n });\n }\n // this._dateChange.emit(e);\n }\n maxdateChange(e: OuiDatepickerInputEvent) {\n this.maxDate = new Date(e.value);\n if (this.minDate) {\n this._dateChange.emit({\n min: this.minDate,\n max: this.maxDate,\n });\n }\n // this._dateChange.emit(e);\n }\n}\n", + "sourceCode": "import {\r\n Component,\r\n Output,\r\n EventEmitter,\r\n Input,\r\n OnChanges,\r\n} from '@angular/core';\r\nimport { OuiDatepickerInputEvent } from '../../components/datepicker';\r\nimport { OuiDateFormats, OUI_DATE_FORMATS } from '../../components';\r\n\r\nexport const OUI_CUSTOM_DATE_FORMATS: OuiDateFormats = {\r\n parse: {\r\n dateInput: null,\r\n },\r\n display: {\r\n dateInput: {\r\n year: 'numeric',\r\n day: '2-digit',\r\n month: '2-digit',\r\n },\r\n monthYearLabel: { year: 'numeric', month: 'short' },\r\n dateA11yLabel: { year: 'numeric', month: 'long', day: 'numeric' },\r\n monthYearA11yLabel: { year: 'numeric', month: 'long' },\r\n },\r\n};\r\n\r\n@Component({\r\n selector: 'oui-datepicker-storybook',\r\n template: `\r\n
\r\n \r\n \r\n \r\n \r\n \r\n
\r\n `,\r\n})\r\nexport class OuiDatepickerStorybook implements OnChanges {\r\n @Input() appearance = 'standard';\r\n @Input() color = 'primary';\r\n @Input() startView = ['month', 'year', 'multi-year'];\r\n @Input() opened = false;\r\n @Input() disabled = false;\r\n @Input() mindate: Date = new Date();\r\n minDate: Date = new Date();\r\n @Input() value: Date = new Date();\r\n _value: Date = new Date();\r\n @Input() maxdate: Date = new Date();\r\n maxDate: Date = new Date();\r\n @Output()\r\n readonly _closed: EventEmitter = new EventEmitter();\r\n @Output()\r\n readonly _monthSelected: EventEmitter = new EventEmitter();\r\n @Output()\r\n readonly _opened: EventEmitter = new EventEmitter();\r\n @Output()\r\n readonly _yearSelected: EventEmitter = new EventEmitter();\r\n @Output()\r\n readonly _dateChange: EventEmitter = new EventEmitter();\r\n constructor() {}\r\n ngOnChanges() {\r\n this.minDate = new Date(this.mindate);\r\n this.maxDate = new Date(this.maxdate);\r\n this._value = new Date(this.value);\r\n if (this.opened) {\r\n (document.querySelector('.oui-datepicker-toggle') as HTMLElement).focus();\r\n }\r\n }\r\n\r\n closed(e?: string) {\r\n this._closed.emit(e);\r\n }\r\n monthSelected(e?: string) {\r\n this._monthSelected.emit(e);\r\n }\r\n datepickeropened(e?: string) {\r\n this._opened.emit(e);\r\n }\r\n yearSelected(e?: string) {\r\n this._yearSelected.emit(e);\r\n }\r\n dateChange(e?: string) {\r\n this._dateChange.emit(e);\r\n }\r\n}\r\n\r\n@Component({\r\n selector: 'oui-datepicker-custom-storybook',\r\n template: `\r\n
\r\n \r\n \r\n \r\n \r\n \r\n
\r\n `,\r\n providers: [{ provide: OUI_DATE_FORMATS, useValue: OUI_CUSTOM_DATE_FORMATS }],\r\n})\r\nexport class OuiDatepickerCustomStorybook implements OnChanges {\r\n @Input() appearance = 'standard';\r\n @Input() color = 'primary';\r\n @Input() startView = ['month', 'year', 'multi-year'];\r\n @Input() opened = false;\r\n @Input() disabled = false;\r\n @Input() mindate: Date = new Date();\r\n minDate: Date = new Date();\r\n @Input() value: Date = new Date();\r\n _value: Date = new Date();\r\n @Input() maxdate: Date = new Date();\r\n maxDate: Date = new Date();\r\n @Output()\r\n readonly _closed: EventEmitter = new EventEmitter();\r\n @Output()\r\n readonly _monthSelected: EventEmitter = new EventEmitter();\r\n @Output()\r\n readonly _opened: EventEmitter = new EventEmitter();\r\n @Output()\r\n readonly _yearSelected: EventEmitter = new EventEmitter();\r\n @Output()\r\n readonly _dateChange: EventEmitter = new EventEmitter();\r\n constructor() {}\r\n ngOnChanges() {\r\n this.minDate = new Date(this.mindate);\r\n this.maxDate = new Date(this.maxdate);\r\n this._value = new Date(this.value);\r\n if (this.opened) {\r\n (document.querySelector('.oui-datepicker-toggle') as HTMLElement).focus();\r\n }\r\n }\r\n closed(e?: string) {\r\n this._closed.emit(e);\r\n }\r\n monthSelected(e?: string) {\r\n this._monthSelected.emit(e);\r\n }\r\n datepickeropened(e?: string) {\r\n this._opened.emit(e);\r\n }\r\n yearSelected(e?: string) {\r\n this._yearSelected.emit(e);\r\n }\r\n dateChange(e?: string) {\r\n this._dateChange.emit(e);\r\n }\r\n}\r\n\r\n@Component({\r\n selector: 'oui-daterangepicker-storybook',\r\n template: `\r\n
\r\n
\r\n \r\n \r\n \r\n \r\n \r\n
\r\n
\r\n \r\n \r\n \r\n \r\n \r\n
\r\n
\r\n `,\r\n})\r\nexport class OuiDaterangepickerStorybook implements OnChanges {\r\n @Input() appearance = 'standard';\r\n @Input() color = 'primary';\r\n @Input() startView = 'primary';\r\n @Input() opened = false;\r\n @Input() disabled = false;\r\n @Input() mindate: Date;\r\n minDate: Date = new Date();\r\n minRangeDate: Date;\r\n @Input() maxdate: Date;\r\n maxRangeDate: Date;\r\n maxDate: Date;\r\n @Output()\r\n readonly _dateChange: EventEmitter<{}> = new EventEmitter<{}>();\r\n constructor() {}\r\n ngOnChanges() {\r\n this.minRangeDate = new Date(this.mindate);\r\n this.maxRangeDate = new Date(this.maxdate);\r\n }\r\n mindateChange(e: OuiDatepickerInputEvent) {\r\n this.minDate = new Date(e.value);\r\n if (this.maxDate) {\r\n this._dateChange.emit({\r\n min: this.minDate,\r\n max: this.maxDate,\r\n });\r\n }\r\n // this._dateChange.emit(e);\r\n }\r\n maxdateChange(e: OuiDatepickerInputEvent) {\r\n this.maxDate = new Date(e.value);\r\n if (this.minDate) {\r\n this._dateChange.emit({\r\n min: this.minDate,\r\n max: this.maxDate,\r\n });\r\n }\r\n // this._dateChange.emit(e);\r\n }\r\n}\r\n", "assetsDirs": [], "styleUrlsData": "", "stylesData": "", @@ -27409,6 +27758,7 @@ "args": [], "line": 249 }, + "extends": [], "implements": [ "OnChanges" ] @@ -27435,6 +27785,7 @@ "dialog-container.html" ], "viewProviders": [], + "hostDirectives": [], "inputsClass": [], "outputsClass": [], "propertiesClass": [ @@ -27458,7 +27809,7 @@ "description": "", "line": 79, "modifierKind": [ - 123 + 125 ] }, { @@ -27472,7 +27823,7 @@ "line": 69, "rawdescription": "\nElement that was focused before the dialog was opened. Save this to restore upon close.", "modifierKind": [ - 121 + 123 ] }, { @@ -27485,7 +27836,7 @@ "line": 66, "rawdescription": "\nThe class that traps and manages focus within the dialog.", "modifierKind": [ - 121 + 123 ] }, { @@ -27512,6 +27863,9 @@ "name": "ViewChild", "stringifiedArguments": "CdkPortalOutlet, {static: true}" } + ], + "modifierKind": [ + 170 ] }, { @@ -27523,7 +27877,7 @@ "description": "", "line": 80, "modifierKind": [ - 123 + 125 ] } ], @@ -27540,7 +27894,7 @@ "rawdescription": "\n\nSetting up the focus trap and saves a reference to the element that was focused before the dialog was open.\n", "description": "

Setting up the focus trap and saves a reference to the element that was focused before the dialog was open.

\n", "modifierKind": [ - 121 + 123 ] }, { @@ -27553,7 +27907,7 @@ "deprecated": false, "deprecationMessage": "", "modifierKind": [ - 121 + 123 ] }, { @@ -27568,7 +27922,7 @@ "rawdescription": "\nOnly return when there is focus inside the dialog", "description": "

Only return when there is focus inside the dialog

\n", "modifierKind": [ - 121 + 123 ] }, { @@ -27583,7 +27937,7 @@ "rawdescription": "\nRestores focus to the element that was focused before the dialog opened.", "description": "

Restores focus to the element that was focused before the dialog opened.

\n", "modifierKind": [ - 123 + 125 ] }, { @@ -27598,7 +27952,7 @@ "rawdescription": "\nMoves the focus inside the focus trap.", "description": "

Moves the focus inside the focus trap.

\n", "modifierKind": [ - 123 + 125 ] }, { @@ -27626,10 +27980,10 @@ "name": { "pos": 2942, "end": 2948, - "flags": 4227072, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "portal" }, "type": "ComponentPortal", @@ -27638,10 +27992,10 @@ "tagName": { "pos": 2936, "end": 2941, - "flags": 4227072, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "param" }, "comment": "

Portal to be attached as the dialog content.

\n" @@ -27673,10 +28027,10 @@ "name": { "pos": 3356, "end": 3362, - "flags": 4227072, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "portal" }, "type": "TemplatePortal", @@ -27685,10 +28039,10 @@ "tagName": { "pos": 3350, "end": 3355, - "flags": 4227072, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "param" }, "comment": "

Portal to be attached as the dialog content.

\n" @@ -27710,6 +28064,8 @@ "deprecationMessage": "", "hostBindings": [], "hostListeners": [], + "standalone": false, + "imports": [], "description": "

Internal component that wraps user-provided dialog content.

\n", "rawdescription": "\n\nInternal component that wraps user-provided dialog content.\n\n", "type": "component", @@ -27793,7 +28149,9 @@ } ] }, - "extends": "BasePortalOutlet", + "extends": [ + "BasePortalOutlet" + ], "implements": [ "OnInit" ], @@ -27816,6 +28174,7 @@ "template": "", "templateUrl": [], "viewProviders": [], + "hostDirectives": [], "inputsClass": [], "outputsClass": [], "propertiesClass": [ @@ -27829,7 +28188,7 @@ "description": "", "line": 98, "modifierKind": [ - 121 + 123 ] } ], @@ -27849,6 +28208,8 @@ "deprecationMessage": "", "hostBindings": [], "hostListeners": [], + "standalone": false, + "imports": [], "description": "

header action article.

\n", "rawdescription": "\n\nheader action article.\n", "type": "component", @@ -27942,6 +28303,7 @@ } ] }, + "extends": [], "implements": [ "OnDestroy" ] @@ -27963,6 +28325,7 @@ "template": "", "templateUrl": [], "viewProviders": [], + "hostDirectives": [], "inputsClass": [], "outputsClass": [], "propertiesClass": [ @@ -27976,7 +28339,7 @@ "description": "", "line": 170, "modifierKind": [ - 121 + 123 ] } ], @@ -27996,6 +28359,8 @@ "deprecationMessage": "", "hostBindings": [], "hostListeners": [], + "standalone": false, + "imports": [], "description": "

header action close

\n", "rawdescription": "\n\nheader action close\n", "type": "component", @@ -28089,6 +28454,7 @@ } ] }, + "extends": [], "implements": [ "OnDestroy" ] @@ -28110,6 +28476,7 @@ "template": "", "templateUrl": [], "viewProviders": [], + "hostDirectives": [], "inputsClass": [], "outputsClass": [], "propertiesClass": [ @@ -28123,7 +28490,7 @@ "description": "", "line": 133, "modifierKind": [ - 121 + 123 ] } ], @@ -28143,6 +28510,8 @@ "deprecationMessage": "", "hostBindings": [], "hostListeners": [], + "standalone": false, + "imports": [], "description": "

header action article.

\n", "rawdescription": "\n\nheader action article.\n", "type": "component", @@ -28236,6 +28605,7 @@ } ] }, + "extends": [], "implements": [ "OnDestroy" ] @@ -28255,6 +28625,7 @@ "template": "\n\n
\n \n
\n
\n \n \n \n
\n
\n
\n
\n
\n \n \n
\n
\n \n \n
\n
\n
\n", "templateUrl": [], "viewProviders": [], + "hostDirectives": [], "inputsClass": [ { "name": "disabled", @@ -28290,6 +28661,9 @@ "name": "ViewChild", "stringifiedArguments": "'dialogTemplate'" } + ], + "modifierKind": [ + 170 ] } ], @@ -28329,6 +28703,8 @@ "deprecationMessage": "", "hostBindings": [], "hostListeners": [], + "standalone": false, + "imports": [], "description": "", "rawdescription": "\n", "type": "component", @@ -28361,7 +28737,8 @@ } } ] - } + }, + "extends": [] }, { "name": "OuiFooterRow", @@ -28387,6 +28764,7 @@ "template": "CDK_ROW_TEMPLATE", "templateUrl": [], "viewProviders": [], + "hostDirectives": [], "inputsClass": [], "outputsClass": [], "propertiesClass": [], @@ -28395,6 +28773,8 @@ "deprecationMessage": "", "hostBindings": [], "hostListeners": [], + "standalone": false, + "imports": [], "description": "

Footer template container that contains the cell outlet. Adds the right class and role.

\n", "rawdescription": "\nFooter template container that contains the cell outlet. Adds the right class and role.", "type": "component", @@ -28402,7 +28782,9 @@ "assetsDirs": [], "styleUrlsData": "", "stylesData": "", - "extends": "CdkFooterRow" + "extends": [ + "CdkFooterRow" + ] }, { "name": "OuiFormField", @@ -28427,6 +28809,7 @@ "form-field.html" ], "viewProviders": [], + "hostDirectives": [], "inputsClass": [ { "name": "appearance", @@ -28471,6 +28854,9 @@ "name": "ViewChild", "stringifiedArguments": "'connectionContainer'" } + ], + "modifierKind": [ + 170 ] }, { @@ -28486,6 +28872,9 @@ "name": "ContentChild", "stringifiedArguments": "OuiFormFieldControl" } + ], + "modifierKind": [ + 170 ] }, { @@ -28498,7 +28887,7 @@ "description": "", "line": 84, "modifierKind": [ - 121 + 123 ] }, { @@ -28510,7 +28899,7 @@ "description": "", "line": 104, "modifierKind": [ - 123 + 125 ] }, { @@ -28526,6 +28915,9 @@ "name": "ViewChild", "stringifiedArguments": "'inputContainer'" } + ], + "modifierKind": [ + 170 ] } ], @@ -28542,7 +28934,7 @@ "rawdescription": "\nThrows an error if the form field's control is missing.", "description": "

Throws an error if the form field's control is missing.

\n", "modifierKind": [ - 122 + 124 ] }, { @@ -28590,6 +28982,8 @@ "deprecationMessage": "", "hostBindings": [], "hostListeners": [], + "standalone": false, + "imports": [], "description": "

Container for form controls that applies Oncehub Design styling and behavior.

\n", "rawdescription": "\nContainer for form controls that applies Oncehub Design styling and behavior.", "type": "component", @@ -28658,7 +29052,9 @@ } ] }, - "extends": "_OuiFormFieldMixinBase", + "extends": [ + "_OuiFormFieldMixinBase" + ], "implements": [ "AfterContentInit", "AfterContentChecked", @@ -28730,6 +29126,7 @@ "template": "CDK_ROW_TEMPLATE", "templateUrl": [], "viewProviders": [], + "hostDirectives": [], "inputsClass": [], "outputsClass": [], "propertiesClass": [], @@ -28738,6 +29135,8 @@ "deprecationMessage": "", "hostBindings": [], "hostListeners": [], + "standalone": false, + "imports": [], "description": "

Footer template container that contains the cell outlet. Adds the right class and role.

\n", "rawdescription": "\nFooter template container that contains the cell outlet. Adds the right class and role.", "type": "component", @@ -28745,7 +29144,9 @@ "assetsDirs": [], "styleUrlsData": "", "stylesData": "", - "extends": "CdkHeaderRow" + "extends": [ + "CdkHeaderRow" + ] }, { "name": "OuiIconButtonStorybook", @@ -28762,6 +29163,7 @@ "template": "\n {{ text }}\n\n", "templateUrl": [], "viewProviders": [], + "hostDirectives": [], "inputsClass": [], "outputsClass": [], "propertiesClass": [], @@ -28770,6 +29172,8 @@ "deprecationMessage": "", "hostBindings": [], "hostListeners": [], + "standalone": false, + "imports": [], "description": "", "rawdescription": "\n", "type": "component", @@ -28817,7 +29221,8 @@ } } ] - } + }, + "extends": [] }, { "name": "OuiiconStorybook", @@ -28834,6 +29239,7 @@ "template": "
\n", "templateUrl": [], "viewProviders": [], + "hostDirectives": [], "inputsClass": [ { "name": "color", @@ -28870,6 +29276,8 @@ "deprecationMessage": "", "hostBindings": [], "hostListeners": [], + "standalone": false, + "imports": [], "description": "", "rawdescription": "\n", "type": "component", @@ -28917,7 +29325,8 @@ } } ] - } + }, + "extends": [] }, { "name": "OuiMenu", @@ -28945,6 +29354,7 @@ "menu.html" ], "viewProviders": [], + "hostDirectives": [], "inputsClass": [ { "name": "backdropClass", @@ -28965,27 +29375,27 @@ { "pos": 5079, "end": 5117, - "flags": 4227072, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 338, + "kind": 348, "tagName": { "pos": 5080, "end": 5085, - "flags": 4227072, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "param" }, "comment": "

list of class names

\n", "name": { "pos": 5086, "end": 5093, - "flags": 4227072, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "classes" }, "isNameFirst": true, @@ -29051,17 +29461,17 @@ { "pos": 5701, "end": 5745, - "flags": 4227072, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 329, + "kind": 338, "tagName": { "pos": 5702, "end": 5712, - "flags": 4227072, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "deprecated" }, "comment": "

Switch to closed instead

\n" @@ -29069,17 +29479,17 @@ { "pos": 5745, "end": 5771, - "flags": 4227072, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 325, + "kind": 334, "tagName": { "pos": 5746, "end": 5761, - "flags": 4227072, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "breaking-change" }, "comment": "

8.0.0

\n" @@ -29120,7 +29530,7 @@ "description": "", "line": 118, "modifierKind": [ - 121 + 123 ] }, { @@ -29134,7 +29544,7 @@ "line": 95, "rawdescription": "\nEmits whenever the amount of menu items changes.", "modifierKind": [ - 121 + 123 ] }, { @@ -29148,7 +29558,7 @@ "line": 92, "rawdescription": "\nMenu items inside the current menu.", "modifierKind": [ - 121 + 123 ] }, { @@ -29160,7 +29570,7 @@ "description": "", "line": 87, "modifierKind": [ - 121 + 123 ] }, { @@ -29173,7 +29583,7 @@ "description": "", "line": 175, "modifierKind": [ - 121 + 123 ] }, { @@ -29187,7 +29597,7 @@ "line": 98, "rawdescription": "\nSubscription to tab events on the menu panel", "modifierKind": [ - 121 + 123 ] }, { @@ -29200,7 +29610,7 @@ "description": "", "line": 88, "modifierKind": [ - 121 + 123 ] }, { @@ -29213,7 +29623,7 @@ "description": "", "line": 89, "modifierKind": [ - 121 + 123 ] }, { @@ -29231,21 +29641,24 @@ "stringifiedArguments": "OuiMenuItem" } ], + "modifierKind": [ + 170 + ], "jsdoctags": [ { "pos": 4256, "end": 4273, - "flags": 4227072, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 329, + "kind": 338, "tagName": { "pos": 4257, "end": 4267, - "flags": 4227072, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "deprecated" }, "comment": "" @@ -29253,17 +29666,17 @@ { "pos": 4273, "end": 4299, - "flags": 4227072, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 325, + "kind": 334, "tagName": { "pos": 4274, "end": 4289, - "flags": 4227072, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "breaking-change" }, "comment": "

8.0.0

\n" @@ -29285,21 +29698,24 @@ "stringifiedArguments": "OuiMenuContent" } ], + "modifierKind": [ + 170 + ], "jsdoctags": [ { "pos": 4432, "end": 4449, - "flags": 4227072, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 325, + "kind": 334, "tagName": { "pos": 4433, "end": 4445, - "flags": 4227072, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "docs-private" }, "comment": "" @@ -29331,21 +29747,24 @@ "stringifiedArguments": "TemplateRef" } ], + "modifierKind": [ + 170 + ], "jsdoctags": [ { "pos": 4122, "end": 4136, - "flags": 4227072, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 325, + "kind": 334, "tagName": { "pos": 4123, "end": 4135, - "flags": 4227072, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "docs-private" }, "comment": "" @@ -29450,10 +29869,10 @@ "name": { "pos": 7280, "end": 7286, - "flags": 4227072, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "origin" }, "type": "FocusOrigin", @@ -29463,10 +29882,10 @@ "tagName": { "pos": 7274, "end": 7279, - "flags": 4227072, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "param" }, "comment": "

Action from which the focus originated. Used to set the correct styling.

\n" @@ -29576,10 +29995,10 @@ "name": { "pos": 9160, "end": 9164, - "flags": 4227072, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "posX" }, "type": "MenuPositionX", @@ -29589,10 +30008,10 @@ "tagName": { "pos": 9154, "end": 9159, - "flags": 4227072, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "param" }, "comment": "

Position of the menu along the x axis.

\n" @@ -29601,10 +30020,10 @@ "name": { "pos": 9216, "end": 9220, - "flags": 4227072, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "posY" }, "type": "MenuPositionY", @@ -29614,10 +30033,10 @@ "tagName": { "pos": 9210, "end": 9215, - "flags": 4227072, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "param" }, "comment": "

Position of the menu along the y axis.

\n" @@ -29629,6 +30048,8 @@ "deprecationMessage": "", "hostBindings": [], "hostListeners": [], + "standalone": false, + "imports": [], "description": "", "rawdescription": "\n", "type": "component", @@ -29697,6 +30118,7 @@ } ] }, + "extends": [], "implements": [ "AfterContentInit", "OuiMenuPanel", @@ -29880,10 +30302,10 @@ "name": { "pos": 5086, "end": 5093, - "flags": 4227072, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "classes" }, "type": "string", @@ -29892,10 +30314,10 @@ "tagName": { "pos": 5080, "end": 5085, - "flags": 4227072, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "param" }, "comment": "

list of class names

\n" @@ -29928,6 +30350,7 @@ "template": "
\n \n
\n", "templateUrl": [], "viewProviders": [], + "hostDirectives": [], "inputsClass": [ { "name": "vertical", @@ -29950,7 +30373,7 @@ "description": "", "line": 32, "modifierKind": [ - 121 + 123 ] } ], @@ -29965,7 +30388,7 @@ "deprecated": false, "deprecationMessage": "", "modifierKind": [ - 121 + 123 ] }, { @@ -30013,6 +30436,8 @@ "deprecationMessage": "", "hostBindings": [], "hostListeners": [], + "standalone": false, + "imports": [], "description": "", "rawdescription": "\n", "type": "component", @@ -30081,6 +30506,7 @@ } ] }, + "extends": [], "implements": [ "AfterContentInit", "OnChanges" @@ -30109,6 +30535,7 @@ "menu-item.html" ], "viewProviders": [], + "hostDirectives": [], "inputsClass": [ { "name": "role", @@ -30133,7 +30560,7 @@ "description": "", "line": 57, "modifierKind": [ - 121 + 123 ] }, { @@ -30158,7 +30585,7 @@ "line": 60, "rawdescription": "\nStream that emits when the menu item is hovered.", "modifierKind": [ - 144 + 148 ] }, { @@ -30299,6 +30726,8 @@ "deprecationMessage": "", "hostBindings": [], "hostListeners": [], + "standalone": false, + "imports": [], "description": "

This directive is intended to be used inside an oui-menu tag.\nIt exists mostly to set the role attribute.

\n", "rawdescription": "\n\nThis directive is intended to be used inside an oui-menu tag.\nIt exists mostly to set the role attribute.\n", "type": "component", @@ -30383,7 +30812,9 @@ } ] }, - "extends": "_OuiMenuItemMixinBase", + "extends": [ + "_OuiMenuItemMixinBase" + ], "implements": [ "FocusableOption", "CanDisable", @@ -30406,6 +30837,7 @@ "template": "
\n \n \n
\n\n \n \n \n\n", "templateUrl": [], "viewProviders": [], + "hostDirectives": [], "inputsClass": [ { "name": "hasBackdrop", @@ -30507,6 +30939,8 @@ "deprecationMessage": "", "hostBindings": [], "hostListeners": [], + "standalone": false, + "imports": [], "description": "", "rawdescription": "\n", "type": "component", @@ -30554,7 +30988,8 @@ } } ] - } + }, + "extends": [] }, { "name": "OuiMonthView", @@ -30576,6 +31011,7 @@ "month-view.html" ], "viewProviders": [], + "hostDirectives": [], "inputsClass": [ { "name": "activeDate", @@ -30680,7 +31116,7 @@ "description": "", "line": 70, "modifierKind": [ - 121 + 123 ] }, { @@ -30698,7 +31134,8 @@ } ], "modifierKind": [ - 123 + 170, + 125 ] }, { @@ -30720,7 +31157,7 @@ "description": "", "line": 107, "modifierKind": [ - 121 + 123 ] }, { @@ -30732,7 +31169,7 @@ "description": "", "line": 95, "modifierKind": [ - 121 + 123 ] }, { @@ -30759,6 +31196,9 @@ "name": "ViewChild", "stringifiedArguments": "OuiCalendarBody" } + ], + "modifierKind": [ + 170 ] }, { @@ -30770,7 +31210,7 @@ "description": "", "line": 83, "modifierKind": [ - 121 + 123 ] }, { @@ -30827,7 +31267,7 @@ "rawdescription": "\nCreates OuiCalendarCells for the dates in this month.", "description": "

Creates OuiCalendarCells for the dates in this month.

\n", "modifierKind": [ - 121 + 123 ] }, { @@ -30891,7 +31331,7 @@ "rawdescription": "\n\nGets the date in this month that the given Date falls on.\nReturns null if the given Date is in another month.\n", "description": "

Gets the date in this month that the given Date falls on.\nReturns null if the given Date is in another month.

\n", "modifierKind": [ - 121 + 123 ], "jsdoctags": [ { @@ -30924,17 +31364,17 @@ "rawdescription": "\n\n", "description": "", "modifierKind": [ - 121 + 123 ], "jsdoctags": [ { "name": { "pos": 11297, "end": 11300, - "flags": 4227072, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "obj" }, "type": "any", @@ -30943,10 +31383,10 @@ "tagName": { "pos": 11291, "end": 11296, - "flags": 4227072, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "param" }, "comment": "

The object to check.

\n" @@ -30955,10 +31395,10 @@ "tagName": { "pos": 11328, "end": 11335, - "flags": 4227072, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "returns" }, "comment": "

The given object if it is both a date instance and valid, otherwise null.

\n" @@ -31020,7 +31460,7 @@ "rawdescription": "\nChecks whether the 2 dates are non-null and fall within the same month of the same year.", "description": "

Checks whether the 2 dates are non-null and fall within the same month of the same year.

\n", "modifierKind": [ - 121 + 123 ], "jsdoctags": [ { @@ -31067,7 +31507,7 @@ "rawdescription": "\nDetermines whether the user has the RTL layout direction.", "description": "

Determines whether the user has the RTL layout direction.

\n", "modifierKind": [ - 121 + 123 ] }, { @@ -31089,7 +31529,7 @@ "rawdescription": "\nDate filter for the month", "description": "

Date filter for the month

\n", "modifierKind": [ - 121 + 123 ], "jsdoctags": [ { @@ -31118,6 +31558,8 @@ "deprecationMessage": "", "hostBindings": [], "hostListeners": [], + "standalone": false, + "imports": [], "description": "

An internal component used to display a single month in the datepicker.

\n", "rawdescription": "\n\nAn internal component used to display a single month in the datepicker.\n", "type": "component", @@ -31198,6 +31640,7 @@ } ] }, + "extends": [], "implements": [ "AfterContentInit" ], @@ -31377,6 +31820,7 @@ "multi-year-view.html" ], "viewProviders": [], + "hostDirectives": [], "inputsClass": [ { "name": "activeDate", @@ -31471,7 +31915,7 @@ "description": "", "line": 67, "modifierKind": [ - 121 + 123 ] }, { @@ -31489,7 +31933,8 @@ } ], "modifierKind": [ - 123 + 170, + 125 ] }, { @@ -31501,7 +31946,7 @@ "description": "", "line": 105, "modifierKind": [ - 121 + 123 ] }, { @@ -31513,7 +31958,7 @@ "description": "", "line": 93, "modifierKind": [ - 121 + 123 ] }, { @@ -31530,6 +31975,9 @@ "name": "ViewChild", "stringifiedArguments": "OuiCalendarBody" } + ], + "modifierKind": [ + 170 ] }, { @@ -31541,7 +31989,7 @@ "description": "", "line": 81, "modifierKind": [ - 121 + 123 ] }, { @@ -31595,7 +32043,7 @@ "rawdescription": "\nCreates an OuiCalendarCell for the given year.", "description": "

Creates an OuiCalendarCell for the given year.

\n", "modifierKind": [ - 121 + 123 ], "jsdoctags": [ { @@ -31650,17 +32098,17 @@ "rawdescription": "\n\n", "description": "", "modifierKind": [ - 121 + 123 ], "jsdoctags": [ { "name": { "pos": 9036, "end": 9039, - "flags": 4227072, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "obj" }, "type": "any", @@ -31669,10 +32117,10 @@ "tagName": { "pos": 9030, "end": 9035, - "flags": 4227072, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "param" }, "comment": "

The object to check.

\n" @@ -31681,10 +32129,10 @@ "tagName": { "pos": 9067, "end": 9074, - "flags": 4227072, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "returns" }, "comment": "

The given object if it is both a date instance and valid, otherwise null.

\n" @@ -31745,7 +32193,7 @@ "rawdescription": "\nDetermines whether the user has the RTL layout direction.", "description": "

Determines whether the user has the RTL layout direction.

\n", "modifierKind": [ - 121 + 123 ] }, { @@ -31767,7 +32215,7 @@ "rawdescription": "\nWhether the given year is enabled.", "description": "

Whether the given year is enabled.

\n", "modifierKind": [ - 121 + 123 ], "jsdoctags": [ { @@ -31826,6 +32274,8 @@ "deprecationMessage": "", "hostBindings": [], "hostListeners": [], + "standalone": false, + "imports": [], "description": "

An internal component used to display a year selector in the datepicker.

\n", "rawdescription": "\n\nAn internal component used to display a year selector in the datepicker.\n", "type": "component", @@ -31891,6 +32341,7 @@ } ] }, + "extends": [], "implements": [ "AfterContentInit" ], @@ -32065,6 +32516,7 @@ "template": "
\n \n \n
\n\n \n \n\n\n\n \n \n \n\n", "templateUrl": [], "viewProviders": [], + "hostDirectives": [], "inputsClass": [ { "name": "hasBackdrop", @@ -32166,6 +32618,8 @@ "deprecationMessage": "", "hostBindings": [], "hostListeners": [], + "standalone": false, + "imports": [], "description": "", "rawdescription": "\n", "type": "component", @@ -32213,7 +32667,8 @@ } } ] - } + }, + "extends": [] }, { "name": "OuiOptgroup", @@ -32240,6 +32695,7 @@ "optgroup.html" ], "viewProviders": [], + "hostDirectives": [], "inputsClass": [ { "name": "label", @@ -32271,6 +32727,8 @@ "deprecationMessage": "", "hostBindings": [], "hostListeners": [], + "standalone": false, + "imports": [], "description": "

Component that is used to group instances of oui-option.

\n", "rawdescription": "\n\nComponent that is used to group instances of `oui-option`.\n", "type": "component", @@ -32283,7 +32741,9 @@ } ], "stylesData": "", - "extends": "_OuiOptgroupMixinBase", + "extends": [ + "_OuiOptgroupMixinBase" + ], "implements": [ "CanDisable" ], @@ -32312,6 +32772,7 @@ "option.html" ], "viewProviders": [], + "hostDirectives": [], "inputsClass": [ { "name": "disabled", @@ -32368,7 +32829,7 @@ "description": "", "line": 84, "modifierKind": [ - 121 + 123 ] }, { @@ -32381,7 +32842,7 @@ "description": "", "line": 85, "modifierKind": [ - 121 + 123 ] }, { @@ -32394,7 +32855,7 @@ "description": "", "line": 87, "modifierKind": [ - 121 + 123 ] }, { @@ -32407,7 +32868,7 @@ "description": "", "line": 86, "modifierKind": [ - 121 + 123 ] }, { @@ -32420,7 +32881,7 @@ "description": "", "line": 83, "modifierKind": [ - 121 + 123 ] }, { @@ -32434,7 +32895,7 @@ "line": 124, "rawdescription": "\nEmits when the state of the option changes and any parents have to be notified.", "modifierKind": [ - 144 + 148 ] } ], @@ -32459,7 +32920,7 @@ "rawdescription": "\nEmits the selection change event.", "description": "

Emits the selection change event.

\n", "modifierKind": [ - 121 + 123 ], "jsdoctags": [ { @@ -32637,6 +33098,8 @@ "deprecationMessage": "", "hostBindings": [], "hostListeners": [], + "standalone": false, + "imports": [], "description": "

Single option inside of a <oui-select> element.

\n", "rawdescription": "\n\nSingle option inside of a `` element.\n", "type": "component", @@ -32765,6 +33228,7 @@ } ] }, + "extends": [], "implements": [ "AfterViewChecked", "OnDestroy" @@ -32891,6 +33355,7 @@ "paginator.html" ], "viewProviders": [], + "hostDirectives": [], "inputsClass": [ { "name": "hidePageSize", @@ -32966,7 +33431,7 @@ "description": "", "line": 125, "modifierKind": [ - 121 + 123 ] }, { @@ -32978,7 +33443,7 @@ "description": "", "line": 82, "modifierKind": [ - 121 + 123 ] }, { @@ -32990,7 +33455,7 @@ "description": "", "line": 135, "modifierKind": [ - 123 + 125 ] }, { @@ -33002,7 +33467,7 @@ "description": "", "line": 83, "modifierKind": [ - 121 + 123 ] }, { @@ -33035,7 +33500,7 @@ "description": "", "line": 115, "modifierKind": [ - 121 + 123 ] } ], @@ -33089,7 +33554,7 @@ "rawdescription": "\nEmits an event notifying that a change of the paginator's properties has been triggered.", "description": "

Emits an event notifying that a change of the paginator's properties has been triggered.

\n", "modifierKind": [ - 121 + 123 ], "jsdoctags": [ { @@ -33248,6 +33713,8 @@ "deprecationMessage": "", "hostBindings": [], "hostListeners": [], + "standalone": false, + "imports": [], "description": "

Component to provide navigation between paged information. Displays the size of the current\npage, user-selectable options to change that size, what items are being shown, and\nnavigational button to go to the previous or next page.

\n", "rawdescription": "\n\nComponent to provide navigation between paged information. Displays the size of the current\npage, user-selectable options to change that size, what items are being shown, and\nnavigational button to go to the previous or next page.\n", "type": "component", @@ -33301,7 +33768,9 @@ } ] }, - "extends": "_OuiPaginatorBase", + "extends": [ + "_OuiPaginatorBase" + ], "implements": [ "OnInit", "OnDestroy", @@ -33466,7 +33935,7 @@ }, { "name": "OuiPanel", - "id": "component-OuiPanel-75834551469a77f2f75f2c9c42d0de964ac0ed9710e9d05128f9c9784e8e494b743a4a79301ee2a9f23c2c02744b30e7f33d4244928766088870a565b9863ed3", + "id": "component-OuiPanel-065bb74cd1fa7f57341de83af5abd480b4a05e128e287e5f54c73e268d54b3b383070ce1cfa253877356eca1debdca5c7fc6658f6f2f2690c8fd1b55a9d5486e", "file": "ui/src/components/panel/panel.ts", "changeDetection": "ChangeDetectionStrategy.OnPush", "encapsulation": [ @@ -33486,6 +33955,7 @@ "panel.html" ], "viewProviders": [], + "hostDirectives": [], "inputsClass": [ { "name": "width", @@ -33550,8 +34020,8 @@ "description": "", "line": 69, "modifierKind": [ - 121, - 144 + 123, + 148 ] }, { @@ -33564,8 +34034,8 @@ "description": "", "line": 67, "modifierKind": [ - 121, - 144 + 123, + 148 ] }, { @@ -33578,7 +34048,7 @@ "description": "", "line": 65, "modifierKind": [ - 121 + 123 ] }, { @@ -33591,7 +34061,7 @@ "description": "", "line": 66, "modifierKind": [ - 121 + 123 ] }, { @@ -33604,7 +34074,7 @@ "description": "", "line": 71, "modifierKind": [ - 123 + 125 ] }, { @@ -33622,21 +34092,24 @@ "stringifiedArguments": "OuiPanelContent" } ], + "modifierKind": [ + 170 + ], "jsdoctags": [ { "pos": 2482, "end": 2499, - "flags": 4227072, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 325, + "kind": 334, "tagName": { "pos": 2483, "end": 2495, - "flags": 4227072, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "docs-private" }, "comment": "" @@ -33652,7 +34125,7 @@ "description": "", "line": 70, "modifierKind": [ - 123 + 125 ] }, { @@ -33664,7 +34137,7 @@ "description": "", "line": 68, "modifierKind": [ - 123 + 125 ] }, { @@ -33680,6 +34153,9 @@ "name": "ViewChild", "stringifiedArguments": "TemplateRef" } + ], + "modifierKind": [ + 170 ] } ], @@ -33694,7 +34170,7 @@ "deprecated": false, "deprecationMessage": "", "modifierKind": [ - 123 + 125 ] }, { @@ -33714,7 +34190,7 @@ "deprecated": false, "deprecationMessage": "", "modifierKind": [ - 123 + 125 ], "jsdoctags": [ { @@ -33745,7 +34221,7 @@ "deprecated": false, "deprecationMessage": "", "modifierKind": [ - 123 + 125 ], "jsdoctags": [ { @@ -33800,10 +34276,10 @@ "name": { "pos": 3785, "end": 3789, - "flags": 4227072, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "posX" }, "type": "PanelPositionX", @@ -33813,10 +34289,10 @@ "tagName": { "pos": 3779, "end": 3784, - "flags": 4227072, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "param" }, "comment": "

Position of the panel along the x axis.

\n" @@ -33825,10 +34301,10 @@ "name": { "pos": 3842, "end": 3846, - "flags": 4227072, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "posY" }, "type": "PanelPositionY", @@ -33838,10 +34314,10 @@ "tagName": { "pos": 3836, "end": 3841, - "flags": 4227072, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "param" }, "comment": "

Position of the panel along the y axis.

\n" @@ -33853,10 +34329,12 @@ "deprecationMessage": "", "hostBindings": [], "hostListeners": [], + "standalone": false, + "imports": [], "description": "", "rawdescription": "\n", "type": "component", - "sourceCode": "import {\n ChangeDetectionStrategy,\n ViewEncapsulation,\n Component,\n InjectionToken,\n Inject,\n Input,\n ViewChild,\n TemplateRef,\n OnInit,\n ContentChild,\n Output,\n EventEmitter,\n Attribute,\n NgZone,\n ElementRef,\n OnDestroy,\n} from '@angular/core';\nimport { PanelPositionX, PanelPositionY } from './panel-positions';\nimport {\n throwOuiPanelInvalidPositionX,\n throwOuiPanelInvalidPositionY,\n} from './panel-errors';\nimport { OuiPanelOverlay } from './panel-overlay';\nimport { OuiPanelContent } from './panel-content';\nimport { Subject, Observable, Subscription } from 'rxjs';\nimport { OuiIconRegistry } from '../icon/icon-registery';\nimport { DomSanitizer } from '@angular/platform-browser';\nimport { ICONS } from '../core/shared/icons';\nimport { FocusMonitor } from '@angular/cdk/a11y';\n\n/** Default `oui-panel` options that can be overridden. */\nexport interface OuiPanelDefaultOptions {\n /** The x-axis position of the menu. */\n xPosition: PanelPositionX;\n\n /** The y-axis position of the menu. */\n yPosition: PanelPositionY;\n}\n\n/** Injection token to be used to override the default options for `oui-menu`. */\nexport const OUI_PANEL_DEFAULT_OPTIONS =\n new InjectionToken('oui-panel-default-options', {\n providedIn: 'root',\n factory: OUI_PANEL_DEFAULT_OPTIONS_FACTORY,\n });\n\n/** @docs-private */\nexport function OUI_PANEL_DEFAULT_OPTIONS_FACTORY(): OuiPanelDefaultOptions {\n return {\n xPosition: 'after',\n yPosition: 'below',\n };\n}\n\n@Component({\n selector: 'oui-panel',\n templateUrl: 'panel.html',\n styleUrls: ['panel.scss'],\n changeDetection: ChangeDetectionStrategy.OnPush,\n encapsulation: ViewEncapsulation.None,\n exportAs: 'ouiPanel',\n})\nexport class OuiPanel implements OnInit, OuiPanelOverlay {\n private _xPosition: PanelPositionX = this._defaultOptions.xPosition;\n private _yPosition: PanelPositionY = this._defaultOptions.yPosition;\n private readonly _mouseLeave: Subject = new Subject();\n public mouseLeave: Observable;\n private readonly _mouseEnter: Subject = new Subject();\n public mouseEnter: Observable;\n public escapeEvent: Subject = new Subject();\n\n @Input() width?: number;\n\n /** Config object to be passed into the menu's ngClass */\n _classList: { [key: string]: boolean } = {};\n\n @ViewChild(TemplateRef)\n templateRef: TemplateRef;\n\n /**\n * Panel content that will be rendered lazily.\n *\n * @docs-private\n */\n @ContentChild(OuiPanelContent)\n lazyContent: OuiPanelContent;\n\n /** Event emitted when the menu is closed. */\n @Output()\n readonly closed: EventEmitter = new EventEmitter();\n\n /** Position of the menu in the X axis. */\n @Input()\n get xPosition(): PanelPositionX {\n return this._xPosition;\n }\n set xPosition(value: PanelPositionX) {\n if (value !== 'before' && value !== 'after') {\n throwOuiPanelInvalidPositionX();\n }\n this._xPosition = value;\n this.setPositionClasses();\n }\n\n /** Position of the menu in the Y axis. */\n @Input()\n get yPosition(): PanelPositionY {\n return this._yPosition;\n }\n set yPosition(value: PanelPositionY) {\n if (value !== 'above' && value !== 'below') {\n throwOuiPanelInvalidPositionY();\n }\n this._yPosition = value;\n this.setPositionClasses();\n }\n constructor(\n @Inject(OUI_PANEL_DEFAULT_OPTIONS)\n private _defaultOptions: OuiPanelDefaultOptions\n ) {\n this.mouseLeave = this._mouseLeave.asObservable();\n this.mouseEnter = this._mouseEnter.asObservable();\n }\n\n ngOnInit() {\n this.setPositionClasses();\n }\n\n /**\n * Adds classes to the panel-overlay based on its position. Can be used by\n * consumers to add specific styling based on the position.\n *\n * @param posX Position of the panel along the x axis.\n * @param posY Position of the panel along the y axis.\n * @docs-private\n */\n setPositionClasses(\n posX: PanelPositionX = this.xPosition,\n posY: PanelPositionY = this.yPosition\n ) {\n const classes = this._classList;\n classes['oui-panel-before'] = posX === 'before';\n classes['oui-panel-after'] = posX === 'after';\n classes['oui-panel-above'] = posY === 'above';\n classes['oui-panel-below'] = posY === 'below';\n }\n\n public _handleMouseLeave(event: MouseEvent) {\n this._mouseLeave.next(event);\n }\n\n public _handleMouseEnter(event: MouseEvent) {\n this._mouseEnter.next(event);\n }\n\n public _handleCloseIcon() {\n this.escapeEvent.next();\n }\n}\n\n@Component({\n selector: 'oui-panel-icon',\n template:\n '',\n styleUrls: ['panel.scss'],\n changeDetection: ChangeDetectionStrategy.OnPush,\n encapsulation: ViewEncapsulation.None,\n exportAs: 'ouiPanelIcon',\n})\nexport class OuiPanelIcon implements OnDestroy {\n private _monitorSubscription: Subscription = Subscription.EMPTY;\n tabIndex: any;\n constructor(\n private _elementRef: ElementRef,\n private ouiIconRegistry: OuiIconRegistry,\n private domSanitizer: DomSanitizer,\n private _focusMonitor: FocusMonitor,\n private _ngZone: NgZone,\n @Attribute('tabindex') tabIndex: string\n ) {\n this.tabIndex = parseInt(tabIndex, 10) || 0;\n this._monitorSubscription = this._focusMonitor\n .monitor(this._elementRef, true)\n .subscribe(() => this._ngZone.run(() => {}));\n\n this.ouiIconRegistry.addSvgIconLiteral(\n `panel-icon`,\n this.domSanitizer.bypassSecurityTrustHtml(ICONS.PANEL_ICON)\n );\n this.ouiIconRegistry.addSvgIconLiteral(\n `close-icon_8X8`,\n this.domSanitizer.bypassSecurityTrustHtml(ICONS.CLOSE_ICON_8X8)\n );\n }\n\n ngOnDestroy() {\n this._focusMonitor.stopMonitoring(this._elementRef.nativeElement);\n this._monitorSubscription.unsubscribe();\n }\n}\n", + "sourceCode": "import {\n ChangeDetectionStrategy,\n ViewEncapsulation,\n Component,\n InjectionToken,\n Inject,\n Input,\n ViewChild,\n TemplateRef,\n OnInit,\n ContentChild,\n Output,\n EventEmitter,\n Attribute,\n NgZone,\n ElementRef,\n OnDestroy,\n} from '@angular/core';\nimport { PanelPositionX, PanelPositionY } from './panel-positions';\nimport {\n throwOuiPanelInvalidPositionX,\n throwOuiPanelInvalidPositionY,\n} from './panel-errors';\nimport { OuiPanelOverlay } from './panel-overlay';\nimport { OuiPanelContent } from './panel-content';\nimport { Subject, Observable, Subscription } from 'rxjs';\nimport { OuiIconRegistry } from '../icon/icon-registery';\nimport { DomSanitizer } from '@angular/platform-browser';\nimport { ICONS } from '../core/shared/icons';\nimport { FocusMonitor } from '@angular/cdk/a11y';\n\n/** Default `oui-panel` options that can be overridden. */\nexport interface OuiPanelDefaultOptions {\n /** The x-axis position of the menu. */\n xPosition: PanelPositionX;\n\n /** The y-axis position of the menu. */\n yPosition: PanelPositionY;\n}\n\n/** Injection token to be used to override the default options for `oui-menu`. */\nexport const OUI_PANEL_DEFAULT_OPTIONS =\n new InjectionToken('oui-panel-default-options', {\n providedIn: 'root',\n factory: OUI_PANEL_DEFAULT_OPTIONS_FACTORY,\n });\n\n/** @docs-private */\nexport function OUI_PANEL_DEFAULT_OPTIONS_FACTORY(): OuiPanelDefaultOptions {\n return {\n xPosition: 'after',\n yPosition: 'below',\n };\n}\n\n@Component({\n selector: 'oui-panel',\n templateUrl: 'panel.html',\n styleUrls: ['panel.scss'],\n changeDetection: ChangeDetectionStrategy.OnPush,\n encapsulation: ViewEncapsulation.None,\n exportAs: 'ouiPanel',\n})\nexport class OuiPanel implements OnInit, OuiPanelOverlay {\n private _xPosition: PanelPositionX = this._defaultOptions.xPosition;\n private _yPosition: PanelPositionY = this._defaultOptions.yPosition;\n private readonly _mouseLeave: Subject = new Subject();\n public mouseLeave: Observable;\n private readonly _mouseEnter: Subject = new Subject();\n public mouseEnter: Observable;\n public escapeEvent: Subject = new Subject();\n\n @Input() width?: number;\n\n /** Config object to be passed into the menu's ngClass */\n _classList: { [key: string]: boolean } = {};\n\n @ViewChild(TemplateRef)\n templateRef: TemplateRef;\n\n /**\n * Panel content that will be rendered lazily.\n *\n * @docs-private\n */\n @ContentChild(OuiPanelContent)\n lazyContent: OuiPanelContent;\n\n /** Event emitted when the menu is closed. */\n @Output()\n readonly closed: EventEmitter = new EventEmitter();\n\n /** Position of the menu in the X axis. */\n @Input()\n get xPosition(): PanelPositionX {\n return this._xPosition;\n }\n set xPosition(value: PanelPositionX) {\n if (value !== 'before' && value !== 'after') {\n throwOuiPanelInvalidPositionX();\n }\n this._xPosition = value;\n this.setPositionClasses();\n }\n\n /** Position of the menu in the Y axis. */\n @Input()\n get yPosition(): PanelPositionY {\n return this._yPosition;\n }\n set yPosition(value: PanelPositionY) {\n if (value !== 'above' && value !== 'below') {\n throwOuiPanelInvalidPositionY();\n }\n this._yPosition = value;\n this.setPositionClasses();\n }\n constructor(\n @Inject(OUI_PANEL_DEFAULT_OPTIONS)\n private _defaultOptions: OuiPanelDefaultOptions\n ) {\n this.mouseLeave = this._mouseLeave.asObservable();\n this.mouseEnter = this._mouseEnter.asObservable();\n }\n\n ngOnInit() {\n this.setPositionClasses();\n }\n\n /**\n * Adds classes to the panel-overlay based on its position. Can be used by\n * consumers to add specific styling based on the position.\n *\n * @param posX Position of the panel along the x axis.\n * @param posY Position of the panel along the y axis.\n * @docs-private\n */\n setPositionClasses(\n posX: PanelPositionX = this.xPosition,\n posY: PanelPositionY = this.yPosition\n ) {\n const classes = this._classList;\n classes['oui-panel-before'] = posX === 'before';\n classes['oui-panel-after'] = posX === 'after';\n classes['oui-panel-above'] = posY === 'above';\n classes['oui-panel-below'] = posY === 'below';\n }\n\n public _handleMouseLeave(event: MouseEvent) {\n this._mouseLeave.next(event);\n }\n\n public _handleMouseEnter(event: MouseEvent) {\n this._mouseEnter.next(event);\n }\n\n public _handleCloseIcon() {\n this.escapeEvent.next();\n }\n}\n\n@Component({\n selector: 'oui-panel-icon',\n template:\n '',\n styleUrls: ['panel.scss'],\n changeDetection: ChangeDetectionStrategy.OnPush,\n encapsulation: ViewEncapsulation.None,\n exportAs: 'ouiPanelIcon',\n})\nexport class OuiPanelIcon implements OnDestroy {\n private _monitorSubscription: Subscription = Subscription.EMPTY;\n tabIndex: any;\n constructor(\n private _elementRef: ElementRef,\n private ouiIconRegistry: OuiIconRegistry,\n private domSanitizer: DomSanitizer,\n private _focusMonitor: FocusMonitor,\n private _ngZone: NgZone,\n @Attribute('tabindex') tabIndex: string\n ) {\n this.tabIndex = parseInt(tabIndex, 10) || 0;\n this._monitorSubscription = this._focusMonitor\n .monitor(this._elementRef, true)\n .subscribe(() => this._ngZone.run(() => {}));\n\n this.ouiIconRegistry.addSvgIconLiteral(\n `panel-icon`,\n this.domSanitizer.bypassSecurityTrustHtml(ICONS.PANEL_ICON)\n );\n this.ouiIconRegistry.addSvgIconLiteral(\n `close-icon_8X8`,\n this.domSanitizer.bypassSecurityTrustHtml(ICONS.CLOSE_ICON_8X8)\n );\n }\n\n ngOnDestroy() {\n this._focusMonitor.stopMonitoring(this._elementRef.nativeElement);\n this._monitorSubscription.unsubscribe();\n }\n}\n", "assetsDirs": [], "styleUrlsData": [ { @@ -33891,6 +34369,7 @@ } ] }, + "extends": [], "implements": [ "OnInit", "OuiPanelOverlay" @@ -33977,7 +34456,7 @@ }, { "name": "OuiPanelIcon", - "id": "component-OuiPanelIcon-75834551469a77f2f75f2c9c42d0de964ac0ed9710e9d05128f9c9784e8e494b743a4a79301ee2a9f23c2c02744b30e7f33d4244928766088870a565b9863ed3", + "id": "component-OuiPanelIcon-065bb74cd1fa7f57341de83af5abd480b4a05e128e287e5f54c73e268d54b3b383070ce1cfa253877356eca1debdca5c7fc6658f6f2f2690c8fd1b55a9d5486e", "file": "ui/src/components/panel/panel.ts", "changeDetection": "ChangeDetectionStrategy.OnPush", "encapsulation": [ @@ -33993,9 +34472,10 @@ "panel.scss" ], "styles": [], - "template": "", + "template": "", "templateUrl": [], "viewProviders": [], + "hostDirectives": [], "inputsClass": [], "outputsClass": [], "propertiesClass": [ @@ -34009,7 +34489,7 @@ "description": "", "line": 172, "modifierKind": [ - 121 + 123 ] }, { @@ -34038,10 +34518,12 @@ "deprecationMessage": "", "hostBindings": [], "hostListeners": [], + "standalone": false, + "imports": [], "description": "", "rawdescription": "\n", "type": "component", - "sourceCode": "import {\n ChangeDetectionStrategy,\n ViewEncapsulation,\n Component,\n InjectionToken,\n Inject,\n Input,\n ViewChild,\n TemplateRef,\n OnInit,\n ContentChild,\n Output,\n EventEmitter,\n Attribute,\n NgZone,\n ElementRef,\n OnDestroy,\n} from '@angular/core';\nimport { PanelPositionX, PanelPositionY } from './panel-positions';\nimport {\n throwOuiPanelInvalidPositionX,\n throwOuiPanelInvalidPositionY,\n} from './panel-errors';\nimport { OuiPanelOverlay } from './panel-overlay';\nimport { OuiPanelContent } from './panel-content';\nimport { Subject, Observable, Subscription } from 'rxjs';\nimport { OuiIconRegistry } from '../icon/icon-registery';\nimport { DomSanitizer } from '@angular/platform-browser';\nimport { ICONS } from '../core/shared/icons';\nimport { FocusMonitor } from '@angular/cdk/a11y';\n\n/** Default `oui-panel` options that can be overridden. */\nexport interface OuiPanelDefaultOptions {\n /** The x-axis position of the menu. */\n xPosition: PanelPositionX;\n\n /** The y-axis position of the menu. */\n yPosition: PanelPositionY;\n}\n\n/** Injection token to be used to override the default options for `oui-menu`. */\nexport const OUI_PANEL_DEFAULT_OPTIONS =\n new InjectionToken('oui-panel-default-options', {\n providedIn: 'root',\n factory: OUI_PANEL_DEFAULT_OPTIONS_FACTORY,\n });\n\n/** @docs-private */\nexport function OUI_PANEL_DEFAULT_OPTIONS_FACTORY(): OuiPanelDefaultOptions {\n return {\n xPosition: 'after',\n yPosition: 'below',\n };\n}\n\n@Component({\n selector: 'oui-panel',\n templateUrl: 'panel.html',\n styleUrls: ['panel.scss'],\n changeDetection: ChangeDetectionStrategy.OnPush,\n encapsulation: ViewEncapsulation.None,\n exportAs: 'ouiPanel',\n})\nexport class OuiPanel implements OnInit, OuiPanelOverlay {\n private _xPosition: PanelPositionX = this._defaultOptions.xPosition;\n private _yPosition: PanelPositionY = this._defaultOptions.yPosition;\n private readonly _mouseLeave: Subject = new Subject();\n public mouseLeave: Observable;\n private readonly _mouseEnter: Subject = new Subject();\n public mouseEnter: Observable;\n public escapeEvent: Subject = new Subject();\n\n @Input() width?: number;\n\n /** Config object to be passed into the menu's ngClass */\n _classList: { [key: string]: boolean } = {};\n\n @ViewChild(TemplateRef)\n templateRef: TemplateRef;\n\n /**\n * Panel content that will be rendered lazily.\n *\n * @docs-private\n */\n @ContentChild(OuiPanelContent)\n lazyContent: OuiPanelContent;\n\n /** Event emitted when the menu is closed. */\n @Output()\n readonly closed: EventEmitter = new EventEmitter();\n\n /** Position of the menu in the X axis. */\n @Input()\n get xPosition(): PanelPositionX {\n return this._xPosition;\n }\n set xPosition(value: PanelPositionX) {\n if (value !== 'before' && value !== 'after') {\n throwOuiPanelInvalidPositionX();\n }\n this._xPosition = value;\n this.setPositionClasses();\n }\n\n /** Position of the menu in the Y axis. */\n @Input()\n get yPosition(): PanelPositionY {\n return this._yPosition;\n }\n set yPosition(value: PanelPositionY) {\n if (value !== 'above' && value !== 'below') {\n throwOuiPanelInvalidPositionY();\n }\n this._yPosition = value;\n this.setPositionClasses();\n }\n constructor(\n @Inject(OUI_PANEL_DEFAULT_OPTIONS)\n private _defaultOptions: OuiPanelDefaultOptions\n ) {\n this.mouseLeave = this._mouseLeave.asObservable();\n this.mouseEnter = this._mouseEnter.asObservable();\n }\n\n ngOnInit() {\n this.setPositionClasses();\n }\n\n /**\n * Adds classes to the panel-overlay based on its position. Can be used by\n * consumers to add specific styling based on the position.\n *\n * @param posX Position of the panel along the x axis.\n * @param posY Position of the panel along the y axis.\n * @docs-private\n */\n setPositionClasses(\n posX: PanelPositionX = this.xPosition,\n posY: PanelPositionY = this.yPosition\n ) {\n const classes = this._classList;\n classes['oui-panel-before'] = posX === 'before';\n classes['oui-panel-after'] = posX === 'after';\n classes['oui-panel-above'] = posY === 'above';\n classes['oui-panel-below'] = posY === 'below';\n }\n\n public _handleMouseLeave(event: MouseEvent) {\n this._mouseLeave.next(event);\n }\n\n public _handleMouseEnter(event: MouseEvent) {\n this._mouseEnter.next(event);\n }\n\n public _handleCloseIcon() {\n this.escapeEvent.next();\n }\n}\n\n@Component({\n selector: 'oui-panel-icon',\n template:\n '',\n styleUrls: ['panel.scss'],\n changeDetection: ChangeDetectionStrategy.OnPush,\n encapsulation: ViewEncapsulation.None,\n exportAs: 'ouiPanelIcon',\n})\nexport class OuiPanelIcon implements OnDestroy {\n private _monitorSubscription: Subscription = Subscription.EMPTY;\n tabIndex: any;\n constructor(\n private _elementRef: ElementRef,\n private ouiIconRegistry: OuiIconRegistry,\n private domSanitizer: DomSanitizer,\n private _focusMonitor: FocusMonitor,\n private _ngZone: NgZone,\n @Attribute('tabindex') tabIndex: string\n ) {\n this.tabIndex = parseInt(tabIndex, 10) || 0;\n this._monitorSubscription = this._focusMonitor\n .monitor(this._elementRef, true)\n .subscribe(() => this._ngZone.run(() => {}));\n\n this.ouiIconRegistry.addSvgIconLiteral(\n `panel-icon`,\n this.domSanitizer.bypassSecurityTrustHtml(ICONS.PANEL_ICON)\n );\n this.ouiIconRegistry.addSvgIconLiteral(\n `close-icon_8X8`,\n this.domSanitizer.bypassSecurityTrustHtml(ICONS.CLOSE_ICON_8X8)\n );\n }\n\n ngOnDestroy() {\n this._focusMonitor.stopMonitoring(this._elementRef.nativeElement);\n this._monitorSubscription.unsubscribe();\n }\n}\n", + "sourceCode": "import {\n ChangeDetectionStrategy,\n ViewEncapsulation,\n Component,\n InjectionToken,\n Inject,\n Input,\n ViewChild,\n TemplateRef,\n OnInit,\n ContentChild,\n Output,\n EventEmitter,\n Attribute,\n NgZone,\n ElementRef,\n OnDestroy,\n} from '@angular/core';\nimport { PanelPositionX, PanelPositionY } from './panel-positions';\nimport {\n throwOuiPanelInvalidPositionX,\n throwOuiPanelInvalidPositionY,\n} from './panel-errors';\nimport { OuiPanelOverlay } from './panel-overlay';\nimport { OuiPanelContent } from './panel-content';\nimport { Subject, Observable, Subscription } from 'rxjs';\nimport { OuiIconRegistry } from '../icon/icon-registery';\nimport { DomSanitizer } from '@angular/platform-browser';\nimport { ICONS } from '../core/shared/icons';\nimport { FocusMonitor } from '@angular/cdk/a11y';\n\n/** Default `oui-panel` options that can be overridden. */\nexport interface OuiPanelDefaultOptions {\n /** The x-axis position of the menu. */\n xPosition: PanelPositionX;\n\n /** The y-axis position of the menu. */\n yPosition: PanelPositionY;\n}\n\n/** Injection token to be used to override the default options for `oui-menu`. */\nexport const OUI_PANEL_DEFAULT_OPTIONS =\n new InjectionToken('oui-panel-default-options', {\n providedIn: 'root',\n factory: OUI_PANEL_DEFAULT_OPTIONS_FACTORY,\n });\n\n/** @docs-private */\nexport function OUI_PANEL_DEFAULT_OPTIONS_FACTORY(): OuiPanelDefaultOptions {\n return {\n xPosition: 'after',\n yPosition: 'below',\n };\n}\n\n@Component({\n selector: 'oui-panel',\n templateUrl: 'panel.html',\n styleUrls: ['panel.scss'],\n changeDetection: ChangeDetectionStrategy.OnPush,\n encapsulation: ViewEncapsulation.None,\n exportAs: 'ouiPanel',\n})\nexport class OuiPanel implements OnInit, OuiPanelOverlay {\n private _xPosition: PanelPositionX = this._defaultOptions.xPosition;\n private _yPosition: PanelPositionY = this._defaultOptions.yPosition;\n private readonly _mouseLeave: Subject = new Subject();\n public mouseLeave: Observable;\n private readonly _mouseEnter: Subject = new Subject();\n public mouseEnter: Observable;\n public escapeEvent: Subject = new Subject();\n\n @Input() width?: number;\n\n /** Config object to be passed into the menu's ngClass */\n _classList: { [key: string]: boolean } = {};\n\n @ViewChild(TemplateRef)\n templateRef: TemplateRef;\n\n /**\n * Panel content that will be rendered lazily.\n *\n * @docs-private\n */\n @ContentChild(OuiPanelContent)\n lazyContent: OuiPanelContent;\n\n /** Event emitted when the menu is closed. */\n @Output()\n readonly closed: EventEmitter = new EventEmitter();\n\n /** Position of the menu in the X axis. */\n @Input()\n get xPosition(): PanelPositionX {\n return this._xPosition;\n }\n set xPosition(value: PanelPositionX) {\n if (value !== 'before' && value !== 'after') {\n throwOuiPanelInvalidPositionX();\n }\n this._xPosition = value;\n this.setPositionClasses();\n }\n\n /** Position of the menu in the Y axis. */\n @Input()\n get yPosition(): PanelPositionY {\n return this._yPosition;\n }\n set yPosition(value: PanelPositionY) {\n if (value !== 'above' && value !== 'below') {\n throwOuiPanelInvalidPositionY();\n }\n this._yPosition = value;\n this.setPositionClasses();\n }\n constructor(\n @Inject(OUI_PANEL_DEFAULT_OPTIONS)\n private _defaultOptions: OuiPanelDefaultOptions\n ) {\n this.mouseLeave = this._mouseLeave.asObservable();\n this.mouseEnter = this._mouseEnter.asObservable();\n }\n\n ngOnInit() {\n this.setPositionClasses();\n }\n\n /**\n * Adds classes to the panel-overlay based on its position. Can be used by\n * consumers to add specific styling based on the position.\n *\n * @param posX Position of the panel along the x axis.\n * @param posY Position of the panel along the y axis.\n * @docs-private\n */\n setPositionClasses(\n posX: PanelPositionX = this.xPosition,\n posY: PanelPositionY = this.yPosition\n ) {\n const classes = this._classList;\n classes['oui-panel-before'] = posX === 'before';\n classes['oui-panel-after'] = posX === 'after';\n classes['oui-panel-above'] = posY === 'above';\n classes['oui-panel-below'] = posY === 'below';\n }\n\n public _handleMouseLeave(event: MouseEvent) {\n this._mouseLeave.next(event);\n }\n\n public _handleMouseEnter(event: MouseEvent) {\n this._mouseEnter.next(event);\n }\n\n public _handleCloseIcon() {\n this.escapeEvent.next();\n }\n}\n\n@Component({\n selector: 'oui-panel-icon',\n template:\n '',\n styleUrls: ['panel.scss'],\n changeDetection: ChangeDetectionStrategy.OnPush,\n encapsulation: ViewEncapsulation.None,\n exportAs: 'ouiPanelIcon',\n})\nexport class OuiPanelIcon implements OnDestroy {\n private _monitorSubscription: Subscription = Subscription.EMPTY;\n tabIndex: any;\n constructor(\n private _elementRef: ElementRef,\n private ouiIconRegistry: OuiIconRegistry,\n private domSanitizer: DomSanitizer,\n private _focusMonitor: FocusMonitor,\n private _ngZone: NgZone,\n @Attribute('tabindex') tabIndex: string\n ) {\n this.tabIndex = parseInt(tabIndex, 10) || 0;\n this._monitorSubscription = this._focusMonitor\n .monitor(this._elementRef, true)\n .subscribe(() => this._ngZone.run(() => {}));\n\n this.ouiIconRegistry.addSvgIconLiteral(\n `panel-icon`,\n this.domSanitizer.bypassSecurityTrustHtml(ICONS.PANEL_ICON)\n );\n this.ouiIconRegistry.addSvgIconLiteral(\n `close-icon_8X8`,\n this.domSanitizer.bypassSecurityTrustHtml(ICONS.CLOSE_ICON_8X8)\n );\n }\n\n ngOnDestroy() {\n this._focusMonitor.stopMonitoring(this._elementRef.nativeElement);\n this._monitorSubscription.unsubscribe();\n }\n}\n", "assetsDirs": [], "styleUrlsData": [ { @@ -34151,6 +34633,7 @@ } ] }, + "extends": [], "implements": [ "OnDestroy" ] @@ -34170,6 +34653,7 @@ "template": "\n\n\n
Lorem ipsum, dolor sit amet consectetur
\n

\n Loremipsumdolorsit,ametconsecteturadipisicingelit. Cupiditate harum quod\n a incidunt? Obcaecati dolores omnis odio repudiandae quo quidem?\n Learn more\n

\n

\n Lorem ipsum dolor sit amet consectetur adipisicing elit. Cupiditate,\n dolorum! Reprehenderit reiciendis hic magnam esse odio asperiores qui\n tempora beatae.\n Learn more\n

\n\n", "templateUrl": [], "viewProviders": [], + "hostDirectives": [], "inputsClass": [ { "name": "width", @@ -34206,6 +34690,8 @@ "deprecationMessage": "", "hostBindings": [], "hostListeners": [], + "standalone": false, + "imports": [], "description": "", "rawdescription": "\n", "type": "component", @@ -34220,7 +34706,8 @@ "deprecationMessage": "", "args": [], "line": 32 - } + }, + "extends": [] }, { "name": "OuiPanelWithImageStorybook", @@ -34237,6 +34724,7 @@ "template": "\n\n\n
Lorem ipsum, dolor sit amet consectetur
\n \n

\n Lorem ipsum dolor sit, amet consectetur adipisicing elit. Cupiditate\n harum quod a incidunt? Obcaecati dolores omnis odio repudiandae quo\n quidem?\n

\n

\n Lorem ipsum dolor sit amet consectetur adipisicing elit. Cupiditate,\n dolorum! Reprehenderit reiciendis hic magnam esse odio asperiores qui\n tempora beatae.\n

\n
\n", "templateUrl": [], "viewProviders": [], + "hostDirectives": [], "inputsClass": [ { "name": "xPosition", @@ -34264,6 +34752,8 @@ "deprecationMessage": "", "hostBindings": [], "hostListeners": [], + "standalone": false, + "imports": [], "description": "", "rawdescription": "\n", "type": "component", @@ -34278,7 +34768,8 @@ "deprecationMessage": "", "args": [], "line": 60 - } + }, + "extends": [] }, { "name": "OuiProgressBar", @@ -34303,6 +34794,7 @@ "./progress-bar.html" ], "viewProviders": [], + "hostDirectives": [], "inputsClass": [ { "name": "color", @@ -34341,7 +34833,7 @@ "description": "", "line": 38, "modifierKind": [ - 121 + 123 ] }, { @@ -34354,7 +34846,7 @@ "description": "", "line": 37, "modifierKind": [ - 121 + 123 ] }, { @@ -34374,6 +34866,8 @@ "deprecationMessage": "", "hostBindings": [], "hostListeners": [], + "standalone": false, + "imports": [], "description": "", "rawdescription": "\n", "type": "component", @@ -34412,7 +34906,9 @@ } ] }, - "extends": "_OuiProgressBarMixinBase", + "extends": [ + "_OuiProgressBarMixinBase" + ], "accessors": { "value": { "name": "value", @@ -34512,6 +35008,7 @@ "./progress-spinner.html" ], "viewProviders": [], + "hostDirectives": [], "inputsClass": [ { "name": "color", @@ -34559,7 +35056,7 @@ "description": "", "line": 96, "modifierKind": [ - 121 + 123 ] }, { @@ -34571,7 +35068,7 @@ "description": "", "line": 83, "modifierKind": [ - 121 + 123 ] }, { @@ -34584,7 +35081,7 @@ "description": "", "line": 82, "modifierKind": [ - 121 + 123 ] }, { @@ -34597,8 +35094,8 @@ "description": "", "line": 80, "modifierKind": [ - 121, - 124 + 123, + 126 ] }, { @@ -34622,8 +35119,8 @@ "description": "", "line": 81, "modifierKind": [ - 121, - 124 + 123, + 126 ] } ], @@ -34640,7 +35137,7 @@ "rawdescription": "\nDynamically generates a style tag containing the correct animation for this diameter.", "description": "

Dynamically generates a style tag containing the correct animation for this diameter.

\n", "modifierKind": [ - 121 + 123 ] }, { @@ -34655,7 +35152,7 @@ "rawdescription": "\nGenerates animation styles adjusted for the spinner's diameter.", "description": "

Generates animation styles adjusted for the spinner's diameter.

\n", "modifierKind": [ - 121 + 123 ] } ], @@ -34663,6 +35160,8 @@ "deprecationMessage": "", "hostBindings": [], "hostListeners": [], + "standalone": false, + "imports": [], "description": "", "rawdescription": "\n", "type": "component", @@ -34716,7 +35215,9 @@ } ] }, - "extends": "_OuiProgressSpinnerMixinBase", + "extends": [ + "_OuiProgressSpinnerMixinBase" + ], "accessors": { "diameter": { "name": "diameter", @@ -34903,6 +35404,7 @@ "template": "", "templateUrl": [], "viewProviders": [], + "hostDirectives": [], "inputsClass": [ { "name": "disabled", @@ -34948,7 +35450,9 @@ } ], "modifierKind": [ - 123 + 170, + 170, + 125 ] }, { @@ -34961,7 +35465,7 @@ "description": "", "line": 56, "modifierKind": [ - 121 + 123 ] } ], @@ -34981,6 +35485,8 @@ "deprecationMessage": "", "hostBindings": [], "hostListeners": [], + "standalone": false, + "imports": [], "description": "

Component that shows a simplified checkbox without including any kind of "real" checkbox.\nMeant to be used when the checkbox is purely decorative and a large number of them will be\nincluded, such as for the options in a multi-select. Uses no SVGs or complex animations.\nNote that theming is meant to be handled by the parent element, e.g.\noui-primary .oui-pseudo-checkbox.

\n

Note that this component will be completely invisible to screen-reader users. This is not\ninterchangeable with <oui-checkbox> and should not be used if the user would directly\ninteract with the checkbox. The pseudo-checkbox should only be used as an implementation detail\nof more complex components that appropriately handle selected / checked state.

\n", "rawdescription": "\n\nComponent that shows a simplified checkbox without including any kind of \"real\" checkbox.\nMeant to be used when the checkbox is purely decorative and a large number of them will be\nincluded, such as for the options in a multi-select. Uses no SVGs or complex animations.\nNote that theming is meant to be handled by the parent element, e.g.\n`oui-primary .oui-pseudo-checkbox`.\n\nNote that this component will be completely invisible to screen-reader users. This is *not*\ninterchangeable with `` and should *not* be used if the user would directly\ninteract with the checkbox. The pseudo-checkbox should only be used as an implementation detail\nof more complex components that appropriately handle selected / checked state.\n\n", "type": "component", @@ -34988,7 +35494,7 @@ "assetsDirs": [], "styleUrlsData": [ { - "data": "@import '../../../checkbox/checkbox.scss';\n\n// The width/height of the checkbox element.\n$oui-checkbox-size: 16px !default;\n\n// The width of the checkbox border shown when the checkbox is unchecked.\n$oui-checkbox-border-width: 1px;\n\n// The base duration used for the majority of transitions for the checkbox.\n$oui-checkbox-transition-duration: 90ms;\n\n// Padding inside of a pseudo checkbox.\n$_oui-pseudo-checkbox-padding: $oui-checkbox-border-width * 2;\n\n// Size of the checkmark in a pseudo checkbox.\n$_oui-pseudo-checkmark-size: $oui-checkbox-size -\n (3.5 * $_oui-pseudo-checkbox-padding);\n\n.oui-pseudo-checkbox {\n width: $oui-checkbox-size;\n height: $oui-checkbox-size;\n border: 1px solid #9c9c9c;\n border-radius: 3px;\n cursor: pointer;\n display: block;\n box-sizing: border-box;\n position: relative;\n flex-shrink: 0;\n transition: border-color $oui-checkbox-transition-duration\n $oui-linear-out-slow-in-timing-function,\n background-color $oui-checkbox-transition-duration\n $oui-linear-out-slow-in-timing-function;\n\n // Used to render the checkmark/mixedmark inside of the box.\n &::after {\n content: '';\n display: block;\n position: absolute;\n box-sizing: border-box;\n transform: rotate(-45deg);\n border-bottom: 2px solid #333;\n border-left: 2px solid #333;\n top: 3.5px;\n left: 2px;\n width: 10px;\n height: 5px;\n transition: opacity 90ms $oui-linear-out-slow-in-timing-function;\n opacity: 0;\n }\n}\n\n.oui-pseudo-checkbox-disabled {\n cursor: default;\n}\n\n.oui-pseudo-checkbox-checked::after {\n opacity: 1;\n}\n", + "data": "@import '../../../checkbox/checkbox.scss';\r\n\r\n// The width/height of the checkbox element.\r\n$oui-checkbox-size: 16px !default;\r\n\r\n// The width of the checkbox border shown when the checkbox is unchecked.\r\n$oui-checkbox-border-width: 1px;\r\n\r\n// The base duration used for the majority of transitions for the checkbox.\r\n$oui-checkbox-transition-duration: 90ms;\r\n\r\n// Padding inside of a pseudo checkbox.\r\n$_oui-pseudo-checkbox-padding: $oui-checkbox-border-width * 2;\r\n\r\n// Size of the checkmark in a pseudo checkbox.\r\n$_oui-pseudo-checkmark-size: $oui-checkbox-size -\r\n (3.5 * $_oui-pseudo-checkbox-padding);\r\n\r\n.oui-pseudo-checkbox {\r\n width: $oui-checkbox-size;\r\n height: $oui-checkbox-size;\r\n border: $oui-checkbox-border-width solid #9c9c9c;\r\n border-radius: 3px;\r\n cursor: pointer;\r\n display: inline-block;\r\n vertical-align: middle;\r\n box-sizing: border-box;\r\n position: relative;\r\n flex-shrink: 0;\r\n transition: border-color $oui-checkbox-transition-duration\r\n $oui-linear-out-slow-in-timing-function,\r\n background-color $oui-checkbox-transition-duration\r\n $oui-linear-out-slow-in-timing-function;\r\n\r\n // Used to render the checkmark/mixedmark inside of the box.\r\n &::after {\r\n position: absolute;\r\n opacity: 0;\r\n content: '';\r\n border-bottom: $oui-checkbox-border-width * 2 solid #333;\r\n transition: opacity $oui-checkbox-transition-duration\r\n $oui-linear-out-slow-in-timing-function;\r\n }\r\n}\r\n\r\n.oui-pseudo-checkbox-disabled {\r\n cursor: default;\r\n}\r\n\r\n.oui-pseudo-checkbox-checked::after {\r\n top: ($oui-checkbox-size * 0.5) - ($_oui-pseudo-checkmark-size * 0.25) -\r\n ($oui-checkbox-size * 0.1) - $oui-checkbox-border-width;\r\n left: $_oui-pseudo-checkbox-padding - $oui-checkbox-border-width * 0.5;\r\n width: 10px;\r\n height: 6px;\r\n border-left: $oui-checkbox-border-width * 2 solid #333;\r\n transform: rotate(-45deg);\r\n opacity: 1;\r\n}\r\n", "styleUrl": "pseudo-checkbox.scss" } ], @@ -35066,6 +35572,7 @@ } ] }, + "extends": [], "implements": [ "OnDestroy" ] @@ -35093,6 +35600,7 @@ "radio.html" ], "viewProviders": [], + "hostDirectives": [], "inputsClass": [ { "name": "aria-describedby", @@ -35249,7 +35757,9 @@ } ], "modifierKind": [ - 123 + 170, + 170, + 125 ] }, { @@ -35263,7 +35773,7 @@ "line": 473, "rawdescription": "\nWhether this radio is checked.", "modifierKind": [ - 121 + 123 ] }, { @@ -35276,7 +35786,7 @@ "line": 476, "rawdescription": "\nWhether this radio is disabled.", "modifierKind": [ - 121 + 123 ] }, { @@ -35293,6 +35803,9 @@ "name": "ViewChild", "stringifiedArguments": "'input'" } + ], + "modifierKind": [ + 170 ] }, { @@ -35304,7 +35817,7 @@ "description": "", "line": 426, "modifierKind": [ - 121 + 123 ] }, { @@ -35317,7 +35830,7 @@ "description": "", "line": 339, "modifierKind": [ - 121 + 123 ] }, { @@ -35331,7 +35844,7 @@ "line": 485, "rawdescription": "\nUnregister function for _radioDispatcher", "modifierKind": [ - 121 + 123 ] }, { @@ -35344,7 +35857,7 @@ "line": 479, "rawdescription": "\nWhether this radio is required.", "modifierKind": [ - 121 + 123 ] }, { @@ -35357,7 +35870,7 @@ "description": "", "line": 338, "modifierKind": [ - 121 + 123 ] }, { @@ -35371,7 +35884,7 @@ "line": 482, "rawdescription": "\nValue assigned to this radio.", "modifierKind": [ - 121 + 123 ] }, { @@ -35398,7 +35911,7 @@ "rawdescription": "\nDispatch change event with current value.", "description": "

Dispatch change event with current value.

\n", "modifierKind": [ - 121 + 123 ] }, { @@ -35528,6 +36041,8 @@ "deprecationMessage": "", "hostBindings": [], "hostListeners": [], + "standalone": false, + "imports": [], "description": "", "rawdescription": "\n", "type": "component", @@ -35643,7 +36158,9 @@ } ] }, - "extends": "OuiRadioButtonMixinBase", + "extends": [ + "OuiRadioButtonMixinBase" + ], "implements": [ "OnInit", "AfterViewInit", @@ -35875,6 +36392,7 @@ "template": "", "templateUrl": [], "viewProviders": [], + "hostDirectives": [], "inputsClass": [ { "name": "disabled", @@ -35972,7 +36490,7 @@ "line": 101, "rawdescription": "\nWhether the radio group is disabled.", "modifierKind": [ - 121 + 123 ] }, { @@ -35986,7 +36504,7 @@ "line": 95, "rawdescription": "\nWhether the `value` has been set to its initial value.", "modifierKind": [ - 121 + 123 ] }, { @@ -36000,7 +36518,7 @@ "line": 98, "rawdescription": "\nWhether the labels should appear after or before the radio-buttons. Defaults to 'after'", "modifierKind": [ - 121 + 123 ] }, { @@ -36014,7 +36532,7 @@ "line": 89, "rawdescription": "\nThe HTML name attribute applied to radio buttons in this group.", "modifierKind": [ - 121 + 123 ] }, { @@ -36031,6 +36549,9 @@ "name": "ContentChildren", "stringifiedArguments": "undefined, {descendants: true}" } + ], + "modifierKind": [ + 170 ] }, { @@ -36044,7 +36565,7 @@ "line": 104, "rawdescription": "\nWhether the radio group is required.", "modifierKind": [ - 121 + 123 ] }, { @@ -36058,7 +36579,7 @@ "line": 92, "rawdescription": "\nThe currently selected radio button. Should match value.", "modifierKind": [ - 121 + 123 ] }, { @@ -36072,7 +36593,7 @@ "line": 86, "rawdescription": "\nSelected value for the radio group.", "modifierKind": [ - 121 + 123 ] }, { @@ -36089,17 +36610,17 @@ { "pos": 3428, "end": 3445, - "flags": 4227072, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 325, + "kind": 334, "tagName": { "pos": 3429, "end": 3441, - "flags": 4227072, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "docs-private" }, "comment": "" @@ -36162,7 +36683,7 @@ "deprecated": false, "deprecationMessage": "", "modifierKind": [ - 121 + 123 ] }, { @@ -36177,7 +36698,7 @@ "rawdescription": "\nUpdates the `selected` radio button from the internal _value state.", "description": "

Updates the selected radio button from the internal _value state.

\n", "modifierKind": [ - 121 + 123 ] }, { @@ -36223,10 +36744,10 @@ "name": { "pos": 7819, "end": 7821, - "flags": 4227072, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "fn" }, "type": "function", @@ -36243,10 +36764,10 @@ "tagName": { "pos": 7813, "end": 7818, - "flags": 4227072, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "param" }, "comment": "

Callback to be registered.

\n" @@ -36276,10 +36797,10 @@ "name": { "pos": 8096, "end": 8098, - "flags": 4227072, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "fn" }, "type": "any", @@ -36288,10 +36809,10 @@ "tagName": { "pos": 8090, "end": 8095, - "flags": 4227072, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "param" }, "comment": "

Callback to be registered.

\n" @@ -36321,10 +36842,10 @@ "name": { "pos": 8308, "end": 8318, - "flags": 4227072, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "isDisabled" }, "type": "boolean", @@ -36333,10 +36854,10 @@ "tagName": { "pos": 8302, "end": 8307, - "flags": 4227072, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "param" }, "comment": "

Whether the control should be disabled.

\n" @@ -36366,10 +36887,10 @@ "name": { "pos": 7565, "end": 7570, - "flags": 4227072, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "value" }, "type": "any", @@ -36378,10 +36899,10 @@ "tagName": { "pos": 7559, "end": 7564, - "flags": 4227072, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "param" }, "comment": "" @@ -36393,6 +36914,8 @@ "deprecationMessage": "", "hostBindings": [], "hostListeners": [], + "standalone": false, + "imports": [], "description": "

A group of radio buttons. May contain one or more <oui-radio-button> elements.

\n", "rawdescription": "\n\nA group of radio buttons. May contain one or more `` elements.\n", "type": "component", @@ -36426,6 +36949,7 @@ } ] }, + "extends": [], "implements": [ "AfterContentInit", "ControlValueAccessor" @@ -36685,6 +37209,7 @@ "template": "CDK_ROW_TEMPLATE", "templateUrl": [], "viewProviders": [], + "hostDirectives": [], "inputsClass": [], "outputsClass": [], "propertiesClass": [ @@ -36698,7 +37223,7 @@ "description": "", "line": 108, "modifierKind": [ - 121 + 123 ] } ], @@ -36718,6 +37243,8 @@ "deprecationMessage": "", "hostBindings": [], "hostListeners": [], + "standalone": false, + "imports": [], "description": "

Data row template container that contains the cell outlet. Adds the right class and role.

\n", "rawdescription": "\nData row template container that contains the cell outlet. Adds the right class and role.", "type": "component", @@ -36796,7 +37323,9 @@ } ] }, - "extends": "CdkRow", + "extends": [ + "CdkRow" + ], "implements": [ "OnDestroy" ] @@ -36823,6 +37352,7 @@ "template": "", "templateUrl": [], "viewProviders": [], + "hostDirectives": [], "inputsClass": [ { "name": "oui-scrollbar-large", @@ -36847,7 +37377,7 @@ "description": "", "line": 24, "modifierKind": [ - 121 + 123 ] } ], @@ -36856,6 +37386,8 @@ "deprecationMessage": "", "hostBindings": [], "hostListeners": [], + "standalone": false, + "imports": [], "description": "", "rawdescription": "\n", "type": "component", @@ -36863,7 +37395,7 @@ "assetsDirs": [], "styleUrlsData": [ { - "data": ".oui-scrollbar-container::-webkit-scrollbar {\n width: 10px;\n}\n.oui-scrollbar-container::-webkit-scrollbar-track {\n display: none;\n}\n.oui-scrollbar-container::-webkit-scrollbar-thumb {\n background-color: #ccc !important;\n border: 2px #fff solid;\n border-radius: 15px;\n}\n.oui-scrollbar-container-large::-webkit-scrollbar {\n width: 16px;\n}\n.oui-scrollbar-container-large::-webkit-scrollbar-thumb {\n border: 4px #fff solid !important;\n}\n\n.oui-scrollbar-container {\n overflow-y: auto;\n scrollbar-color: #ccc transparent;\n scrollbar-width: thin;\n}\n", + "data": ".oui-scrollbar-container::-webkit-scrollbar {\r\n width: 10px;\r\n}\r\n.oui-scrollbar-container::-webkit-scrollbar-track {\r\n display: none;\r\n}\r\n.oui-scrollbar-container::-webkit-scrollbar-thumb {\r\n background-color: #ccc !important;\r\n border: 2px #fff solid;\r\n border-radius: 15px;\r\n}\r\n.oui-scrollbar-container-large::-webkit-scrollbar {\r\n width: 16px;\r\n}\r\n.oui-scrollbar-container-large::-webkit-scrollbar-thumb {\r\n border: 4px #fff solid !important;\r\n}\r\n\r\n.oui-scrollbar-container {\r\n overflow-y: auto;\r\n scrollbar-color: #ccc transparent;\r\n scrollbar-width: thin;\r\n}\r\n", "styleUrl": "scrollbar.scss" } ], @@ -36876,6 +37408,7 @@ "args": [], "line": 33 }, + "extends": [], "accessors": { "large": { "name": "large", @@ -36932,6 +37465,7 @@ "template": "\n
    \n
  • {{ item }}
  • \n
\n\n", "templateUrl": [], "viewProviders": [], + "hostDirectives": [], "inputsClass": [ { "name": "height", @@ -36979,6 +37513,8 @@ "deprecationMessage": "", "hostBindings": [], "hostListeners": [], + "standalone": false, + "imports": [], "description": "", "rawdescription": "\n", "type": "component", @@ -36993,7 +37529,8 @@ "deprecationMessage": "", "args": [], "line": 43 - } + }, + "extends": [] }, { "name": "OuiScrollbarTextStorybook", @@ -37010,6 +37547,7 @@ "template": "\n {{ text }}\n\n", "templateUrl": [], "viewProviders": [], + "hostDirectives": [], "inputsClass": [ { "name": "height", @@ -37057,6 +37595,8 @@ "deprecationMessage": "", "hostBindings": [], "hostListeners": [], + "standalone": false, + "imports": [], "description": "", "rawdescription": "\n", "type": "component", @@ -37071,11 +37611,12 @@ "deprecationMessage": "", "args": [], "line": 20 - } + }, + "extends": [] }, { "name": "OuiSelect", - "id": "component-OuiSelect-d85db46eab36d315c1fdcd891bdac570b57a0ccdc711e79255f204f23073d94dc6b0707254460df0585b83b8338fb5a5a8a9bcb9d49bc6bf529c53c663cbdac2", + "id": "component-OuiSelect-69627b742fec8101b0c412f353bb903b4d499f0f8291080ef1d6ac0c418484f2235fec3981e84104b948fe2f242b0a29fea2c39687b9ed9b01e6aa4fcda7ba37", "file": "ui/src/components/select/select.component.ts", "changeDetection": "ChangeDetectionStrategy.OnPush", "encapsulation": [ @@ -37107,6 +37648,7 @@ "select.html" ], "viewProviders": [], + "hostDirectives": [], "inputsClass": [ { "name": "actionItems", @@ -37264,7 +37806,7 @@ "outputsClass": [ { "name": "closed", - "defaultValue": "this.openedChange.pipe(\n filter((o) => !o),\n map(() => {\n this.isSearchFieldPresent = false;\n })\n )", + "defaultValue": "this.openedChange.pipe(\r\n filter((o) => !o),\r\n map(() => {\r\n this.isSearchFieldPresent = false;\r\n })\r\n )", "deprecated": false, "deprecationMessage": "", "rawdescription": "\nEvent emitted when the select has been closed.", @@ -37274,7 +37816,7 @@ }, { "name": "opened", - "defaultValue": "this.openedChange.pipe(\n filter((o) => o),\n map(() => {})\n )", + "defaultValue": "this.openedChange.pipe(\r\n filter((o) => o),\r\n map(() => {})\r\n )", "deprecated": false, "deprecationMessage": "", "rawdescription": "\nEvent emitted when the select has been opened.", @@ -37321,19 +37863,19 @@ "description": "

Event that emits whenever the raw value of the select changes. This is here primarily\nto facilitate the two-way binding for the value input.

\n", "jsdoctags": [ { - "pos": 11160, - "end": 11177, - "flags": 4227072, + "pos": 11538, + "end": 11556, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 325, + "kind": 334, "tagName": { - "pos": 11161, - "end": 11173, - "flags": 4227072, + "pos": 11539, + "end": 11551, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "docs-private" }, "comment": "" @@ -37355,7 +37897,7 @@ "line": 231, "rawdescription": "\nWhether filling out the select is required in the form.", "modifierKind": [ - 121 + 123 ] }, { @@ -37379,7 +37921,7 @@ "line": 436, "rawdescription": "\nComparison function to specify which option is displayed. Defaults to object equality.", "modifierKind": [ - 121 + 123 ] }, { @@ -37393,8 +37935,8 @@ "line": 303, "rawdescription": "\nEmits whenever the component is destroyed.", "modifierKind": [ - 121, - 144 + 123, + 148 ] }, { @@ -37408,7 +37950,7 @@ "line": 306, "rawdescription": "\nWhether the component is disabling centering of the active option over the trigger.", "modifierKind": [ - 121 + 123 ] }, { @@ -37420,7 +37962,7 @@ "description": "", "line": 563, "modifierKind": [ - 123 + 125 ] }, { @@ -37433,7 +37975,7 @@ "description": "", "line": 308, "modifierKind": [ - 121 + 123 ] }, { @@ -37445,7 +37987,7 @@ "description": "", "line": 355, "modifierKind": [ - 121 + 123 ] }, { @@ -37468,7 +38010,7 @@ "description": "", "line": 342, "modifierKind": [ - 121 + 123 ] }, { @@ -37491,7 +38033,7 @@ "line": 240, "rawdescription": "\nWhether the component is in multiple selection mode.", "modifierKind": [ - 121 + 123 ] }, { @@ -37547,7 +38089,7 @@ "description": "", "line": 564, "modifierKind": [ - 123 + 125 ] }, { @@ -37572,7 +38114,7 @@ "line": 225, "rawdescription": "\nWhether or not the overlay panel is open.", "modifierKind": [ - 121 + 123 ] }, { @@ -37585,12 +38127,12 @@ "line": 237, "rawdescription": "\nThe placeholder displayed in the trigger of the select.", "modifierKind": [ - 121 + 123 ] }, { "name": "_positions", - "defaultValue": "[\n {\n originX: 'start',\n originY: 'top',\n overlayX: 'start',\n overlayY: 'top',\n },\n {\n originX: 'start',\n originY: 'bottom',\n overlayX: 'start',\n overlayY: 'bottom',\n },\n ]", + "defaultValue": "[\r\n {\r\n originX: 'start',\r\n originY: 'top',\r\n overlayX: 'start',\r\n overlayY: 'top',\r\n },\r\n {\r\n originX: 'start',\r\n originY: 'bottom',\r\n overlayX: 'start',\r\n overlayY: 'bottom',\r\n },\r\n ]", "deprecated": false, "deprecationMessage": "", "type": "[]", @@ -37610,7 +38152,7 @@ "line": 228, "rawdescription": "\nWhether filling out the select is required in the form.", "modifierKind": [ - 121 + 123 ] }, { @@ -37624,7 +38166,7 @@ "line": 234, "rawdescription": "\nThe scroll position of the overlay panel, calculated to center the selected option.", "modifierKind": [ - 121 + 123 ] }, { @@ -37680,7 +38222,7 @@ "line": 246, "rawdescription": "\nUnique id for this input.", "modifierKind": [ - 121 + 123 ] }, { @@ -37692,7 +38234,7 @@ "description": "", "line": 325, "modifierKind": [ - 121 + 123 ] }, { @@ -37731,6 +38273,9 @@ "name": "ContentChild", "stringifiedArguments": "OuiSelectTrigger" } + ], + "modifierKind": [ + 170 ] }, { @@ -37747,6 +38292,9 @@ "name": "ViewChild", "stringifiedArguments": "'ddCancelButton', {read: ElementRef}" } + ], + "modifierKind": [ + 170 ] }, { @@ -37763,6 +38311,9 @@ "name": "ViewChild", "stringifiedArguments": "'ddDoneButton', {read: ElementRef}" } + ], + "modifierKind": [ + 170 ] }, { @@ -37805,7 +38356,9 @@ } ], "modifierKind": [ - 123 + 170, + 170, + 125 ] }, { @@ -37822,6 +38375,9 @@ "name": "ContentChildren", "stringifiedArguments": "OuiOptgroup" } + ], + "modifierKind": [ + 170 ] }, { @@ -37838,11 +38394,14 @@ "name": "ContentChildren", "stringifiedArguments": "OuiOption, {descendants: true}" } + ], + "modifierKind": [ + 170 ] }, { "name": "optionSelectionChanges", - "defaultValue": "defer(\n (): Observable => {\n if (this.options) {\n return merge(...this.options.map((option) => option.onSelectionChange));\n }\n\n return this._ngZone.onStable.asObservable().pipe(\n take(1),\n switchMap(() => this.optionSelectionChanges)\n );\n }\n )", + "defaultValue": "defer(\r\n (): Observable => {\r\n if (this.options) {\r\n return merge(...this.options.map((option) => option.onSelectionChange));\r\n }\r\n\r\n return this._ngZone.onStable.asObservable().pipe(\r\n take(1),\r\n switchMap(() => this.optionSelectionChanges)\r\n );\r\n }\r\n )", "deprecated": false, "deprecationMessage": "", "type": "Observable", @@ -37851,7 +38410,7 @@ "line": 362, "rawdescription": "\nCombined stream of all of the child options' change events.", "modifierKind": [ - 144 + 148 ] }, { @@ -37878,6 +38437,9 @@ "name": "ViewChild", "stringifiedArguments": "CdkConnectedOverlay" } + ], + "modifierKind": [ + 170 ] }, { @@ -37894,6 +38456,9 @@ "name": "ViewChild", "stringifiedArguments": "'panel', {read: ElementRef}" } + ], + "modifierKind": [ + 170 ] }, { @@ -37910,6 +38475,9 @@ "name": "ViewChild", "stringifiedArguments": "'trigger'" } + ], + "modifierKind": [ + 170 ] } ], @@ -37968,7 +38536,7 @@ "optional": false, "returnType": "number", "typeParameters": [], - "line": 1433, + "line": 1429, "deprecated": false, "deprecationMessage": "", "rawdescription": "\nReturns the panel's scrollTop.", @@ -37993,7 +38561,7 @@ "rawdescription": "\nHandles keyboard events while the select is closed.", "description": "

Handles keyboard events while the select is closed.

\n", "modifierKind": [ - 121 + 123 ], "jsdoctags": [ { @@ -38056,7 +38624,7 @@ "rawdescription": "\nHandles keyboard events when the selected is open.", "description": "

Handles keyboard events when the selected is open.

\n", "modifierKind": [ - 121 + 123 ], "jsdoctags": [ { @@ -38082,7 +38650,7 @@ "rawdescription": "\n\nHighlights the selected item. If no option is selected, it will highlight\nthe first item instead.\n", "description": "

Highlights the selected item. If no option is selected, it will highlight\nthe first item instead.

\n", "modifierKind": [ - 121 + 123 ] }, { @@ -38097,7 +38665,7 @@ "rawdescription": "\n\nHighlights the first of the filtered options if no element is currently highlighted\n", "description": "

Highlights the first of the filtered options if no element is currently highlighted

\n", "modifierKind": [ - 121 + 123 ] }, { @@ -38110,7 +38678,7 @@ "deprecated": false, "deprecationMessage": "", "modifierKind": [ - 121 + 123 ] }, { @@ -38125,7 +38693,7 @@ "rawdescription": "\nSets up a key manager to listen to keyboard events on the overlay panel.", "description": "

Sets up a key manager to listen to keyboard events on the overlay panel.

\n", "modifierKind": [ - 121 + 123 ] }, { @@ -38199,7 +38767,7 @@ "rawdescription": "\nInvoked when an option is clicked.", "description": "

Invoked when an option is clicked.

\n", "modifierKind": [ - 121 + 123 ], "jsdoctags": [ { @@ -38242,7 +38810,7 @@ "rawdescription": "\nEmits change event to set the model value.", "description": "

Emits change event to set the model value.

\n", "modifierKind": [ - 121 + 123 ], "jsdoctags": [ { @@ -38269,7 +38837,7 @@ "rawdescription": "\nDrops current option subscriptions and IDs and resets from scratch.", "description": "

Drops current option subscriptions and IDs and resets from scratch.

\n", "modifierKind": [ - 121 + 123 ] }, { @@ -38278,13 +38846,13 @@ "optional": false, "returnType": "void", "typeParameters": [], - "line": 1397, + "line": 1400, "deprecated": false, "deprecationMessage": "", "rawdescription": "\n\nGiven that we are not actually focusing active options, we must manually adjust scroll\nto reveal options below the fold. First, we find the offset of the option from the top\nof the panel. If that offset is below the fold, the new scrollTop will be the offset -\nthe panel height + the option height, so the active option will be just visible at the\nbottom of the panel. If that offset is above the top of the visible panel, the new scrollTop\nwill become the offset. If that offset is visible within the panel already, the scrollTop is\nnot adjusted.\n", "description": "

Given that we are not actually focusing active options, we must manually adjust scroll\nto reveal options below the fold. First, we find the offset of the option from the top\nof the panel. If that offset is below the fold, the new scrollTop will be the offset -\nthe panel height + the option height, so the active option will be just visible at the\nbottom of the panel. If that offset is above the top of the visible panel, the new scrollTop\nwill become the offset. If that offset is visible within the panel already, the scrollTop is\nnot adjusted.

\n", "modifierKind": [ - 121 + 123 ] }, { @@ -38306,7 +38874,7 @@ "rawdescription": "\n\nFinds and selects and option based on its value.\n\n", "description": "

Finds and selects and option based on its value.

\n", "modifierKind": [ - 121 + 123 ], "jsdoctags": [ { @@ -38320,12 +38888,12 @@ }, { "tagName": { - "pos": 32477, - "end": 32484, - "flags": 4227072, + "pos": 33560, + "end": 33567, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "returns" }, "comment": "

Option that has the corresponding value.

\n" @@ -38344,7 +38912,7 @@ "rawdescription": "\nRecords option IDs to pass to the aria-owns property.", "description": "

Records option IDs to pass to the aria-owns property.

\n", "modifierKind": [ - 121 + 123 ] }, { @@ -38359,7 +38927,7 @@ "rawdescription": "\nSets the pseudo checkbox padding size based on the width of the pseudo checkbox.", "description": "

Sets the pseudo checkbox padding size based on the width of the pseudo checkbox.

\n", "modifierKind": [ - 121 + 123 ] }, { @@ -38375,7 +38943,7 @@ "optional": false, "returnType": "void", "typeParameters": [], - "line": 1425, + "line": 1422, "deprecated": false, "deprecationMessage": "", "rawdescription": "\n\nSets the panel scrollTop. This allows us to manually scroll to display options\nabove or below the fold, as they are not actually being focused when active.\n", @@ -38411,7 +38979,7 @@ "rawdescription": "\n\nSets the selected option based on a value. If no option can be\nfound with the designated value, the select trigger is cleared.\n", "description": "

Sets the selected option based on a value. If no option can be\nfound with the designated value, the select trigger is cleared.

\n", "modifierKind": [ - 121 + 123 ], "jsdoctags": [ { @@ -38437,7 +39005,7 @@ "rawdescription": "\nSorts the selected values in the selected based on their order in the panel.", "description": "

Sorts the selected values in the selected based on their order in the panel.

\n", "modifierKind": [ - 121 + 123 ] }, { @@ -38496,7 +39064,7 @@ "rawdescription": "\n\nHandle ctrl key\n", "description": "

Handle ctrl key

\n", "modifierKind": [ - 121 + 123 ] }, { @@ -38536,101 +39104,101 @@ "rawdescription": "\n\n", "description": "", "modifierKind": [ - 121 + 123 ], "jsdoctags": [ { "name": { - "pos": 28391, - "end": 28398, - "flags": 4227072, + "pos": 29336, + "end": 29343, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "manager" }, "type": "ActiveDescendantKeyManager", "deprecated": false, "deprecationMessage": "", "tagName": { - "pos": 28385, - "end": 28390, - "flags": 4227072, + "pos": 29330, + "end": 29335, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "param" }, "comment": "" }, { "name": { - "pos": 28411, - "end": 28416, - "flags": 4227072, + "pos": 29357, + "end": 29362, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "event" }, "type": "KeyboardEvent", "deprecated": false, "deprecationMessage": "", "tagName": { - "pos": 28405, - "end": 28410, - "flags": 4227072, + "pos": 29351, + "end": 29356, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "param" }, "comment": "" }, { "name": { - "pos": 28429, - "end": 28439, - "flags": 4227072, + "pos": 29376, + "end": 29386, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "isArrowKey" }, "type": "boolean", "deprecated": false, "deprecationMessage": "", "tagName": { - "pos": 28423, - "end": 28428, - "flags": 4227072, + "pos": 29370, + "end": 29375, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "param" }, "comment": "" }, { "name": { - "pos": 28452, - "end": 28459, - "flags": 4227072, + "pos": 29400, + "end": 29407, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "keyCode" }, "type": "number", "deprecated": false, "deprecationMessage": "", "tagName": { - "pos": 28446, - "end": 28451, - "flags": 4227072, + "pos": 29394, + "end": 29399, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "param" }, "comment": "" @@ -38828,12 +39396,12 @@ "jsdoctags": [ { "name": { - "pos": 21160, - "end": 21162, - "flags": 4227072, + "pos": 21875, + "end": 21877, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "fn" }, "type": "function", @@ -38848,12 +39416,12 @@ } ], "tagName": { - "pos": 21154, - "end": 21159, - "flags": 4227072, + "pos": 21869, + "end": 21874, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "param" }, "comment": "

Callback to be triggered when the value changes.

\n" @@ -38882,12 +39450,12 @@ "jsdoctags": [ { "name": { - "pos": 21515, - "end": 21517, - "flags": 4227072, + "pos": 22241, + "end": 22243, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "fn" }, "type": "function", @@ -38895,12 +39463,12 @@ "deprecationMessage": "", "function": [], "tagName": { - "pos": 21509, - "end": 21514, - "flags": 4227072, + "pos": 22235, + "end": 22240, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "param" }, "comment": "

Callback to be triggered when the component has been touched.

\n" @@ -38920,7 +39488,7 @@ "optional": false, "returnType": "void", "typeParameters": [], - "line": 1373, + "line": 1376, "deprecated": false, "deprecationMessage": "", "jsdoctags": [ @@ -38998,24 +39566,24 @@ "jsdoctags": [ { "name": { - "pos": 21809, - "end": 21819, - "flags": 4227072, + "pos": 22545, + "end": 22555, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "isDisabled" }, "type": "boolean", "deprecated": false, "deprecationMessage": "", "tagName": { - "pos": 21803, - "end": 21808, - "flags": 4227072, + "pos": 22539, + "end": 22544, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "param" }, "comment": "

Sets whether the component is disabled.

\n" @@ -39077,7 +39645,7 @@ "rawdescription": "\nOn Tab key press select the buttons at the bottom if actionItems is enabled and searchbar", "description": "

On Tab key press select the buttons at the bottom if actionItems is enabled and searchbar

\n", "modifierKind": [ - 121 + 123 ], "jsdoctags": [ { @@ -39133,24 +39701,24 @@ "jsdoctags": [ { "name": { - "pos": 20779, - "end": 20784, - "flags": 4227072, + "pos": 21481, + "end": 21486, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "value" }, "type": "any", "deprecated": false, "deprecationMessage": "", "tagName": { - "pos": 20773, - "end": 20778, - "flags": 4227072, + "pos": 21475, + "end": 21480, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "param" }, "comment": "

New value to be written to the model.

\n" @@ -39162,14 +39730,16 @@ "deprecationMessage": "", "hostBindings": [], "hostListeners": [], + "standalone": false, + "imports": [], "description": "", "rawdescription": "\n", "type": "component", - "sourceCode": "import { ActiveDescendantKeyManager, FocusMonitor } from '@angular/cdk/a11y';\nimport { Directionality } from '@angular/cdk/bidi';\nimport { coerceBooleanProperty } from '@angular/cdk/coercion';\nimport { SelectionModel } from '@angular/cdk/collections';\nimport {\n A,\n DOWN_ARROW,\n END,\n ENTER,\n HOME,\n LEFT_ARROW,\n RIGHT_ARROW,\n SPACE,\n UP_ARROW,\n hasModifierKey,\n TAB,\n} from '@angular/cdk/keycodes';\nimport { CdkConnectedOverlay } from '@angular/cdk/overlay';\nimport {\n AfterContentInit,\n Attribute,\n ChangeDetectionStrategy,\n ChangeDetectorRef,\n Component,\n ContentChild,\n ContentChildren,\n Directive,\n DoCheck,\n ElementRef,\n EventEmitter,\n Input,\n isDevMode,\n NgZone,\n OnChanges,\n OnDestroy,\n OnInit,\n Optional,\n Output,\n QueryList,\n Self,\n SimpleChanges,\n ViewChild,\n ViewEncapsulation,\n Inject,\n} from '@angular/core';\nimport {\n ControlValueAccessor,\n FormGroupDirective,\n NgControl,\n NgForm,\n} from '@angular/forms';\nimport {\n _countGroupLabelsBeforeOption,\n _getOptionScrollPosition,\n CanDisable,\n CanDisableCtor,\n CanUpdateErrorState,\n CanUpdateErrorStateCtor,\n HasTabIndex,\n HasTabIndexCtor,\n OuiOptionSelectionChange,\n mixinErrorState,\n mixinTabIndex,\n mixinDisabled,\n} from '../core';\nimport { OuiFormField, OuiFormFieldControl } from '../form-field/public-api';\nimport { DOCUMENT } from '@angular/common';\nimport { OUI_OPTION_PARENT_COMPONENT, OuiOption } from '../core/option/option';\nimport { OuiOptgroup } from '../core/option/optgroup';\nimport { ErrorStateMatcher } from '../core/error/error-options';\nimport { defer, merge, Observable, Subject } from 'rxjs';\nimport {\n distinctUntilChanged,\n filter,\n map,\n startWith,\n switchMap,\n take,\n takeUntil,\n} from 'rxjs/operators';\nimport {\n getOuiSelectDynamicMultipleError,\n getOuiSelectNonArrayValueError,\n getOuiSelectNonFunctionValueError,\n} from './select-errors';\nimport { OuiIconRegistry } from '../icon/icon-registery';\nimport { DomSanitizer } from '@angular/platform-browser';\nimport { ICONS } from '../core/shared/icons';\n\nlet nextUniqueId = 0;\n\n/**\n * The following style constants are necessary to save here in order\n * to properly calculate the alignment of the selected option over\n * the trigger element.\n */\n\n/** The height of each select option. */\nexport const SELECT_OPTION_HEIGHT = 40;\n\n/** The panel's padding on the x-axis */\nexport const SELECT_PANEL_PADDING_X = 16;\n\n/** The panel's x axis padding if it is indented (e.g. there is an option group). */\nexport const SELECT_PANEL_INDENT_PADDING_X = SELECT_PANEL_PADDING_X * 2;\n\n/** The height of the select items in `em` units. */\nexport const SELECT_ITEM_HEIGHT_EM = 3;\n\n/** The total height of the select panel. */\nexport const SELECT_PANEL_HEIGHT = 200;\n\n// TODO(josephperrott): Revert to a constant after 2018 spec updates are fully merged.\n/**\n * Distance between the panel edge and the option text in\n * multi-selection mode.\n *\n * Calculated as:\n * (SELECT_PANEL_PADDING_X * 1.5) + 20 = 44\n * The padding is multiplied by 1.5 because the checkbox's margin is half the padding.\n * The checkbox width is 16px.\n */\nexport let SELECT_MULTIPLE_PANEL_PADDING_X = 0;\n\n/**\n * The select panel will only \"fit\" inside the viewport if it is positioned at\n * this value or more away from the viewport boundary.\n */\nexport const SELECT_PANEL_VIEWPORT_PADDING = 8;\n\n/** Change event object that is emitted when the select value has changed. */\nexport class OuiSelectChange {\n constructor(\n /** Reference to the select that emitted the change event. */\n public source: OuiSelect,\n /** Current value of the select that emitted the event. */\n public value: any\n ) {}\n}\n\n// Boilerplate for applying mixins to OuiSelect.\n/** @docs-private */\nexport class OuiSelectBase {\n constructor(\n public _elementRef: ElementRef,\n public _defaultErrorStateMatcher: ErrorStateMatcher,\n public _parentForm: NgForm,\n public _parentFormGroup: FormGroupDirective,\n public ngControl: NgControl\n ) {}\n}\n\nexport const _OuiSelectMixinBase: CanDisableCtor &\n HasTabIndexCtor &\n CanUpdateErrorStateCtor &\n typeof OuiSelectBase = mixinTabIndex(\n mixinDisabled(mixinErrorState(OuiSelectBase))\n);\n\n/**\n * Allows the user to customize the trigger that is displayed when the select has a value.\n */\n@Directive({\n // eslint-disable-next-line @angular-eslint/directive-selector\n selector: 'oui-select-trigger',\n})\nexport class OuiSelectTrigger {}\n\n@Component({\n selector: 'oui-select',\n exportAs: 'ouiSelect',\n templateUrl: 'select.html',\n styleUrls: ['select.scss'],\n // eslint-disable-next-line @angular-eslint/no-inputs-metadata-property\n inputs: ['disabled', 'tabIndex'],\n encapsulation: ViewEncapsulation.None,\n changeDetection: ChangeDetectionStrategy.OnPush,\n // eslint-disable-next-line @angular-eslint/no-host-metadata-property\n host: {\n role: 'listbox',\n '[attr.id]': 'id',\n '[attr.tabindex]': 'tabIndex',\n '[attr.aria-label]': '_getAriaLabel()',\n '[attr.aria-labelledby]': '_getAriaLabelledby()',\n '[attr.aria-required]': 'required.toString()',\n '[attr.aria-disabled]': 'disabled.toString()',\n '[attr.aria-invalid]': 'errorState',\n '[attr.aria-owns]': 'panelOpen ? _optionIds : null',\n '[attr.aria-multiselectable]': 'multiple',\n '[attr.aria-describedby]': '_ariaDescribedby || null',\n '[attr.aria-activedescendant]': '_getAriaActiveDescendant()',\n '[class.oui-select-disabled]': 'disabled',\n '[class.oui-select-invalid]': 'errorState',\n '[class.oui-select-required]': 'required',\n '[class.oui-select-empty]': 'empty',\n class: 'oui-select oui-input',\n '(keydown)': '_handleKeydown($event)',\n '(focus)': '_onFocus()',\n '(blur)': '_onBlur()',\n },\n providers: [\n { provide: OuiFormFieldControl, useExisting: OuiSelect },\n { provide: OUI_OPTION_PARENT_COMPONENT, useExisting: OuiSelect },\n ],\n})\nexport class OuiSelect\n extends _OuiSelectMixinBase\n implements\n AfterContentInit,\n OnChanges,\n OnDestroy,\n OnInit,\n DoCheck,\n ControlValueAccessor,\n CanDisable,\n HasTabIndex,\n OuiFormFieldControl,\n CanUpdateErrorState\n{\n /**Holds selected values after done */\n @Input() savedValues = [];\n /**Done button disabled until dropdown is dirty */\n disableDoneButton = true;\n /** Whether or not the overlay panel is open. */\n private _panelOpen = false;\n\n /** Whether filling out the select is required in the form. */\n private _required = false;\n\n /** Whether filling out the select is required in the form. */\n private _actionItems = false;\n\n /** The scroll position of the overlay panel, calculated to center the selected option. */\n private _scrollTop = 0;\n\n /** The placeholder displayed in the trigger of the select. */\n private _placeholder: string;\n\n /** Whether the component is in multiple selection mode. */\n private _multiple = false;\n\n /** Search input field **/\n isSearchFieldPresent: boolean;\n\n /** Unique id for this input. */\n private _uid = `oui-select-${nextUniqueId++}`;\n\n /** The last measured value for the trigger's client bounding rect. */\n _triggerRect: ClientRect;\n\n /** The aria-describedby attribute on the select for improved a11y. */\n _ariaDescribedby: string;\n\n /** The cached font-size of the trigger element. */\n _triggerFontSize = 0;\n\n /** Deals with the selection logic. */\n _selectionModel: SelectionModel;\n\n /** Manages keyboard events for options in the panel. */\n _keyManager: ActiveDescendantKeyManager;\n\n /** The IDs of child options to be passed to the aria-owns attribute. */\n _optionIds = '';\n\n /** The value of the select panel's transform-origin property. */\n _transformOrigin = 'top';\n\n /** If there is search input field a class is added dynamically to the perfect scrollbar **/\n ouiSelectInputOuterClassName: string;\n\n /** Adding top class to overlay panel */\n cdkConnectionOverlayPanel = '';\n\n /**\n * The y-offset of the overlay panel in relation to the trigger's top start corner.\n * This must be adjusted to align the selected option text over the trigger text.\n * when the panel opens. Will change based on the y-position of the selected option.\n */\n _offsetY = 0;\n\n /**\n * This position config ensures that the top \"start\" corner of the overlay\n * is aligned with with the top \"start\" of the origin by default (overlapping\n * the trigger completely). If the panel cannot fit below the trigger, it\n * will fall back to a position above the trigger.\n */\n _positions = [\n {\n originX: 'start',\n originY: 'top',\n overlayX: 'start',\n overlayY: 'top',\n },\n {\n originX: 'start',\n originY: 'bottom',\n overlayX: 'start',\n overlayY: 'bottom',\n },\n ];\n /** Emits whenever the component is destroyed. */\n private readonly _destroy = new Subject();\n\n /** Whether the component is disabling centering of the active option over the trigger. */\n private _disableOptionCentering = false;\n\n private _focused = false;\n\n /** A name for this control that can be used by `oui-form-field`. */\n controlType = 'oui-select';\n\n /** Trigger that opens the select. */\n @ViewChild('trigger') trigger: ElementRef;\n\n /** Trigger that opens the select. */\n @ViewChild('ddCancelButton', { read: ElementRef }) ddCancelButton: ElementRef;\n\n /** Trigger that opens the select. */\n @ViewChild('ddDoneButton', { read: ElementRef }) ddDoneButton: ElementRef;\n\n /** Panel containing the select options. */\n @ViewChild('panel', { read: ElementRef }) panel: ElementRef;\n\n private _value: any;\n\n /**\n * Function used to sort the values in a select in multiple mode.\n * Follows the same logic as `Array.prototype.sort`.\n */\n @Input() sortComparator: (\n a: OuiOption,\n b: OuiOption,\n options: OuiOption[]\n ) => number;\n\n /** Aria label of the select. If not specified, the placeholder will be used as label. */\n @Input('aria-label') ariaLabel = '';\n\n /** Input that can be used to specify the `aria-labelledby` attribute. */\n @Input('aria-labelledby') ariaLabelledby: string;\n private _large = false;\n _monitorSubscription: any;\n\n /** Whether the oui-select is of large size. */\n @Input()\n get large(): boolean {\n return this._large;\n }\n set large(value) {\n this._large = coerceBooleanProperty(value);\n this._changeDetectorRef.markForCheck();\n }\n\n private _id: string;\n\n /** Event emitted when the select panel has been toggled. */\n @Output()\n readonly openedChange: EventEmitter = new EventEmitter();\n\n /** Combined stream of all of the child options' change events. */\n readonly optionSelectionChanges: Observable = defer(\n (): Observable => {\n if (this.options) {\n return merge(...this.options.map((option) => option.onSelectionChange));\n }\n\n return this._ngZone.onStable.asObservable().pipe(\n take(1),\n switchMap(() => this.optionSelectionChanges)\n );\n }\n );\n\n /**\n * Event that emits whenever the raw value of the select changes. This is here primarily\n * to facilitate the two-way binding for the `value` input.\n *\n * @docs-private\n */\n @Output() readonly valueChange: EventEmitter = new EventEmitter();\n\n /** Object used to control when error messages are shown. */\n @Input() errorStateMatcher: ErrorStateMatcher;\n\n /** All of the defined select options. */\n @ContentChildren(OuiOption, { descendants: true })\n options: QueryList;\n\n /** Event emitted when the select has been opened. */\n // eslint-disable-next-line @angular-eslint/no-output-rename\n @Output('opened')\n readonly _openedStream: Observable = this.openedChange.pipe(\n filter((o) => o),\n map(() => {})\n );\n\n /** Event emitted when the select has been closed. */\n // eslint-disable-next-line @angular-eslint/no-output-rename\n @Output('closed')\n readonly _closedStream: Observable = this.openedChange.pipe(\n filter((o) => !o),\n map(() => {\n this.isSearchFieldPresent = false;\n })\n );\n\n /** Event emitted when the selected value has been changed by the user. */\n @Output()\n readonly selectionChange: EventEmitter =\n new EventEmitter();\n\n /** Event emitted when the selected value has been changed and saved by the user. */\n @Output()\n readonly saveSelectionChange: EventEmitter =\n new EventEmitter();\n\n /** All of the defined groups of options. */\n @ContentChildren(OuiOptgroup) optionGroups: QueryList;\n\n /** User-supplied override of the trigger element. */\n @ContentChild(OuiSelectTrigger)\n customTrigger: OuiSelectTrigger;\n\n /** Classes to be passed to the select panel. Supports the same syntax as `ngClass`. */\n @Input() panelClass: string | string[] | Set | { [key: string]: any };\n\n /** Overlay pane containing the options. */\n @ViewChild(CdkConnectedOverlay)\n overlayDir: CdkConnectedOverlay;\n\n /** Emits when the panel element is finished transforming in. */\n _panelDoneAnimatingStream = new Subject();\n\n /** Comparison function to specify which option is displayed. Defaults to object equality. */\n private _compareWith = (o1: any, o2: any) => o1 === o2;\n\n /** Whether the select is focused. */\n get focused(): boolean {\n return this._focused || this._panelOpen;\n }\n /**\n * @deprecated Setter to be removed as this property is intended to be readonly.\n */\n set focused(value: boolean) {\n this._focused = value;\n }\n /** `View -> model callback called when value changes` */\n _onChange: (value: any) => void = () => {};\n\n /** `View -> model callback called when select has been touched` */\n _onTouched = () => {};\n\n /** Placeholder to be shown if no value has been selected. */\n @Input()\n get placeholder(): string {\n return this._placeholder;\n }\n set placeholder(value: string) {\n this._placeholder = value;\n this.stateChanges.next();\n }\n\n /** Whether the component is required. */\n @Input()\n get required(): boolean {\n return this._required;\n }\n set required(value: boolean) {\n this._required = coerceBooleanProperty(value);\n this.stateChanges.next();\n }\n\n /** Whether the user should be allowed to select multiple options. */\n @Input()\n get multiple(): boolean {\n return this._multiple;\n }\n set multiple(value: boolean) {\n if (this._selectionModel) {\n throw getOuiSelectDynamicMultipleError();\n }\n\n this._multiple = coerceBooleanProperty(value);\n }\n\n /** Whether the action items are required and use saveSelectionChange instead of selectionChange. */\n @Input()\n get actionItems(): boolean {\n return this._actionItems;\n }\n set actionItems(value: boolean) {\n if (this._multiple) {\n this._actionItems = coerceBooleanProperty(value);\n this.stateChanges.next();\n }\n }\n\n /** Whether to center the active option over the trigger. */\n @Input()\n get disableOptionCentering(): boolean {\n return this._disableOptionCentering;\n }\n set disableOptionCentering(value: boolean) {\n this._disableOptionCentering = coerceBooleanProperty(value);\n }\n\n /**\n * Function to compare the option values with the selected values. The first argument\n * is a value from an option. The second is a value from the selection. A boolean\n * should be returned.\n */\n @Input()\n get compareWith() {\n return this._compareWith;\n }\n set compareWith(fn: (o1: any, o2: any) => boolean) {\n if (typeof fn !== 'function') {\n throw getOuiSelectNonFunctionValueError();\n }\n this._compareWith = fn;\n if (this._selectionModel) {\n // A different comparator means the selection could change.\n this._initializeSelection();\n }\n }\n\n /** Value of the select control. */\n @Input()\n get value(): any {\n return this._value;\n }\n set value(newValue: any) {\n if (newValue !== this._value) {\n this.writeValue(newValue);\n this._value = newValue;\n }\n }\n\n /** Unique id of the element. */\n @Input()\n get id(): string {\n return this._id;\n }\n set id(value: string) {\n this._id = value || this._uid;\n this.stateChanges.next();\n }\n\n constructor(\n private _changeDetectorRef: ChangeDetectorRef,\n private _ngZone: NgZone,\n _defaultErrorStateMatcher: ErrorStateMatcher,\n elementRef: ElementRef,\n private _focusMonitor: FocusMonitor,\n @Optional() private _dir: Directionality,\n @Optional() _parentForm: NgForm,\n @Optional() _parentFormGroup: FormGroupDirective,\n @Optional() private _parentFormField: OuiFormField,\n @Self() @Optional() public ngControl: NgControl,\n @Attribute('tabindex') tabIndex: string,\n @Optional() @Inject(DOCUMENT) private _document: any,\n public _elementRef: ElementRef,\n public _ouiIconRegistry: OuiIconRegistry,\n private _domSanitizer: DomSanitizer\n ) {\n super(\n elementRef,\n _defaultErrorStateMatcher,\n _parentForm,\n _parentFormGroup,\n ngControl\n );\n this._monitorSubscription = this._focusMonitor\n .monitor(this._elementRef, true)\n .subscribe(() => this._ngZone.run(() => {}));\n this._ouiIconRegistry.addSvgIconLiteral(\n `select-arrow-icon`,\n this._domSanitizer.bypassSecurityTrustHtml(ICONS.SELECT_ARROW_ICON)\n );\n\n if (this.ngControl) {\n // Note: we provide the value accessor through here, instead of\n // the `providers` to avoid running into a circular import.\n this.ngControl.valueAccessor = this;\n }\n\n this.tabIndex = parseInt(tabIndex, 10) || 0;\n\n // Force setter to be called in case id was not specified.\n this.id = this.id;\n }\n\n ngOnInit() {\n this._selectionModel = new SelectionModel(this.multiple);\n this.stateChanges.next();\n\n // We need `distinctUntilChanged` here, because some browsers will\n // fire the animation end event twice for the same animation. See:\n // https://github.com/angular/angular/issues/24084\n this._panelDoneAnimatingStream\n .pipe(distinctUntilChanged(), takeUntil(this._destroy))\n .subscribe(() => {\n if (this.panelOpen) {\n this._scrollTop = 0;\n this.openedChange.emit(true);\n } else {\n this.openedChange.emit(false);\n this.overlayDir.offsetX = 0;\n this._changeDetectorRef.markForCheck();\n }\n });\n }\n\n ngAfterContentInit() {\n this._initKeyManager();\n\n this._selectionModel.changed\n .pipe(takeUntil(this._destroy))\n .subscribe((event) => {\n event.added.forEach((option) => option.select());\n event.removed.forEach((option) => option.deselect());\n });\n\n this.options.changes\n .pipe(startWith(null), takeUntil(this._destroy))\n .subscribe(() => {\n this._resetOptions();\n this._initializeSelection();\n });\n }\n\n ngDoCheck() {\n if (this.ngControl) {\n this.updateErrorState();\n }\n }\n\n ngOnChanges(changes: SimpleChanges) {\n // Updating the disabled state is handled by `mixinDisabled`, but we need to additionally let\n // the parent form field know to run change detection when the disabled state changes.\n if (changes.disabled) {\n this.stateChanges.next();\n }\n }\n\n ngOnDestroy() {\n this._monitorSubscription.unsubscribe();\n this._focusMonitor.stopMonitoring(this._elementRef);\n this._destroy.next();\n this._destroy.complete();\n this.stateChanges.complete();\n }\n\n /** Toggles the overlay panel open or closed. */\n toggle(): void {\n this.panelOpen ? this.close() : this.open();\n }\n\n /** Opens the overlay panel. */\n open(): void {\n if (\n this.disabled ||\n !this.options ||\n !this.options.length ||\n this._panelOpen\n ) {\n return;\n }\n\n this._triggerRect = this.trigger.nativeElement.getBoundingClientRect();\n\n this._panelOpen = true;\n this._keyManager.withHorizontalOrientation(null);\n\n this._highlightCorrectOption();\n this._changeDetectorRef.markForCheck();\n this.openedChange.emit(true);\n this._elementRef.nativeElement.classList.add(\n 'oui-select-list-options-opened'\n );\n }\n\n /** Closes the overlay panel and focuses the host element. */\n close(): void {\n if (this._panelOpen) {\n this._panelOpen = false;\n this._keyManager.withHorizontalOrientation(this._isRtl() ? 'rtl' : 'ltr');\n this._changeDetectorRef.markForCheck();\n this._onTouched();\n this.openedChange.emit(false);\n this._elementRef.nativeElement.classList.remove(\n 'oui-select-list-options-opened'\n );\n setTimeout((_) => this._document.activeElement.blur());\n }\n }\n\n /**\n * Sets the select's value. Part of the ControlValueAccessor interface\n * required to integrate with Angular's core forms API.\n *\n * @param value New value to be written to the model.\n */\n writeValue(value: any): void {\n if (this.options) {\n this._setSelectionByValue(value);\n }\n }\n\n /**\n * Saves a callback function to be invoked when the select's value\n * changes from user input. Part of the ControlValueAccessor interface\n * required to integrate with Angular's core forms API.\n *\n * @param fn Callback to be triggered when the value changes.\n */\n registerOnChange(fn: (value: any) => void): void {\n this._onChange = fn;\n }\n\n /**\n * Saves a callback function to be invoked when the select is blurred\n * by the user. Part of the ControlValueAccessor interface required\n * to integrate with Angular's core forms API.\n *\n * @param fn Callback to be triggered when the component has been touched.\n */\n registerOnTouched(fn: () => {}): void {\n this._onTouched = fn;\n }\n\n /**\n * Disables the select. Part of the ControlValueAccessor interface required\n * to integrate with Angular's core forms API.\n *\n * @param isDisabled Sets whether the component is disabled.\n */\n setDisabledState(isDisabled: boolean): void {\n this.disabled = isDisabled;\n this._changeDetectorRef.markForCheck();\n this.stateChanges.next();\n }\n\n /** Whether or not the overlay panel is open. */\n get panelOpen(): boolean {\n return this._panelOpen;\n }\n\n /** The currently selected option. */\n get selected(): OuiOption | OuiOption[] {\n return this.multiple\n ? this._selectionModel.selected\n : this._selectionModel.selected[0];\n }\n\n /** The value displayed in the trigger. */\n get triggerValue(): string {\n if (this.empty) {\n return '';\n }\n if (this._multiple) {\n const selectedOptions = this._selectionModel.selected.map(\n (option) => option.viewValueForSelect\n );\n\n if (this._isRtl()) {\n selectedOptions.reverse();\n }\n return selectedOptions.join(', ');\n }\n return this._selectionModel.selected[0].viewValueForSelect;\n }\n\n /** Whether the element is in RTL mode. */\n _isRtl(): boolean {\n return this._dir ? this._dir.value === 'rtl' : false;\n }\n\n /** Handles all keydown events on the select. */\n _handleKeydown(event: KeyboardEvent): void {\n if (!this.disabled) {\n this.panelOpen\n ? this._handleOpenKeydown(event)\n : this._handleClosedKeydown(event);\n }\n }\n\n /** Handles keyboard events while the select is closed. */\n private _handleClosedKeydown(event: KeyboardEvent): void {\n const keyCode = event.keyCode;\n const isArrowKey =\n keyCode === DOWN_ARROW ||\n keyCode === UP_ARROW ||\n keyCode === LEFT_ARROW ||\n keyCode === RIGHT_ARROW;\n const isOpenKey = keyCode === ENTER || keyCode === SPACE;\n const manager = this._keyManager;\n\n // Open the select on ALT + arrow key to match the native \n event.preventDefault();\n this.close();\n } else if (\n (keyCode === ENTER || keyCode === SPACE) &&\n manager.activeItem &&\n !hasModifierKey(event)\n ) {\n event.preventDefault();\n manager.activeItem._selectViaInteraction();\n } else if (this._multiple && keyCode === A && event.ctrlKey) {\n event.preventDefault();\n this.handleCtrlKey();\n } else if (normalNavigationCheck) {\n // Check for non multiple select dropdown that the key pressed is not Tab, Space, Enter\n if (!this.isSearchFieldPresent) this.focus();\n this.handleScrolling(manager, event, isArrowKey, keyCode);\n }\n }\n\n /**\n * Handle ctrl key\n */\n private handleCtrlKey() {\n const hasDeselectedOptions = this.options.some(\n (opt) => !opt.disabled && !opt.selected\n );\n\n this.options.forEach((option) => {\n if (!option.disabled) {\n hasDeselectedOptions ? option.select() : option.deselect();\n }\n });\n }\n\n /**\n * @param manager\n * @param event\n * @param isArrowKey\n * @param keyCode\n */\n private handleScrolling(\n manager: ActiveDescendantKeyManager,\n event: KeyboardEvent,\n isArrowKey: boolean,\n keyCode: number\n ) {\n const previouslyFocusedIndex = manager.activeItemIndex;\n\n manager.onKeydown(event);\n\n if (\n this._multiple &&\n isArrowKey &&\n event.shiftKey &&\n manager.activeItem &&\n manager.activeItemIndex !== previouslyFocusedIndex\n ) {\n manager.activeItem._selectViaInteraction();\n }\n if (isArrowKey && manager.activeItemIndex !== previouslyFocusedIndex) {\n this._scrollToOption();\n } else {\n // First or last\n if (keyCode === DOWN_ARROW) {\n manager.setFirstItemActive();\n this._setScrollTop(0);\n }\n if (keyCode === UP_ARROW) {\n manager.setLastItemActive();\n this._scrollToOption();\n }\n }\n }\n\n _onFocus() {\n if (!this.disabled) {\n this._focused = true;\n this.stateChanges.next();\n }\n }\n\n /**\n * Calls the touched callback only if the panel is closed. Otherwise, the trigger will\n * \"blur\" to the panel when it opens, causing a false positive.\n */\n _onBlur() {\n this._focused = false;\n // this.isSearchFieldPresent = false;\n\n if (!this.disabled && !this.panelOpen) {\n this._onTouched();\n this._changeDetectorRef.markForCheck();\n this.stateChanges.next();\n }\n }\n\n /**\n * Callback that is invoked when the overlay panel has been attached.\n */\n _onAttached(): void {\n this.overlayDir.positionChange.pipe(take(1)).subscribe(() => {\n this._setPseudoCheckboxPaddingSize();\n this._changeDetectorRef.detectChanges();\n this.panel.nativeElement.scrollTop = this._scrollTop;\n });\n }\n\n /** Returns the theme to be used on the panel. */\n _getPanelTheme(): string {\n return this._parentFormField ? `oui-${this._parentFormField.color}` : '';\n }\n\n // TODO(josephperrott): Remove after 2018 spec updates are fully merged.\n /** Sets the pseudo checkbox padding size based on the width of the pseudo checkbox. */\n private _setPseudoCheckboxPaddingSize() {\n if (!SELECT_MULTIPLE_PANEL_PADDING_X && this.multiple) {\n const pseudoCheckbox = this.panel.nativeElement.querySelector(\n '.oui-pseudo-checkbox'\n );\n if (pseudoCheckbox) {\n SELECT_MULTIPLE_PANEL_PADDING_X =\n SELECT_PANEL_PADDING_X * 1.5 + pseudoCheckbox.offsetWidth;\n }\n }\n }\n\n /** Whether the select has a value. */\n get empty(): boolean {\n return !this._selectionModel || this._selectionModel.isEmpty();\n }\n\n private _initializeSelection(): void {\n // Defer setting the value in order to avoid the \"Expression\n // has changed after it was checked\" errors from Angular.\n Promise.resolve().then(() => {\n this._setSelectionByValue(\n this.ngControl ? this.ngControl.value : this._value\n );\n this.savedValues = this.ngControl ? this.ngControl.value : this._value;\n if (this.multiple) {\n this._highlightFirstFilteredOption();\n }\n });\n }\n\n /**\n * Sets the selected option based on a value. If no option can be\n * found with the designated value, the select trigger is cleared.\n */\n private _setSelectionByValue(value: any | any[]): void {\n if (this.multiple && value) {\n if (!Array.isArray(value)) {\n throw getOuiSelectNonArrayValueError();\n }\n\n this._selectionModel.clear();\n value.forEach((currentValue: any) => this._selectValue(currentValue));\n this._sortValues();\n } else {\n this._selectionModel.clear();\n const correspondingOption = this._selectValue(value);\n // Shift focus to the active item. Note that we shouldn't do this in multiple\n // mode, because we don't know what option the user interacted with last.\n if (correspondingOption) {\n this._keyManager.setActiveItem(correspondingOption);\n }\n }\n this._changeDetectorRef.markForCheck();\n }\n\n /**\n * Finds and selects and option based on its value.\n *\n * @returns Option that has the corresponding value.\n */\n private _selectValue(value: any): OuiOption | undefined {\n const correspondingOption = this.options.find((option: OuiOption) => {\n try {\n // Treat null as a special reset value.\n return option.value != null && this._compareWith(option.value, value);\n } catch (error) {\n if (isDevMode()) {\n // Notify developers of errors in their comparator.\n console.warn(error);\n }\n return false;\n }\n });\n\n if (correspondingOption) {\n this._selectionModel.select(correspondingOption);\n }\n\n return correspondingOption;\n }\n\n /** Sets up a key manager to listen to keyboard events on the overlay panel. */\n private _initKeyManager() {\n this._keyManager = new ActiveDescendantKeyManager(this.options)\n .withTypeAhead()\n .withVerticalOrientation()\n .withHorizontalOrientation(this._isRtl() ? 'rtl' : 'ltr')\n .withAllowedModifierKeys(['shiftKey']);\n\n this._keyManager.tabOut.pipe(takeUntil(this._destroy)).subscribe(() => {\n // Restore focus to the trigger before closing. Ensures that the focus\n // position won't be lost if the user got focus into the overlay.\n this.focus();\n this.close();\n });\n\n this._keyManager.change.pipe(takeUntil(this._destroy)).subscribe(() => {\n if (this._panelOpen && this.panel) {\n // Panel is opened\n // Need not to scroll\n } else if (\n !this._panelOpen &&\n !this.multiple &&\n this._keyManager.activeItem\n ) {\n this._keyManager.activeItem._selectViaInteraction();\n }\n });\n }\n\n /** Drops current option subscriptions and IDs and resets from scratch. */\n private _resetOptions(): void {\n const changedOrDestroyed = merge(this.options.changes, this._destroy);\n\n this.optionSelectionChanges\n .pipe(takeUntil(changedOrDestroyed))\n .subscribe((event) => {\n this._onSelect(event.source, event.isUserInput);\n\n if (event.isUserInput && !this.multiple && this._panelOpen) {\n this.close();\n this.focus();\n }\n });\n\n // Listen to changes in the internal state of the options and react accordingly.\n // Handles cases like the labels of the selected options changing.\n merge(...this.options.map((option) => option._stateChanges))\n .pipe(takeUntil(changedOrDestroyed))\n .subscribe(() => {\n this._changeDetectorRef.markForCheck();\n this.stateChanges.next();\n });\n\n this._setOptionIds();\n }\n\n /** Invoked when an option is clicked. */\n private _onSelect(option: OuiOption, isUserInput: boolean): void {\n const wasSelected = this._selectionModel.isSelected(option);\n\n if (option.value == null && !this._multiple) {\n option.deselect();\n this._selectionModel.clear();\n this._propagateChanges(option.value);\n } else {\n option.selected\n ? this._selectionModel.select(option)\n : this._selectionModel.deselect(option);\n\n if (isUserInput) {\n this._keyManager.setActiveItem(option);\n }\n\n if (this.multiple) {\n this._sortValues();\n\n if (isUserInput) {\n // In case the user selected the option with their mouse, we\n // want to restore focus back to the trigger, in order to\n // prevent the select keyboard controls from clashing with\n // the ones from `oui-option`.\n this.focus();\n }\n }\n }\n\n if (wasSelected !== this._selectionModel.isSelected(option)) {\n this._propagateChanges();\n }\n this.disableDoneButton = false;\n this.stateChanges.next();\n }\n discardRecentChanges() {\n this.value = this.savedValues;\n this._setSelectionByValue(this.value);\n this.disableDoneButton = true;\n this.close();\n }\n doneRecentChanges() {\n this.savedValues = this.value;\n this.disableDoneButton = true;\n this.saveSelectionChange.emit(new OuiSelectChange(this, this.value));\n this.close();\n }\n /** Sorts the selected values in the selected based on their order in the panel. */\n private _sortValues() {\n if (this.multiple) {\n const options = this.options.toArray();\n\n this._selectionModel.sort((a, b) =>\n this.sortComparator\n ? this.sortComparator(a, b, options)\n : options.indexOf(a) - options.indexOf(b)\n );\n this.stateChanges.next();\n }\n }\n\n /** Emits change event to set the model value. */\n private _propagateChanges(fallbackValue?: any): void {\n let valueToEmit: any = null;\n\n if (this.multiple) {\n valueToEmit = (this.selected as OuiOption[]).map(\n (option) => option.value\n );\n } else {\n valueToEmit = this.selected\n ? (this.selected as OuiOption).value\n : fallbackValue;\n }\n\n this._value = valueToEmit;\n this.valueChange.emit(valueToEmit);\n this._onChange(valueToEmit);\n this.selectionChange.emit(new OuiSelectChange(this, valueToEmit));\n this._changeDetectorRef.markForCheck();\n }\n\n /** Records option IDs to pass to the aria-owns property. */\n private _setOptionIds() {\n this._optionIds = this.options.map((option) => option.id).join(' ');\n }\n\n /**\n * Highlights the selected item. If no option is selected, it will highlight\n * the first item instead.\n */\n private _highlightCorrectOption(): void {\n if (this.multiple) {\n this._highlightFirstFilteredOption();\n } else if (this._keyManager) {\n if (this.empty) {\n this._keyManager.setFirstItemActive();\n } else {\n this._keyManager.setActiveItem(this._selectionModel.selected[0]);\n }\n }\n }\n\n /**\n * Highlights the first of the filtered options if no element is currently highlighted\n */\n private _highlightFirstFilteredOption(): void {\n if (this._keyManager) {\n const activeElement = this._keyManager.activeItem?._getHostElement();\n // activeElement is not part of DOM if there is no parent element\n if (!activeElement || !activeElement.parentElement) {\n // highlight first element if there is no active element or active element is not part of DOM\n this._keyManager.setFirstItemActive();\n }\n }\n }\n\n /** Focuses the select element. */\n focus(): void {\n this._elementRef.nativeElement.focus();\n }\n\n /** Returns the aria-label of the select component. */\n _getAriaLabel(): string | null {\n // If an ariaLabelledby value has been set by the consumer, the select should not overwrite the\n // `aria-labelledby` value by setting the ariaLabel to the placeholder.\n return this.ariaLabelledby ? null : this.ariaLabel || this.placeholder;\n }\n\n /** Returns the aria-labelledby of the select component. */\n _getAriaLabelledby(): string | null {\n if (this.ariaLabelledby) {\n return this.ariaLabelledby;\n }\n\n return null;\n }\n\n /** Determines the `aria-activedescendant` to be set on the host. */\n _getAriaActiveDescendant(): string | null {\n if (this.panelOpen && this._keyManager && this._keyManager.activeItem) {\n return this._keyManager.activeItem.id;\n }\n\n return null;\n }\n\n /**\n * Implemented as part of OuiFormFieldControl.\n *\n * @docs-private\n */\n setDescribedByIds(ids: string[]) {\n this._ariaDescribedby = ids.join(' ');\n }\n\n /**\n * Implemented as part of OuiFormFieldControl.\n *\n * @docs-private\n */\n onContainerClick() {\n this.focus();\n this.open();\n }\n\n /**\n * Implemented as part of OuiFormFieldControl.\n *\n * @docs-private\n */\n get shouldLabelFloat(): boolean {\n return this._panelOpen || !this.empty;\n }\n\n /**\n * Add outer class to perfect scrollbar\n * This is added only when there is a search field\n */\n ouiSelectInputOuter() {\n this.ouiSelectInputOuterClassName = 'oui-select-input-outer';\n }\n\n /**\n * Custom overlay class for cdk overlay container\n */\n openCdk() {\n this.overlayDir.positionChange.pipe(take(1)).subscribe((e) => {\n this.cdkConnectionOverlayPanel = '';\n if (e.connectionPair.originY === 'top') {\n this.cdkConnectionOverlayPanel = 'select-overlay-top';\n }\n this._changeDetectorRef.detectChanges();\n setTimeout((_) => this._scrollToOption());\n });\n\n const cdkOverLayContainer = this._document.querySelector(\n '.cdk-overlay-container'\n );\n const ouiSelectPanel = this._document.querySelector('.oui-select-panel');\n cdkOverLayContainer.classList.add('oui-select-overlay-container');\n const containerWidth = this._elementRef.nativeElement.offsetWidth;\n ouiSelectPanel.style.width = `${containerWidth}px`;\n const searchQueryString = '.oui-select-search-inner';\n if (this._document.querySelector(searchQueryString)) {\n this.scrollCalc(searchQueryString);\n this.isSearchFieldPresent = true;\n }\n }\n scrollCalc(selectQueryString: string) {\n const searchInput = this._document.querySelector(selectQueryString);\n const outter = this._document.querySelector('.oui-select-panel');\n let inner = this._document.querySelector('.oui-option');\n if (inner === null) {\n inner = 0;\n }\n const scrollbarWidth = outter.offsetWidth - inner.offsetWidth;\n if (scrollbarWidth > 5) {\n searchInput.style.width = `${inner.offsetWidth}px`;\n } else {\n searchInput.style.width = `calc(100% + 8px)`;\n }\n }\n\n /**\n * Given that we are not actually focusing active options, we must manually adjust scroll\n * to reveal options below the fold. First, we find the offset of the option from the top\n * of the panel. If that offset is below the fold, the new scrollTop will be the offset -\n * the panel height + the option height, so the active option will be just visible at the\n * bottom of the panel. If that offset is above the top of the visible panel, the new scrollTop\n * will become the offset. If that offset is visible within the panel already, the scrollTop is\n * not adjusted.\n */\n private _scrollToOption(): void {\n const manager = this._keyManager;\n const index = manager.activeItemIndex || 0;\n const labelCount = _countGroupLabelsBeforeOption(\n index,\n this.options,\n this.optionGroups\n );\n const scrollTop = this._getScrollTop();\n const newScrollPosition = _getOptionScrollPosition(\n index + labelCount,\n SELECT_OPTION_HEIGHT,\n scrollTop,\n this.actionItems && this.isSearchFieldPresent && labelCount\n ? SELECT_PANEL_HEIGHT - (50 + labelCount * 19)\n : (this.actionItems && this.isSearchFieldPresent && !labelCount) ||\n (this.actionItems && !this.isSearchFieldPresent && labelCount) ||\n (!this.actionItems && this.isSearchFieldPresent && labelCount)\n ? SELECT_PANEL_HEIGHT - 50\n : SELECT_PANEL_HEIGHT\n );\n this._setScrollTop(newScrollPosition);\n }\n\n /**\n * Sets the panel scrollTop. This allows us to manually scroll to display options\n * above or below the fold, as they are not actually being focused when active.\n */\n _setScrollTop(scrollTop: number): void {\n if (this.panel) {\n this.panel.nativeElement.querySelector('.oui-select-options').scrollTop =\n scrollTop;\n }\n }\n\n /** Returns the panel's scrollTop. */\n _getScrollTop(): number {\n return this.panel ? this.panel.nativeElement.scrollTop : 0;\n }\n}\n", + "sourceCode": "import { ActiveDescendantKeyManager, FocusMonitor } from '@angular/cdk/a11y';\r\nimport { Directionality } from '@angular/cdk/bidi';\r\nimport { coerceBooleanProperty } from '@angular/cdk/coercion';\r\nimport { SelectionModel } from '@angular/cdk/collections';\r\nimport {\r\n A,\r\n DOWN_ARROW,\r\n END,\r\n ENTER,\r\n HOME,\r\n LEFT_ARROW,\r\n RIGHT_ARROW,\r\n SPACE,\r\n UP_ARROW,\r\n hasModifierKey,\r\n TAB,\r\n} from '@angular/cdk/keycodes';\r\nimport { CdkConnectedOverlay } from '@angular/cdk/overlay';\r\nimport {\r\n AfterContentInit,\r\n Attribute,\r\n ChangeDetectionStrategy,\r\n ChangeDetectorRef,\r\n Component,\r\n ContentChild,\r\n ContentChildren,\r\n Directive,\r\n DoCheck,\r\n ElementRef,\r\n EventEmitter,\r\n Input,\r\n isDevMode,\r\n NgZone,\r\n OnChanges,\r\n OnDestroy,\r\n OnInit,\r\n Optional,\r\n Output,\r\n QueryList,\r\n Self,\r\n SimpleChanges,\r\n ViewChild,\r\n ViewEncapsulation,\r\n Inject,\r\n} from '@angular/core';\r\nimport {\r\n ControlValueAccessor,\r\n FormGroupDirective,\r\n NgControl,\r\n NgForm,\r\n} from '@angular/forms';\r\nimport {\r\n _countGroupLabelsBeforeOption,\r\n _getOptionScrollPosition,\r\n CanDisable,\r\n CanDisableCtor,\r\n CanUpdateErrorState,\r\n CanUpdateErrorStateCtor,\r\n HasTabIndex,\r\n HasTabIndexCtor,\r\n OuiOptionSelectionChange,\r\n mixinErrorState,\r\n mixinTabIndex,\r\n mixinDisabled,\r\n} from '../core';\r\nimport { OuiFormField, OuiFormFieldControl } from '../form-field/public-api';\r\nimport { DOCUMENT } from '@angular/common';\r\nimport { OUI_OPTION_PARENT_COMPONENT, OuiOption } from '../core/option/option';\r\nimport { OuiOptgroup } from '../core/option/optgroup';\r\nimport { ErrorStateMatcher } from '../core/error/error-options';\r\nimport { defer, merge, Observable, Subject } from 'rxjs';\r\nimport {\r\n distinctUntilChanged,\r\n filter,\r\n map,\r\n startWith,\r\n switchMap,\r\n take,\r\n takeUntil,\r\n} from 'rxjs/operators';\r\nimport {\r\n getOuiSelectDynamicMultipleError,\r\n getOuiSelectNonArrayValueError,\r\n getOuiSelectNonFunctionValueError,\r\n} from './select-errors';\r\nimport { OuiIconRegistry } from '../icon/icon-registery';\r\nimport { DomSanitizer } from '@angular/platform-browser';\r\nimport { ICONS } from '../core/shared/icons';\r\n\r\nlet nextUniqueId = 0;\r\n\r\n/**\r\n * The following style constants are necessary to save here in order\r\n * to properly calculate the alignment of the selected option over\r\n * the trigger element.\r\n */\r\n\r\n/** The height of each select option. */\r\nexport const SELECT_OPTION_HEIGHT = 40;\r\n\r\n/** The panel's padding on the x-axis */\r\nexport const SELECT_PANEL_PADDING_X = 16;\r\n\r\n/** The panel's x axis padding if it is indented (e.g. there is an option group). */\r\nexport const SELECT_PANEL_INDENT_PADDING_X = SELECT_PANEL_PADDING_X * 2;\r\n\r\n/** The height of the select items in `em` units. */\r\nexport const SELECT_ITEM_HEIGHT_EM = 3;\r\n\r\n/** The total height of the select panel. */\r\nexport const SELECT_PANEL_HEIGHT = 200;\r\n\r\n// TODO(josephperrott): Revert to a constant after 2018 spec updates are fully merged.\r\n/**\r\n * Distance between the panel edge and the option text in\r\n * multi-selection mode.\r\n *\r\n * Calculated as:\r\n * (SELECT_PANEL_PADDING_X * 1.5) + 20 = 44\r\n * The padding is multiplied by 1.5 because the checkbox's margin is half the padding.\r\n * The checkbox width is 16px.\r\n */\r\nexport let SELECT_MULTIPLE_PANEL_PADDING_X = 0;\r\n\r\n/**\r\n * The select panel will only \"fit\" inside the viewport if it is positioned at\r\n * this value or more away from the viewport boundary.\r\n */\r\nexport const SELECT_PANEL_VIEWPORT_PADDING = 8;\r\n\r\n/** Change event object that is emitted when the select value has changed. */\r\nexport class OuiSelectChange {\r\n constructor(\r\n /** Reference to the select that emitted the change event. */\r\n public source: OuiSelect,\r\n /** Current value of the select that emitted the event. */\r\n public value: any\r\n ) {}\r\n}\r\n\r\n// Boilerplate for applying mixins to OuiSelect.\r\n/** @docs-private */\r\nexport class OuiSelectBase {\r\n constructor(\r\n public _elementRef: ElementRef,\r\n public _defaultErrorStateMatcher: ErrorStateMatcher,\r\n public _parentForm: NgForm,\r\n public _parentFormGroup: FormGroupDirective,\r\n public ngControl: NgControl\r\n ) {}\r\n}\r\n\r\nexport const _OuiSelectMixinBase: CanDisableCtor &\r\n HasTabIndexCtor &\r\n CanUpdateErrorStateCtor &\r\n typeof OuiSelectBase = mixinTabIndex(\r\n mixinDisabled(mixinErrorState(OuiSelectBase))\r\n);\r\n\r\n/**\r\n * Allows the user to customize the trigger that is displayed when the select has a value.\r\n */\r\n@Directive({\r\n // eslint-disable-next-line @angular-eslint/directive-selector\r\n selector: 'oui-select-trigger',\r\n})\r\nexport class OuiSelectTrigger {}\r\n\r\n@Component({\r\n selector: 'oui-select',\r\n exportAs: 'ouiSelect',\r\n templateUrl: 'select.html',\r\n styleUrls: ['select.scss'],\r\n // eslint-disable-next-line @angular-eslint/no-inputs-metadata-property\r\n inputs: ['disabled', 'tabIndex'],\r\n encapsulation: ViewEncapsulation.None,\r\n changeDetection: ChangeDetectionStrategy.OnPush,\r\n // eslint-disable-next-line @angular-eslint/no-host-metadata-property\r\n host: {\r\n role: 'listbox',\r\n '[attr.id]': 'id',\r\n '[attr.tabindex]': 'tabIndex',\r\n '[attr.aria-label]': '_getAriaLabel()',\r\n '[attr.aria-labelledby]': '_getAriaLabelledby()',\r\n '[attr.aria-required]': 'required.toString()',\r\n '[attr.aria-disabled]': 'disabled.toString()',\r\n '[attr.aria-invalid]': 'errorState',\r\n '[attr.aria-owns]': 'panelOpen ? _optionIds : null',\r\n '[attr.aria-multiselectable]': 'multiple',\r\n '[attr.aria-describedby]': '_ariaDescribedby || null',\r\n '[attr.aria-activedescendant]': '_getAriaActiveDescendant()',\r\n '[class.oui-select-disabled]': 'disabled',\r\n '[class.oui-select-invalid]': 'errorState',\r\n '[class.oui-select-required]': 'required',\r\n '[class.oui-select-empty]': 'empty',\r\n class: 'oui-select oui-input',\r\n '(keydown)': '_handleKeydown($event)',\r\n '(focus)': '_onFocus()',\r\n '(blur)': '_onBlur()',\r\n },\r\n providers: [\r\n { provide: OuiFormFieldControl, useExisting: OuiSelect },\r\n { provide: OUI_OPTION_PARENT_COMPONENT, useExisting: OuiSelect },\r\n ],\r\n})\r\nexport class OuiSelect\r\n extends _OuiSelectMixinBase\r\n implements\r\n AfterContentInit,\r\n OnChanges,\r\n OnDestroy,\r\n OnInit,\r\n DoCheck,\r\n ControlValueAccessor,\r\n CanDisable,\r\n HasTabIndex,\r\n OuiFormFieldControl,\r\n CanUpdateErrorState\r\n{\r\n /**Holds selected values after done */\r\n @Input() savedValues = [];\r\n /**Done button disabled until dropdown is dirty */\r\n disableDoneButton = true;\r\n /** Whether or not the overlay panel is open. */\r\n private _panelOpen = false;\r\n\r\n /** Whether filling out the select is required in the form. */\r\n private _required = false;\r\n\r\n /** Whether filling out the select is required in the form. */\r\n private _actionItems = false;\r\n\r\n /** The scroll position of the overlay panel, calculated to center the selected option. */\r\n private _scrollTop = 0;\r\n\r\n /** The placeholder displayed in the trigger of the select. */\r\n private _placeholder: string;\r\n\r\n /** Whether the component is in multiple selection mode. */\r\n private _multiple = false;\r\n\r\n /** Search input field **/\r\n isSearchFieldPresent: boolean;\r\n\r\n /** Unique id for this input. */\r\n private _uid = `oui-select-${nextUniqueId++}`;\r\n\r\n /** The last measured value for the trigger's client bounding rect. */\r\n _triggerRect: ClientRect;\r\n\r\n /** The aria-describedby attribute on the select for improved a11y. */\r\n _ariaDescribedby: string;\r\n\r\n /** The cached font-size of the trigger element. */\r\n _triggerFontSize = 0;\r\n\r\n /** Deals with the selection logic. */\r\n _selectionModel: SelectionModel;\r\n\r\n /** Manages keyboard events for options in the panel. */\r\n _keyManager: ActiveDescendantKeyManager;\r\n\r\n /** The IDs of child options to be passed to the aria-owns attribute. */\r\n _optionIds = '';\r\n\r\n /** The value of the select panel's transform-origin property. */\r\n _transformOrigin = 'top';\r\n\r\n /** If there is search input field a class is added dynamically to the perfect scrollbar **/\r\n ouiSelectInputOuterClassName: string;\r\n\r\n /** Adding top class to overlay panel */\r\n cdkConnectionOverlayPanel = '';\r\n\r\n /**\r\n * The y-offset of the overlay panel in relation to the trigger's top start corner.\r\n * This must be adjusted to align the selected option text over the trigger text.\r\n * when the panel opens. Will change based on the y-position of the selected option.\r\n */\r\n _offsetY = 0;\r\n\r\n /**\r\n * This position config ensures that the top \"start\" corner of the overlay\r\n * is aligned with with the top \"start\" of the origin by default (overlapping\r\n * the trigger completely). If the panel cannot fit below the trigger, it\r\n * will fall back to a position above the trigger.\r\n */\r\n _positions = [\r\n {\r\n originX: 'start',\r\n originY: 'top',\r\n overlayX: 'start',\r\n overlayY: 'top',\r\n },\r\n {\r\n originX: 'start',\r\n originY: 'bottom',\r\n overlayX: 'start',\r\n overlayY: 'bottom',\r\n },\r\n ];\r\n /** Emits whenever the component is destroyed. */\r\n private readonly _destroy = new Subject();\r\n\r\n /** Whether the component is disabling centering of the active option over the trigger. */\r\n private _disableOptionCentering = false;\r\n\r\n private _focused = false;\r\n\r\n /** A name for this control that can be used by `oui-form-field`. */\r\n controlType = 'oui-select';\r\n\r\n /** Trigger that opens the select. */\r\n @ViewChild('trigger') trigger: ElementRef;\r\n\r\n /** Trigger that opens the select. */\r\n @ViewChild('ddCancelButton', { read: ElementRef }) ddCancelButton: ElementRef;\r\n\r\n /** Trigger that opens the select. */\r\n @ViewChild('ddDoneButton', { read: ElementRef }) ddDoneButton: ElementRef;\r\n\r\n /** Panel containing the select options. */\r\n @ViewChild('panel', { read: ElementRef }) panel: ElementRef;\r\n\r\n private _value: any;\r\n\r\n /**\r\n * Function used to sort the values in a select in multiple mode.\r\n * Follows the same logic as `Array.prototype.sort`.\r\n */\r\n @Input() sortComparator: (\r\n a: OuiOption,\r\n b: OuiOption,\r\n options: OuiOption[]\r\n ) => number;\r\n\r\n /** Aria label of the select. If not specified, the placeholder will be used as label. */\r\n @Input('aria-label') ariaLabel = '';\r\n\r\n /** Input that can be used to specify the `aria-labelledby` attribute. */\r\n @Input('aria-labelledby') ariaLabelledby: string;\r\n private _large = false;\r\n _monitorSubscription: any;\r\n\r\n /** Whether the oui-select is of large size. */\r\n @Input()\r\n get large(): boolean {\r\n return this._large;\r\n }\r\n set large(value) {\r\n this._large = coerceBooleanProperty(value);\r\n this._changeDetectorRef.markForCheck();\r\n }\r\n\r\n private _id: string;\r\n\r\n /** Event emitted when the select panel has been toggled. */\r\n @Output()\r\n readonly openedChange: EventEmitter = new EventEmitter();\r\n\r\n /** Combined stream of all of the child options' change events. */\r\n readonly optionSelectionChanges: Observable = defer(\r\n (): Observable => {\r\n if (this.options) {\r\n return merge(...this.options.map((option) => option.onSelectionChange));\r\n }\r\n\r\n return this._ngZone.onStable.asObservable().pipe(\r\n take(1),\r\n switchMap(() => this.optionSelectionChanges)\r\n );\r\n }\r\n );\r\n\r\n /**\r\n * Event that emits whenever the raw value of the select changes. This is here primarily\r\n * to facilitate the two-way binding for the `value` input.\r\n *\r\n * @docs-private\r\n */\r\n @Output() readonly valueChange: EventEmitter = new EventEmitter();\r\n\r\n /** Object used to control when error messages are shown. */\r\n @Input() errorStateMatcher: ErrorStateMatcher;\r\n\r\n /** All of the defined select options. */\r\n @ContentChildren(OuiOption, { descendants: true })\r\n options: QueryList;\r\n\r\n /** Event emitted when the select has been opened. */\r\n // eslint-disable-next-line @angular-eslint/no-output-rename\r\n @Output('opened')\r\n readonly _openedStream: Observable = this.openedChange.pipe(\r\n filter((o) => o),\r\n map(() => {})\r\n );\r\n\r\n /** Event emitted when the select has been closed. */\r\n // eslint-disable-next-line @angular-eslint/no-output-rename\r\n @Output('closed')\r\n readonly _closedStream: Observable = this.openedChange.pipe(\r\n filter((o) => !o),\r\n map(() => {\r\n this.isSearchFieldPresent = false;\r\n })\r\n );\r\n\r\n /** Event emitted when the selected value has been changed by the user. */\r\n @Output()\r\n readonly selectionChange: EventEmitter =\r\n new EventEmitter();\r\n\r\n /** Event emitted when the selected value has been changed and saved by the user. */\r\n @Output()\r\n readonly saveSelectionChange: EventEmitter =\r\n new EventEmitter();\r\n\r\n /** All of the defined groups of options. */\r\n @ContentChildren(OuiOptgroup) optionGroups: QueryList;\r\n\r\n /** User-supplied override of the trigger element. */\r\n @ContentChild(OuiSelectTrigger)\r\n customTrigger: OuiSelectTrigger;\r\n\r\n /** Classes to be passed to the select panel. Supports the same syntax as `ngClass`. */\r\n @Input() panelClass: string | string[] | Set | { [key: string]: any };\r\n\r\n /** Overlay pane containing the options. */\r\n @ViewChild(CdkConnectedOverlay)\r\n overlayDir: CdkConnectedOverlay;\r\n\r\n /** Emits when the panel element is finished transforming in. */\r\n _panelDoneAnimatingStream = new Subject();\r\n\r\n /** Comparison function to specify which option is displayed. Defaults to object equality. */\r\n private _compareWith = (o1: any, o2: any) => o1 === o2;\r\n\r\n /** Whether the select is focused. */\r\n get focused(): boolean {\r\n return this._focused || this._panelOpen;\r\n }\r\n /**\r\n * @deprecated Setter to be removed as this property is intended to be readonly.\r\n */\r\n set focused(value: boolean) {\r\n this._focused = value;\r\n }\r\n /** `View -> model callback called when value changes` */\r\n _onChange: (value: any) => void = () => {};\r\n\r\n /** `View -> model callback called when select has been touched` */\r\n _onTouched = () => {};\r\n\r\n /** Placeholder to be shown if no value has been selected. */\r\n @Input()\r\n get placeholder(): string {\r\n return this._placeholder;\r\n }\r\n set placeholder(value: string) {\r\n this._placeholder = value;\r\n this.stateChanges.next();\r\n }\r\n\r\n /** Whether the component is required. */\r\n @Input()\r\n get required(): boolean {\r\n return this._required;\r\n }\r\n set required(value: boolean) {\r\n this._required = coerceBooleanProperty(value);\r\n this.stateChanges.next();\r\n }\r\n\r\n /** Whether the user should be allowed to select multiple options. */\r\n @Input()\r\n get multiple(): boolean {\r\n return this._multiple;\r\n }\r\n set multiple(value: boolean) {\r\n if (this._selectionModel) {\r\n throw getOuiSelectDynamicMultipleError();\r\n }\r\n\r\n this._multiple = coerceBooleanProperty(value);\r\n }\r\n\r\n /** Whether the action items are required and use saveSelectionChange instead of selectionChange. */\r\n @Input()\r\n get actionItems(): boolean {\r\n return this._actionItems;\r\n }\r\n set actionItems(value: boolean) {\r\n if (this._multiple) {\r\n this._actionItems = coerceBooleanProperty(value);\r\n this.stateChanges.next();\r\n }\r\n }\r\n\r\n /** Whether to center the active option over the trigger. */\r\n @Input()\r\n get disableOptionCentering(): boolean {\r\n return this._disableOptionCentering;\r\n }\r\n set disableOptionCentering(value: boolean) {\r\n this._disableOptionCentering = coerceBooleanProperty(value);\r\n }\r\n\r\n /**\r\n * Function to compare the option values with the selected values. The first argument\r\n * is a value from an option. The second is a value from the selection. A boolean\r\n * should be returned.\r\n */\r\n @Input()\r\n get compareWith() {\r\n return this._compareWith;\r\n }\r\n set compareWith(fn: (o1: any, o2: any) => boolean) {\r\n if (typeof fn !== 'function') {\r\n throw getOuiSelectNonFunctionValueError();\r\n }\r\n this._compareWith = fn;\r\n if (this._selectionModel) {\r\n // A different comparator means the selection could change.\r\n this._initializeSelection();\r\n }\r\n }\r\n\r\n /** Value of the select control. */\r\n @Input()\r\n get value(): any {\r\n return this._value;\r\n }\r\n set value(newValue: any) {\r\n if (newValue !== this._value) {\r\n this.writeValue(newValue);\r\n this._value = newValue;\r\n }\r\n }\r\n\r\n /** Unique id of the element. */\r\n @Input()\r\n get id(): string {\r\n return this._id;\r\n }\r\n set id(value: string) {\r\n this._id = value || this._uid;\r\n this.stateChanges.next();\r\n }\r\n\r\n constructor(\r\n private _changeDetectorRef: ChangeDetectorRef,\r\n private _ngZone: NgZone,\r\n _defaultErrorStateMatcher: ErrorStateMatcher,\r\n elementRef: ElementRef,\r\n private _focusMonitor: FocusMonitor,\r\n @Optional() private _dir: Directionality,\r\n @Optional() _parentForm: NgForm,\r\n @Optional() _parentFormGroup: FormGroupDirective,\r\n @Optional() private _parentFormField: OuiFormField,\r\n @Self() @Optional() public ngControl: NgControl,\r\n @Attribute('tabindex') tabIndex: string,\r\n @Optional() @Inject(DOCUMENT) private _document: any,\r\n public _elementRef: ElementRef,\r\n public _ouiIconRegistry: OuiIconRegistry,\r\n private _domSanitizer: DomSanitizer\r\n ) {\r\n super(\r\n elementRef,\r\n _defaultErrorStateMatcher,\r\n _parentForm,\r\n _parentFormGroup,\r\n ngControl\r\n );\r\n this._monitorSubscription = this._focusMonitor\r\n .monitor(this._elementRef, true)\r\n .subscribe(() => this._ngZone.run(() => {}));\r\n this._ouiIconRegistry.addSvgIconLiteral(\r\n `select-arrow-icon`,\r\n this._domSanitizer.bypassSecurityTrustHtml(ICONS.SELECT_ARROW_ICON)\r\n );\r\n\r\n if (this.ngControl) {\r\n // Note: we provide the value accessor through here, instead of\r\n // the `providers` to avoid running into a circular import.\r\n this.ngControl.valueAccessor = this;\r\n }\r\n\r\n this.tabIndex = parseInt(tabIndex, 10) || 0;\r\n\r\n // Force setter to be called in case id was not specified.\r\n this.id = this.id;\r\n }\r\n\r\n ngOnInit() {\r\n this._selectionModel = new SelectionModel(this.multiple);\r\n this.stateChanges.next();\r\n\r\n // We need `distinctUntilChanged` here, because some browsers will\r\n // fire the animation end event twice for the same animation. See:\r\n // https://github.com/angular/angular/issues/24084\r\n this._panelDoneAnimatingStream\r\n .pipe(distinctUntilChanged(), takeUntil(this._destroy))\r\n .subscribe(() => {\r\n if (this.panelOpen) {\r\n this._scrollTop = 0;\r\n this.openedChange.emit(true);\r\n } else {\r\n this.openedChange.emit(false);\r\n this.overlayDir.offsetX = 0;\r\n this._changeDetectorRef.markForCheck();\r\n }\r\n });\r\n }\r\n\r\n ngAfterContentInit() {\r\n this._initKeyManager();\r\n\r\n this._selectionModel.changed\r\n .pipe(takeUntil(this._destroy))\r\n .subscribe((event) => {\r\n event.added.forEach((option) => option.select());\r\n event.removed.forEach((option) => option.deselect());\r\n });\r\n\r\n this.options.changes\r\n .pipe(startWith(null), takeUntil(this._destroy))\r\n .subscribe(() => {\r\n this._resetOptions();\r\n this._initializeSelection();\r\n });\r\n }\r\n\r\n ngDoCheck() {\r\n if (this.ngControl) {\r\n this.updateErrorState();\r\n }\r\n }\r\n\r\n ngOnChanges(changes: SimpleChanges) {\r\n // Updating the disabled state is handled by `mixinDisabled`, but we need to additionally let\r\n // the parent form field know to run change detection when the disabled state changes.\r\n if (changes.disabled) {\r\n this.stateChanges.next();\r\n }\r\n }\r\n\r\n ngOnDestroy() {\r\n this._monitorSubscription.unsubscribe();\r\n this._focusMonitor.stopMonitoring(this._elementRef);\r\n this._destroy.next();\r\n this._destroy.complete();\r\n this.stateChanges.complete();\r\n }\r\n\r\n /** Toggles the overlay panel open or closed. */\r\n toggle(): void {\r\n this.panelOpen ? this.close() : this.open();\r\n }\r\n\r\n /** Opens the overlay panel. */\r\n open(): void {\r\n if (\r\n this.disabled ||\r\n !this.options ||\r\n !this.options.length ||\r\n this._panelOpen\r\n ) {\r\n return;\r\n }\r\n\r\n this._triggerRect = this.trigger.nativeElement.getBoundingClientRect();\r\n\r\n this._panelOpen = true;\r\n this._keyManager.withHorizontalOrientation(null);\r\n\r\n this._highlightCorrectOption();\r\n this._changeDetectorRef.markForCheck();\r\n this.openedChange.emit(true);\r\n this._elementRef.nativeElement.classList.add(\r\n 'oui-select-list-options-opened'\r\n );\r\n }\r\n\r\n /** Closes the overlay panel and focuses the host element. */\r\n close(): void {\r\n if (this._panelOpen) {\r\n this._panelOpen = false;\r\n this._keyManager.withHorizontalOrientation(this._isRtl() ? 'rtl' : 'ltr');\r\n this._changeDetectorRef.markForCheck();\r\n this._onTouched();\r\n this.openedChange.emit(false);\r\n this._elementRef.nativeElement.classList.remove(\r\n 'oui-select-list-options-opened'\r\n );\r\n setTimeout((_) => this._document.activeElement.blur());\r\n }\r\n }\r\n\r\n /**\r\n * Sets the select's value. Part of the ControlValueAccessor interface\r\n * required to integrate with Angular's core forms API.\r\n *\r\n * @param value New value to be written to the model.\r\n */\r\n writeValue(value: any): void {\r\n if (this.options) {\r\n this._setSelectionByValue(value);\r\n }\r\n }\r\n\r\n /**\r\n * Saves a callback function to be invoked when the select's value\r\n * changes from user input. Part of the ControlValueAccessor interface\r\n * required to integrate with Angular's core forms API.\r\n *\r\n * @param fn Callback to be triggered when the value changes.\r\n */\r\n registerOnChange(fn: (value: any) => void): void {\r\n this._onChange = fn;\r\n }\r\n\r\n /**\r\n * Saves a callback function to be invoked when the select is blurred\r\n * by the user. Part of the ControlValueAccessor interface required\r\n * to integrate with Angular's core forms API.\r\n *\r\n * @param fn Callback to be triggered when the component has been touched.\r\n */\r\n registerOnTouched(fn: () => {}): void {\r\n this._onTouched = fn;\r\n }\r\n\r\n /**\r\n * Disables the select. Part of the ControlValueAccessor interface required\r\n * to integrate with Angular's core forms API.\r\n *\r\n * @param isDisabled Sets whether the component is disabled.\r\n */\r\n setDisabledState(isDisabled: boolean): void {\r\n this.disabled = isDisabled;\r\n this._changeDetectorRef.markForCheck();\r\n this.stateChanges.next();\r\n }\r\n\r\n /** Whether or not the overlay panel is open. */\r\n get panelOpen(): boolean {\r\n return this._panelOpen;\r\n }\r\n\r\n /** The currently selected option. */\r\n get selected(): OuiOption | OuiOption[] {\r\n return this.multiple\r\n ? this._selectionModel.selected\r\n : this._selectionModel.selected[0];\r\n }\r\n\r\n /** The value displayed in the trigger. */\r\n get triggerValue(): string {\r\n if (this.empty) {\r\n return '';\r\n }\r\n if (this._multiple) {\r\n const selectedOptions = this._selectionModel.selected.map(\r\n (option) => option.viewValueForSelect\r\n );\r\n\r\n if (this._isRtl()) {\r\n selectedOptions.reverse();\r\n }\r\n return selectedOptions.join(', ');\r\n }\r\n return this._selectionModel.selected[0].viewValueForSelect;\r\n }\r\n\r\n /** Whether the element is in RTL mode. */\r\n _isRtl(): boolean {\r\n return this._dir ? this._dir.value === 'rtl' : false;\r\n }\r\n\r\n /** Handles all keydown events on the select. */\r\n _handleKeydown(event: KeyboardEvent): void {\r\n if (!this.disabled) {\r\n this.panelOpen\r\n ? this._handleOpenKeydown(event)\r\n : this._handleClosedKeydown(event);\r\n }\r\n }\r\n\r\n /** Handles keyboard events while the select is closed. */\r\n private _handleClosedKeydown(event: KeyboardEvent): void {\r\n const keyCode = event.keyCode;\r\n const isArrowKey =\r\n keyCode === DOWN_ARROW ||\r\n keyCode === UP_ARROW ||\r\n keyCode === LEFT_ARROW ||\r\n keyCode === RIGHT_ARROW;\r\n const isOpenKey = keyCode === ENTER || keyCode === SPACE;\r\n const manager = this._keyManager;\r\n\r\n // Open the select on ALT + arrow key to match the native \r\n event.preventDefault();\r\n this.close();\r\n } else if (\r\n (keyCode === ENTER || keyCode === SPACE) &&\r\n manager.activeItem &&\r\n !hasModifierKey(event)\r\n ) {\r\n event.preventDefault();\r\n manager.activeItem._selectViaInteraction();\r\n } else if (this._multiple && keyCode === A && event.ctrlKey) {\r\n event.preventDefault();\r\n this.handleCtrlKey();\r\n } else if (normalNavigationCheck) {\r\n // Check for non multiple select dropdown that the key pressed is not Tab, Space, Enter\r\n if (!this.isSearchFieldPresent) this.focus();\r\n this.handleScrolling(manager, event, isArrowKey, keyCode);\r\n }\r\n }\r\n\r\n /**\r\n * Handle ctrl key\r\n */\r\n private handleCtrlKey() {\r\n const hasDeselectedOptions = this.options.some(\r\n (opt) => !opt.disabled && !opt.selected\r\n );\r\n\r\n this.options.forEach((option) => {\r\n if (!option.disabled) {\r\n hasDeselectedOptions ? option.select() : option.deselect();\r\n }\r\n });\r\n }\r\n\r\n /**\r\n * @param manager\r\n * @param event\r\n * @param isArrowKey\r\n * @param keyCode\r\n */\r\n private handleScrolling(\r\n manager: ActiveDescendantKeyManager,\r\n event: KeyboardEvent,\r\n isArrowKey: boolean,\r\n keyCode: number\r\n ) {\r\n const previouslyFocusedIndex = manager.activeItemIndex;\r\n\r\n manager.onKeydown(event);\r\n\r\n if (\r\n this._multiple &&\r\n isArrowKey &&\r\n event.shiftKey &&\r\n manager.activeItem &&\r\n manager.activeItemIndex !== previouslyFocusedIndex\r\n ) {\r\n manager.activeItem._selectViaInteraction();\r\n }\r\n if (isArrowKey && manager.activeItemIndex !== previouslyFocusedIndex) {\r\n this._scrollToOption();\r\n } else {\r\n // First or last\r\n if (keyCode === DOWN_ARROW) {\r\n manager.setFirstItemActive();\r\n this._setScrollTop(0);\r\n }\r\n if (keyCode === UP_ARROW) {\r\n manager.setLastItemActive();\r\n this._scrollToOption();\r\n }\r\n }\r\n }\r\n\r\n _onFocus() {\r\n if (!this.disabled) {\r\n this._focused = true;\r\n this.stateChanges.next();\r\n }\r\n }\r\n\r\n /**\r\n * Calls the touched callback only if the panel is closed. Otherwise, the trigger will\r\n * \"blur\" to the panel when it opens, causing a false positive.\r\n */\r\n _onBlur() {\r\n this._focused = false;\r\n // this.isSearchFieldPresent = false;\r\n\r\n if (!this.disabled && !this.panelOpen) {\r\n this._onTouched();\r\n this._changeDetectorRef.markForCheck();\r\n this.stateChanges.next();\r\n }\r\n }\r\n\r\n /**\r\n * Callback that is invoked when the overlay panel has been attached.\r\n */\r\n _onAttached(): void {\r\n this.overlayDir.positionChange.pipe(take(1)).subscribe(() => {\r\n this._setPseudoCheckboxPaddingSize();\r\n this._changeDetectorRef.detectChanges();\r\n this.panel.nativeElement.scrollTop = this._scrollTop;\r\n });\r\n }\r\n\r\n /** Returns the theme to be used on the panel. */\r\n _getPanelTheme(): string {\r\n return this._parentFormField ? `oui-${this._parentFormField.color}` : '';\r\n }\r\n\r\n // TODO(josephperrott): Remove after 2018 spec updates are fully merged.\r\n /** Sets the pseudo checkbox padding size based on the width of the pseudo checkbox. */\r\n private _setPseudoCheckboxPaddingSize() {\r\n if (!SELECT_MULTIPLE_PANEL_PADDING_X && this.multiple) {\r\n const pseudoCheckbox = this.panel.nativeElement.querySelector(\r\n '.oui-pseudo-checkbox'\r\n );\r\n if (pseudoCheckbox) {\r\n SELECT_MULTIPLE_PANEL_PADDING_X =\r\n SELECT_PANEL_PADDING_X * 1.5 + pseudoCheckbox.offsetWidth;\r\n }\r\n }\r\n }\r\n\r\n /** Whether the select has a value. */\r\n get empty(): boolean {\r\n return !this._selectionModel || this._selectionModel.isEmpty();\r\n }\r\n\r\n private _initializeSelection(): void {\r\n // Defer setting the value in order to avoid the \"Expression\r\n // has changed after it was checked\" errors from Angular.\r\n Promise.resolve().then(() => {\r\n this._setSelectionByValue(\r\n this.ngControl ? this.ngControl.value : this._value\r\n );\r\n this.savedValues = this.ngControl ? this.ngControl.value : this._value;\r\n if (this.multiple) {\r\n this._highlightFirstFilteredOption();\r\n }\r\n });\r\n }\r\n\r\n /**\r\n * Sets the selected option based on a value. If no option can be\r\n * found with the designated value, the select trigger is cleared.\r\n */\r\n private _setSelectionByValue(value: any | any[]): void {\r\n if (this.multiple && value) {\r\n if (!Array.isArray(value)) {\r\n throw getOuiSelectNonArrayValueError();\r\n }\r\n\r\n this._selectionModel.clear();\r\n value.forEach((currentValue: any) => this._selectValue(currentValue));\r\n this._sortValues();\r\n } else {\r\n this._selectionModel.clear();\r\n const correspondingOption = this._selectValue(value);\r\n // Shift focus to the active item. Note that we shouldn't do this in multiple\r\n // mode, because we don't know what option the user interacted with last.\r\n if (correspondingOption) {\r\n this._keyManager.setActiveItem(correspondingOption);\r\n }\r\n }\r\n this._changeDetectorRef.markForCheck();\r\n }\r\n\r\n /**\r\n * Finds and selects and option based on its value.\r\n *\r\n * @returns Option that has the corresponding value.\r\n */\r\n private _selectValue(value: any): OuiOption | undefined {\r\n const correspondingOption = this.options.find((option: OuiOption) => {\r\n try {\r\n // Treat null as a special reset value.\r\n return option.value != null && this._compareWith(option.value, value);\r\n } catch (error) {\r\n if (isDevMode()) {\r\n // Notify developers of errors in their comparator.\r\n console.warn(error);\r\n }\r\n return false;\r\n }\r\n });\r\n\r\n if (correspondingOption) {\r\n this._selectionModel.select(correspondingOption);\r\n }\r\n\r\n return correspondingOption;\r\n }\r\n\r\n /** Sets up a key manager to listen to keyboard events on the overlay panel. */\r\n private _initKeyManager() {\r\n this._keyManager = new ActiveDescendantKeyManager(this.options)\r\n .withTypeAhead()\r\n .withVerticalOrientation()\r\n .withHorizontalOrientation(this._isRtl() ? 'rtl' : 'ltr')\r\n .withAllowedModifierKeys(['shiftKey']);\r\n\r\n this._keyManager.tabOut.pipe(takeUntil(this._destroy)).subscribe(() => {\r\n // Restore focus to the trigger before closing. Ensures that the focus\r\n // position won't be lost if the user got focus into the overlay.\r\n this.focus();\r\n this.close();\r\n });\r\n\r\n this._keyManager.change.pipe(takeUntil(this._destroy)).subscribe(() => {\r\n if (this._panelOpen && this.panel) {\r\n // Panel is opened\r\n // Need not to scroll\r\n } else if (\r\n !this._panelOpen &&\r\n !this.multiple &&\r\n this._keyManager.activeItem\r\n ) {\r\n this._keyManager.activeItem._selectViaInteraction();\r\n }\r\n });\r\n }\r\n\r\n /** Drops current option subscriptions and IDs and resets from scratch. */\r\n private _resetOptions(): void {\r\n const changedOrDestroyed = merge(this.options.changes, this._destroy);\r\n\r\n this.optionSelectionChanges\r\n .pipe(takeUntil(changedOrDestroyed))\r\n .subscribe((event) => {\r\n this._onSelect(event.source, event.isUserInput);\r\n\r\n if (event.isUserInput && !this.multiple && this._panelOpen) {\r\n this.close();\r\n this.focus();\r\n }\r\n });\r\n\r\n // Listen to changes in the internal state of the options and react accordingly.\r\n // Handles cases like the labels of the selected options changing.\r\n merge(...this.options.map((option) => option._stateChanges))\r\n .pipe(takeUntil(changedOrDestroyed))\r\n .subscribe(() => {\r\n this._changeDetectorRef.markForCheck();\r\n this.stateChanges.next();\r\n });\r\n\r\n this._setOptionIds();\r\n }\r\n\r\n /** Invoked when an option is clicked. */\r\n private _onSelect(option: OuiOption, isUserInput: boolean): void {\r\n const wasSelected = this._selectionModel.isSelected(option);\r\n\r\n if (option.value == null && !this._multiple) {\r\n option.deselect();\r\n this._selectionModel.clear();\r\n this._propagateChanges(option.value);\r\n } else {\r\n option.selected\r\n ? this._selectionModel.select(option)\r\n : this._selectionModel.deselect(option);\r\n\r\n if (isUserInput) {\r\n this._keyManager.setActiveItem(option);\r\n }\r\n\r\n if (this.multiple) {\r\n this._sortValues();\r\n\r\n if (isUserInput) {\r\n // In case the user selected the option with their mouse, we\r\n // want to restore focus back to the trigger, in order to\r\n // prevent the select keyboard controls from clashing with\r\n // the ones from `oui-option`.\r\n this.focus();\r\n }\r\n }\r\n }\r\n\r\n if (wasSelected !== this._selectionModel.isSelected(option)) {\r\n this._propagateChanges();\r\n }\r\n this.disableDoneButton = false;\r\n this.stateChanges.next();\r\n }\r\n discardRecentChanges() {\r\n this.value = this.savedValues;\r\n this._setSelectionByValue(this.value);\r\n this.disableDoneButton = true;\r\n this.close();\r\n }\r\n doneRecentChanges() {\r\n this.savedValues = this.value;\r\n this.disableDoneButton = true;\r\n this.saveSelectionChange.emit(new OuiSelectChange(this, this.value));\r\n this.close();\r\n }\r\n /** Sorts the selected values in the selected based on their order in the panel. */\r\n private _sortValues() {\r\n if (this.multiple) {\r\n const options = this.options.toArray();\r\n\r\n this._selectionModel.sort((a, b) =>\r\n this.sortComparator\r\n ? this.sortComparator(a, b, options)\r\n : options.indexOf(a) - options.indexOf(b)\r\n );\r\n this.stateChanges.next();\r\n }\r\n }\r\n\r\n /** Emits change event to set the model value. */\r\n private _propagateChanges(fallbackValue?: any): void {\r\n let valueToEmit: any = null;\r\n\r\n if (this.multiple) {\r\n valueToEmit = (this.selected as OuiOption[]).map(\r\n (option) => option.value\r\n );\r\n } else {\r\n valueToEmit = this.selected\r\n ? (this.selected as OuiOption).value\r\n : fallbackValue;\r\n }\r\n\r\n this._value = valueToEmit;\r\n this.valueChange.emit(valueToEmit);\r\n this._onChange(valueToEmit);\r\n this.selectionChange.emit(new OuiSelectChange(this, valueToEmit));\r\n this._changeDetectorRef.markForCheck();\r\n }\r\n\r\n /** Records option IDs to pass to the aria-owns property. */\r\n private _setOptionIds() {\r\n this._optionIds = this.options.map((option) => option.id).join(' ');\r\n }\r\n\r\n /**\r\n * Highlights the selected item. If no option is selected, it will highlight\r\n * the first item instead.\r\n */\r\n private _highlightCorrectOption(): void {\r\n if (this.multiple) {\r\n this._highlightFirstFilteredOption();\r\n } else if (this._keyManager) {\r\n if (this.empty) {\r\n this._keyManager.setFirstItemActive();\r\n } else {\r\n this._keyManager.setActiveItem(this._selectionModel.selected[0]);\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * Highlights the first of the filtered options if no element is currently highlighted\r\n */\r\n private _highlightFirstFilteredOption(): void {\r\n if (this._keyManager) {\r\n const activeElement = this._keyManager.activeItem?._getHostElement();\r\n // activeElement is not part of DOM if there is no parent element\r\n if (!activeElement || !activeElement.parentElement) {\r\n // highlight first element if there is no active element or active element is not part of DOM\r\n this._keyManager.setFirstItemActive();\r\n }\r\n }\r\n }\r\n\r\n /** Focuses the select element. */\r\n focus(): void {\r\n this._elementRef.nativeElement.focus();\r\n }\r\n\r\n /** Returns the aria-label of the select component. */\r\n _getAriaLabel(): string | null {\r\n // If an ariaLabelledby value has been set by the consumer, the select should not overwrite the\r\n // `aria-labelledby` value by setting the ariaLabel to the placeholder.\r\n return this.ariaLabelledby ? null : this.ariaLabel || this.placeholder;\r\n }\r\n\r\n /** Returns the aria-labelledby of the select component. */\r\n _getAriaLabelledby(): string | null {\r\n if (this.ariaLabelledby) {\r\n return this.ariaLabelledby;\r\n }\r\n\r\n return null;\r\n }\r\n\r\n /** Determines the `aria-activedescendant` to be set on the host. */\r\n _getAriaActiveDescendant(): string | null {\r\n if (this.panelOpen && this._keyManager && this._keyManager.activeItem) {\r\n return this._keyManager.activeItem.id;\r\n }\r\n\r\n return null;\r\n }\r\n\r\n /**\r\n * Implemented as part of OuiFormFieldControl.\r\n *\r\n * @docs-private\r\n */\r\n setDescribedByIds(ids: string[]) {\r\n this._ariaDescribedby = ids.join(' ');\r\n }\r\n\r\n /**\r\n * Implemented as part of OuiFormFieldControl.\r\n *\r\n * @docs-private\r\n */\r\n onContainerClick() {\r\n this.focus();\r\n this.open();\r\n }\r\n\r\n /**\r\n * Implemented as part of OuiFormFieldControl.\r\n *\r\n * @docs-private\r\n */\r\n get shouldLabelFloat(): boolean {\r\n return this._panelOpen || !this.empty;\r\n }\r\n\r\n /**\r\n * Add outer class to perfect scrollbar\r\n * This is added only when there is a search field\r\n */\r\n ouiSelectInputOuter() {\r\n this.ouiSelectInputOuterClassName = 'oui-select-input-outer';\r\n }\r\n\r\n /**\r\n * Custom overlay class for cdk overlay container\r\n */\r\n openCdk() {\r\n this.overlayDir.positionChange.pipe(take(1)).subscribe((e) => {\r\n this.cdkConnectionOverlayPanel = '';\r\n if (e.connectionPair.originY === 'top') {\r\n this.cdkConnectionOverlayPanel = 'select-overlay-top';\r\n }\r\n this._changeDetectorRef.detectChanges();\r\n setTimeout((_) => this._scrollToOption());\r\n });\r\n\r\n const cdkOverLayContainer = this._document.querySelector(\r\n '.cdk-overlay-container'\r\n );\r\n const ouiSelectPanel = this._document.querySelector('.oui-select-panel');\r\n cdkOverLayContainer.classList.add('oui-select-overlay-container');\r\n const containerWidth = this._elementRef.nativeElement.offsetWidth;\r\n ouiSelectPanel.style.width = `${containerWidth}px`;\r\n const searchQueryString = '.oui-select-search-inner';\r\n if (this._document.querySelector(searchQueryString)) {\r\n this.scrollCalc(searchQueryString);\r\n }\r\n const actionItemsQueryString = '.oui-select-action-items';\r\n if (this._document.querySelector(actionItemsQueryString)) {\r\n this.scrollCalc(actionItemsQueryString);\r\n }\r\n }\r\n scrollCalc(selectQueryString: string) {\r\n const searchInput = this._document.querySelector(selectQueryString);\r\n const outter = this._document.querySelector('.oui-select-panel');\r\n let inner = this._document.querySelector('.oui-option');\r\n if (inner === null) {\r\n inner = 0;\r\n }\r\n const scrollbarWidth = outter.offsetWidth - inner.offsetWidth;\r\n if (scrollbarWidth > 5) {\r\n searchInput.style.width = `${inner.offsetWidth}px`;\r\n } else {\r\n searchInput.style.width = `calc(100% + 8px)`;\r\n }\r\n }\r\n\r\n /**\r\n * Given that we are not actually focusing active options, we must manually adjust scroll\r\n * to reveal options below the fold. First, we find the offset of the option from the top\r\n * of the panel. If that offset is below the fold, the new scrollTop will be the offset -\r\n * the panel height + the option height, so the active option will be just visible at the\r\n * bottom of the panel. If that offset is above the top of the visible panel, the new scrollTop\r\n * will become the offset. If that offset is visible within the panel already, the scrollTop is\r\n * not adjusted.\r\n */\r\n private _scrollToOption(): void {\r\n const manager = this._keyManager;\r\n const index = manager.activeItemIndex || 0;\r\n const labelCount = _countGroupLabelsBeforeOption(\r\n index,\r\n this.options,\r\n this.optionGroups\r\n );\r\n const scrollTop = this._getScrollTop();\r\n const newScrollPosition = _getOptionScrollPosition(\r\n index + labelCount,\r\n SELECT_OPTION_HEIGHT,\r\n scrollTop,\r\n SELECT_PANEL_HEIGHT\r\n );\r\n this._setScrollTop(newScrollPosition);\r\n }\r\n\r\n /**\r\n * Sets the panel scrollTop. This allows us to manually scroll to display options\r\n * above or below the fold, as they are not actually being focused when active.\r\n */\r\n _setScrollTop(scrollTop: number): void {\r\n if (this.panel) {\r\n this.panel.nativeElement.scrollTop = scrollTop;\r\n }\r\n }\r\n\r\n /** Returns the panel's scrollTop. */\r\n _getScrollTop(): number {\r\n return this.panel ? this.panel.nativeElement.scrollTop : 0;\r\n }\r\n}\r\n", "assetsDirs": [], "styleUrlsData": [ { - "data": "@use 'sass:math';\n\n@import '../core/style/menu-common';\n@import '../core/style/list-common';\n@import '../core/style/variables';\n@import '../core/style/vendor-prefixes';\n$oui-select-arrow-size: 5px !default;\n$oui-select-arrow-margin: 4px !default;\n$oui-select-panel-max-height: 256px !default;\n$oui-select-item-height: 40px !default;\n$oui-select-placeholder-arrow-space: 2 *\n ($oui-select-arrow-size + $oui-select-arrow-margin);\n$gray-color: #eee;\n\n%placeholder {\n font-size: 14px;\n}\n\n.oui-error {\n @extend %placeholder;\n}\n.oui-select {\n display: inline-block;\n width: 100%;\n outline: none;\n div {\n margin: 0;\n vertical-align: middle;\n }\n .oui-select-value {\n @extend %placeholder;\n line-height: 19px;\n padding: 2px 8px 2px 0;\n }\n}\n\n.oui-select-trigger {\n display: inline-table;\n cursor: pointer;\n position: relative;\n box-sizing: border-box;\n\n .oui-select-disabled & {\n @include user-select(none);\n cursor: default;\n }\n}\n\n.oui-select-value {\n display: table-cell;\n max-width: 0;\n width: 100%;\n}\n\n.oui-select-value-text {\n display: inline-block;\n width: 100%;\n @include oui-truncate-line();\n span img {\n max-width: 20px;\n max-height: 20px;\n }\n}\n\n.oui-select-arrow-wrapper {\n display: inline-block;\n vertical-align: middle;\n\n // When used in a box appearance form-field the arrow should be shifted up 50%.\n .oui-form-field-appearance-fill & {\n transform: translateY(-50%);\n }\n\n // When used in a outline form-field the arrow should be shifted up 25%.\n .oui-form-field-appearance-outline & {\n transform: translateY(-25%);\n }\n\n // Animate the arrow position, but only when the transitioning to empty (animate the arrow down)\n // This is in line with the oui-form-field label animation\n .oui-form-field-appearance-standard .oui-select.oui-select-empty & {\n transition: transform $swift-ease-out-duration\n $swift-ease-out-timing-function;\n }\n\n ._oui-animation-noopable.oui-form-field-appearance-standard\n .oui-select.oui-select-empty\n & {\n transition: none;\n }\n}\n\n.oui-select-arrow {\n width: 12px;\n}\n\n.oui-focused {\n .oui-select-arrow {\n transform: rotate(180deg);\n }\n .oui-select.oui-input:not(.oui-select-list-options-opened) {\n .oui-select-arrow {\n transform: rotate(0deg);\n }\n }\n}\n\n.oui-select-large {\n max-height: 392px !important;\n}\n\n// Override optgroup and option to scale based on font-size of the trigger.\n.oui-select-panel {\n color: #333;\n -webkit-overflow-scrolling: touch; // for momentum scroll on mobile\n overflow-x: hidden;\n padding-bottom: 0;\n position: relative;\n border: 1px solid #c8c8c8;\n background-color: #ffffff;\n max-height: 272px;\n margin: 6px 0 0 -10px;\n box-sizing: border-box;\n min-width: 100px;\n font-family: 'Open Sans', Helvetica, Arial, sans-serif;\n box-shadow: 0 2px 4px -1px rgba(0, 0, 0, 0.2), 0 4px 5px 0 rgba(0, 0, 0, 0.14),\n 0 1px 10px 0 rgba(0, 0, 0, 0.12);\n border-top: 0;\n .oui-select-options {\n -webkit-overflow-scrolling: touch; // for momentum scroll on mobile\n overflow-x: hidden;\n height: 100%;\n padding-top: 10px;\n box-sizing: border-box;\n }\n &.oui-select-input-outer {\n .oui-select-options {\n padding-top: 0;\n }\n }\n &.action-item {\n padding-bottom: 56px;\n }\n .oui-option {\n line-height: $oui-select-item-height;\n height: $oui-select-item-height;\n padding: 0 10px;\n font-size: 14px;\n &.oui-active {\n background: $gray-color;\n color: #333;\n }\n &.oui-option-disabled {\n color: rgba(0, 0, 0, 0.38);\n }\n &:last-child {\n margin-bottom: 10px;\n }\n oui-checkbox {\n width: 100%;\n label {\n width: 100%;\n display: block;\n }\n }\n }\n .oui-option-multiple.oui-selected,\n .oui-option-multiple.oui-active {\n background: none;\n }\n .oui-optgroup-label {\n font-weight: 700;\n display: block;\n padding: 0 10px;\n font-size: 14px;\n line-height: $oui-select-item-height;\n }\n}\n\n.oui-form-field-type-oui-select {\n &:not(.oui-form-field-disabled) .oui-form-field-flex {\n cursor: pointer;\n }\n\n .oui-form-field-label {\n width: calc(100% - #{$oui-select-placeholder-arrow-space});\n }\n}\n\n.oui-select-placeholder {\n // Delay the transition until the label has animated about a third of the way through, in\n // order to prevent the placeholder from overlapping for a split second.\n @include oui-truncate-line();\n display: inline-block;\n width: 100%;\n transition: color $swift-ease-out-duration\n math.div($swift-ease-out-duration, 3) $swift-ease-out-timing-function;\n color: #666;\n ._oui-animation-noopable & {\n transition: none;\n }\n\n .oui-form-field-hide-placeholder & {\n color: transparent;\n\n // Overwrite browser specific CSS properties that can overwrite the `color` property.\n // Some developers seem to use this approach to easily overwrite the placeholder / label color.\n -webkit-text-fill-color: transparent;\n\n // Remove the transition to prevent the placeholder\n // from overlapping when the label comes back down.\n transition: none;\n // Prevents the '...' from showing on the parent element.\n display: block;\n }\n}\n/*-- search dropdown --*/\n\n.oui-select-input-outer {\n box-sizing: border-box;\n}\n\n/*-- search dropdown --*/\n\n/*-- search ddropdown --*/\n.ui-select-overlay-container {\n position: absolute;\n}\n.oui-select-has-a-panel\n .oui-option.oui-selected:not(.oui-option-multiple):not(.oui-option-disabled) {\n background: rgba(0, 0, 0, 0.12);\n color: #3f51b5;\n font-weight: 500;\n}\n.oui-select-has-a-panel .oui-option:hover:not(.oui-option-disabled) {\n background: rgba(0, 0, 0, 0.04);\n}\n\n/*-- search ddropdown --*/\n\n/*-- search dropdown underline --*/\n.oui-form-field-appearance-underline {\n .oui-select-trigger {\n margin-left: 9px;\n .oui-select-value {\n overflow: visible;\n .oui-select-placeholder,\n .oui-select-value-text {\n width: 100%;\n @include oui-truncate-line();\n margin-left: -9px;\n display: block;\n height: 19px;\n }\n }\n }\n .oui-select.oui-input {\n border: 1px solid transparent;\n padding-left: 0;\n padding-right: 0;\n border-bottom: 1px solid #c8c8c8;\n > div {\n padding-right: 9px;\n }\n &:after {\n content: '';\n height: 1px;\n width: 100%;\n background: #c8c8c8;\n position: absolute;\n left: 0;\n bottom: 0;\n }\n }\n}\n\n.oui-form-field.oui-form-field-appearance-underline .oui-select.oui-input {\n &.oui-select-disabled {\n border: 1px solid transparent;\n border-bottom: 1px solid #e4e4e4;\n background: transparent;\n &:after {\n background: #e4e4e4;\n }\n }\n}\n.oui-form-field .oui-select.oui-input {\n &.oui-select-disabled {\n border: 1px solid #e4e4e4;\n background-color: #f9f9f9;\n color: #9b9b9b;\n cursor: default;\n .oui-select-arrow svg path {\n fill: #c8c8c8;\n }\n }\n &.oui-form-field-appearance-underline {\n .oui-select.oui-input {\n transition: border 0.5s, padding 0.5s;\n }\n }\n}\n\n/*-- search dropdown underline --*/\n\n.oui-option:focus:not(.oui-option-disabled),\n.oui-option:hover:not(.oui-option-disabled),\n.oui-option.oui-selected:not(.oui-option-multiple):not(.oui-option-disabled) {\n background: $gray-color;\n}\n\n.select-overlay-top.oui-select-panel {\n margin-bottom: 9px;\n border-top: 1px solid #c8c8c8;\n}\n\n.noResults {\n color: #333333;\n font-size: 14px;\n line-height: 22px;\n padding: 0 10px;\n margin: 17px 0 21px;\n word-break: break-all;\n}\n\noui-select-search {\n height: 60px;\n display: block;\n}\n.oui-select-disabled .oui-select-placeholder {\n color: #9b9b9b;\n}\n.oui-select-action-wrapper {\n height: 56px;\n padding: 10px;\n border-top: 1px solid #ddd;\n box-sizing: border-box;\n background: #fff;\n display: block;\n width: 100%;\n position: absolute;\n bottom: 0px;\n left: 0px;\n}\n\n.oui-select-action-items {\n width: 100%;\n display: flex;\n justify-content: space-between;\n align-items: center;\n}\n", + "data": "@use 'sass:math';\r\n\r\n@import '../core/style/menu-common';\r\n@import '../core/style/list-common';\r\n@import '../core/style/variables';\r\n@import '../core/style/vendor-prefixes';\r\n$oui-select-arrow-size: 5px !default;\r\n$oui-select-arrow-margin: 4px !default;\r\n$oui-select-panel-max-height: 256px !default;\r\n$oui-select-item-height: 40px !default;\r\n$oui-select-placeholder-arrow-space: 2 *\r\n ($oui-select-arrow-size + $oui-select-arrow-margin);\r\n$gray-color: #eee;\r\n\r\n%placeholder {\r\n font-size: 14px;\r\n}\r\n\r\n.oui-error {\r\n @extend %placeholder;\r\n}\r\n.oui-select {\r\n display: inline-block;\r\n width: 100%;\r\n outline: none;\r\n div {\r\n margin: 0;\r\n vertical-align: middle;\r\n }\r\n .oui-select-value {\r\n @extend %placeholder;\r\n line-height: 19px;\r\n padding: 2px 8px 2px 0;\r\n }\r\n}\r\n\r\n.oui-select-trigger {\r\n display: inline-table;\r\n cursor: pointer;\r\n position: relative;\r\n box-sizing: border-box;\r\n\r\n .oui-select-disabled & {\r\n @include user-select(none);\r\n cursor: default;\r\n }\r\n}\r\n\r\n.oui-select-value {\r\n display: table-cell;\r\n max-width: 0;\r\n width: 100%;\r\n}\r\n\r\n.oui-select-value-text {\r\n display: inline-block;\r\n width: 100%;\r\n @include oui-truncate-line();\r\n span img {\r\n max-width: 20px;\r\n max-height: 20px;\r\n }\r\n}\r\n\r\n.oui-select-arrow-wrapper {\r\n display: inline-block;\r\n vertical-align: middle;\r\n\r\n // When used in a box appearance form-field the arrow should be shifted up 50%.\r\n .oui-form-field-appearance-fill & {\r\n transform: translateY(-50%);\r\n }\r\n\r\n // When used in a outline form-field the arrow should be shifted up 25%.\r\n .oui-form-field-appearance-outline & {\r\n transform: translateY(-25%);\r\n }\r\n\r\n // Animate the arrow position, but only when the transitioning to empty (animate the arrow down)\r\n // This is in line with the oui-form-field label animation\r\n .oui-form-field-appearance-standard .oui-select.oui-select-empty & {\r\n transition: transform $swift-ease-out-duration\r\n $swift-ease-out-timing-function;\r\n }\r\n\r\n ._oui-animation-noopable.oui-form-field-appearance-standard\r\n .oui-select.oui-select-empty\r\n & {\r\n transition: none;\r\n }\r\n}\r\n\r\n.oui-select-arrow {\r\n width: 12px;\r\n}\r\n\r\n.oui-focused {\r\n .oui-select-arrow {\r\n transform: rotate(180deg);\r\n }\r\n .oui-select.oui-input:not(.oui-select-list-options-opened) {\r\n .oui-select-arrow {\r\n transform: rotate(0deg);\r\n }\r\n }\r\n}\r\n\r\n.oui-select-large {\r\n max-height: 392px !important;\r\n}\r\n\r\n// Override optgroup and option to scale based on font-size of the trigger.\r\n.oui-select-panel {\r\n color: #333;\r\n -webkit-overflow-scrolling: touch; // for momentum scroll on mobile\r\n overflow-x: hidden;\r\n padding-bottom: 0;\r\n border: 1px solid #c8c8c8;\r\n background-color: #ffffff;\r\n max-height: 272px;\r\n margin: 6px 0 0 -10px;\r\n box-sizing: border-box;\r\n min-width: 100px;\r\n font-family: 'Open Sans', Helvetica, Arial, sans-serif;\r\n box-shadow: 0 2px 4px -1px rgba(0, 0, 0, 0.2), 0 4px 5px 0 rgba(0, 0, 0, 0.14),\r\n 0 1px 10px 0 rgba(0, 0, 0, 0.12);\r\n padding-top: 10px;\r\n border-top: 0;\r\n &.oui-select-input-outer {\r\n padding-top: 0;\r\n }\r\n .oui-optgroup-label,\r\n .oui-option {\r\n line-height: $oui-select-item-height;\r\n height: $oui-select-item-height;\r\n padding: 0 10px;\r\n font-size: 14px;\r\n &.oui-active {\r\n background: $gray-color;\r\n color: #333;\r\n }\r\n &.oui-option-disabled {\r\n color: rgba(0, 0, 0, 0.38);\r\n }\r\n &:last-child {\r\n margin-bottom: 10px;\r\n }\r\n oui-checkbox {\r\n width: 100%;\r\n label {\r\n width: 100%;\r\n display: block;\r\n }\r\n }\r\n }\r\n .oui-option-multiple.oui-selected,\r\n .oui-option-multiple.oui-active {\r\n background: none;\r\n }\r\n .oui-optgroup-label {\r\n font-weight: 700;\r\n }\r\n}\r\n\r\n.oui-form-field-type-oui-select {\r\n &:not(.oui-form-field-disabled) .oui-form-field-flex {\r\n cursor: pointer;\r\n }\r\n\r\n .oui-form-field-label {\r\n width: calc(100% - #{$oui-select-placeholder-arrow-space});\r\n }\r\n}\r\n\r\n.oui-select-placeholder {\r\n // Delay the transition until the label has animated about a third of the way through, in\r\n // order to prevent the placeholder from overlapping for a split second.\r\n @include oui-truncate-line();\r\n display: inline-block;\r\n width: 100%;\r\n transition: color $swift-ease-out-duration\r\n math.div($swift-ease-out-duration, 3) $swift-ease-out-timing-function;\r\n color: #666;\r\n ._oui-animation-noopable & {\r\n transition: none;\r\n }\r\n\r\n .oui-form-field-hide-placeholder & {\r\n color: transparent;\r\n\r\n // Overwrite browser specific CSS properties that can overwrite the `color` property.\r\n // Some developers seem to use this approach to easily overwrite the placeholder / label color.\r\n -webkit-text-fill-color: transparent;\r\n\r\n // Remove the transition to prevent the placeholder\r\n // from overlapping when the label comes back down.\r\n transition: none;\r\n // Prevents the '...' from showing on the parent element.\r\n display: block;\r\n }\r\n}\r\n/*-- search dropdown --*/\r\n\r\n.oui-select-input-outer {\r\n box-sizing: border-box;\r\n}\r\n\r\n/*-- search dropdown --*/\r\n\r\n/*-- search ddropdown --*/\r\n.ui-select-overlay-container {\r\n position: absolute;\r\n}\r\n.oui-select-has-a-panel\r\n .oui-option.oui-selected:not(.oui-option-multiple):not(.oui-option-disabled) {\r\n background: rgba(0, 0, 0, 0.12);\r\n color: #3f51b5;\r\n font-weight: 500;\r\n}\r\n.oui-select-has-a-panel .oui-option:hover:not(.oui-option-disabled) {\r\n background: rgba(0, 0, 0, 0.04);\r\n}\r\n\r\n/*-- search ddropdown --*/\r\n\r\n/*-- search dropdown underline --*/\r\n.oui-form-field-appearance-underline {\r\n .oui-select-trigger {\r\n margin-left: 9px;\r\n .oui-select-value {\r\n overflow: visible;\r\n .oui-select-placeholder,\r\n .oui-select-value-text {\r\n width: 100%;\r\n @include oui-truncate-line();\r\n margin-left: -9px;\r\n display: block;\r\n height: 19px;\r\n }\r\n }\r\n }\r\n .oui-select.oui-input {\r\n border: 1px solid transparent;\r\n padding-left: 0;\r\n padding-right: 0;\r\n border-bottom: 1px solid #c8c8c8;\r\n > div {\r\n padding-right: 9px;\r\n }\r\n &:after {\r\n content: '';\r\n height: 1px;\r\n width: 100%;\r\n background: #c8c8c8;\r\n position: absolute;\r\n left: 0;\r\n bottom: 0;\r\n }\r\n }\r\n}\r\n\r\n.oui-form-field.oui-form-field-appearance-underline .oui-select.oui-input {\r\n &.oui-select-disabled {\r\n border: 1px solid transparent;\r\n border-bottom: 1px solid #e4e4e4;\r\n background: transparent;\r\n &:after {\r\n background: #e4e4e4;\r\n }\r\n }\r\n}\r\n.oui-form-field .oui-select.oui-input {\r\n &.oui-select-disabled {\r\n border: 1px solid #e4e4e4;\r\n background-color: #f9f9f9;\r\n color: #9b9b9b;\r\n cursor: default;\r\n .oui-select-arrow svg path {\r\n fill: #c8c8c8;\r\n }\r\n }\r\n &.oui-form-field-appearance-underline {\r\n .oui-select.oui-input {\r\n transition: border 0.5s, padding 0.5s;\r\n }\r\n }\r\n}\r\n\r\n/*-- search dropdown underline --*/\r\n\r\n.oui-option:focus:not(.oui-option-disabled),\r\n.oui-option:hover:not(.oui-option-disabled),\r\n.oui-option.oui-selected:not(.oui-option-multiple):not(.oui-option-disabled) {\r\n background: $gray-color;\r\n}\r\n\r\n.select-overlay-top.oui-select-panel {\r\n margin-bottom: 9px;\r\n border-top: 1px solid #c8c8c8;\r\n}\r\n\r\n.noResults {\r\n color: #333333;\r\n font-size: 14px;\r\n line-height: 22px;\r\n padding: 0 10px;\r\n margin: 17px 0 21px;\r\n word-break: break-all;\r\n}\r\n\r\noui-select-search {\r\n height: 60px;\r\n display: block;\r\n}\r\n.oui-select-disabled .oui-select-placeholder {\r\n color: #9b9b9b;\r\n}\r\n.oui-select-action-wrapper {\r\n height: 60px;\r\n display: block;\r\n margin-top: 10px;\r\n}\r\n\r\n.oui-select-action-items {\r\n position: absolute;\r\n background: #fff;\r\n bottom: 1px;\r\n border-top: 1px solid #ddd;\r\n padding: 12px 10px;\r\n z-index: 100;\r\n box-sizing: border-box;\r\n width: 100%;\r\n display: flex;\r\n justify-content: space-between;\r\n}\r\n", "styleUrl": "select.scss" } ], @@ -39410,7 +39980,9 @@ } ] }, - "extends": "_OuiSelectMixinBase", + "extends": [ + "_OuiSelectMixinBase" + ], "implements": [ "AfterContentInit", "OnChanges", @@ -39889,19 +40461,19 @@ "description": "

Implemented as part of OuiFormFieldControl.

\n", "jsdoctags": [ { - "pos": 39988, - "end": 40005, - "flags": 4227072, + "pos": 41320, + "end": 41338, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 325, + "kind": 334, "tagName": { - "pos": 39989, - "end": 40001, - "flags": 4227072, + "pos": 41321, + "end": 41333, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "docs-private" }, "comment": "" @@ -39910,7 +40482,7 @@ } } }, - "templateData": "\n
\n \n \n \n \n \n \n \n
\n\n
\n \n
\n\n\n \n
\n \n
\n
\n
\n \n Cancel\n Done\n \n
\n
\n \n
\n" + "templateData": "\r\n
\r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n
\r\n\r\n
\r\n \r\n
\r\n\r\n\r\n \r\n \r\n
\r\n
\r\n \r\n Cancel\r\n Done\r\n \r\n
\r\n
\r\n \r\n
\r\n" }, { "name": "OuiSelectSearchComponent", @@ -39935,6 +40507,7 @@ "./option-search.html" ], "viewProviders": [], + "hostDirectives": [], "inputsClass": [ { "name": "aria-label", @@ -39970,7 +40543,7 @@ "line": 39, "rawdescription": "\nSubject that emits when the component has been destroyed.", "modifierKind": [ - 121 + 123 ] }, { @@ -39982,7 +40555,7 @@ "description": "", "line": 49, "modifierKind": [ - 121 + 123 ] }, { @@ -39995,7 +40568,7 @@ "description": "", "line": 50, "modifierKind": [ - 121 + 123 ] }, { @@ -40023,7 +40596,8 @@ } ], "modifierKind": [ - 123 + 170, + 125 ] }, { @@ -40036,7 +40610,7 @@ "line": 36, "rawdescription": "\nPreviously selected values when using ", "modifierKind": [ - 121 + 123 ] }, { @@ -40053,6 +40627,9 @@ "name": "ViewChild", "stringifiedArguments": "'searchSelectInput', {read: ElementRef, static: true}" } + ], + "modifierKind": [ + 170 ] } ], @@ -40069,7 +40646,7 @@ "rawdescription": "\n\nFocuses the search input field\n", "description": "

Focuses the search input field

\n", "modifierKind": [ - 123 + 125 ] }, { @@ -40092,7 +40669,7 @@ "rawdescription": "\n\nResets the current search value\nfocus whether to focus after resetting\n", "description": "

Resets the current search value\nfocus whether to focus after resetting

\n", "modifierKind": [ - 123 + 125 ], "jsdoctags": [ { @@ -40117,7 +40694,7 @@ "deprecated": false, "deprecationMessage": "", "modifierKind": [ - 121 + 123 ] }, { @@ -40290,7 +40867,7 @@ "deprecated": false, "deprecationMessage": "", "modifierKind": [ - 121 + 123 ] }, { @@ -40326,6 +40903,8 @@ "deprecationMessage": "", "hostBindings": [], "hostListeners": [], + "standalone": false, + "imports": [], "description": "", "rawdescription": "\n", "type": "component", @@ -40333,7 +40912,7 @@ "assetsDirs": [], "styleUrlsData": [ { - "data": "$oui-menu-side-padding: 16px !default;\n$scrollbar-width: 17px;\n$clear-button-width: 20px;\n$multiple-check-width: 33px;\n$defaul-color: #c8c8c8;\n\n.oui-select-search-hidden {\n visibility: hidden;\n}\n.oui-select-search-inner {\n position: absolute;\n background: #fff;\n top: px;\n left: 0px;\n width: 100%;\n z-index: 100;\n padding: 10px;\n box-sizing: border-box;\n &.oui-select-search-inner-multiple {\n width: calc(\n 100% + #{2 * $oui-menu-side-padding - $scrollbar-width +\n $multiple-check-width}\n );\n }\n .oui-select-search-input {\n &:focus {\n border-color: $defaul-color;\n }\n }\n}\n.oui-select-search-panel {\n /* allow absolute positioning relative to outer options container */\n transform: none !important;\n max-height: 150px;\n}\n.oui-select-search-no-entries-found {\n padding: $oui-menu-side-padding;\n}\n.oui-select-search-clear {\n position: absolute;\n right: 0;\n top: 4px;\n}\n", + "data": "$oui-menu-side-padding: 16px !default;\r\n$scrollbar-width: 17px;\r\n$clear-button-width: 20px;\r\n$multiple-check-width: 33px;\r\n$defaul-color: #c8c8c8;\r\n\r\n.oui-select-search-hidden {\r\n visibility: hidden;\r\n}\r\n.oui-select-search-inner {\r\n position: absolute;\r\n background: #fff;\r\n top: 6px;\r\n left: -9px;\r\n width: 100%;\r\n z-index: 100;\r\n padding: 10px;\r\n box-sizing: border-box;\r\n &.oui-select-search-inner-multiple {\r\n width: calc(\r\n 100% + #{2 * $oui-menu-side-padding - $scrollbar-width +\r\n $multiple-check-width}\r\n );\r\n }\r\n .oui-select-search-input {\r\n &:focus {\r\n border-color: $defaul-color;\r\n }\r\n }\r\n}\r\n.oui-select-search-panel {\r\n /* allow absolute positioning relative to outer options container */\r\n transform: none !important;\r\n max-height: 150px;\r\n}\r\n.oui-select-search-no-entries-found {\r\n padding: $oui-menu-side-padding;\r\n}\r\n.oui-select-search-clear {\r\n position: absolute;\r\n right: 0;\r\n top: 4px;\r\n}\r\n", "styleUrl": "./option-search.scss" } ], @@ -40379,6 +40958,7 @@ } ] }, + "extends": [], "implements": [ "OnInit", "AfterViewChecked", @@ -40417,6 +40997,7 @@ "slide-toggle.html" ], "viewProviders": [], + "hostDirectives": [], "inputsClass": [ { "name": "aria-label", @@ -40499,7 +41080,7 @@ "description": "", "line": 62, "modifierKind": [ - 121 + 123 ] }, { @@ -40512,7 +41093,7 @@ "description": "", "line": 65, "modifierKind": [ - 121 + 123 ] }, { @@ -40525,7 +41106,7 @@ "description": "", "line": 64, "modifierKind": [ - 121 + 123 ] }, { @@ -40538,7 +41119,7 @@ "description": "", "line": 96, "modifierKind": [ - 121 + 123 ] }, { @@ -40551,7 +41132,7 @@ "description": "", "line": 97, "modifierKind": [ - 121 + 123 ] }, { @@ -40753,6 +41334,8 @@ "deprecationMessage": "", "hostBindings": [], "hostListeners": [], + "standalone": false, + "imports": [], "description": "

Container for form controls that applies Oncehub Design styling and behavior.

\n", "rawdescription": "\nContainer for form controls that applies Oncehub Design styling and behavior.", "type": "component", @@ -40851,7 +41434,9 @@ } ] }, - "extends": "_OuiSlideToggleMixinBase", + "extends": [ + "_OuiSlideToggleMixinBase" + ], "implements": [ "AfterContentInit", "ControlValueAccessor", @@ -40924,6 +41509,7 @@ "sort-header.html" ], "viewProviders": [], + "hostDirectives": [], "inputsClass": [ { "name": "arrowPosition", @@ -40999,7 +41585,9 @@ } ], "modifierKind": [ - 123 + 170, + 170, + 125 ] }, { @@ -41011,7 +41599,7 @@ "description": "", "line": 145, "modifierKind": [ - 121 + 123 ] }, { @@ -41034,7 +41622,7 @@ "description": "", "line": 148, "modifierKind": [ - 123 + 125 ] }, { @@ -41047,7 +41635,7 @@ "description": "", "line": 146, "modifierKind": [ - 121 + 123 ] }, { @@ -41059,7 +41647,7 @@ "description": "", "line": 98, "modifierKind": [ - 121 + 123 ] }, { @@ -41088,7 +41676,8 @@ } ], "modifierKind": [ - 123 + 170, + 125 ] }, { @@ -41279,6 +41868,8 @@ "deprecationMessage": "", "hostBindings": [], "hostListeners": [], + "standalone": false, + "imports": [], "description": "

Applies sorting behavior (click to change sort) and styles to an element, including an\narrow to display the current sort direction.

\n

Must be provided with an id and contained within a parent OuiSort directive.

\n

If used on header cells in a CdkTable, it will automatically default its id from its containing\ncolumn definition.

\n", "rawdescription": "\n\nApplies sorting behavior (click to change sort) and styles to an element, including an\narrow to display the current sort direction.\n\nMust be provided with an id and contained within a parent OuiSort directive.\n\nIf used on header cells in a CdkTable, it will automatically default its id from its containing\ncolumn definition.\n", "type": "component", @@ -41437,7 +42028,9 @@ } ] }, - "extends": "_OuiSortHeaderMixinBase", + "extends": [ + "_OuiSortHeaderMixinBase" + ], "implements": [ "CanDisable", "OuiSortable", @@ -41488,7 +42081,7 @@ }, { "name": "OuiTab", - "id": "component-OuiTab-45bae687b6cd051731506a0bb8869f3a20d3380d7104d6f3cdfb49e2bd1fdb6c4a90a32d60d32382a5489b93a236c24544d86f0a65f4cca3d9f50ece71ea5c93", + "id": "component-OuiTab-90101422686a726eb69c50499e9ec74197febce4088a5e86c3b704858597fd644e9b89a1b60a173f1983d03998f71c65913b11ac249b411b2c954bfd8a2e0b22", "file": "ui/src/components/tabs/tab.ts", "changeDetection": "ChangeDetectionStrategy.Default", "encapsulation": [ @@ -41512,6 +42105,7 @@ "tab.html" ], "viewProviders": [], + "hostDirectives": [], "inputsClass": [ { "name": "aria-label", @@ -41604,7 +42198,9 @@ } ], "modifierKind": [ - 123 + 170, + 170, + 125 ] }, { @@ -41618,7 +42214,7 @@ "line": 118, "rawdescription": "\nPortal that will be the hosted content of the tab", "modifierKind": [ - 121 + 123 ] }, { @@ -41638,7 +42234,8 @@ } ], "modifierKind": [ - 121 + 170, + 123 ] }, { @@ -41655,6 +42252,9 @@ "name": "ViewChild", "stringifiedArguments": "TemplateRef, {static: true}" } + ], + "modifierKind": [ + 170 ] }, { @@ -41668,7 +42268,7 @@ "line": 126, "rawdescription": "\nEmits whenever the internal state of the tab changes.", "modifierKind": [ - 144 + 148 ] }, { @@ -41684,6 +42284,9 @@ "name": "ViewChild", "stringifiedArguments": "'tab1'" } + ], + "modifierKind": [ + 170 ] }, { @@ -41696,7 +42299,7 @@ "line": 69, "rawdescription": "\nContent for the tab label given by ``.", "modifierKind": [ - 121 + 123 ] }, { @@ -41762,7 +42365,7 @@ "rawdescription": "\n\nThis has been extracted to a util because of TS 4 and VE.\nView Engine doesn't support property rename inheritance.\nTS 4.0 doesn't allow properties to override accessors or vice-versa.\n", "description": "

This has been extracted to a util because of TS 4 and VE.\nView Engine doesn't support property rename inheritance.\nTS 4.0 doesn't allow properties to override accessors or vice-versa.

\n", "modifierKind": [ - 121 + 123 ], "jsdoctags": [ { @@ -41839,10 +42442,12 @@ "deprecationMessage": "", "hostBindings": [], "hostListeners": [], + "standalone": false, + "imports": [], "description": "", "rawdescription": "\n", "type": "component", - "sourceCode": "import {\n ChangeDetectionStrategy,\n Component,\n ContentChild,\n ElementRef,\n Inject,\n InjectionToken,\n Input,\n OnChanges,\n OnDestroy,\n OnInit,\n Optional,\n SimpleChanges,\n TemplateRef,\n ViewChild,\n ViewContainerRef,\n ViewEncapsulation,\n} from '@angular/core';\nimport { OuiTabContent } from './tab-content';\nimport { OUI_TAB, OuiTabLabel } from './tab-label';\nimport { CanDisable, mixinColor } from '../core';\nimport { TemplatePortal } from '@angular/cdk/portal';\nimport { Subject } from 'rxjs';\n\nexport class OuiTabsBase {\n constructor(public _elementRef: ElementRef) {}\n}\n// Boilerplate for applying mixins to OuiTab.\n/** @docs-private */\nconst _OuiTabMixinBase: typeof OuiTabsBase = mixinColor(OuiTabsBase);\n\n/**\n * Used to provide a tab group to a tab without causing a circular dependency.\n * @docs-private\n */\nexport const OUI_TAB_GROUP = new InjectionToken('OUI_TAB_GROUP');\n\n/** Default color palette for the tab */\nconst DEFAULT_COLOR = 'primary';\n\n@Component({\n selector: 'oui-tab',\n\n // Note that usually we'd go through a bit more trouble and set up another class so that\n // the inlined template of `OuiTab` isn't duplicated, however the template is small enough\n // that creating the extra class will generate more code than just duplicating the template.\n templateUrl: 'tab.html',\n // eslint-disable-next-line @angular-eslint/no-inputs-metadata-property\n inputs: ['disabled'],\n // eslint-disable-next-line @angular-eslint/no-inputs-metadata-property\n changeDetection: ChangeDetectionStrategy.Default,\n encapsulation: ViewEncapsulation.None,\n exportAs: 'OuiTab',\n providers: [{ provide: OUI_TAB, useExisting: OuiTab }],\n})\nexport class OuiTab\n extends _OuiTabMixinBase\n implements CanDisable, OnInit, OnChanges, OnDestroy\n{\n /** Content for the tab label given by ``. */\n private _templateLabel: OuiTabLabel;\n disabled: any;\n @ContentChild(OuiTabLabel)\n get templateLabel(): OuiTabLabel {\n return this._templateLabel;\n }\n set templateLabel(value: OuiTabLabel) {\n this._setTemplateLabelInput(value);\n }\n\n /**\n * Template provided in the tab content that will be used if present, used to enable lazy-loading\n */\n @ContentChild(OuiTabContent, { read: TemplateRef, static: true })\n // We need an initializer here to avoid a TS error. The value will be set in `ngAfterViewInit`.\n private _explicitContent: TemplateRef = undefined!;\n\n /** Template inside the OuiTab view that contains an ``. */\n @ViewChild(TemplateRef, { static: true }) _implicitContent: TemplateRef;\n\n /** Plain text label for the tab, used when there is no template label. */\n @Input('label') textLabel = '';\n\n @Input('text') givenText = '';\n\n /** Aria label for the tab. */\n @Input('aria-label') ariaLabel: string;\n\n @Input() color = 'accent';\n\n /**\n * Reference to the element that the tab is labelled by.\n * Will be cleared if `aria-label` is set at the same time.\n */\n @Input('aria-labelledby') ariaLabelledby: string;\n\n /**\n * Classes to be passed to the tab label inside the oui-tab-header container.\n * Supports string and string array values, same as `ngClass`.\n */\n @Input() labelClass: string | string[];\n\n /**\n * Classes to be passed to the tab oui-tab-body container.\n * Supports string and string array values, same as `ngClass`.\n */\n @Input() bodyClass: string | string[];\n\n /** Portal that will be the hosted content of the tab */\n private _contentPortal: TemplatePortal | null = null;\n\n /** @docs-private */\n get content(): TemplatePortal | null {\n return this._contentPortal;\n }\n\n /** Emits whenever the internal state of the tab changes. */\n readonly _stateChanges = new Subject();\n\n /**\n * The relatively indexed position where 0 represents the center, negative is left, and positive\n * represents the right.\n */\n position: number | null = null;\n\n /**\n * The initial relatively index origin of the tab if it was created and selected after there\n * was already a selected tab. Provides context of what position the tab should originate from.\n */\n origin: number | null = null;\n\n /**\n * Whether the tab is currently active.\n */\n isActive = false;\n\n @ViewChild('tab1') _tab1: ElementRef;\n constructor(\n private _viewContainerRef: ViewContainerRef,\n @Inject(OUI_TAB_GROUP) @Optional() public _closestTabGroup: any,\n _elementRef: ElementRef\n ) {\n super(_elementRef);\n this.addThemeColor();\n }\n\n ngOnChanges(changes: SimpleChanges): void {\n if (\n Object.prototype.hasOwnProperty.call(changes, 'textLabel') ||\n Object.prototype.hasOwnProperty.call(changes, 'disabled')\n ) {\n this._stateChanges.next();\n }\n if (\n Object.prototype.hasOwnProperty.call(changes, '_tab2') ||\n Object.prototype.hasOwnProperty.call(changes, 'disabled')\n ) {\n this._stateChanges.next();\n }\n }\n\n addThemeColor() {\n if (!this.color) {\n this.color = DEFAULT_COLOR;\n }\n }\n\n ngOnDestroy(): void {\n this._stateChanges.complete();\n }\n\n ngOnInit(): void {\n this._contentPortal = new TemplatePortal(\n this._explicitContent || this._implicitContent,\n this._viewContainerRef,\n this._tab1\n );\n }\n\n /**\n * This has been extracted to a util because of TS 4 and VE.\n * View Engine doesn't support property rename inheritance.\n * TS 4.0 doesn't allow properties to override accessors or vice-versa.\n * @docs-private\n */\n private _setTemplateLabelInput(value: OuiTabLabel | undefined) {\n // Only update the label if the query managed to find one. This works around an issue where a\n // user may have manually set `templateLabel` during creation mode, which would then get\n // clobbered by `undefined` when the query resolves. Also note that we check that the closest\n // tab matches the current one so that we don't pick up labels from nested tabs.\n if (value && value._closestTab === this) {\n this._templateLabel = value;\n }\n }\n}\n", + "sourceCode": "import {\r\n ChangeDetectionStrategy,\r\n Component,\r\n ContentChild,\r\n ElementRef,\r\n Inject,\r\n InjectionToken,\r\n Input,\r\n OnChanges,\r\n OnDestroy,\r\n OnInit,\r\n Optional,\r\n SimpleChanges,\r\n TemplateRef,\r\n ViewChild,\r\n ViewContainerRef,\r\n ViewEncapsulation,\r\n} from '@angular/core';\r\nimport { OuiTabContent } from './tab-content';\r\nimport { OUI_TAB, OuiTabLabel } from './tab-label';\r\nimport { CanDisable, mixinColor } from '../core';\r\nimport { TemplatePortal } from '@angular/cdk/portal';\r\nimport { Subject } from 'rxjs';\r\n\r\nexport class OuiTabsBase {\r\n constructor(public _elementRef: ElementRef) {}\r\n}\r\n// Boilerplate for applying mixins to OuiTab.\r\n/** @docs-private */\r\nconst _OuiTabMixinBase: typeof OuiTabsBase = mixinColor(OuiTabsBase);\r\n\r\n/**\r\n * Used to provide a tab group to a tab without causing a circular dependency.\r\n * @docs-private\r\n */\r\nexport const OUI_TAB_GROUP = new InjectionToken('OUI_TAB_GROUP');\r\n\r\n/** Default color palette for the tab */\r\nconst DEFAULT_COLOR = 'primary';\r\n\r\n@Component({\r\n selector: 'oui-tab',\r\n\r\n // Note that usually we'd go through a bit more trouble and set up another class so that\r\n // the inlined template of `OuiTab` isn't duplicated, however the template is small enough\r\n // that creating the extra class will generate more code than just duplicating the template.\r\n templateUrl: 'tab.html',\r\n // eslint-disable-next-line @angular-eslint/no-inputs-metadata-property\r\n inputs: ['disabled'],\r\n // eslint-disable-next-line @angular-eslint/no-inputs-metadata-property\r\n changeDetection: ChangeDetectionStrategy.Default,\r\n encapsulation: ViewEncapsulation.None,\r\n exportAs: 'OuiTab',\r\n providers: [{ provide: OUI_TAB, useExisting: OuiTab }],\r\n})\r\nexport class OuiTab\r\n extends _OuiTabMixinBase\r\n implements CanDisable, OnInit, OnChanges, OnDestroy\r\n{\r\n /** Content for the tab label given by ``. */\r\n private _templateLabel: OuiTabLabel;\r\n disabled: any;\r\n @ContentChild(OuiTabLabel)\r\n get templateLabel(): OuiTabLabel {\r\n return this._templateLabel;\r\n }\r\n set templateLabel(value: OuiTabLabel) {\r\n this._setTemplateLabelInput(value);\r\n }\r\n\r\n /**\r\n * Template provided in the tab content that will be used if present, used to enable lazy-loading\r\n */\r\n @ContentChild(OuiTabContent, { read: TemplateRef, static: true })\r\n // We need an initializer here to avoid a TS error. The value will be set in `ngAfterViewInit`.\r\n private _explicitContent: TemplateRef = undefined!;\r\n\r\n /** Template inside the OuiTab view that contains an ``. */\r\n @ViewChild(TemplateRef, { static: true }) _implicitContent: TemplateRef;\r\n\r\n /** Plain text label for the tab, used when there is no template label. */\r\n @Input('label') textLabel = '';\r\n\r\n @Input('text') givenText = '';\r\n\r\n /** Aria label for the tab. */\r\n @Input('aria-label') ariaLabel: string;\r\n\r\n @Input() color = 'accent';\r\n\r\n /**\r\n * Reference to the element that the tab is labelled by.\r\n * Will be cleared if `aria-label` is set at the same time.\r\n */\r\n @Input('aria-labelledby') ariaLabelledby: string;\r\n\r\n /**\r\n * Classes to be passed to the tab label inside the oui-tab-header container.\r\n * Supports string and string array values, same as `ngClass`.\r\n */\r\n @Input() labelClass: string | string[];\r\n\r\n /**\r\n * Classes to be passed to the tab oui-tab-body container.\r\n * Supports string and string array values, same as `ngClass`.\r\n */\r\n @Input() bodyClass: string | string[];\r\n\r\n /** Portal that will be the hosted content of the tab */\r\n private _contentPortal: TemplatePortal | null = null;\r\n\r\n /** @docs-private */\r\n get content(): TemplatePortal | null {\r\n return this._contentPortal;\r\n }\r\n\r\n /** Emits whenever the internal state of the tab changes. */\r\n readonly _stateChanges = new Subject();\r\n\r\n /**\r\n * The relatively indexed position where 0 represents the center, negative is left, and positive\r\n * represents the right.\r\n */\r\n position: number | null = null;\r\n\r\n /**\r\n * The initial relatively index origin of the tab if it was created and selected after there\r\n * was already a selected tab. Provides context of what position the tab should originate from.\r\n */\r\n origin: number | null = null;\r\n\r\n /**\r\n * Whether the tab is currently active.\r\n */\r\n isActive = false;\r\n\r\n @ViewChild('tab1') _tab1: ElementRef;\r\n constructor(\r\n private _viewContainerRef: ViewContainerRef,\r\n @Inject(OUI_TAB_GROUP) @Optional() public _closestTabGroup: any,\r\n _elementRef: ElementRef\r\n ) {\r\n super(_elementRef);\r\n this.addThemeColor();\r\n }\r\n\r\n ngOnChanges(changes: SimpleChanges): void {\r\n if (\r\n Object.prototype.hasOwnProperty.call(changes, 'textLabel') ||\r\n Object.prototype.hasOwnProperty.call(changes, 'disabled')\r\n ) {\r\n this._stateChanges.next();\r\n }\r\n if (\r\n Object.prototype.hasOwnProperty.call(changes, '_tab2') ||\r\n Object.prototype.hasOwnProperty.call(changes, 'disabled')\r\n ) {\r\n this._stateChanges.next();\r\n }\r\n }\r\n\r\n addThemeColor() {\r\n if (!this.color) {\r\n this.color = DEFAULT_COLOR;\r\n }\r\n }\r\n\r\n ngOnDestroy(): void {\r\n this._stateChanges.complete();\r\n }\r\n\r\n ngOnInit(): void {\r\n this._contentPortal = new TemplatePortal(\r\n this._explicitContent || this._implicitContent,\r\n this._viewContainerRef,\r\n this._tab1\r\n );\r\n }\r\n\r\n /**\r\n * This has been extracted to a util because of TS 4 and VE.\r\n * View Engine doesn't support property rename inheritance.\r\n * TS 4.0 doesn't allow properties to override accessors or vice-versa.\r\n * @docs-private\r\n */\r\n private _setTemplateLabelInput(value: OuiTabLabel | undefined) {\r\n // Only update the label if the query managed to find one. This works around an issue where a\r\n // user may have manually set `templateLabel` during creation mode, which would then get\r\n // clobbered by `undefined` when the query resolves. Also note that we check that the closest\r\n // tab matches the current one so that we don't pick up labels from nested tabs.\r\n if (value && value._closestTab === this) {\r\n this._templateLabel = value;\r\n }\r\n }\r\n}\r\n", "assetsDirs": [], "styleUrlsData": "", "stylesData": "", @@ -41902,7 +42507,9 @@ } ] }, - "extends": "_OuiTabMixinBase", + "extends": [ + "_OuiTabMixinBase" + ], "implements": [ "CanDisable", "OnInit", @@ -41957,19 +42564,19 @@ "description": "", "jsdoctags": [ { - "pos": 3727, - "end": 3741, - "flags": 4227072, + "pos": 3846, + "end": 3860, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 325, + "kind": 334, "tagName": { - "pos": 3728, - "end": 3740, - "flags": 4227072, + "pos": 3847, + "end": 3859, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "docs-private" }, "comment": "" @@ -41978,11 +42585,11 @@ } } }, - "templateData": "\n\n" + "templateData": "\r\n\r\n" }, { "name": "OuiTabBody", - "id": "component-OuiTabBody-d9aba0e7f5c272163d8a1fcdea5954740c5bac6598de09205831a017a4275c387861d98bd5093d058798cb1713335c4f3d57c032469562999ee21727593e8750", + "id": "component-OuiTabBody-35910442aae2ae956d9d640aaca92c9ecb135a5b0cac0d799979fba8976ff19c4489f5f438564beb0bb143fbe9b12783c9ba692171c5c13d4e4497c1d052be96", "file": "ui/src/components/tabs/tab-body.ts", "changeDetection": "ChangeDetectionStrategy.Default", "encapsulation": [ @@ -42000,6 +42607,7 @@ "tab-body.html" ], "viewProviders": [], + "hostDirectives": [], "inputsClass": [ { "name": "animationDuration", @@ -42077,7 +42685,7 @@ }, { "name": "_onCentered", - "defaultValue": "new EventEmitter(\n true\n )", + "defaultValue": "new EventEmitter(\r\n true\r\n )", "deprecated": false, "deprecationMessage": "", "rawdescription": "\nEvent emitted when the tab completes its animation towards the center.", @@ -42108,7 +42716,7 @@ "line": 118, "rawdescription": "\nSubscription to the directionality change observable.", "modifierKind": [ - 121 + 123 ] }, { @@ -42134,6 +42742,9 @@ "name": "ViewChild", "stringifiedArguments": "CdkPortalOutlet" } + ], + "modifierKind": [ + 170 ] }, { @@ -42156,7 +42767,7 @@ "line": 115, "rawdescription": "\nCurrent position of the tab-body in the tab-group. Zero means that the tab is visible.", "modifierKind": [ - 121 + 123 ] }, { @@ -42170,7 +42781,7 @@ "line": 124, "rawdescription": "\nEmits when an animation on the tab is complete.", "modifierKind": [ - 144 + 148 ] } ], @@ -42195,7 +42806,7 @@ "rawdescription": "\nComputes the position state that will be used for the tab-body animation trigger.", "description": "

Computes the position state that will be used for the tab-body animation trigger.

\n", "modifierKind": [ - 121 + 123 ], "jsdoctags": [ { @@ -42229,7 +42840,7 @@ "rawdescription": "\n\nComputes the position state based on the specified origin position. This is used if the\ntab is becoming visible immediately after creation.\n", "description": "

Computes the position state based on the specified origin position. This is used if the\ntab is becoming visible immediately after creation.

\n", "modifierKind": [ - 121 + 123 ], "jsdoctags": [ { @@ -42340,10 +42951,12 @@ "deprecationMessage": "", "hostBindings": [], "hostListeners": [], + "standalone": false, + "imports": [], "description": "

Wrapper for the contents of a tab.

\n", "rawdescription": "\n\nWrapper for the contents of a tab.\n", "type": "component", - "sourceCode": "import {\n ChangeDetectionStrategy,\n ChangeDetectorRef,\n Component,\n ComponentFactoryResolver,\n Directive,\n ElementRef,\n EventEmitter,\n // forwardRef,\n Inject,\n Input,\n OnDestroy,\n OnInit,\n Optional,\n Output,\n ViewChild,\n ViewContainerRef,\n ViewEncapsulation,\n} from '@angular/core';\nimport { CdkPortalOutlet } from '@angular/cdk/portal';\nimport { Direction, Directionality } from '@angular/cdk/bidi';\nimport { DOCUMENT } from '@angular/common';\nimport { Subject, Subscription } from 'rxjs';\nimport {\n distinctUntilChanged,\n // startWith\n} from 'rxjs/operators';\nimport { AnimationEvent } from '@angular/animations';\nimport { ouiTabsAnimations } from './tabs-animations';\n\n/**\n * The portal host directive for the contents of the tab.\n * @docs-private\n */\n\n@Directive({\n // eslint-disable-next-line @angular-eslint/directive-selector\n selector: `OuiTabBodyHost`,\n})\nexport class OuiTabBodyPortal\n extends CdkPortalOutlet\n implements OnInit, OnDestroy\n{\n /** Subscription to events for when the tab body begins centering. */\n private _centeringSub = Subscription.EMPTY;\n /** Subscription to events for when the tab body finishes leaving from center position. */\n private _leavingSub = Subscription.EMPTY;\n\n constructor(\n componentFactoryResolver: ComponentFactoryResolver,\n viewContainerRef: ViewContainerRef,\n // @Inject(forwardRef(() => OuiTabBody)) private _host: OuiTabBody,\n @Inject(DOCUMENT) _document: any\n ) {\n super(componentFactoryResolver, viewContainerRef, _document);\n }\n\n /** Set initial visibility or set up subscription for changing visibility. */\n override ngOnInit(): void {\n super.ngOnInit();\n }\n\n /** Clean up centering subscription. */\n override ngOnDestroy(): void {\n super.ngOnDestroy();\n this._centeringSub.unsubscribe();\n this._leavingSub.unsubscribe();\n }\n}\n\n/**\n * These position states are used internally as animation states for the tab body. Setting the\n * position state to left, right, or center will transition the tab body from its current\n * position to its respective state. If there is not current position (void, in the case of a new\n * tab body), then there will be no transition animation to its state.\n *\n * In the case of a new tab body that should immediately be centered with an animating transition,\n * then left-origin-center or right-origin-center can be used, which will use left or right as its\n * pseudo-prior state.\n */\nexport type OuiTabBodyPositionState =\n | 'left'\n | 'center'\n | 'right'\n | 'left-origin-center'\n | 'right-origin-center';\n\n/**\n * Wrapper for the contents of a tab.\n * @docs-private\n */\n@Component({\n selector: 'oui-tab-body',\n templateUrl: 'tab-body.html',\n // styleUrls: ['tab-body.css'],\n encapsulation: ViewEncapsulation.None,\n // tslint:disable-next-line:validate-decorators\n changeDetection: ChangeDetectionStrategy.Default,\n animations: [ouiTabsAnimations.translateTab],\n // eslint-disable-next-line @angular-eslint/no-host-metadata-property\n host: {\n class: 'oui-mdc-tab-body',\n },\n})\nexport class OuiTabBody implements OnInit, OnDestroy {\n /** Current position of the tab-body in the tab-group. Zero means that the tab is visible. */\n private _positionIndex: number;\n\n /** Subscription to the directionality change observable. */\n private _dirChangeSubscription = Subscription.EMPTY;\n\n /** Tab body position state. Used by the animation trigger for the current state. */\n _position: OuiTabBodyPositionState;\n\n /** Emits when an animation on the tab is complete. */\n readonly _translateTabComplete = new Subject();\n\n /** Event emitted when the tab begins to animate towards the center as the active tab. */\n @Output() readonly _onCentering: EventEmitter =\n new EventEmitter();\n\n /** Event emitted before the centering of the tab begins. */\n @Output() readonly _beforeCentering: EventEmitter =\n new EventEmitter();\n\n /** Event emitted before the centering of the tab begins. */\n @Output() readonly _afterLeavingCenter: EventEmitter =\n new EventEmitter();\n\n /** Event emitted when the tab completes its animation towards the center. */\n @Output() readonly _onCentered: EventEmitter = new EventEmitter(\n true\n );\n\n /** The portal host inside of this container into which the tab body content will be loaded. */\n @ViewChild(CdkPortalOutlet) _portalHost: CdkPortalOutlet;\n\n /** The tab body content to display. */\n @Input('content') _content: any;\n\n /** Position that will be used when the tab is immediately becoming visible after creation. */\n @Input() origin: number | null;\n\n // Note that the default value will always be overwritten by `OuiTabBody`, but we need one\n // anyway to prevent the animations module from throwing an error if the body is used on its own.\n /** Duration for the tab's animation. */\n @Input() animationDuration = '0';\n\n /** Whether the tab's content should be kept in the DOM while it's off-screen. */\n @Input() preserveContent = false;\n _innerContent: any;\n\n /** The shifted index position of the tab body, where zero represents the active center tab. */\n @Input()\n set position(position: number) {\n this._positionIndex = position;\n this._computePositionAnimationState();\n }\n\n constructor(\n private _elementRef: ElementRef,\n @Optional() private _dir: Directionality,\n changeDetectorRef: ChangeDetectorRef\n ) {\n if (_dir) {\n this._dirChangeSubscription = _dir.change.subscribe((dir: Direction) => {\n this._computePositionAnimationState(dir);\n changeDetectorRef.markForCheck();\n });\n }\n\n // Ensure that we get unique animation events, because the `.done` callback can get\n // invoked twice in some browsers. See https://github.com/angular/angular/issues/24084.\n this._translateTabComplete\n .pipe(\n distinctUntilChanged((x, y) => {\n return x.fromState === y.fromState && x.toState === y.toState;\n })\n )\n .subscribe((event) => {\n // If the transition to the center is complete, emit an event.\n if (\n this._isCenterPosition(event.toState) &&\n this._isCenterPosition(this._position)\n ) {\n this._onCentered.emit();\n }\n\n if (\n this._isCenterPosition(event.fromState) &&\n !this._isCenterPosition(this._position)\n ) {\n this._afterLeavingCenter.emit();\n }\n });\n }\n\n /**\n * After initialized, check if the content is centered and has an origin. If so, set the\n * special position states that transition the tab from the left or right before centering.\n */\n ngOnInit() {\n if (this._position == 'center' && this.origin != null) {\n this._position = this._computePositionFromOrigin(this.origin);\n }\n this._innerContent = this._content ? this._content : '';\n }\n\n ngOnDestroy() {\n this._dirChangeSubscription.unsubscribe();\n this._translateTabComplete.complete();\n }\n\n _onTranslateTabStarted(event: AnimationEvent): void {\n const isCentering = this._isCenterPosition(event.toState);\n this._beforeCentering.emit(isCentering);\n if (isCentering) {\n this._onCentering.emit(this._elementRef.nativeElement.clientHeight);\n }\n }\n\n /** The text direction of the containing app. */\n _getLayoutDirection(): Direction {\n return this._dir && this._dir.value === 'rtl' ? 'rtl' : 'ltr';\n }\n\n /** Whether the provided position state is considered center, regardless of origin. */\n _isCenterPosition(position: OuiTabBodyPositionState | string): boolean {\n return (\n position == 'center' ||\n position == 'left-origin-center' ||\n position == 'right-origin-center'\n );\n }\n\n /** Computes the position state that will be used for the tab-body animation trigger. */\n private _computePositionAnimationState(\n dir: Direction = this._getLayoutDirection()\n ) {\n if (this._positionIndex < 0) {\n this._position = dir == 'ltr' ? 'left' : 'right';\n } else if (this._positionIndex > 0) {\n this._position = dir == 'ltr' ? 'right' : 'left';\n } else {\n this._position = 'center';\n }\n }\n\n /**\n * Computes the position state based on the specified origin position. This is used if the\n * tab is becoming visible immediately after creation.\n */\n private _computePositionFromOrigin(origin: number): OuiTabBodyPositionState {\n const dir = this._getLayoutDirection();\n\n if ((dir == 'ltr' && origin <= 0) || (dir == 'rtl' && origin > 0)) {\n return 'left-origin-center';\n }\n\n return 'right-origin-center';\n }\n}\n\n/**\n * The origin state is an internally used state that is set on a new tab body indicating if it\n * began to the left or right of the prior selected index. For example, if the selected index was\n * set to 1, and a new tab is created and selected at index 2, then the tab body would have an\n * origin of right because its index was greater than the prior selected index.\n */\nexport type OuiTabBodyOriginState = 'left' | 'right';\n", + "sourceCode": "import {\r\n ChangeDetectionStrategy,\r\n ChangeDetectorRef,\r\n Component,\r\n ComponentFactoryResolver,\r\n Directive,\r\n ElementRef,\r\n EventEmitter,\r\n // forwardRef,\r\n Inject,\r\n Input,\r\n OnDestroy,\r\n OnInit,\r\n Optional,\r\n Output,\r\n ViewChild,\r\n ViewContainerRef,\r\n ViewEncapsulation,\r\n} from '@angular/core';\r\nimport { CdkPortalOutlet } from '@angular/cdk/portal';\r\nimport { Direction, Directionality } from '@angular/cdk/bidi';\r\nimport { DOCUMENT } from '@angular/common';\r\nimport { Subject, Subscription } from 'rxjs';\r\nimport {\r\n distinctUntilChanged,\r\n // startWith\r\n} from 'rxjs/operators';\r\nimport { AnimationEvent } from '@angular/animations';\r\nimport { ouiTabsAnimations } from './tabs-animations';\r\n\r\n/**\r\n * The portal host directive for the contents of the tab.\r\n * @docs-private\r\n */\r\n\r\n@Directive({\r\n // eslint-disable-next-line @angular-eslint/directive-selector\r\n selector: `OuiTabBodyHost`,\r\n})\r\nexport class OuiTabBodyPortal\r\n extends CdkPortalOutlet\r\n implements OnInit, OnDestroy\r\n{\r\n /** Subscription to events for when the tab body begins centering. */\r\n private _centeringSub = Subscription.EMPTY;\r\n /** Subscription to events for when the tab body finishes leaving from center position. */\r\n private _leavingSub = Subscription.EMPTY;\r\n\r\n constructor(\r\n componentFactoryResolver: ComponentFactoryResolver,\r\n viewContainerRef: ViewContainerRef,\r\n // @Inject(forwardRef(() => OuiTabBody)) private _host: OuiTabBody,\r\n @Inject(DOCUMENT) _document: any\r\n ) {\r\n super(componentFactoryResolver, viewContainerRef, _document);\r\n }\r\n\r\n /** Set initial visibility or set up subscription for changing visibility. */\r\n override ngOnInit(): void {\r\n super.ngOnInit();\r\n }\r\n\r\n /** Clean up centering subscription. */\r\n override ngOnDestroy(): void {\r\n super.ngOnDestroy();\r\n this._centeringSub.unsubscribe();\r\n this._leavingSub.unsubscribe();\r\n }\r\n}\r\n\r\n/**\r\n * These position states are used internally as animation states for the tab body. Setting the\r\n * position state to left, right, or center will transition the tab body from its current\r\n * position to its respective state. If there is not current position (void, in the case of a new\r\n * tab body), then there will be no transition animation to its state.\r\n *\r\n * In the case of a new tab body that should immediately be centered with an animating transition,\r\n * then left-origin-center or right-origin-center can be used, which will use left or right as its\r\n * pseudo-prior state.\r\n */\r\nexport type OuiTabBodyPositionState =\r\n | 'left'\r\n | 'center'\r\n | 'right'\r\n | 'left-origin-center'\r\n | 'right-origin-center';\r\n\r\n/**\r\n * Wrapper for the contents of a tab.\r\n * @docs-private\r\n */\r\n@Component({\r\n selector: 'oui-tab-body',\r\n templateUrl: 'tab-body.html',\r\n // styleUrls: ['tab-body.css'],\r\n encapsulation: ViewEncapsulation.None,\r\n // tslint:disable-next-line:validate-decorators\r\n changeDetection: ChangeDetectionStrategy.Default,\r\n animations: [ouiTabsAnimations.translateTab],\r\n // eslint-disable-next-line @angular-eslint/no-host-metadata-property\r\n host: {\r\n class: 'oui-mdc-tab-body',\r\n },\r\n})\r\nexport class OuiTabBody implements OnInit, OnDestroy {\r\n /** Current position of the tab-body in the tab-group. Zero means that the tab is visible. */\r\n private _positionIndex: number;\r\n\r\n /** Subscription to the directionality change observable. */\r\n private _dirChangeSubscription = Subscription.EMPTY;\r\n\r\n /** Tab body position state. Used by the animation trigger for the current state. */\r\n _position: OuiTabBodyPositionState;\r\n\r\n /** Emits when an animation on the tab is complete. */\r\n readonly _translateTabComplete = new Subject();\r\n\r\n /** Event emitted when the tab begins to animate towards the center as the active tab. */\r\n @Output() readonly _onCentering: EventEmitter =\r\n new EventEmitter();\r\n\r\n /** Event emitted before the centering of the tab begins. */\r\n @Output() readonly _beforeCentering: EventEmitter =\r\n new EventEmitter();\r\n\r\n /** Event emitted before the centering of the tab begins. */\r\n @Output() readonly _afterLeavingCenter: EventEmitter =\r\n new EventEmitter();\r\n\r\n /** Event emitted when the tab completes its animation towards the center. */\r\n @Output() readonly _onCentered: EventEmitter = new EventEmitter(\r\n true\r\n );\r\n\r\n /** The portal host inside of this container into which the tab body content will be loaded. */\r\n @ViewChild(CdkPortalOutlet) _portalHost: CdkPortalOutlet;\r\n\r\n /** The tab body content to display. */\r\n @Input('content') _content: any;\r\n\r\n /** Position that will be used when the tab is immediately becoming visible after creation. */\r\n @Input() origin: number | null;\r\n\r\n // Note that the default value will always be overwritten by `OuiTabBody`, but we need one\r\n // anyway to prevent the animations module from throwing an error if the body is used on its own.\r\n /** Duration for the tab's animation. */\r\n @Input() animationDuration = '0';\r\n\r\n /** Whether the tab's content should be kept in the DOM while it's off-screen. */\r\n @Input() preserveContent = false;\r\n _innerContent: any;\r\n\r\n /** The shifted index position of the tab body, where zero represents the active center tab. */\r\n @Input()\r\n set position(position: number) {\r\n this._positionIndex = position;\r\n this._computePositionAnimationState();\r\n }\r\n\r\n constructor(\r\n private _elementRef: ElementRef,\r\n @Optional() private _dir: Directionality,\r\n changeDetectorRef: ChangeDetectorRef\r\n ) {\r\n if (_dir) {\r\n this._dirChangeSubscription = _dir.change.subscribe((dir: Direction) => {\r\n this._computePositionAnimationState(dir);\r\n changeDetectorRef.markForCheck();\r\n });\r\n }\r\n\r\n // Ensure that we get unique animation events, because the `.done` callback can get\r\n // invoked twice in some browsers. See https://github.com/angular/angular/issues/24084.\r\n this._translateTabComplete\r\n .pipe(\r\n distinctUntilChanged((x, y) => {\r\n return x.fromState === y.fromState && x.toState === y.toState;\r\n })\r\n )\r\n .subscribe((event) => {\r\n // If the transition to the center is complete, emit an event.\r\n if (\r\n this._isCenterPosition(event.toState) &&\r\n this._isCenterPosition(this._position)\r\n ) {\r\n this._onCentered.emit();\r\n }\r\n\r\n if (\r\n this._isCenterPosition(event.fromState) &&\r\n !this._isCenterPosition(this._position)\r\n ) {\r\n this._afterLeavingCenter.emit();\r\n }\r\n });\r\n }\r\n\r\n /**\r\n * After initialized, check if the content is centered and has an origin. If so, set the\r\n * special position states that transition the tab from the left or right before centering.\r\n */\r\n ngOnInit() {\r\n if (this._position == 'center' && this.origin != null) {\r\n this._position = this._computePositionFromOrigin(this.origin);\r\n }\r\n this._innerContent = this._content ? this._content : '';\r\n }\r\n\r\n ngOnDestroy() {\r\n this._dirChangeSubscription.unsubscribe();\r\n this._translateTabComplete.complete();\r\n }\r\n\r\n _onTranslateTabStarted(event: AnimationEvent): void {\r\n const isCentering = this._isCenterPosition(event.toState);\r\n this._beforeCentering.emit(isCentering);\r\n if (isCentering) {\r\n this._onCentering.emit(this._elementRef.nativeElement.clientHeight);\r\n }\r\n }\r\n\r\n /** The text direction of the containing app. */\r\n _getLayoutDirection(): Direction {\r\n return this._dir && this._dir.value === 'rtl' ? 'rtl' : 'ltr';\r\n }\r\n\r\n /** Whether the provided position state is considered center, regardless of origin. */\r\n _isCenterPosition(position: OuiTabBodyPositionState | string): boolean {\r\n return (\r\n position == 'center' ||\r\n position == 'left-origin-center' ||\r\n position == 'right-origin-center'\r\n );\r\n }\r\n\r\n /** Computes the position state that will be used for the tab-body animation trigger. */\r\n private _computePositionAnimationState(\r\n dir: Direction = this._getLayoutDirection()\r\n ) {\r\n if (this._positionIndex < 0) {\r\n this._position = dir == 'ltr' ? 'left' : 'right';\r\n } else if (this._positionIndex > 0) {\r\n this._position = dir == 'ltr' ? 'right' : 'left';\r\n } else {\r\n this._position = 'center';\r\n }\r\n }\r\n\r\n /**\r\n * Computes the position state based on the specified origin position. This is used if the\r\n * tab is becoming visible immediately after creation.\r\n */\r\n private _computePositionFromOrigin(origin: number): OuiTabBodyPositionState {\r\n const dir = this._getLayoutDirection();\r\n\r\n if ((dir == 'ltr' && origin <= 0) || (dir == 'rtl' && origin > 0)) {\r\n return 'left-origin-center';\r\n }\r\n\r\n return 'right-origin-center';\r\n }\r\n}\r\n\r\n/**\r\n * The origin state is an internally used state that is set on a new tab body indicating if it\r\n * began to the left or right of the prior selected index. For example, if the selected index was\r\n * set to 1, and a new tab is created and selected at index 2, then the tab body would have an\r\n * origin of right because its index was greater than the prior selected index.\r\n */\r\nexport type OuiTabBodyOriginState = 'left' | 'right';\r\n", "assetsDirs": [], "styleUrlsData": "", "stylesData": "", @@ -42403,6 +43016,7 @@ } ] }, + "extends": [], "implements": [ "OnInit", "OnDestroy" @@ -42441,11 +43055,11 @@ } } }, - "templateData": "\n \n \n\n" + "templateData": "
\r\n \r\n \r\n
\r\n" }, { "name": "ouiTabGroup", - "id": "component-ouiTabGroup-4d0b5030ca195d184c74343feab780aa235b8d985fd04212cdaaa64ed005edd09a6056c8ba4c4954752c47f07323482c45b313640a731c2d5d0547df5865b67d", + "id": "component-ouiTabGroup-589c514ba2f48297f4aa02fd4ced821bdcbc822779026ff6c817d949a12f81fcb79562a1d57b8975a29ae4b3cacdebafe77cf4a4035a5d582aa823ca4fafe395", "file": "ui/src/components/tabs/tab-group.ts", "changeDetection": "ChangeDetectionStrategy.Default", "encapsulation": [ @@ -42473,6 +43087,7 @@ "tab-group.html" ], "viewProviders": [], + "hostDirectives": [], "inputsClass": [ { "name": "animationDuration", @@ -42633,6 +43248,9 @@ "name": "ContentChildren", "stringifiedArguments": "OuiTab, {descendants: true}" } + ], + "modifierKind": [ + 170 ] }, { @@ -42644,7 +43262,7 @@ "description": "", "line": 199, "modifierKind": [ - 121 + 123 ] }, { @@ -42666,7 +43284,9 @@ } ], "modifierKind": [ - 123 + 170, + 170, + 125 ] }, { @@ -42678,7 +43298,7 @@ "description": "", "line": 270, "modifierKind": [ - 121 + 123 ] }, { @@ -42690,7 +43310,7 @@ "description": "", "line": 216, "modifierKind": [ - 121 + 123 ] }, { @@ -42703,7 +43323,7 @@ "description": "", "line": 231, "modifierKind": [ - 121 + 123 ] }, { @@ -42716,7 +43336,7 @@ "description": "", "line": 169, "modifierKind": [ - 121 + 123 ] }, { @@ -42729,7 +43349,7 @@ "description": "", "line": 147, "modifierKind": [ - 121 + 123 ] }, { @@ -42741,7 +43361,7 @@ "description": "", "line": 288, "modifierKind": [ - 121 + 123 ] }, { @@ -42755,7 +43375,7 @@ "line": 124, "rawdescription": "\nThe tab index that should be selected after the content has been checked.", "modifierKind": [ - 121 + 123 ] }, { @@ -42769,7 +43389,7 @@ "line": 127, "rawdescription": "\nIndex of the tab that was focused last.", "modifierKind": [ - 121 + 123 ] }, { @@ -42782,7 +43402,7 @@ "description": "", "line": 247, "modifierKind": [ - 121 + 123 ] }, { @@ -42795,7 +43415,7 @@ "description": "", "line": 181, "modifierKind": [ - 121 + 123 ] }, { @@ -42808,7 +43428,7 @@ "description": "", "line": 157, "modifierKind": [ - 121 + 123 ] }, { @@ -42824,6 +43444,9 @@ "name": "ViewChild", "stringifiedArguments": "'tabBodyWrapper'" } + ], + "modifierKind": [ + 170 ] }, { @@ -42837,7 +43460,7 @@ "line": 130, "rawdescription": "\nSnapshot of the height of the tab body wrapper before another tab is activated.", "modifierKind": [ - 121 + 123 ] }, { @@ -42853,6 +43476,9 @@ "name": "ViewChild", "stringifiedArguments": "'tabHeader'" } + ], + "modifierKind": [ + 170 ] }, { @@ -42866,7 +43492,7 @@ "line": 136, "rawdescription": "\nSubscription to changes in the tab labels.", "modifierKind": [ - 121 + 123 ] }, { @@ -42891,7 +43517,7 @@ "line": 133, "rawdescription": "\nSubscription to tabs being added/removed.", "modifierKind": [ - 121 + 123 ] }, { @@ -42933,7 +43559,7 @@ "rawdescription": "\nClamps the given index to the bounds of 0 and the tabs length.", "description": "

Clamps the given index to the bounds of 0 and the tabs length.

\n", "modifierKind": [ - 121 + 123 ], "jsdoctags": [ { @@ -42964,7 +43590,7 @@ "deprecated": false, "deprecationMessage": "", "modifierKind": [ - 121 + 123 ], "jsdoctags": [ { @@ -43220,7 +43846,7 @@ "rawdescription": "\nListens to changes in all of the tabs.", "description": "

Listens to changes in all of the tabs.

\n", "modifierKind": [ - 121 + 123 ] }, { @@ -43235,8 +43861,9 @@ "rawdescription": "\n\nSubscribes to changes in the tab labels. This is needed, because the @Input for the label is\non the OuiTab component, whereas the data binding is inside the ouiTabGroup. In order for the\nbinding to be updated, we need to subscribe to changes in it and trigger change detection\nmanually.\n", "description": "

Subscribes to changes in the tab labels. This is needed, because the @Input for the label is\non the OuiTab component, whereas the data binding is inside the ouiTabGroup. In order for the\nbinding to be updated, we need to subscribe to changes in it and trigger change detection\nmanually.

\n", "modifierKind": [ - 121 - ] + 123 + ], + "jsdoctags": [] }, { "name": "_tabFocusChanged", @@ -43304,24 +43931,24 @@ "jsdoctags": [ { "name": { - "pos": 15636, - "end": 15641, - "flags": 4227072, + "pos": 16108, + "end": 16113, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "index" }, "type": "number", "deprecated": false, "deprecationMessage": "", "tagName": { - "pos": 15630, - "end": 15635, - "flags": 4227072, + "pos": 16102, + "end": 16107, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "param" }, "comment": "

Index of the tab to be focused.

\n" @@ -43389,14 +44016,16 @@ "deprecationMessage": "", "hostBindings": [], "hostListeners": [], + "standalone": false, + "imports": [], "description": "

Material design tab-group component. Supports basic tab pairs (label + content) and includes\nanimated ink-bar, keyboard navigation, and screen reader.\nSee: https://material.io/design/components/tabs.html

\n", "rawdescription": "\n\nMaterial design tab-group component. Supports basic tab pairs (label + content) and includes\nanimated ink-bar, keyboard navigation, and screen reader.\nSee: https://material.io/design/components/tabs.html\n", "type": "component", - "sourceCode": "import {\n AfterContentChecked,\n AfterContentInit,\n ChangeDetectionStrategy,\n ChangeDetectorRef,\n Component,\n ContentChildren,\n ElementRef,\n EventEmitter,\n Inject,\n Input,\n OnDestroy,\n Optional,\n Output,\n QueryList,\n ViewChild,\n ViewEncapsulation,\n} from '@angular/core';\nimport { ANIMATION_MODULE_TYPE } from '@angular/platform-browser/animations';\nimport { OUI_TAB_GROUP, OuiTab } from './tab';\nimport { OuiTabHeader } from './tab-header';\nimport {\n BooleanInput,\n coerceBooleanProperty,\n coerceNumberProperty,\n NumberInput,\n} from '@angular/cdk/coercion';\nimport {\n CanColor,\n CanDisableRipple,\n mixinColor,\n mixinDisableRipple,\n ThemePalette,\n} from '../core';\nimport { merge, Subscription } from 'rxjs';\nimport { OUI_TABS_CONFIG, OuiTabsConfig } from './tab-config';\nimport { startWith } from 'rxjs/operators';\nimport { FocusOrigin } from '@angular/cdk/a11y';\n\n/** Used to generate unique ID's for each tab component */\nlet nextId = 0;\n\n// Boilerplate for applying mixins to ouiTabGroup.\n/** @docs-private */\nconst _OuiTabGroupMixinBase = mixinColor(\n mixinDisableRipple(\n class {\n constructor(public _elementRef: ElementRef) {}\n }\n ),\n 'primary'\n);\n\n/** @docs-private */\nexport interface OuiTabGroupBaseHeader {\n _alignInkBarToSelectedTab(): void;\n updatePagination(): void;\n focusIndex: number;\n}\n\n/** Possible positions for the tab header. */\nexport type OuiTabHeaderPosition = 'above' | 'below';\n\n/**\n * Material design tab-group component. Supports basic tab pairs (label + content) and includes\n * animated ink-bar, keyboard navigation, and screen reader.\n * See: https://material.io/design/components/tabs.html\n */\n@Component({\n selector: 'oui-tab-group',\n exportAs: 'ouiTabGroup',\n templateUrl: 'tab-group.html',\n styleUrls: ['tab-group.scss'],\n encapsulation: ViewEncapsulation.None,\n // tslint:disable-next-line:validate-decorators\n changeDetection: ChangeDetectionStrategy.Default,\n // eslint-disable-next-line\n inputs: ['color', 'disableRipple'],\n providers: [\n {\n provide: OUI_TAB_GROUP,\n useExisting: ouiTabGroup,\n },\n ],\n // eslint-disable-next-line\n host: {\n ngSkipHydration: '',\n class: 'oui-mdc-tab-group oui-tab',\n '[class.oui-mdc-tab-group-dynamic-height]': 'dynamicHeight',\n '[class.oui-mdc-tab-group-inverted-header]': 'headerPosition === \"below\"',\n '[class.oui-mdc-tab-group-stretch-tabs]': 'stretchTabs',\n '[style.--oui-tab-animation-duration]': 'animationDuration',\n },\n})\nexport class ouiTabGroup\n extends _OuiTabGroupMixinBase\n implements\n AfterContentInit,\n AfterContentChecked,\n OnDestroy,\n CanColor,\n CanDisableRipple\n{\n /**\n * All tabs inside the tab group. This includes tabs that belong to groups that are nested\n * inside the current one. We filter out only the tabs that belong to this group in `_tabs`.\n */\n @ContentChildren(OuiTab, { descendants: true }) _allTabs: QueryList;\n @ViewChild('tabBodyWrapper') _tabBodyWrapper: ElementRef;\n @ViewChild('tabHeader') _tabHeader: OuiTabHeader;\n\n /** All of the tabs that belong to the group. */\n _tabs: QueryList = new QueryList();\n\n /** The tab index that should be selected after the content has been checked. */\n private _indexToSelect: number | null = 0;\n\n /** Index of the tab that was focused last. */\n private _lastFocusedTabIndex: number | null = null;\n\n /** Snapshot of the height of the tab body wrapper before another tab is activated. */\n private _tabBodyWrapperHeight = 0;\n\n /** Subscription to tabs being added/removed. */\n private _tabsSubscription = Subscription.EMPTY;\n\n /** Subscription to changes in the tab labels. */\n private _tabLabelSubscription = Subscription.EMPTY;\n\n /** Whether the ink bar should fit its width to the size of the tab label content. */\n @Input()\n get fitInkBarToContent(): boolean {\n return this._fitInkBarToContent;\n }\n set fitInkBarToContent(v: BooleanInput) {\n this._fitInkBarToContent = coerceBooleanProperty(v);\n this._changeDetectorRef.markForCheck();\n }\n private _fitInkBarToContent = false;\n\n /** Whether tabs should be stretched to fill the header. */\n @Input('oui-stretch-tabs')\n get stretchTabs(): boolean {\n return this._stretchTabs;\n }\n set stretchTabs(v: BooleanInput) {\n this._stretchTabs = coerceBooleanProperty(v);\n }\n private _stretchTabs = true;\n\n /** Whether the tab group should grow to the size of the active tab. */\n @Input()\n get dynamicHeight(): boolean {\n return this._dynamicHeight;\n }\n\n set dynamicHeight(value: BooleanInput) {\n this._dynamicHeight = coerceBooleanProperty(value);\n }\n\n private _dynamicHeight = false;\n\n /** The index of the active tab. */\n @Input()\n get selectedIndex(): number | null {\n return this._selectedIndex;\n }\n\n set selectedIndex(value: NumberInput) {\n this._indexToSelect = coerceNumberProperty(value, null);\n }\n\n private _selectedIndex: number | null = null;\n\n /** Position of the tab header. */\n @Input() headerPosition: OuiTabHeaderPosition = 'above';\n\n /** Duration for the tab animation. Will be normalized to milliseconds if no units are set. */\n @Input()\n get animationDuration(): string {\n return this._animationDuration;\n }\n\n set animationDuration(value: NumberInput) {\n // eslint-disable-next-line @typescript-eslint/restrict-plus-operands\n this._animationDuration = /^\\d+$/.test(value + '') // eslint-disable-next-line @typescript-eslint/restrict-plus-operands\n ? value + 'ms'\n : (value as string);\n }\n\n private _animationDuration: string;\n\n /**\n * `tabindex` to be set on the inner element that wraps the tab content. Can be used for improved\n * accessibility when the tab does not have focusable elements or if it has scrollable content.\n * The `tabindex` will be removed automatically for inactive tabs.\n * Read more at https://www.w3.org/TR/wai-aria-practices/examples/tabs/tabs-2/tabs.html\n */\n @Input()\n get contentTabIndex(): number | null {\n return this._contentTabIndex;\n }\n\n set contentTabIndex(value: NumberInput) {\n this._contentTabIndex = coerceNumberProperty(value, null);\n }\n\n private _contentTabIndex: number | null;\n\n /**\n * Whether pagination should be disabled. This can be used to avoid unnecessary\n * layout recalculations if it's known that pagination won't be required.\n */\n @Input()\n get disablePagination(): boolean {\n return this._disablePagination;\n }\n\n set disablePagination(value: BooleanInput) {\n this._disablePagination = coerceBooleanProperty(value);\n }\n\n private _disablePagination = false;\n\n /**\n * By default tabs remove their content from the DOM while it's off-screen.\n * Setting this to `true` will keep it in the DOM which will prevent elements\n * like iframes and videos from reloading next time it comes back into the view.\n */\n @Input()\n get preserveContent(): boolean {\n return this._preserveContent;\n }\n\n set preserveContent(value: BooleanInput) {\n this._preserveContent = coerceBooleanProperty(value);\n }\n\n private _preserveContent = false;\n\n /** Background color of the tab group. */\n @Input()\n get backgroundColor(): ThemePalette {\n return this._backgroundColor;\n }\n\n set backgroundColor(value: ThemePalette) {\n const classList: DOMTokenList = this._elementRef.nativeElement.classList;\n\n classList.remove(\n 'oui-tabs-with-background',\n `oui-background-${this.backgroundColor}`\n );\n\n if (value) {\n classList.add('oui-tabs-with-background', `oui-background-${value}`);\n }\n\n this._backgroundColor = value;\n }\n\n private _backgroundColor: ThemePalette;\n\n /** Output to enable support for two-way binding on `[(selectedIndex)]` */\n @Output() readonly selectedIndexChange: EventEmitter =\n new EventEmitter();\n\n /** Event emitted when focus has changed within a tab group. */\n @Output() readonly focusChange: EventEmitter =\n new EventEmitter();\n\n /** Event emitted when the body animation has completed */\n @Output() readonly animationDone: EventEmitter =\n new EventEmitter();\n\n /** Event emitted when the tab selection has changed. */\n @Output() readonly selectedTabChange: EventEmitter =\n new EventEmitter(true);\n\n private _groupId: number;\n getHTMLText: any;\n updatedTabHTML: any;\n\n constructor(\n elementRef: ElementRef,\n private _changeDetectorRef: ChangeDetectorRef,\n @Inject(OUI_TABS_CONFIG) @Optional() defaultConfig?: OuiTabsConfig,\n @Optional() @Inject(ANIMATION_MODULE_TYPE) public _animationMode?: string\n ) {\n super(elementRef);\n this._groupId = nextId++;\n this.animationDuration =\n defaultConfig && defaultConfig.animationDuration\n ? defaultConfig.animationDuration\n : '500ms';\n this.disablePagination =\n defaultConfig && defaultConfig.disablePagination != null\n ? defaultConfig.disablePagination\n : false;\n this.dynamicHeight =\n defaultConfig && defaultConfig.dynamicHeight != null\n ? defaultConfig.dynamicHeight\n : false;\n this.contentTabIndex = defaultConfig?.contentTabIndex ?? null;\n this.preserveContent = !!defaultConfig?.preserveContent;\n this.fitInkBarToContent =\n defaultConfig && defaultConfig.fitInkBarToContent != null\n ? defaultConfig.fitInkBarToContent\n : false;\n this.stretchTabs =\n defaultConfig && defaultConfig.stretchTabs != null\n ? defaultConfig.stretchTabs\n : true;\n }\n\n /**\n * After the content is checked, this component knows what tabs have been defined\n * and what the selected index should be. This is where we can know exactly what position\n * each tab should be in according to the new selected index, and additionally we know how\n * a new selected tab should transition in (from the left or right).\n */\n ngAfterContentChecked() {\n // Don't clamp the `indexToSelect` immediately in the setter because it can happen that\n // the amount of tabs changes before the actual change detection runs.\n const indexToSelect = (this._indexToSelect = this._clampTabIndex(\n this._indexToSelect\n ));\n\n // If there is a change in selected index, emit a change event. Should not trigger if\n // the selected index has not yet been initialized.\n if (this._selectedIndex != indexToSelect) {\n const isFirstRun = this._selectedIndex == null;\n\n if (!isFirstRun) {\n this.selectedTabChange.emit(this._createChangeEvent(indexToSelect));\n // Preserve the height so page doesn't scroll up during tab change.\n // Fixes https://stackblitz.com/edit/mat-tabs-scroll-page-top-on-tab-change\n const wrapper = this._tabBodyWrapper.nativeElement;\n // eslint-disable-next-line @typescript-eslint/restrict-plus-operands\n wrapper.style.minHeight = wrapper.clientHeight + 'px';\n }\n\n // Changing these values after change detection has run\n // since the checked content may contain references to them.\n Promise.resolve().then(() => {\n this._tabs.forEach(\n (tab, index) => (tab.isActive = index === indexToSelect)\n );\n\n if (!isFirstRun) {\n this.selectedIndexChange.emit(indexToSelect);\n // Clear the min-height, this was needed during tab change to avoid\n // unnecessary scrolling.\n this._tabBodyWrapper.nativeElement.style.minHeight = '';\n }\n });\n }\n\n // Setup the position for each tab and optionally setup an origin on the next selected tab.\n this._tabs.forEach((tab: OuiTab, index: number) => {\n tab.position = index - indexToSelect;\n\n // If there is already a selected tab, then set up an origin for the next selected tab\n // if it doesn't have one already.\n if (this._selectedIndex != null && tab.position == 0 && !tab.origin) {\n tab.origin = indexToSelect - this._selectedIndex;\n }\n });\n\n if (this._selectedIndex !== indexToSelect) {\n this._selectedIndex = indexToSelect;\n this._lastFocusedTabIndex = null;\n this._changeDetectorRef.markForCheck();\n }\n }\n\n ngAfterContentInit() {\n this._subscribeToAllTabChanges();\n this._subscribeToTabLabels();\n // Subscribe to changes in the amount of tabs, in order to be\n // able to re-render the content as new tabs are added or removed.\n this._tabsSubscription = this._tabs.changes.subscribe(() => {\n const indexToSelect = this._clampTabIndex(this._indexToSelect);\n\n // Maintain the previously-selected tab if a new tab is added or removed and there is no\n // explicit change that selects a different tab.\n if (indexToSelect === this._selectedIndex) {\n const tabs = this._tabs.toArray();\n let selectedTab: OuiTab | undefined;\n\n for (let i = 0; i < tabs.length; i++) {\n if (tabs[i].isActive) {\n // Assign both to the `_indexToSelect` and `_selectedIndex` so we don't fire a changed\n // event, otherwise the consumer may end up in an infinite loop in some edge cases like\n // adding a tab within the `selectedIndexChange` event.\n this._indexToSelect = this._selectedIndex = i;\n this._lastFocusedTabIndex = null;\n selectedTab = tabs[i];\n break;\n }\n }\n\n // If we haven't found an active tab and a tab exists at the selected index, it means\n // that the active tab was swapped out. Since this won't be picked up by the rendering\n // loop in `ngAfterContentChecked`, we need to sync it up manually.\n if (!selectedTab && tabs[indexToSelect]) {\n Promise.resolve().then(() => {\n tabs[indexToSelect].isActive = true;\n this.selectedTabChange.emit(this._createChangeEvent(indexToSelect));\n });\n }\n }\n\n this._changeDetectorRef.markForCheck();\n });\n }\n\n /** Listens to changes in all of the tabs. */\n private _subscribeToAllTabChanges() {\n // Since we use a query with `descendants: true` to pick up the tabs, we may end up catching\n // some that are inside of nested tab groups. We filter them out manually by checking that\n // the closest group to the tab is the current one.\n this.getHTMLText = this._allTabs['_results'][0].givenText;\n this.updatedTabHTML = this.getHTMLText;\n this._allTabs.changes\n .pipe(startWith(this._allTabs))\n .subscribe((tabs: QueryList) => {\n this._tabs.reset(\n tabs.filter((tab) => {\n return tab._closestTabGroup === this || !tab._closestTabGroup;\n })\n );\n this._tabs.notifyOnChanges();\n });\n }\n\n ngOnDestroy() {\n this._tabs.destroy();\n this._tabsSubscription.unsubscribe();\n this._tabLabelSubscription.unsubscribe();\n }\n\n /** Re-aligns the ink bar to the selected tab element. */\n realignInkBar() {\n if (this._tabHeader) {\n this._tabHeader._alignInkBarToSelectedTab();\n }\n }\n\n /**\n * Recalculates the tab group's pagination dimensions.\n *\n * WARNING: Calling this method can be very costly in terms of performance. It should be called\n * as infrequently as possible from outside of the Tabs component as it causes a reflow of the\n * page.\n */\n updatePagination() {\n if (this._tabHeader) {\n this._tabHeader.updatePagination();\n }\n }\n\n /**\n * Sets focus to a particular tab.\n * @param index Index of the tab to be focused.\n */\n focusTab(index: number) {\n const header = this._tabHeader;\n\n if (header) {\n header.focusIndex = index;\n }\n }\n\n _focusChanged(index: number) {\n this._lastFocusedTabIndex = index;\n this.focusChange.emit(this._createChangeEvent(index));\n }\n\n private _createChangeEvent(index: number): OuiTabChangeEvent {\n const event = new OuiTabChangeEvent();\n event.index = index;\n if (this._tabs && this._tabs.length) {\n event.tab = this._tabs.toArray()[index];\n this.updatedTabHTML = event.tab.givenText;\n }\n return event;\n }\n\n _handleEnter() {\n this.getHTMLText = this.updatedTabHTML;\n }\n\n /**\n * Subscribes to changes in the tab labels. This is needed, because the @Input for the label is\n * on the OuiTab component, whereas the data binding is inside the ouiTabGroup. In order for the\n * binding to be updated, we need to subscribe to changes in it and trigger change detection\n * manually.\n */\n private _subscribeToTabLabels() {\n if (this._tabLabelSubscription) {\n this._tabLabelSubscription.unsubscribe();\n }\n\n this._tabLabelSubscription = merge(\n ...this._tabs.map((tab) => tab._stateChanges)\n ).subscribe(() => this._changeDetectorRef.markForCheck());\n }\n\n /** Clamps the given index to the bounds of 0 and the tabs length. */\n private _clampTabIndex(index: number | null): number {\n // Note the `|| 0`, which ensures that values like NaN can't get through\n // and which would otherwise throw the component into an infinite loop\n // (since Math.max(NaN, 0) === NaN).\n return Math.min(this._tabs.length - 1, Math.max(index || 0, 0));\n }\n\n /** Returns a unique id for each tab label element */\n _getTabLabelId(i: number): string {\n return `oui-tab-label-${this._groupId}-${i}`;\n }\n\n /** Returns a unique id for each tab content element */\n _getTabContentId(i: number): string {\n return `oui-tab-content-${this._groupId}-${i}`;\n }\n\n /**\n * Sets the height of the body wrapper to the height of the activating tab if dynamic\n * height property is true.\n */\n _setTabBodyWrapperHeight(tabHeight: number): void {\n if (!this._dynamicHeight || !this._tabBodyWrapperHeight) {\n return;\n }\n\n const wrapper: HTMLElement = this._tabBodyWrapper.nativeElement;\n // eslint-disable-next-line @typescript-eslint/restrict-plus-operands\n wrapper.style.height = this._tabBodyWrapperHeight + 'px';\n\n // This conditional forces the browser to paint the height so that\n // the animation to the new height can have an origin.\n if (this._tabBodyWrapper.nativeElement.offsetHeight) {\n // eslint-disable-next-line @typescript-eslint/restrict-plus-operands\n wrapper.style.height = tabHeight + 'px';\n }\n }\n\n /** Removes the height of the tab body wrapper. */\n _removeTabBodyWrapperHeight(): void {\n const wrapper = this._tabBodyWrapper.nativeElement;\n this._tabBodyWrapperHeight = wrapper.clientHeight;\n wrapper.style.height = '';\n this.animationDone.emit();\n }\n\n /** Handle click events, setting new selected index if appropriate. */\n _handleClick(tab: OuiTab, tabHeader: OuiTabGroupBaseHeader, index: number) {\n tabHeader.focusIndex = index;\n this.getHTMLText = this.updatedTabHTML;\n\n if (!tab.disabled) {\n this.selectedIndex = index;\n }\n }\n\n /** Retrieves the tabindex for the tab. */\n _getTabIndex(index: number): number {\n const targetIndex = this._lastFocusedTabIndex ?? this.selectedIndex;\n return index === targetIndex ? 0 : -1;\n }\n\n /** Callback for when the focused state of a tab has changed. */\n _tabFocusChanged(focusOrigin: FocusOrigin, index: number) {\n // Mouse/touch focus happens during the `mousedown`/`touchstart` phase which\n // can cause the tab to be moved out from under the pointer, interrupting the\n // click sequence (see #21898). We don't need to scroll the tab into view for\n // such cases anyway, because it will be done when the tab becomes selected.\n if (focusOrigin && focusOrigin !== 'mouse' && focusOrigin !== 'touch') {\n this._tabHeader.focusIndex = index;\n }\n }\n}\n\n/** A simple change event emitted on focus or selection changes. */\nexport class OuiTabChangeEvent {\n /** Index of the currently-selected tab. */\n index: number;\n /** Reference to the currently-selected tab. */\n tab: OuiTab;\n event: Event;\n}\n", + "sourceCode": "import {\r\n AfterContentChecked,\r\n AfterContentInit,\r\n ChangeDetectionStrategy,\r\n ChangeDetectorRef,\r\n Component,\r\n ContentChildren,\r\n ElementRef,\r\n EventEmitter,\r\n Inject,\r\n Input,\r\n OnDestroy,\r\n Optional,\r\n Output,\r\n QueryList,\r\n ViewChild,\r\n ViewEncapsulation,\r\n} from '@angular/core';\r\nimport { ANIMATION_MODULE_TYPE } from '@angular/platform-browser/animations';\r\nimport { OUI_TAB_GROUP, OuiTab } from './tab';\r\nimport { OuiTabHeader } from './tab-header';\r\nimport {\r\n BooleanInput,\r\n coerceBooleanProperty,\r\n coerceNumberProperty,\r\n NumberInput,\r\n} from '@angular/cdk/coercion';\r\nimport {\r\n CanColor,\r\n CanDisableRipple,\r\n mixinColor,\r\n mixinDisableRipple,\r\n ThemePalette,\r\n} from '../core';\r\nimport { merge, Subscription } from 'rxjs';\r\nimport { OUI_TABS_CONFIG, OuiTabsConfig } from './tab-config';\r\nimport { startWith } from 'rxjs/operators';\r\nimport { FocusOrigin } from '@angular/cdk/a11y';\r\n\r\n/** Used to generate unique ID's for each tab component */\r\nlet nextId = 0;\r\n\r\n// Boilerplate for applying mixins to ouiTabGroup.\r\n/** @docs-private */\r\nconst _OuiTabGroupMixinBase = mixinColor(\r\n mixinDisableRipple(\r\n class {\r\n constructor(public _elementRef: ElementRef) {}\r\n }\r\n ),\r\n 'primary'\r\n);\r\n\r\n/** @docs-private */\r\nexport interface OuiTabGroupBaseHeader {\r\n _alignInkBarToSelectedTab(): void;\r\n updatePagination(): void;\r\n focusIndex: number;\r\n}\r\n\r\n/** Possible positions for the tab header. */\r\nexport type OuiTabHeaderPosition = 'above' | 'below';\r\n\r\n/**\r\n * Material design tab-group component. Supports basic tab pairs (label + content) and includes\r\n * animated ink-bar, keyboard navigation, and screen reader.\r\n * See: https://material.io/design/components/tabs.html\r\n */\r\n@Component({\r\n selector: 'oui-tab-group',\r\n exportAs: 'ouiTabGroup',\r\n templateUrl: 'tab-group.html',\r\n styleUrls: ['tab-group.scss'],\r\n encapsulation: ViewEncapsulation.None,\r\n // tslint:disable-next-line:validate-decorators\r\n changeDetection: ChangeDetectionStrategy.Default,\r\n // eslint-disable-next-line\r\n inputs: ['color', 'disableRipple'],\r\n providers: [\r\n {\r\n provide: OUI_TAB_GROUP,\r\n useExisting: ouiTabGroup,\r\n },\r\n ],\r\n // eslint-disable-next-line\r\n host: {\r\n ngSkipHydration: '',\r\n class: 'oui-mdc-tab-group oui-tab',\r\n '[class.oui-mdc-tab-group-dynamic-height]': 'dynamicHeight',\r\n '[class.oui-mdc-tab-group-inverted-header]': 'headerPosition === \"below\"',\r\n '[class.oui-mdc-tab-group-stretch-tabs]': 'stretchTabs',\r\n '[style.--oui-tab-animation-duration]': 'animationDuration',\r\n },\r\n})\r\nexport class ouiTabGroup\r\n extends _OuiTabGroupMixinBase\r\n implements\r\n AfterContentInit,\r\n AfterContentChecked,\r\n OnDestroy,\r\n CanColor,\r\n CanDisableRipple\r\n{\r\n /**\r\n * All tabs inside the tab group. This includes tabs that belong to groups that are nested\r\n * inside the current one. We filter out only the tabs that belong to this group in `_tabs`.\r\n */\r\n @ContentChildren(OuiTab, { descendants: true }) _allTabs: QueryList;\r\n @ViewChild('tabBodyWrapper') _tabBodyWrapper: ElementRef;\r\n @ViewChild('tabHeader') _tabHeader: OuiTabHeader;\r\n\r\n /** All of the tabs that belong to the group. */\r\n _tabs: QueryList = new QueryList();\r\n\r\n /** The tab index that should be selected after the content has been checked. */\r\n private _indexToSelect: number | null = 0;\r\n\r\n /** Index of the tab that was focused last. */\r\n private _lastFocusedTabIndex: number | null = null;\r\n\r\n /** Snapshot of the height of the tab body wrapper before another tab is activated. */\r\n private _tabBodyWrapperHeight = 0;\r\n\r\n /** Subscription to tabs being added/removed. */\r\n private _tabsSubscription = Subscription.EMPTY;\r\n\r\n /** Subscription to changes in the tab labels. */\r\n private _tabLabelSubscription = Subscription.EMPTY;\r\n\r\n /** Whether the ink bar should fit its width to the size of the tab label content. */\r\n @Input()\r\n get fitInkBarToContent(): boolean {\r\n return this._fitInkBarToContent;\r\n }\r\n set fitInkBarToContent(v: BooleanInput) {\r\n this._fitInkBarToContent = coerceBooleanProperty(v);\r\n this._changeDetectorRef.markForCheck();\r\n }\r\n private _fitInkBarToContent = false;\r\n\r\n /** Whether tabs should be stretched to fill the header. */\r\n @Input('oui-stretch-tabs')\r\n get stretchTabs(): boolean {\r\n return this._stretchTabs;\r\n }\r\n set stretchTabs(v: BooleanInput) {\r\n this._stretchTabs = coerceBooleanProperty(v);\r\n }\r\n private _stretchTabs = true;\r\n\r\n /** Whether the tab group should grow to the size of the active tab. */\r\n @Input()\r\n get dynamicHeight(): boolean {\r\n return this._dynamicHeight;\r\n }\r\n\r\n set dynamicHeight(value: BooleanInput) {\r\n this._dynamicHeight = coerceBooleanProperty(value);\r\n }\r\n\r\n private _dynamicHeight = false;\r\n\r\n /** The index of the active tab. */\r\n @Input()\r\n get selectedIndex(): number | null {\r\n return this._selectedIndex;\r\n }\r\n\r\n set selectedIndex(value: NumberInput) {\r\n this._indexToSelect = coerceNumberProperty(value, null);\r\n }\r\n\r\n private _selectedIndex: number | null = null;\r\n\r\n /** Position of the tab header. */\r\n @Input() headerPosition: OuiTabHeaderPosition = 'above';\r\n\r\n /** Duration for the tab animation. Will be normalized to milliseconds if no units are set. */\r\n @Input()\r\n get animationDuration(): string {\r\n return this._animationDuration;\r\n }\r\n\r\n set animationDuration(value: NumberInput) {\r\n // eslint-disable-next-line @typescript-eslint/restrict-plus-operands\r\n this._animationDuration = /^\\d+$/.test(value + '') // eslint-disable-next-line @typescript-eslint/restrict-plus-operands\r\n ? value + 'ms'\r\n : (value as string);\r\n }\r\n\r\n private _animationDuration: string;\r\n\r\n /**\r\n * `tabindex` to be set on the inner element that wraps the tab content. Can be used for improved\r\n * accessibility when the tab does not have focusable elements or if it has scrollable content.\r\n * The `tabindex` will be removed automatically for inactive tabs.\r\n * Read more at https://www.w3.org/TR/wai-aria-practices/examples/tabs/tabs-2/tabs.html\r\n */\r\n @Input()\r\n get contentTabIndex(): number | null {\r\n return this._contentTabIndex;\r\n }\r\n\r\n set contentTabIndex(value: NumberInput) {\r\n this._contentTabIndex = coerceNumberProperty(value, null);\r\n }\r\n\r\n private _contentTabIndex: number | null;\r\n\r\n /**\r\n * Whether pagination should be disabled. This can be used to avoid unnecessary\r\n * layout recalculations if it's known that pagination won't be required.\r\n */\r\n @Input()\r\n get disablePagination(): boolean {\r\n return this._disablePagination;\r\n }\r\n\r\n set disablePagination(value: BooleanInput) {\r\n this._disablePagination = coerceBooleanProperty(value);\r\n }\r\n\r\n private _disablePagination = false;\r\n\r\n /**\r\n * By default tabs remove their content from the DOM while it's off-screen.\r\n * Setting this to `true` will keep it in the DOM which will prevent elements\r\n * like iframes and videos from reloading next time it comes back into the view.\r\n */\r\n @Input()\r\n get preserveContent(): boolean {\r\n return this._preserveContent;\r\n }\r\n\r\n set preserveContent(value: BooleanInput) {\r\n this._preserveContent = coerceBooleanProperty(value);\r\n }\r\n\r\n private _preserveContent = false;\r\n\r\n /** Background color of the tab group. */\r\n @Input()\r\n get backgroundColor(): ThemePalette {\r\n return this._backgroundColor;\r\n }\r\n\r\n set backgroundColor(value: ThemePalette) {\r\n const classList: DOMTokenList = this._elementRef.nativeElement.classList;\r\n\r\n classList.remove(\r\n 'oui-tabs-with-background',\r\n `oui-background-${this.backgroundColor}`\r\n );\r\n\r\n if (value) {\r\n classList.add('oui-tabs-with-background', `oui-background-${value}`);\r\n }\r\n\r\n this._backgroundColor = value;\r\n }\r\n\r\n private _backgroundColor: ThemePalette;\r\n\r\n /** Output to enable support for two-way binding on `[(selectedIndex)]` */\r\n @Output() readonly selectedIndexChange: EventEmitter =\r\n new EventEmitter();\r\n\r\n /** Event emitted when focus has changed within a tab group. */\r\n @Output() readonly focusChange: EventEmitter =\r\n new EventEmitter();\r\n\r\n /** Event emitted when the body animation has completed */\r\n @Output() readonly animationDone: EventEmitter =\r\n new EventEmitter();\r\n\r\n /** Event emitted when the tab selection has changed. */\r\n @Output() readonly selectedTabChange: EventEmitter =\r\n new EventEmitter(true);\r\n\r\n private _groupId: number;\r\n getHTMLText: any;\r\n updatedTabHTML: any;\r\n\r\n constructor(\r\n elementRef: ElementRef,\r\n private _changeDetectorRef: ChangeDetectorRef,\r\n @Inject(OUI_TABS_CONFIG) @Optional() defaultConfig?: OuiTabsConfig,\r\n @Optional() @Inject(ANIMATION_MODULE_TYPE) public _animationMode?: string\r\n ) {\r\n super(elementRef);\r\n this._groupId = nextId++;\r\n this.animationDuration =\r\n defaultConfig && defaultConfig.animationDuration\r\n ? defaultConfig.animationDuration\r\n : '500ms';\r\n this.disablePagination =\r\n defaultConfig && defaultConfig.disablePagination != null\r\n ? defaultConfig.disablePagination\r\n : false;\r\n this.dynamicHeight =\r\n defaultConfig && defaultConfig.dynamicHeight != null\r\n ? defaultConfig.dynamicHeight\r\n : false;\r\n this.contentTabIndex = defaultConfig?.contentTabIndex ?? null;\r\n this.preserveContent = !!defaultConfig?.preserveContent;\r\n this.fitInkBarToContent =\r\n defaultConfig && defaultConfig.fitInkBarToContent != null\r\n ? defaultConfig.fitInkBarToContent\r\n : false;\r\n this.stretchTabs =\r\n defaultConfig && defaultConfig.stretchTabs != null\r\n ? defaultConfig.stretchTabs\r\n : true;\r\n }\r\n\r\n /**\r\n * After the content is checked, this component knows what tabs have been defined\r\n * and what the selected index should be. This is where we can know exactly what position\r\n * each tab should be in according to the new selected index, and additionally we know how\r\n * a new selected tab should transition in (from the left or right).\r\n */\r\n ngAfterContentChecked() {\r\n // Don't clamp the `indexToSelect` immediately in the setter because it can happen that\r\n // the amount of tabs changes before the actual change detection runs.\r\n const indexToSelect = (this._indexToSelect = this._clampTabIndex(\r\n this._indexToSelect\r\n ));\r\n\r\n // If there is a change in selected index, emit a change event. Should not trigger if\r\n // the selected index has not yet been initialized.\r\n if (this._selectedIndex != indexToSelect) {\r\n const isFirstRun = this._selectedIndex == null;\r\n\r\n if (!isFirstRun) {\r\n this.selectedTabChange.emit(this._createChangeEvent(indexToSelect));\r\n // Preserve the height so page doesn't scroll up during tab change.\r\n // Fixes https://stackblitz.com/edit/mat-tabs-scroll-page-top-on-tab-change\r\n const wrapper = this._tabBodyWrapper.nativeElement;\r\n // eslint-disable-next-line @typescript-eslint/restrict-plus-operands\r\n wrapper.style.minHeight = wrapper.clientHeight + 'px';\r\n }\r\n\r\n // Changing these values after change detection has run\r\n // since the checked content may contain references to them.\r\n Promise.resolve().then(() => {\r\n this._tabs.forEach(\r\n (tab, index) => (tab.isActive = index === indexToSelect)\r\n );\r\n\r\n if (!isFirstRun) {\r\n this.selectedIndexChange.emit(indexToSelect);\r\n // Clear the min-height, this was needed during tab change to avoid\r\n // unnecessary scrolling.\r\n this._tabBodyWrapper.nativeElement.style.minHeight = '';\r\n }\r\n });\r\n }\r\n\r\n // Setup the position for each tab and optionally setup an origin on the next selected tab.\r\n this._tabs.forEach((tab: OuiTab, index: number) => {\r\n tab.position = index - indexToSelect;\r\n\r\n // If there is already a selected tab, then set up an origin for the next selected tab\r\n // if it doesn't have one already.\r\n if (this._selectedIndex != null && tab.position == 0 && !tab.origin) {\r\n tab.origin = indexToSelect - this._selectedIndex;\r\n }\r\n });\r\n\r\n if (this._selectedIndex !== indexToSelect) {\r\n this._selectedIndex = indexToSelect;\r\n this._lastFocusedTabIndex = null;\r\n this._changeDetectorRef.markForCheck();\r\n }\r\n }\r\n\r\n ngAfterContentInit() {\r\n this._subscribeToAllTabChanges();\r\n this._subscribeToTabLabels();\r\n // Subscribe to changes in the amount of tabs, in order to be\r\n // able to re-render the content as new tabs are added or removed.\r\n this._tabsSubscription = this._tabs.changes.subscribe(() => {\r\n const indexToSelect = this._clampTabIndex(this._indexToSelect);\r\n\r\n // Maintain the previously-selected tab if a new tab is added or removed and there is no\r\n // explicit change that selects a different tab.\r\n if (indexToSelect === this._selectedIndex) {\r\n const tabs = this._tabs.toArray();\r\n let selectedTab: OuiTab | undefined;\r\n\r\n for (let i = 0; i < tabs.length; i++) {\r\n if (tabs[i].isActive) {\r\n // Assign both to the `_indexToSelect` and `_selectedIndex` so we don't fire a changed\r\n // event, otherwise the consumer may end up in an infinite loop in some edge cases like\r\n // adding a tab within the `selectedIndexChange` event.\r\n this._indexToSelect = this._selectedIndex = i;\r\n this._lastFocusedTabIndex = null;\r\n selectedTab = tabs[i];\r\n break;\r\n }\r\n }\r\n\r\n // If we haven't found an active tab and a tab exists at the selected index, it means\r\n // that the active tab was swapped out. Since this won't be picked up by the rendering\r\n // loop in `ngAfterContentChecked`, we need to sync it up manually.\r\n if (!selectedTab && tabs[indexToSelect]) {\r\n Promise.resolve().then(() => {\r\n tabs[indexToSelect].isActive = true;\r\n this.selectedTabChange.emit(this._createChangeEvent(indexToSelect));\r\n });\r\n }\r\n }\r\n\r\n this._changeDetectorRef.markForCheck();\r\n });\r\n }\r\n\r\n /** Listens to changes in all of the tabs. */\r\n private _subscribeToAllTabChanges() {\r\n // Since we use a query with `descendants: true` to pick up the tabs, we may end up catching\r\n // some that are inside of nested tab groups. We filter them out manually by checking that\r\n // the closest group to the tab is the current one.\r\n this.getHTMLText = this._allTabs['_results'][0].givenText;\r\n this.updatedTabHTML = this.getHTMLText;\r\n this._allTabs.changes\r\n .pipe(startWith(this._allTabs))\r\n .subscribe((tabs: QueryList) => {\r\n this._tabs.reset(\r\n tabs.filter((tab) => {\r\n return tab._closestTabGroup === this || !tab._closestTabGroup;\r\n })\r\n );\r\n this._tabs.notifyOnChanges();\r\n });\r\n }\r\n\r\n ngOnDestroy() {\r\n this._tabs.destroy();\r\n this._tabsSubscription.unsubscribe();\r\n this._tabLabelSubscription.unsubscribe();\r\n }\r\n\r\n /** Re-aligns the ink bar to the selected tab element. */\r\n realignInkBar() {\r\n if (this._tabHeader) {\r\n this._tabHeader._alignInkBarToSelectedTab();\r\n }\r\n }\r\n\r\n /**\r\n * Recalculates the tab group's pagination dimensions.\r\n *\r\n * WARNING: Calling this method can be very costly in terms of performance. It should be called\r\n * as infrequently as possible from outside of the Tabs component as it causes a reflow of the\r\n * page.\r\n */\r\n updatePagination() {\r\n if (this._tabHeader) {\r\n this._tabHeader.updatePagination();\r\n }\r\n }\r\n\r\n /**\r\n * Sets focus to a particular tab.\r\n * @param index Index of the tab to be focused.\r\n */\r\n focusTab(index: number) {\r\n const header = this._tabHeader;\r\n\r\n if (header) {\r\n header.focusIndex = index;\r\n }\r\n }\r\n\r\n _focusChanged(index: number) {\r\n this._lastFocusedTabIndex = index;\r\n this.focusChange.emit(this._createChangeEvent(index));\r\n }\r\n\r\n private _createChangeEvent(index: number): OuiTabChangeEvent {\r\n const event = new OuiTabChangeEvent();\r\n event.index = index;\r\n if (this._tabs && this._tabs.length) {\r\n event.tab = this._tabs.toArray()[index];\r\n this.updatedTabHTML = event.tab.givenText;\r\n }\r\n return event;\r\n }\r\n\r\n _handleEnter() {\r\n this.getHTMLText = this.updatedTabHTML;\r\n }\r\n\r\n /**\r\n * Subscribes to changes in the tab labels. This is needed, because the @Input for the label is\r\n * on the OuiTab component, whereas the data binding is inside the ouiTabGroup. In order for the\r\n * binding to be updated, we need to subscribe to changes in it and trigger change detection\r\n * manually.\r\n */\r\n private _subscribeToTabLabels() {\r\n if (this._tabLabelSubscription) {\r\n this._tabLabelSubscription.unsubscribe();\r\n }\r\n\r\n this._tabLabelSubscription = merge(\r\n ...this._tabs.map((tab) => tab._stateChanges)\r\n ).subscribe(() => this._changeDetectorRef.markForCheck());\r\n }\r\n\r\n /** Clamps the given index to the bounds of 0 and the tabs length. */\r\n private _clampTabIndex(index: number | null): number {\r\n // Note the `|| 0`, which ensures that values like NaN can't get through\r\n // and which would otherwise throw the component into an infinite loop\r\n // (since Math.max(NaN, 0) === NaN).\r\n return Math.min(this._tabs.length - 1, Math.max(index || 0, 0));\r\n }\r\n\r\n /** Returns a unique id for each tab label element */\r\n _getTabLabelId(i: number): string {\r\n return `oui-tab-label-${this._groupId}-${i}`;\r\n }\r\n\r\n /** Returns a unique id for each tab content element */\r\n _getTabContentId(i: number): string {\r\n return `oui-tab-content-${this._groupId}-${i}`;\r\n }\r\n\r\n /**\r\n * Sets the height of the body wrapper to the height of the activating tab if dynamic\r\n * height property is true.\r\n */\r\n _setTabBodyWrapperHeight(tabHeight: number): void {\r\n if (!this._dynamicHeight || !this._tabBodyWrapperHeight) {\r\n return;\r\n }\r\n\r\n const wrapper: HTMLElement = this._tabBodyWrapper.nativeElement;\r\n // eslint-disable-next-line @typescript-eslint/restrict-plus-operands\r\n wrapper.style.height = this._tabBodyWrapperHeight + 'px';\r\n\r\n // This conditional forces the browser to paint the height so that\r\n // the animation to the new height can have an origin.\r\n if (this._tabBodyWrapper.nativeElement.offsetHeight) {\r\n // eslint-disable-next-line @typescript-eslint/restrict-plus-operands\r\n wrapper.style.height = tabHeight + 'px';\r\n }\r\n }\r\n\r\n /** Removes the height of the tab body wrapper. */\r\n _removeTabBodyWrapperHeight(): void {\r\n const wrapper = this._tabBodyWrapper.nativeElement;\r\n this._tabBodyWrapperHeight = wrapper.clientHeight;\r\n wrapper.style.height = '';\r\n this.animationDone.emit();\r\n }\r\n\r\n /** Handle click events, setting new selected index if appropriate. */\r\n _handleClick(tab: OuiTab, tabHeader: OuiTabGroupBaseHeader, index: number) {\r\n tabHeader.focusIndex = index;\r\n this.getHTMLText = this.updatedTabHTML;\r\n\r\n if (!tab.disabled) {\r\n this.selectedIndex = index;\r\n }\r\n }\r\n\r\n /** Retrieves the tabindex for the tab. */\r\n _getTabIndex(index: number): number {\r\n const targetIndex = this._lastFocusedTabIndex ?? this.selectedIndex;\r\n return index === targetIndex ? 0 : -1;\r\n }\r\n\r\n /** Callback for when the focused state of a tab has changed. */\r\n _tabFocusChanged(focusOrigin: FocusOrigin, index: number) {\r\n // Mouse/touch focus happens during the `mousedown`/`touchstart` phase which\r\n // can cause the tab to be moved out from under the pointer, interrupting the\r\n // click sequence (see #21898). We don't need to scroll the tab into view for\r\n // such cases anyway, because it will be done when the tab becomes selected.\r\n if (focusOrigin && focusOrigin !== 'mouse' && focusOrigin !== 'touch') {\r\n this._tabHeader.focusIndex = index;\r\n }\r\n }\r\n}\r\n\r\n/** A simple change event emitted on focus or selection changes. */\r\nexport class OuiTabChangeEvent {\r\n /** Index of the currently-selected tab. */\r\n index: number;\r\n /** Reference to the currently-selected tab. */\r\n tab: OuiTab;\r\n event: Event;\r\n}\r\n", "assetsDirs": [], "styleUrlsData": [ { - "data": "@use '../core/style/variables';\n@use './tabs-common';\n\n@include tabs-common.structural-styles;\n\n.oui-mdc-tab {\n @include tabs-common.tab;\n\n // Note that we only want to target direct descendant tabs.\n .oui-mdc-tab-group.oui-mdc-tab-group-stretch-tabs > .oui-mdc-tab-header & {\n flex-grow: 1;\n }\n}\n\n.oui-mdc-focus-indicator {\n position: relative;\n}\n\n.oui-mdc-tab-body {\n top: 0;\n left: 0;\n right: 0;\n bottom: 0;\n position: absolute;\n display: none;\n overflow: hidden;\n flex-basis: 100%;\n &.oui-mdc-tab-body-active {\n display: block;\n }\n}\n\n.mdc-tab__content {\n display: flex;\n align-items: center;\n justify-content: center;\n height: inherit;\n pointer-events: none;\n}\n\n.oui-mdc-tab.mdc-tab--active .mdc-tab__text-label {\n color: #333;\n}\n\n.oui-mdc-tab-group {\n display: flex;\n flex-direction: column;\n\n // Fixes pagination issues inside flex containers (see #23157).\n max-width: 100%;\n\n &.oui-mdc-tab-group-inverted-header {\n flex-direction: column-reverse;\n\n .mdc-tab-indicator__content--underline {\n align-self: flex-start;\n }\n }\n}\n\n// The bottom section of the view; contains the tab bodies\n.oui-mdc-tab-body-wrapper {\n position: relative;\n overflow: hidden;\n display: flex;\n}\n\n.oui-text-height {\n min-height: 100px;\n}\n", + "data": "@use '../core/style/variables';\r\n@use './tabs-common';\r\n\r\n@include tabs-common.structural-styles;\r\n\r\n.oui-mdc-tab {\r\n @include tabs-common.tab;\r\n\r\n // Note that we only want to target direct descendant tabs.\r\n .oui-mdc-tab-group.oui-mdc-tab-group-stretch-tabs > .oui-mdc-tab-header & {\r\n flex-grow: 1;\r\n }\r\n}\r\n\r\n.oui-mdc-focus-indicator {\r\n position: relative;\r\n}\r\n\r\n.oui-mdc-tab-body {\r\n top: 0;\r\n left: 0;\r\n right: 0;\r\n bottom: 0;\r\n position: absolute;\r\n display: none;\r\n overflow: hidden;\r\n flex-basis: 100%;\r\n &.oui-mdc-tab-body-active {\r\n display: block;\r\n position: relative;\r\n overflow-x: hidden;\r\n overflow-y: auto;\r\n z-index: 1;\r\n }\r\n}\r\n\r\n.mdc-tab__content {\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n height: inherit;\r\n pointer-events: none;\r\n}\r\n\r\n.oui-mdc-tab.mdc-tab--active .mdc-tab__text-label {\r\n color: #333;\r\n}\r\n\r\n.oui-mdc-tab-group {\r\n display: flex;\r\n flex-direction: column;\r\n\r\n // Fixes pagination issues inside flex containers (see #23157).\r\n max-width: 100%;\r\n\r\n &.oui-mdc-tab-group-inverted-header {\r\n flex-direction: column-reverse;\r\n\r\n .mdc-tab-indicator__content--underline {\r\n align-self: flex-start;\r\n }\r\n }\r\n}\r\n\r\n// The bottom section of the view; contains the tab bodies\r\n.oui-mdc-tab-body-wrapper {\r\n position: relative;\r\n overflow: hidden;\r\n display: flex;\r\n}\r\n", "styleUrl": "tab-group.scss" } ], @@ -43476,7 +44105,9 @@ } ] }, - "extends": "_OuiTabGroupMixinBase", + "extends": [ + "_OuiTabGroupMixinBase" + ], "implements": [ "AfterContentInit", "AfterContentChecked", @@ -43828,11 +44459,11 @@ } } }, - "templateData": "\n \n \n\n \n
\n\n \n \n \n \n \n \n\n \n {{tab.textLabel}}\n \n \n \n\n\n\n \n \n\n" + "templateData": "\r\n \r\n \r\n\r\n \r\n
\r\n\r\n \r\n \r\n \r\n \r\n \r\n \r\n\r\n \r\n {{tab.textLabel}}\r\n \r\n \r\n \r\n\r\n\r\n\r\n \r\n \r\n\r\n" }, { "name": "OuiTabHeader", - "id": "component-OuiTabHeader-016c84d32f793bb577e51ca07fba9eae5162e3b232180331299c5914da31606429b5232b2773508750b0346b48522fcaba57e4caa71245e5932ae709e33d2df4", + "id": "component-OuiTabHeader-c7dc741f7c2a8bcba88b76014c267c6698772ef8e37a7613a2ac8cb5b71f7452a57d169ca63fa90bece0006bd1fbbf1b20f01c6286eb5eaa52982204cb7f1baf", "file": "ui/src/components/tabs/tab-header.ts", "changeDetection": "ChangeDetectionStrategy.Default", "encapsulation": [ @@ -43857,6 +44488,7 @@ "tab-header.html" ], "viewProviders": [], + "hostDirectives": [], "inputsClass": [ { "name": "disableRipple", @@ -43894,7 +44526,7 @@ "description": "", "line": 86, "modifierKind": [ - 121 + 123 ] }, { @@ -43923,6 +44555,9 @@ "stringifiedArguments": "ouiTabLabelWrapper, {descendants: false}" } ], + "modifierKind": [ + 170 + ], "inheritance": { "file": "OuiPaginatedTabHeader" } @@ -43941,6 +44576,9 @@ "stringifiedArguments": "'nextPaginator'" } ], + "modifierKind": [ + 170 + ], "inheritance": { "file": "OuiPaginatedTabHeader" } @@ -43959,6 +44597,9 @@ "stringifiedArguments": "'previousPaginator'" } ], + "modifierKind": [ + 170 + ], "inheritance": { "file": "OuiPaginatedTabHeader" } @@ -43977,6 +44618,9 @@ "stringifiedArguments": "'tabList', {static: true}" } ], + "modifierKind": [ + 170 + ], "inheritance": { "file": "OuiPaginatedTabHeader" } @@ -43995,6 +44639,9 @@ "stringifiedArguments": "'tabListContainer', {static: true}" } ], + "modifierKind": [ + 170 + ], "inheritance": { "file": "OuiPaginatedTabHeader" } @@ -44013,6 +44660,9 @@ "stringifiedArguments": "'tabListInner', {static: true}" } ], + "modifierKind": [ + 170 + ], "inheritance": { "file": "OuiPaginatedTabHeader" } @@ -44036,7 +44686,9 @@ } ], "modifierKind": [ - 123 + 170, + 170, + 125 ], "inheritance": { "file": "OuiPaginatedTabHeader" @@ -44052,7 +44704,7 @@ "line": 137, "rawdescription": "\nCached text content of the header.", "modifierKind": [ - 121 + 123 ], "inheritance": { "file": "OuiPaginatedTabHeader" @@ -44069,8 +44721,8 @@ "line": 113, "rawdescription": "\nEmits when the component is destroyed.", "modifierKind": [ - 122, - 144 + 124, + 148 ], "inheritance": { "file": "OuiPaginatedTabHeader" @@ -44086,7 +44738,7 @@ "description": "", "line": 153, "modifierKind": [ - 121 + 123 ], "inheritance": { "file": "OuiPaginatedTabHeader" @@ -44130,7 +44782,7 @@ "line": 134, "rawdescription": "\nUsed to manage focus between the tabs.", "modifierKind": [ - 121 + 123 ], "inheritance": { "file": "OuiPaginatedTabHeader" @@ -44147,7 +44799,7 @@ "line": 107, "rawdescription": "\nThe distance in pixels that the tab labels should be translated to the left.", "modifierKind": [ - 121 + 123 ], "inheritance": { "file": "OuiPaginatedTabHeader" @@ -44163,7 +44815,7 @@ "line": 131, "rawdescription": "\nWhether the scroll distance has changed and should be applied after the view is checked.", "modifierKind": [ - 121 + 123 ], "inheritance": { "file": "OuiPaginatedTabHeader" @@ -44179,7 +44831,7 @@ "description": "", "line": 171, "modifierKind": [ - 121 + 123 ], "inheritance": { "file": "OuiPaginatedTabHeader" @@ -44196,7 +44848,7 @@ "line": 110, "rawdescription": "\nWhether the header should scroll to the selected index after the view has been checked.", "modifierKind": [ - 121 + 123 ], "inheritance": { "file": "OuiPaginatedTabHeader" @@ -44227,7 +44879,7 @@ "line": 140, "rawdescription": "\nStream that will stop the automated scrolling.", "modifierKind": [ - 121 + 123 ], "inheritance": { "file": "OuiPaginatedTabHeader" @@ -44243,7 +44895,7 @@ "line": 128, "rawdescription": "\n\nThe number of tab labels that are displayed on the header. When this changes, the header\nshould re-evaluate the scroll position.\n", "modifierKind": [ - 121 + 123 ], "inheritance": { "file": "OuiPaginatedTabHeader" @@ -44260,7 +44912,7 @@ "line": 178, "rawdescription": "\nEvent emitted when a label is focused.", "modifierKind": [ - 144 + 148 ], "inheritance": { "file": "OuiPaginatedTabHeader" @@ -44277,7 +44929,7 @@ "line": 174, "rawdescription": "\nEvent emitted when the option is selected.", "modifierKind": [ - 144 + 148 ], "inheritance": { "file": "OuiPaginatedTabHeader" @@ -44302,7 +44954,7 @@ "deprecated": false, "deprecationMessage": "", "modifierKind": [ - 122 + 124 ], "jsdoctags": [ { @@ -44329,7 +44981,7 @@ "deprecated": false, "deprecationMessage": "", "modifierKind": [ - 158 + 164 ], "inheritance": { "file": "OuiPaginatedTabHeader" @@ -44504,24 +45156,24 @@ "jsdoctags": [ { "name": { - "pos": 22708, - "end": 22717, - "flags": 4227072, + "pos": 23371, + "end": 23380, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "direction" }, "type": "ScrollDirection", "deprecated": false, "deprecationMessage": "", "tagName": { - "pos": 22702, - "end": 22707, - "flags": 4227072, + "pos": 23365, + "end": 23370, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "param" }, "comment": "

In which direction the paginator should be scrolled.

\n" @@ -44586,7 +45238,7 @@ "rawdescription": "\nSends any changes that could affect the layout of the items.", "description": "

Sends any changes that could affect the layout of the items.

\n", "modifierKind": [ - 121 + 123 ], "inheritance": { "file": "OuiPaginatedTabHeader" @@ -44659,41 +45311,41 @@ "rawdescription": "\n\nScrolls the header to a given position.\n", "description": "

Scrolls the header to a given position.

\n", "modifierKind": [ - 121 + 123 ], "jsdoctags": [ { "name": { - "pos": 23848, - "end": 23856, - "flags": 4227072, + "pos": 24539, + "end": 24547, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "position" }, "type": "number", "deprecated": false, "deprecationMessage": "", "tagName": { - "pos": 23842, - "end": 23847, - "flags": 4227072, + "pos": 24533, + "end": 24538, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "param" }, "comment": "

Position to which to scroll.

\n" }, { "tagName": { - "pos": 23892, - "end": 23899, - "flags": 4227072, + "pos": 24584, + "end": 24591, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "returns" }, "comment": "

Information on the current scroll distance and the maximum.

\n" @@ -44858,14 +45510,16 @@ "deprecationMessage": "", "hostBindings": [], "hostListeners": [], + "standalone": false, + "imports": [], "description": "

The header of the tab group which displays a list of all the tabs in the tab group. Includes\nan ink bar that follows the currently selected tab. When the tabs list's width exceeds the\nwidth of the header container, then arrows will be displayed to allow the user to scroll\nleft and right across the header.

\n", "rawdescription": "\n\nThe header of the tab group which displays a list of all the tabs in the tab group. Includes\nan ink bar that follows the currently selected tab. When the tabs list's width exceeds the\nwidth of the header container, then arrows will be displayed to allow the user to scroll\nleft and right across the header.\n", "type": "component", - "sourceCode": "import {\n AfterContentChecked,\n AfterContentInit,\n AfterViewInit,\n ChangeDetectionStrategy,\n ChangeDetectorRef,\n Component,\n ContentChildren,\n ElementRef,\n Inject,\n Input,\n NgZone,\n OnDestroy,\n Optional,\n QueryList,\n ViewChild,\n ViewEncapsulation,\n} from '@angular/core';\nimport { ViewportRuler } from '@angular/cdk/scrolling';\nimport { Platform } from '@angular/cdk/platform';\nimport { Directionality } from '@angular/cdk/bidi';\nimport { ANIMATION_MODULE_TYPE } from '@angular/platform-browser/animations';\nimport { ouiTabLabelWrapper } from './tab-label-wrapper';\nimport { OuiInkBar } from './ink-bar';\nimport { OuiPaginatedTabHeader } from './paginated-tab-header';\nimport { BooleanInput, coerceBooleanProperty } from '@angular/cdk/coercion';\n\n/**\n * The header of the tab group which displays a list of all the tabs in the tab group. Includes\n * an ink bar that follows the currently selected tab. When the tabs list's width exceeds the\n * width of the header container, then arrows will be displayed to allow the user to scroll\n * left and right across the header.\n * @docs-private\n */\n@Component({\n selector: 'oui-tab-header',\n templateUrl: 'tab-header.html',\n styleUrls: ['tab-header.scss'],\n // eslint-disable-next-line\n inputs: ['selectedIndex'],\n // eslint-disable-next-line\n outputs: ['selectFocusedIndex', 'indexFocused'],\n encapsulation: ViewEncapsulation.None,\n // tslint:disable-next-line\n changeDetection: ChangeDetectionStrategy.Default,\n // eslint-disable-next-line\n host: {\n class: 'oui-mdc-tab-header',\n '[class.oui-mdc-tab-header-pagination-controls-enabled]':\n '_showPaginationControls',\n '[class.oui-mdc-tab-header-rtl]': \"_getLayoutDirection() == 'rtl'\",\n },\n})\nexport class OuiTabHeader\n extends OuiPaginatedTabHeader\n implements AfterContentChecked, AfterContentInit, AfterViewInit, OnDestroy\n{\n @ContentChildren(ouiTabLabelWrapper, { descendants: false })\n _items: QueryList;\n @ViewChild('tabListContainer', { static: true })\n _tabListContainer: ElementRef;\n @ViewChild('tabList', { static: true }) _tabList: ElementRef;\n @ViewChild('tabListInner', { static: true }) _tabListInner: ElementRef;\n @ViewChild('nextPaginator') _nextPaginator: ElementRef;\n @ViewChild('previousPaginator') _previousPaginator: ElementRef;\n _inkBar: OuiInkBar;\n\n /** Whether the ripple effect is disabled or not. */\n @Input()\n get disableRipple(): boolean {\n return this._disableRipple;\n }\n\n set disableRipple(value: BooleanInput) {\n this._disableRipple = coerceBooleanProperty(value);\n }\n\n private _disableRipple = false;\n\n constructor(\n elementRef: ElementRef,\n changeDetectorRef: ChangeDetectorRef,\n viewportRuler: ViewportRuler,\n @Optional() dir: Directionality,\n ngZone: NgZone,\n platform: Platform,\n @Optional() @Inject(ANIMATION_MODULE_TYPE) animationMode?: string\n ) {\n super(\n // eslint-disable-next-line @typescript-eslint/no-unsafe-argument\n elementRef,\n changeDetectorRef,\n viewportRuler,\n dir,\n ngZone,\n platform,\n animationMode\n );\n }\n\n override ngAfterContentInit() {\n this._inkBar = new OuiInkBar(this._items);\n super.ngAfterContentInit();\n }\n\n protected _itemSelected(event: KeyboardEvent) {\n event.preventDefault();\n }\n}\n", + "sourceCode": "import {\r\n AfterContentChecked,\r\n AfterContentInit,\r\n AfterViewInit,\r\n ChangeDetectionStrategy,\r\n ChangeDetectorRef,\r\n Component,\r\n ContentChildren,\r\n ElementRef,\r\n Inject,\r\n Input,\r\n NgZone,\r\n OnDestroy,\r\n Optional,\r\n QueryList,\r\n ViewChild,\r\n ViewEncapsulation,\r\n} from '@angular/core';\r\nimport { ViewportRuler } from '@angular/cdk/scrolling';\r\nimport { Platform } from '@angular/cdk/platform';\r\nimport { Directionality } from '@angular/cdk/bidi';\r\nimport { ANIMATION_MODULE_TYPE } from '@angular/platform-browser/animations';\r\nimport { ouiTabLabelWrapper } from './tab-label-wrapper';\r\nimport { OuiInkBar } from './ink-bar';\r\nimport { OuiPaginatedTabHeader } from './paginated-tab-header';\r\nimport { BooleanInput, coerceBooleanProperty } from '@angular/cdk/coercion';\r\n\r\n/**\r\n * The header of the tab group which displays a list of all the tabs in the tab group. Includes\r\n * an ink bar that follows the currently selected tab. When the tabs list's width exceeds the\r\n * width of the header container, then arrows will be displayed to allow the user to scroll\r\n * left and right across the header.\r\n * @docs-private\r\n */\r\n@Component({\r\n selector: 'oui-tab-header',\r\n templateUrl: 'tab-header.html',\r\n styleUrls: ['tab-header.scss'],\r\n // eslint-disable-next-line\r\n inputs: ['selectedIndex'],\r\n // eslint-disable-next-line\r\n outputs: ['selectFocusedIndex', 'indexFocused'],\r\n encapsulation: ViewEncapsulation.None,\r\n // tslint:disable-next-line\r\n changeDetection: ChangeDetectionStrategy.Default,\r\n // eslint-disable-next-line\r\n host: {\r\n class: 'oui-mdc-tab-header',\r\n '[class.oui-mdc-tab-header-pagination-controls-enabled]':\r\n '_showPaginationControls',\r\n '[class.oui-mdc-tab-header-rtl]': \"_getLayoutDirection() == 'rtl'\",\r\n },\r\n})\r\nexport class OuiTabHeader\r\n extends OuiPaginatedTabHeader\r\n implements AfterContentChecked, AfterContentInit, AfterViewInit, OnDestroy\r\n{\r\n @ContentChildren(ouiTabLabelWrapper, { descendants: false })\r\n _items: QueryList;\r\n @ViewChild('tabListContainer', { static: true })\r\n _tabListContainer: ElementRef;\r\n @ViewChild('tabList', { static: true }) _tabList: ElementRef;\r\n @ViewChild('tabListInner', { static: true }) _tabListInner: ElementRef;\r\n @ViewChild('nextPaginator') _nextPaginator: ElementRef;\r\n @ViewChild('previousPaginator') _previousPaginator: ElementRef;\r\n _inkBar: OuiInkBar;\r\n\r\n /** Whether the ripple effect is disabled or not. */\r\n @Input()\r\n get disableRipple(): boolean {\r\n return this._disableRipple;\r\n }\r\n\r\n set disableRipple(value: BooleanInput) {\r\n this._disableRipple = coerceBooleanProperty(value);\r\n }\r\n\r\n private _disableRipple = false;\r\n\r\n constructor(\r\n elementRef: ElementRef,\r\n changeDetectorRef: ChangeDetectorRef,\r\n viewportRuler: ViewportRuler,\r\n @Optional() dir: Directionality,\r\n ngZone: NgZone,\r\n platform: Platform,\r\n @Optional() @Inject(ANIMATION_MODULE_TYPE) animationMode?: string\r\n ) {\r\n super(\r\n // eslint-disable-next-line @typescript-eslint/no-unsafe-argument\r\n elementRef,\r\n changeDetectorRef,\r\n viewportRuler,\r\n dir,\r\n ngZone,\r\n platform,\r\n animationMode\r\n );\r\n }\r\n\r\n override ngAfterContentInit() {\r\n this._inkBar = new OuiInkBar(this._items);\r\n super.ngAfterContentInit();\r\n }\r\n\r\n protected _itemSelected(event: KeyboardEvent) {\r\n event.preventDefault();\r\n }\r\n}\r\n", "assetsDirs": [], "styleUrlsData": [ { - "data": "@use '@angular/cdk';\n@use './tabs-theme';\n@use './tabs-common';\n\n@include tabs-common.paginated-tab-header;\n\n.oui-mdc-tab-label-container {\n @include tabs-common.paginated-tab-header-container;\n}\n\n.oui-tab-labels-container {\n @include tabs-common.paginated-tab-header-item-wrapper('.oui-mdc-tab-header');\n}\n\n.oui-mdc-tab {\n // For the tab element, default inset/offset values are necessary to ensure that\n // the focus indicator is sufficiently contrastive and renders appropriately.\n &::before {\n margin: 5px;\n }\n\n @include cdk.high-contrast(active, off) {\n // When a tab is disabled in high contrast mode, set the text color to the disabled\n // color, which is (unintuitively) named \"GrayText\".\n &[aria-disabled='true'] {\n color: GrayText;\n }\n }\n}\n", + "data": "@use '@angular/cdk';\r\n@use './tabs-theme';\r\n@use './tabs-common';\r\n\r\n@include tabs-common.paginated-tab-header;\r\n\r\n.oui-mdc-tab-label-container {\r\n @include tabs-common.paginated-tab-header-container;\r\n}\r\n\r\n.oui-tab-labels-container {\r\n @include tabs-common.paginated-tab-header-item-wrapper('.oui-mdc-tab-header');\r\n}\r\n\r\n.oui-mdc-tab {\r\n // For the tab element, default inset/offset values are necessary to ensure that\r\n // the focus indicator is sufficiently contrastive and renders appropriately.\r\n &::before {\r\n margin: 5px;\r\n }\r\n\r\n @include cdk.high-contrast(active, off) {\r\n // When a tab is disabled in high contrast mode, set the text color to the disabled\r\n // color, which is (unintuitively) named \"GrayText\".\r\n &[aria-disabled='true'] {\r\n color: GrayText;\r\n }\r\n }\r\n}\r\n", "styleUrl": "tab-header.scss" } ], @@ -44988,7 +45642,9 @@ } ] }, - "extends": "OuiPaginatedTabHeader", + "extends": [ + "OuiPaginatedTabHeader" + ], "implements": [ "AfterContentChecked", "AfterContentInit", @@ -45035,7 +45691,7 @@ } } }, - "templateData": "\n\n
\n\n\n\n \n
\n \n
\n \n\n\n\n\n
\n\n" + "templateData": "\r\n\r\n
\r\n\r\n\r\n\r\n \r\n
\r\n \r\n
\r\n \r\n\r\n\r\n\r\n\r\n
\r\n\r\n" }, { "name": "OuiTable", @@ -45075,6 +45731,7 @@ "template": "CDK_TABLE_TEMPLATE", "templateUrl": [], "viewProviders": [], + "hostDirectives": [], "inputsClass": [], "outputsClass": [], "propertiesClass": [ @@ -45089,8 +45746,8 @@ "line": 72, "rawdescription": "\nOverrides the need to add position: sticky on every sticky cell element in `CdkTable`.", "modifierKind": [ - 122, - 158 + 124, + 164 ] }, { @@ -45104,8 +45761,8 @@ "line": 69, "rawdescription": "\nOverrides the sticky CSS class set by the `CdkTable`.", "modifierKind": [ - 122, - 158 + 124, + 164 ] } ], @@ -45114,6 +45771,8 @@ "deprecationMessage": "", "hostBindings": [], "hostListeners": [], + "standalone": false, + "imports": [], "description": "

Wrapper for the CdkTable with Once-UI design styles.

\n", "rawdescription": "\n\nWrapper for the CdkTable with Once-UI design styles.\n", "type": "component", @@ -45126,7 +45785,9 @@ } ], "stylesData": "", - "extends": "CdkTable" + "extends": [ + "CdkTable" + ] }, { "name": "OuiTableCustomStorybook", @@ -45143,6 +45804,7 @@ "template": "
\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n
Users\n
\n
\n
\n
\n {{ user.name }}\n
\n
\n {{ user.email }}\n
\n
\n
\n
Role{{ element.role }}\n Integrations\n \n
\n
    \n
  • \n \n
  • \n
\n
\n
\n Licenses\n \n
\n
    \n
  • \n \n
  • \n
\n
\n
\n Status\n {{ element.status }}
\n
\n", "templateUrl": [], "viewProviders": [], + "hostDirectives": [], "inputsClass": [ { "name": "pageSize", @@ -45198,6 +45860,9 @@ "name": "ViewChild", "stringifiedArguments": "OuiSort, {static: true}" } + ], + "modifierKind": [ + 170 ] }, { @@ -45237,6 +45902,8 @@ "deprecationMessage": "", "hostBindings": [], "hostListeners": [], + "standalone": false, + "imports": [], "description": "", "rawdescription": "\n", "type": "component", @@ -45270,6 +45937,7 @@ } ] }, + "extends": [], "implements": [ "OnChanges" ] @@ -45289,6 +45957,7 @@ "template": "\n \n\n
\n \n \n \n \n \n \n \n
\n {{ column }}\n {{ element[column] }}
\n\n \n
\n", "templateUrl": [], "viewProviders": [], + "hostDirectives": [], "inputsClass": [ { "name": "pageSize", @@ -45344,6 +46013,9 @@ "name": "ViewChild", "stringifiedArguments": "OuiPaginator, {static: true}" } + ], + "modifierKind": [ + 170 ] }, { @@ -45359,6 +46031,9 @@ "name": "ViewChild", "stringifiedArguments": "OuiSort, {static: true}" } + ], + "modifierKind": [ + 170 ] } ], @@ -45416,6 +46091,8 @@ "deprecationMessage": "", "hostBindings": [], "hostListeners": [], + "standalone": false, + "imports": [], "description": "", "rawdescription": "\n", "type": "component", @@ -45431,6 +46108,7 @@ "args": [], "line": 63 }, + "extends": [], "implements": [ "OnInit", "OnChanges" @@ -45438,7 +46116,7 @@ }, { "name": "OuiTabLink", - "id": "component-OuiTabLink-9bae65d3c7ced1d19b2c9b521dc10b849a2def4e235b5b53918d1dfeb0d6e848284098bb20976a21d5cb589e2ebe3990b059964fdae21490b898a0aa8c60c4ad", + "id": "component-OuiTabLink-6ce7108d054f1ce731fb3fdfd386c2252b009425dd05e2318aa5d6e1a34d06858b72f8ec2278d0b20e6242ef7a9e6be288d99d19c36c6712b85c978bf5907722", "file": "ui/src/components/tabs/tab-nav-bar/tab-nav-bar.ts", "changeDetection": "ChangeDetectionStrategy.OnPush", "encapsulation": [ @@ -45465,6 +46143,7 @@ "tab-link.html" ], "viewProviders": [], + "hostDirectives": [], "inputsClass": [ { "name": "active", @@ -45500,8 +46179,8 @@ "description": "", "line": 326, "modifierKind": [ - 121, - 144 + 123, + 148 ] }, { @@ -45515,7 +46194,7 @@ "line": 329, "rawdescription": "\nWhether the tab link is active or not.", "modifierKind": [ - 122 + 124 ] } ], @@ -45640,7 +46319,7 @@ "deprecated": false, "deprecationMessage": "", "modifierKind": [ - 158 + 164 ] } ], @@ -45648,14 +46327,16 @@ "deprecationMessage": "", "hostBindings": [], "hostListeners": [], + "standalone": false, + "imports": [], "description": "

Link inside a oui-tab-nav-bar.

\n", "rawdescription": "\n\nLink inside a `oui-tab-nav-bar`.\n", "type": "component", - "sourceCode": "import {\n AfterContentChecked,\n AfterContentInit,\n AfterViewInit,\n Attribute,\n ChangeDetectionStrategy,\n ChangeDetectorRef,\n Component,\n ContentChildren,\n ElementRef,\n forwardRef,\n Inject,\n Input,\n NgZone,\n OnDestroy,\n Optional,\n QueryList,\n ViewChild,\n ViewEncapsulation,\n} from '@angular/core';\nimport { ANIMATION_MODULE_TYPE } from '@angular/platform-browser/animations';\nimport {\n CanDisable,\n CanDisableRipple,\n HasTabIndex,\n mixinDisabled,\n mixinDisableRipple,\n mixinTabIndex,\n ThemePalette,\n} from '../../core';\nimport { FocusableOption, FocusMonitor } from '@angular/cdk/a11y';\nimport { Directionality } from '@angular/cdk/bidi';\nimport { ViewportRuler } from '@angular/cdk/scrolling';\nimport { Platform } from '@angular/cdk/platform';\nimport { OuiInkBar, mixinInkBarItem } from '../ink-bar';\nimport {\n BooleanInput,\n coerceBooleanProperty,\n NumberInput,\n} from '@angular/cdk/coercion';\nimport { BehaviorSubject, Subject } from 'rxjs';\nimport { startWith, takeUntil } from 'rxjs/operators';\nimport { ENTER, SPACE } from '@angular/cdk/keycodes';\nimport { OUI_TABS_CONFIG, OuiTabsConfig } from '../tab-config';\nimport { OuiPaginatedTabHeader } from '../paginated-tab-header';\nimport { isDevMode } from '@angular/core';\n\n// Increasing integer for generating unique ids for tab nav components.\nlet nextUniqueId = 0;\n\n/**\n * Navigation component matching the styles of the tab group header.\n * Provides anchored navigation with animated ink bar.\n */\n@Component({\n // eslint-disable-next-line @angular-eslint/component-selector\n selector: '[oui-tab-nav-bar]',\n exportAs: 'OuiTabNavBar, OuiTabNav',\n // eslint-disable-next-line @angular-eslint/no-inputs-metadata-property\n inputs: ['color'],\n templateUrl: 'tab-nav-bar.html',\n styleUrls: ['tab-nav-bar.scss'],\n // eslint-disable-next-line @angular-eslint/no-host-metadata-property\n host: {\n '[attr.role]': '_getRole()',\n class: 'oui-mdc-tab-nav-bar oui-mdc-tab-header',\n '[class.oui-mdc-tab-header-pagination-controls-enabled]':\n '_showPaginationControls',\n '[class.oui-mdc-tab-header-rtl]': \"_getLayoutDirection() == 'rtl'\",\n '[class.oui-mdc-tab-nav-bar-stretch-tabs]': 'stretchTabs',\n '[class.mat-primary]': 'color !== \"warn\" && color !== \"accent\"',\n '[class.mat-accent]': 'color === \"accent\"',\n '[class.mat-warn]': 'color === \"warn\"',\n '[class._oui-animation-noopable]': '_animationMode === \"NoopAnimations\"',\n '[style.--oui-tab-animation-duration]': 'animationDuration',\n },\n encapsulation: ViewEncapsulation.None,\n // tslint:disable-next-line:validate-decorators\n changeDetection: ChangeDetectionStrategy.Default,\n})\nexport class OuiTabNav\n extends OuiPaginatedTabHeader\n implements AfterContentChecked, AfterContentInit, OnDestroy, AfterViewInit\n{\n /** Whether the ink bar should fit its width to the size of the tab label content. */\n @Input()\n get fitInkBarToContent(): boolean {\n return this._fitInkBarToContent.value;\n }\n set fitInkBarToContent(v: BooleanInput) {\n this._fitInkBarToContent.next(coerceBooleanProperty(v));\n this._changeDetectorRef.markForCheck();\n }\n _fitInkBarToContent = new BehaviorSubject(false);\n\n /** Whether tabs should be stretched to fill the header. */\n @Input('oui-stretch-tabs')\n get stretchTabs(): boolean {\n return this._stretchTabs;\n }\n set stretchTabs(v: BooleanInput) {\n this._stretchTabs = coerceBooleanProperty(v);\n }\n private _stretchTabs = true;\n\n @Input()\n get animationDuration(): string {\n return this._animationDuration;\n }\n\n set animationDuration(value: NumberInput) {\n // eslint-disable-next-line @typescript-eslint/restrict-plus-operands\n this._animationDuration = /^\\d+$/.test(value + '') // eslint-disable-next-line @typescript-eslint/restrict-plus-operands\n ? value + 'ms'\n : (value as string);\n }\n\n private _animationDuration: string;\n\n /** Query list of all tab links of the tab navigation. */\n @ContentChildren(forwardRef(() => OuiTabLink), { descendants: true })\n _items: QueryList;\n\n /** Background color of the tab nav. */\n @Input()\n get backgroundColor(): ThemePalette {\n return this._backgroundColor;\n }\n\n set backgroundColor(value: ThemePalette) {\n const classList = this._elementRef.nativeElement.classList;\n classList.remove(\n 'oui-tabs-with-background',\n `oui-background-${this.backgroundColor}`\n );\n\n if (value) {\n classList.add('oui-tabs-with-background', `oui-background-${value}`);\n }\n\n this._backgroundColor = value;\n }\n\n private _backgroundColor: ThemePalette;\n\n /** Whether the ripple effect is disabled or not. */\n @Input()\n get disableRipple(): boolean {\n return this._disableRipple;\n }\n\n set disableRipple(value: BooleanInput) {\n this._disableRipple = coerceBooleanProperty(value);\n }\n\n private _disableRipple = false;\n\n /** Theme color of the nav bar. */\n @Input() color: ThemePalette = 'accent';\n\n /**\n * Associated tab panel controlled by the nav bar. If not provided, then the nav bar\n * follows the ARIA link / navigation landmark pattern. If provided, it follows the\n * ARIA tabs design pattern.\n */\n @Input() tabPanel?: ouiTabNavPanel;\n\n @ViewChild('tabListContainer', { static: true })\n _tabListContainer: ElementRef;\n @ViewChild('tabList', { static: true }) _tabList: ElementRef;\n @ViewChild('tabListInner', { static: true }) _tabListInner: ElementRef;\n @ViewChild('nextPaginator') _nextPaginator: ElementRef;\n @ViewChild('previousPaginator') _previousPaginator: ElementRef;\n _inkBar: OuiInkBar;\n\n constructor(\n elementRef: ElementRef,\n @Optional() dir: Directionality,\n ngZone: NgZone,\n changeDetectorRef: ChangeDetectorRef,\n viewportRuler: ViewportRuler,\n platform: Platform,\n @Optional() @Inject(ANIMATION_MODULE_TYPE) animationMode?: string,\n @Optional() @Inject(OUI_TABS_CONFIG) defaultConfig?: OuiTabsConfig\n ) {\n super(\n // eslint-disable-next-line @typescript-eslint/no-unsafe-argument\n elementRef,\n changeDetectorRef,\n viewportRuler,\n dir,\n ngZone,\n platform,\n animationMode\n );\n this.disablePagination =\n defaultConfig && defaultConfig.disablePagination != null\n ? defaultConfig.disablePagination\n : false;\n this.fitInkBarToContent =\n defaultConfig && defaultConfig.fitInkBarToContent != null\n ? defaultConfig.fitInkBarToContent\n : false;\n this.stretchTabs =\n defaultConfig && defaultConfig.stretchTabs != null\n ? defaultConfig.stretchTabs\n : true;\n }\n\n protected _itemSelected() {\n // noop\n }\n\n override ngAfterContentInit() {\n this._inkBar = new OuiInkBar(this._items);\n // We need this to run before the `changes` subscription in parent to ensure that the\n // selectedIndex is up-to-date by the time the super class starts looking for it.\n this._items.changes\n .pipe(startWith(null), takeUntil(this._destroyed))\n .subscribe(() => {\n this.updateActiveLink();\n });\n\n super.ngAfterContentInit();\n }\n\n override ngAfterViewInit() {\n if (!this.tabPanel && (typeof isDevMode === 'undefined' || isDevMode)) {\n throw new Error('A oui-tab-nav-panel must be specified via [tabPanel].');\n }\n super.ngAfterViewInit();\n }\n\n /** Notifies the component that the active link has been changed. */\n updateActiveLink() {\n if (!this._items) {\n return;\n }\n\n const items = this._items.toArray();\n\n for (let i = 0; i < items.length; i++) {\n if (items[i].active) {\n this.selectedIndex = i;\n this._changeDetectorRef.markForCheck();\n\n if (this.tabPanel) {\n this.tabPanel._activeTabId = items[i].id;\n }\n\n return;\n }\n }\n\n // The ink bar should hide itself if no items are active.\n this.selectedIndex = -1;\n this._inkBar.hide();\n }\n\n _getRole(): string | null {\n return this.tabPanel\n ? 'tablist'\n : this._elementRef.nativeElement.getAttribute('role');\n }\n}\n\n// Boilerplate for applying mixins to OuiTabLink.\nconst _OuiTabLinkMixinBase = mixinInkBarItem(\n mixinTabIndex(\n mixinDisableRipple(\n mixinDisabled(\n class {\n elementRef: ElementRef;\n }\n )\n )\n )\n);\n\n/**\n * Link inside a `oui-tab-nav-bar`.\n */\n@Component({\n // eslint-disable-next-line\n selector: '[oui-tab-link], [OuiTabLink]',\n exportAs: 'OuiTabLink',\n // eslint-disable-next-line\n inputs: ['disabled', 'disableRipple', 'tabIndex', 'active', 'id'],\n changeDetection: ChangeDetectionStrategy.OnPush,\n encapsulation: ViewEncapsulation.None,\n templateUrl: 'tab-link.html',\n styleUrls: ['tab-link.scss'],\n // eslint-disable-next-line\n host: {\n class: 'mdc-tab oui-mdc-tab-link oui-mdc-focus-indicator',\n '[attr.aria-controls]': '_getAriaControls()',\n '[attr.aria-current]': '_getAriaCurrent()',\n '[attr.aria-disabled]': 'disabled',\n '[attr.aria-selected]': '_getAriaSelected()',\n '[attr.id]': 'id',\n '[attr.tabIndex]': '_getTabIndex()',\n '[attr.role]': '_getRole()',\n '[class.oui-mdc-tab-disabled]': 'disabled',\n '[class.mdc-tab--active]': 'active',\n '(focus)': '_handleFocus()',\n '(keydown)': '_handleKeydown($event)',\n },\n})\nexport class OuiTabLink\n extends _OuiTabLinkMixinBase\n implements\n AfterViewInit,\n OnDestroy,\n CanDisable,\n CanDisableRipple,\n HasTabIndex,\n FocusableOption\n{\n private readonly _destroyed = new Subject();\n\n /** Whether the tab link is active or not. */\n protected _isActive = false;\n\n /** Whether the link is active. */\n @Input()\n get active(): boolean {\n return this._isActive;\n }\n\n set active(value: BooleanInput) {\n const newValue = coerceBooleanProperty(value);\n\n if (newValue !== this._isActive) {\n this._isActive = newValue;\n this._tabNavBar.updateActiveLink();\n }\n }\n\n /**\n * Whether ripples are disabled on interaction.\n * @docs-private\n */\n get rippleDisabled(): boolean {\n return this.disabled || this.disableRipple || this._tabNavBar.disableRipple;\n }\n\n /** Unique id for the tab. */\n @Input() id = `oui-tab-link-${nextUniqueId++}`;\n\n constructor(\n private _tabNavBar: OuiTabNav,\n /** @docs-private */\n override elementRef: ElementRef,\n @Attribute('tabindex') tabIndex: string,\n private _focusMonitor: FocusMonitor,\n @Optional() @Inject(ANIMATION_MODULE_TYPE) animationMode?: string\n ) {\n super();\n\n this.tabIndex = parseInt(tabIndex) || 0;\n\n if (animationMode === 'NoopAnimations') {\n // this.rippleConfig.animation = { enterDuration: 0, exitDuration: 0 };\n }\n\n _tabNavBar._fitInkBarToContent\n .pipe(takeUntil(this._destroyed))\n .subscribe((fitInkBarToContent) => {\n this.fitInkBarToContent = fitInkBarToContent;\n });\n }\n\n /** Focuses the tab link. */\n focus() {\n this.elementRef.nativeElement.focus();\n }\n\n ngAfterViewInit() {\n // eslint-disable-next-line @typescript-eslint/no-unsafe-argument\n this._focusMonitor.monitor(this.elementRef);\n }\n\n override ngOnDestroy() {\n this._destroyed.next();\n this._destroyed.complete();\n super.ngOnDestroy();\n // eslint-disable-next-line @typescript-eslint/no-unsafe-argument\n this._focusMonitor.stopMonitoring(this.elementRef);\n }\n\n _handleFocus() {\n // Since we allow navigation through tabbing in the nav bar, we\n // have to update the focused index whenever the link receives focus.\n this._tabNavBar.focusIndex = this._tabNavBar._items.toArray().indexOf(this);\n }\n\n _handleKeydown(event: KeyboardEvent) {\n if (this.disabled && (event.keyCode === SPACE || event.keyCode === ENTER)) {\n event.preventDefault();\n } else if (this._tabNavBar.tabPanel && event.keyCode === SPACE) {\n this.elementRef.nativeElement.click();\n }\n }\n\n _getAriaControls(): string | null {\n return this._tabNavBar.tabPanel\n ? this._tabNavBar.tabPanel?.id\n : this.elementRef.nativeElement.getAttribute('aria-controls');\n }\n\n _getAriaSelected(): string | null {\n if (this._tabNavBar.tabPanel) {\n return this.active ? 'true' : 'false';\n } else {\n return this.elementRef.nativeElement.getAttribute('aria-selected');\n }\n }\n\n _getAriaCurrent(): string | null {\n return this.active && !this._tabNavBar.tabPanel ? 'page' : null;\n }\n\n _getRole(): string | null {\n return this._tabNavBar.tabPanel\n ? 'tab'\n : this.elementRef.nativeElement.getAttribute('role');\n }\n\n _getTabIndex(): number {\n if (this._tabNavBar.tabPanel) {\n return this._isActive && !this.disabled ? 0 : -1;\n } else {\n return this.tabIndex;\n }\n }\n}\n\n/**\n * Tab panel component associated with OuiTabNav.\n */\n@Component({\n selector: 'oui-tab-nav-panel',\n exportAs: 'ouiTabNavPanel',\n template: '',\n // eslint-disable-next-line @angular-eslint/no-host-metadata-property\n host: {\n '[attr.aria-labelledby]': '_activeTabId',\n '[attr.id]': 'id',\n class: 'oui-mdc-tab-nav-panel',\n role: 'tabpanel',\n },\n encapsulation: ViewEncapsulation.None,\n changeDetection: ChangeDetectionStrategy.OnPush,\n})\nexport class ouiTabNavPanel {\n /** Unique id for the tab panel. */\n @Input() id = `oui-tab-nav-panel-${nextUniqueId++}`;\n\n /** Id of the active tab in the nav bar. */\n _activeTabId?: string;\n}\n", + "sourceCode": "import {\r\n AfterContentChecked,\r\n AfterContentInit,\r\n AfterViewInit,\r\n Attribute,\r\n ChangeDetectionStrategy,\r\n ChangeDetectorRef,\r\n Component,\r\n ContentChildren,\r\n ElementRef,\r\n forwardRef,\r\n Inject,\r\n Input,\r\n NgZone,\r\n OnDestroy,\r\n Optional,\r\n QueryList,\r\n ViewChild,\r\n ViewEncapsulation,\r\n} from '@angular/core';\r\nimport { ANIMATION_MODULE_TYPE } from '@angular/platform-browser/animations';\r\nimport {\r\n CanDisable,\r\n CanDisableRipple,\r\n HasTabIndex,\r\n mixinDisabled,\r\n mixinDisableRipple,\r\n mixinTabIndex,\r\n ThemePalette,\r\n} from '../../core';\r\nimport { FocusableOption, FocusMonitor } from '@angular/cdk/a11y';\r\nimport { Directionality } from '@angular/cdk/bidi';\r\nimport { ViewportRuler } from '@angular/cdk/scrolling';\r\nimport { Platform } from '@angular/cdk/platform';\r\nimport { OuiInkBar, mixinInkBarItem } from '../ink-bar';\r\nimport {\r\n BooleanInput,\r\n coerceBooleanProperty,\r\n NumberInput,\r\n} from '@angular/cdk/coercion';\r\nimport { BehaviorSubject, Subject } from 'rxjs';\r\nimport { startWith, takeUntil } from 'rxjs/operators';\r\nimport { ENTER, SPACE } from '@angular/cdk/keycodes';\r\nimport { OUI_TABS_CONFIG, OuiTabsConfig } from '../tab-config';\r\nimport { OuiPaginatedTabHeader } from '../paginated-tab-header';\r\nimport { isDevMode } from '@angular/core';\r\n\r\n// Increasing integer for generating unique ids for tab nav components.\r\nlet nextUniqueId = 0;\r\n\r\n/**\r\n * Navigation component matching the styles of the tab group header.\r\n * Provides anchored navigation with animated ink bar.\r\n */\r\n@Component({\r\n // eslint-disable-next-line @angular-eslint/component-selector\r\n selector: '[oui-tab-nav-bar]',\r\n exportAs: 'OuiTabNavBar, OuiTabNav',\r\n // eslint-disable-next-line @angular-eslint/no-inputs-metadata-property\r\n inputs: ['color'],\r\n templateUrl: 'tab-nav-bar.html',\r\n styleUrls: ['tab-nav-bar.scss'],\r\n // eslint-disable-next-line @angular-eslint/no-host-metadata-property\r\n host: {\r\n '[attr.role]': '_getRole()',\r\n class: 'oui-mdc-tab-nav-bar oui-mdc-tab-header',\r\n '[class.oui-mdc-tab-header-pagination-controls-enabled]':\r\n '_showPaginationControls',\r\n '[class.oui-mdc-tab-header-rtl]': \"_getLayoutDirection() == 'rtl'\",\r\n '[class.oui-mdc-tab-nav-bar-stretch-tabs]': 'stretchTabs',\r\n '[class.mat-primary]': 'color !== \"warn\" && color !== \"accent\"',\r\n '[class.mat-accent]': 'color === \"accent\"',\r\n '[class.mat-warn]': 'color === \"warn\"',\r\n '[class._oui-animation-noopable]': '_animationMode === \"NoopAnimations\"',\r\n '[style.--oui-tab-animation-duration]': 'animationDuration',\r\n },\r\n encapsulation: ViewEncapsulation.None,\r\n // tslint:disable-next-line:validate-decorators\r\n changeDetection: ChangeDetectionStrategy.Default,\r\n})\r\nexport class OuiTabNav\r\n extends OuiPaginatedTabHeader\r\n implements AfterContentChecked, AfterContentInit, OnDestroy, AfterViewInit\r\n{\r\n /** Whether the ink bar should fit its width to the size of the tab label content. */\r\n @Input()\r\n get fitInkBarToContent(): boolean {\r\n return this._fitInkBarToContent.value;\r\n }\r\n set fitInkBarToContent(v: BooleanInput) {\r\n this._fitInkBarToContent.next(coerceBooleanProperty(v));\r\n this._changeDetectorRef.markForCheck();\r\n }\r\n _fitInkBarToContent = new BehaviorSubject(false);\r\n\r\n /** Whether tabs should be stretched to fill the header. */\r\n @Input('oui-stretch-tabs')\r\n get stretchTabs(): boolean {\r\n return this._stretchTabs;\r\n }\r\n set stretchTabs(v: BooleanInput) {\r\n this._stretchTabs = coerceBooleanProperty(v);\r\n }\r\n private _stretchTabs = true;\r\n\r\n @Input()\r\n get animationDuration(): string {\r\n return this._animationDuration;\r\n }\r\n\r\n set animationDuration(value: NumberInput) {\r\n // eslint-disable-next-line @typescript-eslint/restrict-plus-operands\r\n this._animationDuration = /^\\d+$/.test(value + '') // eslint-disable-next-line @typescript-eslint/restrict-plus-operands\r\n ? value + 'ms'\r\n : (value as string);\r\n }\r\n\r\n private _animationDuration: string;\r\n\r\n /** Query list of all tab links of the tab navigation. */\r\n @ContentChildren(forwardRef(() => OuiTabLink), { descendants: true })\r\n _items: QueryList;\r\n\r\n /** Background color of the tab nav. */\r\n @Input()\r\n get backgroundColor(): ThemePalette {\r\n return this._backgroundColor;\r\n }\r\n\r\n set backgroundColor(value: ThemePalette) {\r\n const classList = this._elementRef.nativeElement.classList;\r\n classList.remove(\r\n 'oui-tabs-with-background',\r\n `oui-background-${this.backgroundColor}`\r\n );\r\n\r\n if (value) {\r\n classList.add('oui-tabs-with-background', `oui-background-${value}`);\r\n }\r\n\r\n this._backgroundColor = value;\r\n }\r\n\r\n private _backgroundColor: ThemePalette;\r\n\r\n /** Whether the ripple effect is disabled or not. */\r\n @Input()\r\n get disableRipple(): boolean {\r\n return this._disableRipple;\r\n }\r\n\r\n set disableRipple(value: BooleanInput) {\r\n this._disableRipple = coerceBooleanProperty(value);\r\n }\r\n\r\n private _disableRipple = false;\r\n\r\n /** Theme color of the nav bar. */\r\n @Input() color: ThemePalette = 'accent';\r\n\r\n /**\r\n * Associated tab panel controlled by the nav bar. If not provided, then the nav bar\r\n * follows the ARIA link / navigation landmark pattern. If provided, it follows the\r\n * ARIA tabs design pattern.\r\n */\r\n @Input() tabPanel?: ouiTabNavPanel;\r\n\r\n @ViewChild('tabListContainer', { static: true })\r\n _tabListContainer: ElementRef;\r\n @ViewChild('tabList', { static: true }) _tabList: ElementRef;\r\n @ViewChild('tabListInner', { static: true }) _tabListInner: ElementRef;\r\n @ViewChild('nextPaginator') _nextPaginator: ElementRef;\r\n @ViewChild('previousPaginator') _previousPaginator: ElementRef;\r\n _inkBar: OuiInkBar;\r\n\r\n constructor(\r\n elementRef: ElementRef,\r\n @Optional() dir: Directionality,\r\n ngZone: NgZone,\r\n changeDetectorRef: ChangeDetectorRef,\r\n viewportRuler: ViewportRuler,\r\n platform: Platform,\r\n @Optional() @Inject(ANIMATION_MODULE_TYPE) animationMode?: string,\r\n @Optional() @Inject(OUI_TABS_CONFIG) defaultConfig?: OuiTabsConfig\r\n ) {\r\n super(\r\n // eslint-disable-next-line @typescript-eslint/no-unsafe-argument\r\n elementRef,\r\n changeDetectorRef,\r\n viewportRuler,\r\n dir,\r\n ngZone,\r\n platform,\r\n animationMode\r\n );\r\n this.disablePagination =\r\n defaultConfig && defaultConfig.disablePagination != null\r\n ? defaultConfig.disablePagination\r\n : false;\r\n this.fitInkBarToContent =\r\n defaultConfig && defaultConfig.fitInkBarToContent != null\r\n ? defaultConfig.fitInkBarToContent\r\n : false;\r\n this.stretchTabs =\r\n defaultConfig && defaultConfig.stretchTabs != null\r\n ? defaultConfig.stretchTabs\r\n : true;\r\n }\r\n\r\n protected _itemSelected() {\r\n // noop\r\n }\r\n\r\n override ngAfterContentInit() {\r\n this._inkBar = new OuiInkBar(this._items);\r\n // We need this to run before the `changes` subscription in parent to ensure that the\r\n // selectedIndex is up-to-date by the time the super class starts looking for it.\r\n this._items.changes\r\n .pipe(startWith(null), takeUntil(this._destroyed))\r\n .subscribe(() => {\r\n this.updateActiveLink();\r\n });\r\n\r\n super.ngAfterContentInit();\r\n }\r\n\r\n override ngAfterViewInit() {\r\n if (!this.tabPanel && (typeof isDevMode === 'undefined' || isDevMode)) {\r\n throw new Error('A oui-tab-nav-panel must be specified via [tabPanel].');\r\n }\r\n super.ngAfterViewInit();\r\n }\r\n\r\n /** Notifies the component that the active link has been changed. */\r\n updateActiveLink() {\r\n if (!this._items) {\r\n return;\r\n }\r\n\r\n const items = this._items.toArray();\r\n\r\n for (let i = 0; i < items.length; i++) {\r\n if (items[i].active) {\r\n this.selectedIndex = i;\r\n this._changeDetectorRef.markForCheck();\r\n\r\n if (this.tabPanel) {\r\n this.tabPanel._activeTabId = items[i].id;\r\n }\r\n\r\n return;\r\n }\r\n }\r\n\r\n // The ink bar should hide itself if no items are active.\r\n this.selectedIndex = -1;\r\n this._inkBar.hide();\r\n }\r\n\r\n _getRole(): string | null {\r\n return this.tabPanel\r\n ? 'tablist'\r\n : this._elementRef.nativeElement.getAttribute('role');\r\n }\r\n}\r\n\r\n// Boilerplate for applying mixins to OuiTabLink.\r\nconst _OuiTabLinkMixinBase = mixinInkBarItem(\r\n mixinTabIndex(\r\n mixinDisableRipple(\r\n mixinDisabled(\r\n class {\r\n elementRef: ElementRef;\r\n }\r\n )\r\n )\r\n )\r\n);\r\n\r\n/**\r\n * Link inside a `oui-tab-nav-bar`.\r\n */\r\n@Component({\r\n // eslint-disable-next-line\r\n selector: '[oui-tab-link], [OuiTabLink]',\r\n exportAs: 'OuiTabLink',\r\n // eslint-disable-next-line\r\n inputs: ['disabled', 'disableRipple', 'tabIndex', 'active', 'id'],\r\n changeDetection: ChangeDetectionStrategy.OnPush,\r\n encapsulation: ViewEncapsulation.None,\r\n templateUrl: 'tab-link.html',\r\n styleUrls: ['tab-link.scss'],\r\n // eslint-disable-next-line\r\n host: {\r\n class: 'mdc-tab oui-mdc-tab-link oui-mdc-focus-indicator',\r\n '[attr.aria-controls]': '_getAriaControls()',\r\n '[attr.aria-current]': '_getAriaCurrent()',\r\n '[attr.aria-disabled]': 'disabled',\r\n '[attr.aria-selected]': '_getAriaSelected()',\r\n '[attr.id]': 'id',\r\n '[attr.tabIndex]': '_getTabIndex()',\r\n '[attr.role]': '_getRole()',\r\n '[class.oui-mdc-tab-disabled]': 'disabled',\r\n '[class.mdc-tab--active]': 'active',\r\n '(focus)': '_handleFocus()',\r\n '(keydown)': '_handleKeydown($event)',\r\n },\r\n})\r\nexport class OuiTabLink\r\n extends _OuiTabLinkMixinBase\r\n implements\r\n AfterViewInit,\r\n OnDestroy,\r\n CanDisable,\r\n CanDisableRipple,\r\n HasTabIndex,\r\n FocusableOption\r\n{\r\n private readonly _destroyed = new Subject();\r\n\r\n /** Whether the tab link is active or not. */\r\n protected _isActive = false;\r\n\r\n /** Whether the link is active. */\r\n @Input()\r\n get active(): boolean {\r\n return this._isActive;\r\n }\r\n\r\n set active(value: BooleanInput) {\r\n const newValue = coerceBooleanProperty(value);\r\n\r\n if (newValue !== this._isActive) {\r\n this._isActive = newValue;\r\n this._tabNavBar.updateActiveLink();\r\n }\r\n }\r\n\r\n /**\r\n * Whether ripples are disabled on interaction.\r\n * @docs-private\r\n */\r\n get rippleDisabled(): boolean {\r\n return this.disabled || this.disableRipple || this._tabNavBar.disableRipple;\r\n }\r\n\r\n /** Unique id for the tab. */\r\n @Input() id = `oui-tab-link-${nextUniqueId++}`;\r\n\r\n constructor(\r\n private _tabNavBar: OuiTabNav,\r\n /** @docs-private */\r\n override elementRef: ElementRef,\r\n @Attribute('tabindex') tabIndex: string,\r\n private _focusMonitor: FocusMonitor,\r\n @Optional() @Inject(ANIMATION_MODULE_TYPE) animationMode?: string\r\n ) {\r\n super();\r\n\r\n this.tabIndex = parseInt(tabIndex) || 0;\r\n\r\n if (animationMode === 'NoopAnimations') {\r\n // this.rippleConfig.animation = { enterDuration: 0, exitDuration: 0 };\r\n }\r\n\r\n _tabNavBar._fitInkBarToContent\r\n .pipe(takeUntil(this._destroyed))\r\n .subscribe((fitInkBarToContent) => {\r\n this.fitInkBarToContent = fitInkBarToContent;\r\n });\r\n }\r\n\r\n /** Focuses the tab link. */\r\n focus() {\r\n this.elementRef.nativeElement.focus();\r\n }\r\n\r\n ngAfterViewInit() {\r\n // eslint-disable-next-line @typescript-eslint/no-unsafe-argument\r\n this._focusMonitor.monitor(this.elementRef);\r\n }\r\n\r\n override ngOnDestroy() {\r\n this._destroyed.next();\r\n this._destroyed.complete();\r\n super.ngOnDestroy();\r\n // eslint-disable-next-line @typescript-eslint/no-unsafe-argument\r\n this._focusMonitor.stopMonitoring(this.elementRef);\r\n }\r\n\r\n _handleFocus() {\r\n // Since we allow navigation through tabbing in the nav bar, we\r\n // have to update the focused index whenever the link receives focus.\r\n this._tabNavBar.focusIndex = this._tabNavBar._items.toArray().indexOf(this);\r\n }\r\n\r\n _handleKeydown(event: KeyboardEvent) {\r\n if (this.disabled && (event.keyCode === SPACE || event.keyCode === ENTER)) {\r\n event.preventDefault();\r\n } else if (this._tabNavBar.tabPanel && event.keyCode === SPACE) {\r\n this.elementRef.nativeElement.click();\r\n }\r\n }\r\n\r\n _getAriaControls(): string | null {\r\n return this._tabNavBar.tabPanel\r\n ? this._tabNavBar.tabPanel?.id\r\n : this.elementRef.nativeElement.getAttribute('aria-controls');\r\n }\r\n\r\n _getAriaSelected(): string | null {\r\n if (this._tabNavBar.tabPanel) {\r\n return this.active ? 'true' : 'false';\r\n } else {\r\n return this.elementRef.nativeElement.getAttribute('aria-selected');\r\n }\r\n }\r\n\r\n _getAriaCurrent(): string | null {\r\n return this.active && !this._tabNavBar.tabPanel ? 'page' : null;\r\n }\r\n\r\n _getRole(): string | null {\r\n return this._tabNavBar.tabPanel\r\n ? 'tab'\r\n : this.elementRef.nativeElement.getAttribute('role');\r\n }\r\n\r\n _getTabIndex(): number {\r\n if (this._tabNavBar.tabPanel) {\r\n return this._isActive && !this.disabled ? 0 : -1;\r\n } else {\r\n return this.tabIndex;\r\n }\r\n }\r\n}\r\n\r\n/**\r\n * Tab panel component associated with OuiTabNav.\r\n */\r\n@Component({\r\n selector: 'oui-tab-nav-panel',\r\n exportAs: 'ouiTabNavPanel',\r\n template: '',\r\n // eslint-disable-next-line @angular-eslint/no-host-metadata-property\r\n host: {\r\n '[attr.aria-labelledby]': '_activeTabId',\r\n '[attr.id]': 'id',\r\n class: 'oui-mdc-tab-nav-panel',\r\n role: 'tabpanel',\r\n },\r\n encapsulation: ViewEncapsulation.None,\r\n changeDetection: ChangeDetectionStrategy.OnPush,\r\n})\r\nexport class ouiTabNavPanel {\r\n /** Unique id for the tab panel. */\r\n @Input() id = `oui-tab-nav-panel-${nextUniqueId++}`;\r\n\r\n /** Id of the active tab in the nav bar. */\r\n _activeTabId?: string;\r\n}\r\n", "assetsDirs": [], "styleUrlsData": [ { - "data": "@use '../../core/style/variables';\n@use '../tabs-common';\n\n// Wraps each link in the header\n.oui-mdc-tab-link {\n // @include tabs-common.tab;\n\n // Note that we only want to target direct descendant tabs.\n .oui-mdc-tab-header.oui-mdc-tab-nav-bar-stretch-tabs & {\n flex-grow: 1;\n }\n\n // For the tab-link element, default inset/offset values are necessary to ensure that\n // the focus indicator is sufficiently contrastive and renders appropriately.\n &::before {\n margin: 5px;\n }\n}\n\n// @media (variables.$xsmall) {\n// .oui-mdc-tab-link {\n// min-width: 72px;\n// }\n// }\n", + "data": "@use '../../core/style/variables';\r\n@use '../tabs-common';\r\n\r\n// Wraps each link in the header\r\n.oui-mdc-tab-link {\r\n // @include tabs-common.tab;\r\n\r\n // Note that we only want to target direct descendant tabs.\r\n .oui-mdc-tab-header.oui-mdc-tab-nav-bar-stretch-tabs & {\r\n flex-grow: 1;\r\n }\r\n\r\n // For the tab-link element, default inset/offset values are necessary to ensure that\r\n // the focus indicator is sufficiently contrastive and renders appropriately.\r\n &::before {\r\n margin: 5px;\r\n }\r\n}\r\n\r\n// @media (variables.$xsmall) {\r\n// .oui-mdc-tab-link {\r\n// min-width: 72px;\r\n// }\r\n// }\r\n", "styleUrl": "tab-link.scss" } ], @@ -45748,7 +46429,9 @@ } ] }, - "extends": "_OuiTabLinkMixinBase", + "extends": [ + "_OuiTabLinkMixinBase" + ], "implements": [ "AfterViewInit", "OnDestroy", @@ -45807,19 +46490,19 @@ "description": "

Whether ripples are disabled on interaction.

\n", "jsdoctags": [ { - "pos": 10137, - "end": 10154, - "flags": 4227072, + "pos": 10484, + "end": 10502, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 325, + "kind": 334, "tagName": { - "pos": 10138, - "end": 10150, - "flags": 4227072, + "pos": 10485, + "end": 10497, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "docs-private" }, "comment": "" @@ -45828,11 +46511,11 @@ } } }, - "templateData": "\n\n
\n\n\n \n \n \n\n" + "templateData": "\r\n\r\n
\r\n\r\n\r\n \r\n \r\n \r\n\r\n" }, { "name": "OuiTabNav", - "id": "component-OuiTabNav-9bae65d3c7ced1d19b2c9b521dc10b849a2def4e235b5b53918d1dfeb0d6e848284098bb20976a21d5cb589e2ebe3990b059964fdae21490b898a0aa8c60c4ad", + "id": "component-OuiTabNav-6ce7108d054f1ce731fb3fdfd386c2252b009425dd05e2318aa5d6e1a34d06858b72f8ec2278d0b20e6242ef7a9e6be288d99d19c36c6712b85c978bf5907722", "file": "ui/src/components/tabs/tab-nav-bar/tab-nav-bar.ts", "changeDetection": "ChangeDetectionStrategy.Default", "encapsulation": [ @@ -45855,6 +46538,7 @@ "tab-nav-bar.html" ], "viewProviders": [], + "hostDirectives": [], "inputsClass": [ { "name": "animationDuration", @@ -45950,7 +46634,7 @@ "description": "", "line": 125, "modifierKind": [ - 121 + 123 ] }, { @@ -45962,7 +46646,7 @@ "description": "", "line": 151, "modifierKind": [ - 121 + 123 ] }, { @@ -45975,7 +46659,7 @@ "description": "", "line": 163, "modifierKind": [ - 121 + 123 ] }, { @@ -46015,6 +46699,9 @@ "stringifiedArguments": "undefined, {descendants: true}" } ], + "modifierKind": [ + 170 + ], "inheritance": { "file": "OuiPaginatedTabHeader" } @@ -46033,6 +46720,9 @@ "stringifiedArguments": "'nextPaginator'" } ], + "modifierKind": [ + 170 + ], "inheritance": { "file": "OuiPaginatedTabHeader" } @@ -46051,6 +46741,9 @@ "stringifiedArguments": "'previousPaginator'" } ], + "modifierKind": [ + 170 + ], "inheritance": { "file": "OuiPaginatedTabHeader" } @@ -46065,7 +46758,7 @@ "description": "", "line": 111, "modifierKind": [ - 121 + 123 ] }, { @@ -46082,6 +46775,9 @@ "stringifiedArguments": "'tabList', {static: true}" } ], + "modifierKind": [ + 170 + ], "inheritance": { "file": "OuiPaginatedTabHeader" } @@ -46100,6 +46796,9 @@ "stringifiedArguments": "'tabListContainer', {static: true}" } ], + "modifierKind": [ + 170 + ], "inheritance": { "file": "OuiPaginatedTabHeader" } @@ -46118,6 +46817,9 @@ "stringifiedArguments": "'tabListInner', {static: true}" } ], + "modifierKind": [ + 170 + ], "inheritance": { "file": "OuiPaginatedTabHeader" } @@ -46141,7 +46843,9 @@ } ], "modifierKind": [ - 123 + 170, + 170, + 125 ], "inheritance": { "file": "OuiPaginatedTabHeader" @@ -46157,7 +46861,7 @@ "line": 137, "rawdescription": "\nCached text content of the header.", "modifierKind": [ - 121 + 123 ], "inheritance": { "file": "OuiPaginatedTabHeader" @@ -46174,8 +46878,8 @@ "line": 113, "rawdescription": "\nEmits when the component is destroyed.", "modifierKind": [ - 122, - 144 + 124, + 148 ], "inheritance": { "file": "OuiPaginatedTabHeader" @@ -46191,7 +46895,7 @@ "description": "", "line": 153, "modifierKind": [ - 121 + 123 ], "inheritance": { "file": "OuiPaginatedTabHeader" @@ -46235,7 +46939,7 @@ "line": 134, "rawdescription": "\nUsed to manage focus between the tabs.", "modifierKind": [ - 121 + 123 ], "inheritance": { "file": "OuiPaginatedTabHeader" @@ -46252,7 +46956,7 @@ "line": 107, "rawdescription": "\nThe distance in pixels that the tab labels should be translated to the left.", "modifierKind": [ - 121 + 123 ], "inheritance": { "file": "OuiPaginatedTabHeader" @@ -46268,7 +46972,7 @@ "line": 131, "rawdescription": "\nWhether the scroll distance has changed and should be applied after the view is checked.", "modifierKind": [ - 121 + 123 ], "inheritance": { "file": "OuiPaginatedTabHeader" @@ -46284,7 +46988,7 @@ "description": "", "line": 171, "modifierKind": [ - 121 + 123 ], "inheritance": { "file": "OuiPaginatedTabHeader" @@ -46301,7 +47005,7 @@ "line": 110, "rawdescription": "\nWhether the header should scroll to the selected index after the view has been checked.", "modifierKind": [ - 121 + 123 ], "inheritance": { "file": "OuiPaginatedTabHeader" @@ -46332,7 +47036,7 @@ "line": 140, "rawdescription": "\nStream that will stop the automated scrolling.", "modifierKind": [ - 121 + 123 ], "inheritance": { "file": "OuiPaginatedTabHeader" @@ -46348,7 +47052,7 @@ "line": 128, "rawdescription": "\n\nThe number of tab labels that are displayed on the header. When this changes, the header\nshould re-evaluate the scroll position.\n", "modifierKind": [ - 121 + 123 ], "inheritance": { "file": "OuiPaginatedTabHeader" @@ -46365,7 +47069,7 @@ "line": 178, "rawdescription": "\nEvent emitted when a label is focused.", "modifierKind": [ - 144 + 148 ], "inheritance": { "file": "OuiPaginatedTabHeader" @@ -46382,7 +47086,7 @@ "line": 174, "rawdescription": "\nEvent emitted when the option is selected.", "modifierKind": [ - 144 + 148 ], "inheritance": { "file": "OuiPaginatedTabHeader" @@ -46410,7 +47114,7 @@ "deprecated": false, "deprecationMessage": "", "modifierKind": [ - 122 + 124 ], "inheritance": { "file": "OuiPaginatedTabHeader" @@ -46426,7 +47130,7 @@ "deprecated": false, "deprecationMessage": "", "modifierKind": [ - 158 + 164 ], "inheritance": { "file": "OuiPaginatedTabHeader" @@ -46442,7 +47146,7 @@ "deprecated": false, "deprecationMessage": "", "modifierKind": [ - 158 + 164 ], "inheritance": { "file": "OuiPaginatedTabHeader" @@ -46629,24 +47333,24 @@ "jsdoctags": [ { "name": { - "pos": 22708, - "end": 22717, - "flags": 4227072, + "pos": 23371, + "end": 23380, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "direction" }, "type": "ScrollDirection", "deprecated": false, "deprecationMessage": "", "tagName": { - "pos": 22702, - "end": 22707, - "flags": 4227072, + "pos": 23365, + "end": 23370, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "param" }, "comment": "

In which direction the paginator should be scrolled.

\n" @@ -46711,7 +47415,7 @@ "rawdescription": "\nSends any changes that could affect the layout of the items.", "description": "

Sends any changes that could affect the layout of the items.

\n", "modifierKind": [ - 121 + 123 ], "inheritance": { "file": "OuiPaginatedTabHeader" @@ -46784,41 +47488,41 @@ "rawdescription": "\n\nScrolls the header to a given position.\n", "description": "

Scrolls the header to a given position.

\n", "modifierKind": [ - 121 + 123 ], "jsdoctags": [ { "name": { - "pos": 23848, - "end": 23856, - "flags": 4227072, + "pos": 24539, + "end": 24547, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "position" }, "type": "number", "deprecated": false, "deprecationMessage": "", "tagName": { - "pos": 23842, - "end": 23847, - "flags": 4227072, + "pos": 24533, + "end": 24538, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "param" }, "comment": "

Position to which to scroll.

\n" }, { "tagName": { - "pos": 23892, - "end": 23899, - "flags": 4227072, + "pos": 24584, + "end": 24591, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "returns" }, "comment": "

Information on the current scroll distance and the maximum.

\n" @@ -46970,14 +47674,16 @@ "deprecationMessage": "", "hostBindings": [], "hostListeners": [], + "standalone": false, + "imports": [], "description": "

Navigation component matching the styles of the tab group header.\nProvides anchored navigation with animated ink bar.

\n", "rawdescription": "\n\nNavigation component matching the styles of the tab group header.\nProvides anchored navigation with animated ink bar.\n", "type": "component", - "sourceCode": "import {\n AfterContentChecked,\n AfterContentInit,\n AfterViewInit,\n Attribute,\n ChangeDetectionStrategy,\n ChangeDetectorRef,\n Component,\n ContentChildren,\n ElementRef,\n forwardRef,\n Inject,\n Input,\n NgZone,\n OnDestroy,\n Optional,\n QueryList,\n ViewChild,\n ViewEncapsulation,\n} from '@angular/core';\nimport { ANIMATION_MODULE_TYPE } from '@angular/platform-browser/animations';\nimport {\n CanDisable,\n CanDisableRipple,\n HasTabIndex,\n mixinDisabled,\n mixinDisableRipple,\n mixinTabIndex,\n ThemePalette,\n} from '../../core';\nimport { FocusableOption, FocusMonitor } from '@angular/cdk/a11y';\nimport { Directionality } from '@angular/cdk/bidi';\nimport { ViewportRuler } from '@angular/cdk/scrolling';\nimport { Platform } from '@angular/cdk/platform';\nimport { OuiInkBar, mixinInkBarItem } from '../ink-bar';\nimport {\n BooleanInput,\n coerceBooleanProperty,\n NumberInput,\n} from '@angular/cdk/coercion';\nimport { BehaviorSubject, Subject } from 'rxjs';\nimport { startWith, takeUntil } from 'rxjs/operators';\nimport { ENTER, SPACE } from '@angular/cdk/keycodes';\nimport { OUI_TABS_CONFIG, OuiTabsConfig } from '../tab-config';\nimport { OuiPaginatedTabHeader } from '../paginated-tab-header';\nimport { isDevMode } from '@angular/core';\n\n// Increasing integer for generating unique ids for tab nav components.\nlet nextUniqueId = 0;\n\n/**\n * Navigation component matching the styles of the tab group header.\n * Provides anchored navigation with animated ink bar.\n */\n@Component({\n // eslint-disable-next-line @angular-eslint/component-selector\n selector: '[oui-tab-nav-bar]',\n exportAs: 'OuiTabNavBar, OuiTabNav',\n // eslint-disable-next-line @angular-eslint/no-inputs-metadata-property\n inputs: ['color'],\n templateUrl: 'tab-nav-bar.html',\n styleUrls: ['tab-nav-bar.scss'],\n // eslint-disable-next-line @angular-eslint/no-host-metadata-property\n host: {\n '[attr.role]': '_getRole()',\n class: 'oui-mdc-tab-nav-bar oui-mdc-tab-header',\n '[class.oui-mdc-tab-header-pagination-controls-enabled]':\n '_showPaginationControls',\n '[class.oui-mdc-tab-header-rtl]': \"_getLayoutDirection() == 'rtl'\",\n '[class.oui-mdc-tab-nav-bar-stretch-tabs]': 'stretchTabs',\n '[class.mat-primary]': 'color !== \"warn\" && color !== \"accent\"',\n '[class.mat-accent]': 'color === \"accent\"',\n '[class.mat-warn]': 'color === \"warn\"',\n '[class._oui-animation-noopable]': '_animationMode === \"NoopAnimations\"',\n '[style.--oui-tab-animation-duration]': 'animationDuration',\n },\n encapsulation: ViewEncapsulation.None,\n // tslint:disable-next-line:validate-decorators\n changeDetection: ChangeDetectionStrategy.Default,\n})\nexport class OuiTabNav\n extends OuiPaginatedTabHeader\n implements AfterContentChecked, AfterContentInit, OnDestroy, AfterViewInit\n{\n /** Whether the ink bar should fit its width to the size of the tab label content. */\n @Input()\n get fitInkBarToContent(): boolean {\n return this._fitInkBarToContent.value;\n }\n set fitInkBarToContent(v: BooleanInput) {\n this._fitInkBarToContent.next(coerceBooleanProperty(v));\n this._changeDetectorRef.markForCheck();\n }\n _fitInkBarToContent = new BehaviorSubject(false);\n\n /** Whether tabs should be stretched to fill the header. */\n @Input('oui-stretch-tabs')\n get stretchTabs(): boolean {\n return this._stretchTabs;\n }\n set stretchTabs(v: BooleanInput) {\n this._stretchTabs = coerceBooleanProperty(v);\n }\n private _stretchTabs = true;\n\n @Input()\n get animationDuration(): string {\n return this._animationDuration;\n }\n\n set animationDuration(value: NumberInput) {\n // eslint-disable-next-line @typescript-eslint/restrict-plus-operands\n this._animationDuration = /^\\d+$/.test(value + '') // eslint-disable-next-line @typescript-eslint/restrict-plus-operands\n ? value + 'ms'\n : (value as string);\n }\n\n private _animationDuration: string;\n\n /** Query list of all tab links of the tab navigation. */\n @ContentChildren(forwardRef(() => OuiTabLink), { descendants: true })\n _items: QueryList;\n\n /** Background color of the tab nav. */\n @Input()\n get backgroundColor(): ThemePalette {\n return this._backgroundColor;\n }\n\n set backgroundColor(value: ThemePalette) {\n const classList = this._elementRef.nativeElement.classList;\n classList.remove(\n 'oui-tabs-with-background',\n `oui-background-${this.backgroundColor}`\n );\n\n if (value) {\n classList.add('oui-tabs-with-background', `oui-background-${value}`);\n }\n\n this._backgroundColor = value;\n }\n\n private _backgroundColor: ThemePalette;\n\n /** Whether the ripple effect is disabled or not. */\n @Input()\n get disableRipple(): boolean {\n return this._disableRipple;\n }\n\n set disableRipple(value: BooleanInput) {\n this._disableRipple = coerceBooleanProperty(value);\n }\n\n private _disableRipple = false;\n\n /** Theme color of the nav bar. */\n @Input() color: ThemePalette = 'accent';\n\n /**\n * Associated tab panel controlled by the nav bar. If not provided, then the nav bar\n * follows the ARIA link / navigation landmark pattern. If provided, it follows the\n * ARIA tabs design pattern.\n */\n @Input() tabPanel?: ouiTabNavPanel;\n\n @ViewChild('tabListContainer', { static: true })\n _tabListContainer: ElementRef;\n @ViewChild('tabList', { static: true }) _tabList: ElementRef;\n @ViewChild('tabListInner', { static: true }) _tabListInner: ElementRef;\n @ViewChild('nextPaginator') _nextPaginator: ElementRef;\n @ViewChild('previousPaginator') _previousPaginator: ElementRef;\n _inkBar: OuiInkBar;\n\n constructor(\n elementRef: ElementRef,\n @Optional() dir: Directionality,\n ngZone: NgZone,\n changeDetectorRef: ChangeDetectorRef,\n viewportRuler: ViewportRuler,\n platform: Platform,\n @Optional() @Inject(ANIMATION_MODULE_TYPE) animationMode?: string,\n @Optional() @Inject(OUI_TABS_CONFIG) defaultConfig?: OuiTabsConfig\n ) {\n super(\n // eslint-disable-next-line @typescript-eslint/no-unsafe-argument\n elementRef,\n changeDetectorRef,\n viewportRuler,\n dir,\n ngZone,\n platform,\n animationMode\n );\n this.disablePagination =\n defaultConfig && defaultConfig.disablePagination != null\n ? defaultConfig.disablePagination\n : false;\n this.fitInkBarToContent =\n defaultConfig && defaultConfig.fitInkBarToContent != null\n ? defaultConfig.fitInkBarToContent\n : false;\n this.stretchTabs =\n defaultConfig && defaultConfig.stretchTabs != null\n ? defaultConfig.stretchTabs\n : true;\n }\n\n protected _itemSelected() {\n // noop\n }\n\n override ngAfterContentInit() {\n this._inkBar = new OuiInkBar(this._items);\n // We need this to run before the `changes` subscription in parent to ensure that the\n // selectedIndex is up-to-date by the time the super class starts looking for it.\n this._items.changes\n .pipe(startWith(null), takeUntil(this._destroyed))\n .subscribe(() => {\n this.updateActiveLink();\n });\n\n super.ngAfterContentInit();\n }\n\n override ngAfterViewInit() {\n if (!this.tabPanel && (typeof isDevMode === 'undefined' || isDevMode)) {\n throw new Error('A oui-tab-nav-panel must be specified via [tabPanel].');\n }\n super.ngAfterViewInit();\n }\n\n /** Notifies the component that the active link has been changed. */\n updateActiveLink() {\n if (!this._items) {\n return;\n }\n\n const items = this._items.toArray();\n\n for (let i = 0; i < items.length; i++) {\n if (items[i].active) {\n this.selectedIndex = i;\n this._changeDetectorRef.markForCheck();\n\n if (this.tabPanel) {\n this.tabPanel._activeTabId = items[i].id;\n }\n\n return;\n }\n }\n\n // The ink bar should hide itself if no items are active.\n this.selectedIndex = -1;\n this._inkBar.hide();\n }\n\n _getRole(): string | null {\n return this.tabPanel\n ? 'tablist'\n : this._elementRef.nativeElement.getAttribute('role');\n }\n}\n\n// Boilerplate for applying mixins to OuiTabLink.\nconst _OuiTabLinkMixinBase = mixinInkBarItem(\n mixinTabIndex(\n mixinDisableRipple(\n mixinDisabled(\n class {\n elementRef: ElementRef;\n }\n )\n )\n )\n);\n\n/**\n * Link inside a `oui-tab-nav-bar`.\n */\n@Component({\n // eslint-disable-next-line\n selector: '[oui-tab-link], [OuiTabLink]',\n exportAs: 'OuiTabLink',\n // eslint-disable-next-line\n inputs: ['disabled', 'disableRipple', 'tabIndex', 'active', 'id'],\n changeDetection: ChangeDetectionStrategy.OnPush,\n encapsulation: ViewEncapsulation.None,\n templateUrl: 'tab-link.html',\n styleUrls: ['tab-link.scss'],\n // eslint-disable-next-line\n host: {\n class: 'mdc-tab oui-mdc-tab-link oui-mdc-focus-indicator',\n '[attr.aria-controls]': '_getAriaControls()',\n '[attr.aria-current]': '_getAriaCurrent()',\n '[attr.aria-disabled]': 'disabled',\n '[attr.aria-selected]': '_getAriaSelected()',\n '[attr.id]': 'id',\n '[attr.tabIndex]': '_getTabIndex()',\n '[attr.role]': '_getRole()',\n '[class.oui-mdc-tab-disabled]': 'disabled',\n '[class.mdc-tab--active]': 'active',\n '(focus)': '_handleFocus()',\n '(keydown)': '_handleKeydown($event)',\n },\n})\nexport class OuiTabLink\n extends _OuiTabLinkMixinBase\n implements\n AfterViewInit,\n OnDestroy,\n CanDisable,\n CanDisableRipple,\n HasTabIndex,\n FocusableOption\n{\n private readonly _destroyed = new Subject();\n\n /** Whether the tab link is active or not. */\n protected _isActive = false;\n\n /** Whether the link is active. */\n @Input()\n get active(): boolean {\n return this._isActive;\n }\n\n set active(value: BooleanInput) {\n const newValue = coerceBooleanProperty(value);\n\n if (newValue !== this._isActive) {\n this._isActive = newValue;\n this._tabNavBar.updateActiveLink();\n }\n }\n\n /**\n * Whether ripples are disabled on interaction.\n * @docs-private\n */\n get rippleDisabled(): boolean {\n return this.disabled || this.disableRipple || this._tabNavBar.disableRipple;\n }\n\n /** Unique id for the tab. */\n @Input() id = `oui-tab-link-${nextUniqueId++}`;\n\n constructor(\n private _tabNavBar: OuiTabNav,\n /** @docs-private */\n override elementRef: ElementRef,\n @Attribute('tabindex') tabIndex: string,\n private _focusMonitor: FocusMonitor,\n @Optional() @Inject(ANIMATION_MODULE_TYPE) animationMode?: string\n ) {\n super();\n\n this.tabIndex = parseInt(tabIndex) || 0;\n\n if (animationMode === 'NoopAnimations') {\n // this.rippleConfig.animation = { enterDuration: 0, exitDuration: 0 };\n }\n\n _tabNavBar._fitInkBarToContent\n .pipe(takeUntil(this._destroyed))\n .subscribe((fitInkBarToContent) => {\n this.fitInkBarToContent = fitInkBarToContent;\n });\n }\n\n /** Focuses the tab link. */\n focus() {\n this.elementRef.nativeElement.focus();\n }\n\n ngAfterViewInit() {\n // eslint-disable-next-line @typescript-eslint/no-unsafe-argument\n this._focusMonitor.monitor(this.elementRef);\n }\n\n override ngOnDestroy() {\n this._destroyed.next();\n this._destroyed.complete();\n super.ngOnDestroy();\n // eslint-disable-next-line @typescript-eslint/no-unsafe-argument\n this._focusMonitor.stopMonitoring(this.elementRef);\n }\n\n _handleFocus() {\n // Since we allow navigation through tabbing in the nav bar, we\n // have to update the focused index whenever the link receives focus.\n this._tabNavBar.focusIndex = this._tabNavBar._items.toArray().indexOf(this);\n }\n\n _handleKeydown(event: KeyboardEvent) {\n if (this.disabled && (event.keyCode === SPACE || event.keyCode === ENTER)) {\n event.preventDefault();\n } else if (this._tabNavBar.tabPanel && event.keyCode === SPACE) {\n this.elementRef.nativeElement.click();\n }\n }\n\n _getAriaControls(): string | null {\n return this._tabNavBar.tabPanel\n ? this._tabNavBar.tabPanel?.id\n : this.elementRef.nativeElement.getAttribute('aria-controls');\n }\n\n _getAriaSelected(): string | null {\n if (this._tabNavBar.tabPanel) {\n return this.active ? 'true' : 'false';\n } else {\n return this.elementRef.nativeElement.getAttribute('aria-selected');\n }\n }\n\n _getAriaCurrent(): string | null {\n return this.active && !this._tabNavBar.tabPanel ? 'page' : null;\n }\n\n _getRole(): string | null {\n return this._tabNavBar.tabPanel\n ? 'tab'\n : this.elementRef.nativeElement.getAttribute('role');\n }\n\n _getTabIndex(): number {\n if (this._tabNavBar.tabPanel) {\n return this._isActive && !this.disabled ? 0 : -1;\n } else {\n return this.tabIndex;\n }\n }\n}\n\n/**\n * Tab panel component associated with OuiTabNav.\n */\n@Component({\n selector: 'oui-tab-nav-panel',\n exportAs: 'ouiTabNavPanel',\n template: '',\n // eslint-disable-next-line @angular-eslint/no-host-metadata-property\n host: {\n '[attr.aria-labelledby]': '_activeTabId',\n '[attr.id]': 'id',\n class: 'oui-mdc-tab-nav-panel',\n role: 'tabpanel',\n },\n encapsulation: ViewEncapsulation.None,\n changeDetection: ChangeDetectionStrategy.OnPush,\n})\nexport class ouiTabNavPanel {\n /** Unique id for the tab panel. */\n @Input() id = `oui-tab-nav-panel-${nextUniqueId++}`;\n\n /** Id of the active tab in the nav bar. */\n _activeTabId?: string;\n}\n", + "sourceCode": "import {\r\n AfterContentChecked,\r\n AfterContentInit,\r\n AfterViewInit,\r\n Attribute,\r\n ChangeDetectionStrategy,\r\n ChangeDetectorRef,\r\n Component,\r\n ContentChildren,\r\n ElementRef,\r\n forwardRef,\r\n Inject,\r\n Input,\r\n NgZone,\r\n OnDestroy,\r\n Optional,\r\n QueryList,\r\n ViewChild,\r\n ViewEncapsulation,\r\n} from '@angular/core';\r\nimport { ANIMATION_MODULE_TYPE } from '@angular/platform-browser/animations';\r\nimport {\r\n CanDisable,\r\n CanDisableRipple,\r\n HasTabIndex,\r\n mixinDisabled,\r\n mixinDisableRipple,\r\n mixinTabIndex,\r\n ThemePalette,\r\n} from '../../core';\r\nimport { FocusableOption, FocusMonitor } from '@angular/cdk/a11y';\r\nimport { Directionality } from '@angular/cdk/bidi';\r\nimport { ViewportRuler } from '@angular/cdk/scrolling';\r\nimport { Platform } from '@angular/cdk/platform';\r\nimport { OuiInkBar, mixinInkBarItem } from '../ink-bar';\r\nimport {\r\n BooleanInput,\r\n coerceBooleanProperty,\r\n NumberInput,\r\n} from '@angular/cdk/coercion';\r\nimport { BehaviorSubject, Subject } from 'rxjs';\r\nimport { startWith, takeUntil } from 'rxjs/operators';\r\nimport { ENTER, SPACE } from '@angular/cdk/keycodes';\r\nimport { OUI_TABS_CONFIG, OuiTabsConfig } from '../tab-config';\r\nimport { OuiPaginatedTabHeader } from '../paginated-tab-header';\r\nimport { isDevMode } from '@angular/core';\r\n\r\n// Increasing integer for generating unique ids for tab nav components.\r\nlet nextUniqueId = 0;\r\n\r\n/**\r\n * Navigation component matching the styles of the tab group header.\r\n * Provides anchored navigation with animated ink bar.\r\n */\r\n@Component({\r\n // eslint-disable-next-line @angular-eslint/component-selector\r\n selector: '[oui-tab-nav-bar]',\r\n exportAs: 'OuiTabNavBar, OuiTabNav',\r\n // eslint-disable-next-line @angular-eslint/no-inputs-metadata-property\r\n inputs: ['color'],\r\n templateUrl: 'tab-nav-bar.html',\r\n styleUrls: ['tab-nav-bar.scss'],\r\n // eslint-disable-next-line @angular-eslint/no-host-metadata-property\r\n host: {\r\n '[attr.role]': '_getRole()',\r\n class: 'oui-mdc-tab-nav-bar oui-mdc-tab-header',\r\n '[class.oui-mdc-tab-header-pagination-controls-enabled]':\r\n '_showPaginationControls',\r\n '[class.oui-mdc-tab-header-rtl]': \"_getLayoutDirection() == 'rtl'\",\r\n '[class.oui-mdc-tab-nav-bar-stretch-tabs]': 'stretchTabs',\r\n '[class.mat-primary]': 'color !== \"warn\" && color !== \"accent\"',\r\n '[class.mat-accent]': 'color === \"accent\"',\r\n '[class.mat-warn]': 'color === \"warn\"',\r\n '[class._oui-animation-noopable]': '_animationMode === \"NoopAnimations\"',\r\n '[style.--oui-tab-animation-duration]': 'animationDuration',\r\n },\r\n encapsulation: ViewEncapsulation.None,\r\n // tslint:disable-next-line:validate-decorators\r\n changeDetection: ChangeDetectionStrategy.Default,\r\n})\r\nexport class OuiTabNav\r\n extends OuiPaginatedTabHeader\r\n implements AfterContentChecked, AfterContentInit, OnDestroy, AfterViewInit\r\n{\r\n /** Whether the ink bar should fit its width to the size of the tab label content. */\r\n @Input()\r\n get fitInkBarToContent(): boolean {\r\n return this._fitInkBarToContent.value;\r\n }\r\n set fitInkBarToContent(v: BooleanInput) {\r\n this._fitInkBarToContent.next(coerceBooleanProperty(v));\r\n this._changeDetectorRef.markForCheck();\r\n }\r\n _fitInkBarToContent = new BehaviorSubject(false);\r\n\r\n /** Whether tabs should be stretched to fill the header. */\r\n @Input('oui-stretch-tabs')\r\n get stretchTabs(): boolean {\r\n return this._stretchTabs;\r\n }\r\n set stretchTabs(v: BooleanInput) {\r\n this._stretchTabs = coerceBooleanProperty(v);\r\n }\r\n private _stretchTabs = true;\r\n\r\n @Input()\r\n get animationDuration(): string {\r\n return this._animationDuration;\r\n }\r\n\r\n set animationDuration(value: NumberInput) {\r\n // eslint-disable-next-line @typescript-eslint/restrict-plus-operands\r\n this._animationDuration = /^\\d+$/.test(value + '') // eslint-disable-next-line @typescript-eslint/restrict-plus-operands\r\n ? value + 'ms'\r\n : (value as string);\r\n }\r\n\r\n private _animationDuration: string;\r\n\r\n /** Query list of all tab links of the tab navigation. */\r\n @ContentChildren(forwardRef(() => OuiTabLink), { descendants: true })\r\n _items: QueryList;\r\n\r\n /** Background color of the tab nav. */\r\n @Input()\r\n get backgroundColor(): ThemePalette {\r\n return this._backgroundColor;\r\n }\r\n\r\n set backgroundColor(value: ThemePalette) {\r\n const classList = this._elementRef.nativeElement.classList;\r\n classList.remove(\r\n 'oui-tabs-with-background',\r\n `oui-background-${this.backgroundColor}`\r\n );\r\n\r\n if (value) {\r\n classList.add('oui-tabs-with-background', `oui-background-${value}`);\r\n }\r\n\r\n this._backgroundColor = value;\r\n }\r\n\r\n private _backgroundColor: ThemePalette;\r\n\r\n /** Whether the ripple effect is disabled or not. */\r\n @Input()\r\n get disableRipple(): boolean {\r\n return this._disableRipple;\r\n }\r\n\r\n set disableRipple(value: BooleanInput) {\r\n this._disableRipple = coerceBooleanProperty(value);\r\n }\r\n\r\n private _disableRipple = false;\r\n\r\n /** Theme color of the nav bar. */\r\n @Input() color: ThemePalette = 'accent';\r\n\r\n /**\r\n * Associated tab panel controlled by the nav bar. If not provided, then the nav bar\r\n * follows the ARIA link / navigation landmark pattern. If provided, it follows the\r\n * ARIA tabs design pattern.\r\n */\r\n @Input() tabPanel?: ouiTabNavPanel;\r\n\r\n @ViewChild('tabListContainer', { static: true })\r\n _tabListContainer: ElementRef;\r\n @ViewChild('tabList', { static: true }) _tabList: ElementRef;\r\n @ViewChild('tabListInner', { static: true }) _tabListInner: ElementRef;\r\n @ViewChild('nextPaginator') _nextPaginator: ElementRef;\r\n @ViewChild('previousPaginator') _previousPaginator: ElementRef;\r\n _inkBar: OuiInkBar;\r\n\r\n constructor(\r\n elementRef: ElementRef,\r\n @Optional() dir: Directionality,\r\n ngZone: NgZone,\r\n changeDetectorRef: ChangeDetectorRef,\r\n viewportRuler: ViewportRuler,\r\n platform: Platform,\r\n @Optional() @Inject(ANIMATION_MODULE_TYPE) animationMode?: string,\r\n @Optional() @Inject(OUI_TABS_CONFIG) defaultConfig?: OuiTabsConfig\r\n ) {\r\n super(\r\n // eslint-disable-next-line @typescript-eslint/no-unsafe-argument\r\n elementRef,\r\n changeDetectorRef,\r\n viewportRuler,\r\n dir,\r\n ngZone,\r\n platform,\r\n animationMode\r\n );\r\n this.disablePagination =\r\n defaultConfig && defaultConfig.disablePagination != null\r\n ? defaultConfig.disablePagination\r\n : false;\r\n this.fitInkBarToContent =\r\n defaultConfig && defaultConfig.fitInkBarToContent != null\r\n ? defaultConfig.fitInkBarToContent\r\n : false;\r\n this.stretchTabs =\r\n defaultConfig && defaultConfig.stretchTabs != null\r\n ? defaultConfig.stretchTabs\r\n : true;\r\n }\r\n\r\n protected _itemSelected() {\r\n // noop\r\n }\r\n\r\n override ngAfterContentInit() {\r\n this._inkBar = new OuiInkBar(this._items);\r\n // We need this to run before the `changes` subscription in parent to ensure that the\r\n // selectedIndex is up-to-date by the time the super class starts looking for it.\r\n this._items.changes\r\n .pipe(startWith(null), takeUntil(this._destroyed))\r\n .subscribe(() => {\r\n this.updateActiveLink();\r\n });\r\n\r\n super.ngAfterContentInit();\r\n }\r\n\r\n override ngAfterViewInit() {\r\n if (!this.tabPanel && (typeof isDevMode === 'undefined' || isDevMode)) {\r\n throw new Error('A oui-tab-nav-panel must be specified via [tabPanel].');\r\n }\r\n super.ngAfterViewInit();\r\n }\r\n\r\n /** Notifies the component that the active link has been changed. */\r\n updateActiveLink() {\r\n if (!this._items) {\r\n return;\r\n }\r\n\r\n const items = this._items.toArray();\r\n\r\n for (let i = 0; i < items.length; i++) {\r\n if (items[i].active) {\r\n this.selectedIndex = i;\r\n this._changeDetectorRef.markForCheck();\r\n\r\n if (this.tabPanel) {\r\n this.tabPanel._activeTabId = items[i].id;\r\n }\r\n\r\n return;\r\n }\r\n }\r\n\r\n // The ink bar should hide itself if no items are active.\r\n this.selectedIndex = -1;\r\n this._inkBar.hide();\r\n }\r\n\r\n _getRole(): string | null {\r\n return this.tabPanel\r\n ? 'tablist'\r\n : this._elementRef.nativeElement.getAttribute('role');\r\n }\r\n}\r\n\r\n// Boilerplate for applying mixins to OuiTabLink.\r\nconst _OuiTabLinkMixinBase = mixinInkBarItem(\r\n mixinTabIndex(\r\n mixinDisableRipple(\r\n mixinDisabled(\r\n class {\r\n elementRef: ElementRef;\r\n }\r\n )\r\n )\r\n )\r\n);\r\n\r\n/**\r\n * Link inside a `oui-tab-nav-bar`.\r\n */\r\n@Component({\r\n // eslint-disable-next-line\r\n selector: '[oui-tab-link], [OuiTabLink]',\r\n exportAs: 'OuiTabLink',\r\n // eslint-disable-next-line\r\n inputs: ['disabled', 'disableRipple', 'tabIndex', 'active', 'id'],\r\n changeDetection: ChangeDetectionStrategy.OnPush,\r\n encapsulation: ViewEncapsulation.None,\r\n templateUrl: 'tab-link.html',\r\n styleUrls: ['tab-link.scss'],\r\n // eslint-disable-next-line\r\n host: {\r\n class: 'mdc-tab oui-mdc-tab-link oui-mdc-focus-indicator',\r\n '[attr.aria-controls]': '_getAriaControls()',\r\n '[attr.aria-current]': '_getAriaCurrent()',\r\n '[attr.aria-disabled]': 'disabled',\r\n '[attr.aria-selected]': '_getAriaSelected()',\r\n '[attr.id]': 'id',\r\n '[attr.tabIndex]': '_getTabIndex()',\r\n '[attr.role]': '_getRole()',\r\n '[class.oui-mdc-tab-disabled]': 'disabled',\r\n '[class.mdc-tab--active]': 'active',\r\n '(focus)': '_handleFocus()',\r\n '(keydown)': '_handleKeydown($event)',\r\n },\r\n})\r\nexport class OuiTabLink\r\n extends _OuiTabLinkMixinBase\r\n implements\r\n AfterViewInit,\r\n OnDestroy,\r\n CanDisable,\r\n CanDisableRipple,\r\n HasTabIndex,\r\n FocusableOption\r\n{\r\n private readonly _destroyed = new Subject();\r\n\r\n /** Whether the tab link is active or not. */\r\n protected _isActive = false;\r\n\r\n /** Whether the link is active. */\r\n @Input()\r\n get active(): boolean {\r\n return this._isActive;\r\n }\r\n\r\n set active(value: BooleanInput) {\r\n const newValue = coerceBooleanProperty(value);\r\n\r\n if (newValue !== this._isActive) {\r\n this._isActive = newValue;\r\n this._tabNavBar.updateActiveLink();\r\n }\r\n }\r\n\r\n /**\r\n * Whether ripples are disabled on interaction.\r\n * @docs-private\r\n */\r\n get rippleDisabled(): boolean {\r\n return this.disabled || this.disableRipple || this._tabNavBar.disableRipple;\r\n }\r\n\r\n /** Unique id for the tab. */\r\n @Input() id = `oui-tab-link-${nextUniqueId++}`;\r\n\r\n constructor(\r\n private _tabNavBar: OuiTabNav,\r\n /** @docs-private */\r\n override elementRef: ElementRef,\r\n @Attribute('tabindex') tabIndex: string,\r\n private _focusMonitor: FocusMonitor,\r\n @Optional() @Inject(ANIMATION_MODULE_TYPE) animationMode?: string\r\n ) {\r\n super();\r\n\r\n this.tabIndex = parseInt(tabIndex) || 0;\r\n\r\n if (animationMode === 'NoopAnimations') {\r\n // this.rippleConfig.animation = { enterDuration: 0, exitDuration: 0 };\r\n }\r\n\r\n _tabNavBar._fitInkBarToContent\r\n .pipe(takeUntil(this._destroyed))\r\n .subscribe((fitInkBarToContent) => {\r\n this.fitInkBarToContent = fitInkBarToContent;\r\n });\r\n }\r\n\r\n /** Focuses the tab link. */\r\n focus() {\r\n this.elementRef.nativeElement.focus();\r\n }\r\n\r\n ngAfterViewInit() {\r\n // eslint-disable-next-line @typescript-eslint/no-unsafe-argument\r\n this._focusMonitor.monitor(this.elementRef);\r\n }\r\n\r\n override ngOnDestroy() {\r\n this._destroyed.next();\r\n this._destroyed.complete();\r\n super.ngOnDestroy();\r\n // eslint-disable-next-line @typescript-eslint/no-unsafe-argument\r\n this._focusMonitor.stopMonitoring(this.elementRef);\r\n }\r\n\r\n _handleFocus() {\r\n // Since we allow navigation through tabbing in the nav bar, we\r\n // have to update the focused index whenever the link receives focus.\r\n this._tabNavBar.focusIndex = this._tabNavBar._items.toArray().indexOf(this);\r\n }\r\n\r\n _handleKeydown(event: KeyboardEvent) {\r\n if (this.disabled && (event.keyCode === SPACE || event.keyCode === ENTER)) {\r\n event.preventDefault();\r\n } else if (this._tabNavBar.tabPanel && event.keyCode === SPACE) {\r\n this.elementRef.nativeElement.click();\r\n }\r\n }\r\n\r\n _getAriaControls(): string | null {\r\n return this._tabNavBar.tabPanel\r\n ? this._tabNavBar.tabPanel?.id\r\n : this.elementRef.nativeElement.getAttribute('aria-controls');\r\n }\r\n\r\n _getAriaSelected(): string | null {\r\n if (this._tabNavBar.tabPanel) {\r\n return this.active ? 'true' : 'false';\r\n } else {\r\n return this.elementRef.nativeElement.getAttribute('aria-selected');\r\n }\r\n }\r\n\r\n _getAriaCurrent(): string | null {\r\n return this.active && !this._tabNavBar.tabPanel ? 'page' : null;\r\n }\r\n\r\n _getRole(): string | null {\r\n return this._tabNavBar.tabPanel\r\n ? 'tab'\r\n : this.elementRef.nativeElement.getAttribute('role');\r\n }\r\n\r\n _getTabIndex(): number {\r\n if (this._tabNavBar.tabPanel) {\r\n return this._isActive && !this.disabled ? 0 : -1;\r\n } else {\r\n return this.tabIndex;\r\n }\r\n }\r\n}\r\n\r\n/**\r\n * Tab panel component associated with OuiTabNav.\r\n */\r\n@Component({\r\n selector: 'oui-tab-nav-panel',\r\n exportAs: 'ouiTabNavPanel',\r\n template: '',\r\n // eslint-disable-next-line @angular-eslint/no-host-metadata-property\r\n host: {\r\n '[attr.aria-labelledby]': '_activeTabId',\r\n '[attr.id]': 'id',\r\n class: 'oui-mdc-tab-nav-panel',\r\n role: 'tabpanel',\r\n },\r\n encapsulation: ViewEncapsulation.None,\r\n changeDetection: ChangeDetectionStrategy.OnPush,\r\n})\r\nexport class ouiTabNavPanel {\r\n /** Unique id for the tab panel. */\r\n @Input() id = `oui-tab-nav-panel-${nextUniqueId++}`;\r\n\r\n /** Id of the active tab in the nav bar. */\r\n _activeTabId?: string;\r\n}\r\n", "assetsDirs": [], "styleUrlsData": [ { - "data": "// @use '../tabs-common';\n\n// @include tabs-common.structural-styles;\n// @include tabs-common.paginated-tab-header;\n\n// .oui-mdc-tab-links {\n// @include tabs-common.paginated-tab-header-item-wrapper('.oui-mdc-tab-link-container');\n// }\n\n// .oui-mdc-tab-link-container {\n// @include tabs-common.paginated-tab-header-container;\n// }\n\n// .oui-mdc-tab-nav-bar {\n// @include tabs-common.paginated-tab-header-with-background('.oui-mdc-tab-link-container',\n// '.oui-mdc-tab-link');\n// }\n", + "data": "// @use '../tabs-common';\r\n\r\n// @include tabs-common.structural-styles;\r\n// @include tabs-common.paginated-tab-header;\r\n\r\n// .oui-mdc-tab-links {\r\n// @include tabs-common.paginated-tab-header-item-wrapper('.oui-mdc-tab-link-container');\r\n// }\r\n\r\n// .oui-mdc-tab-link-container {\r\n// @include tabs-common.paginated-tab-header-container;\r\n// }\r\n\r\n// .oui-mdc-tab-nav-bar {\r\n// @include tabs-common.paginated-tab-header-with-background('.oui-mdc-tab-link-container',\r\n// '.oui-mdc-tab-link');\r\n// }\r\n", "styleUrl": "tab-nav-bar.scss" } ], @@ -47117,7 +47823,9 @@ } ] }, - "extends": "OuiPaginatedTabHeader", + "extends": [ + "OuiPaginatedTabHeader" + ], "implements": [ "AfterContentChecked", "AfterContentInit", @@ -47314,11 +48022,11 @@ } } }, - "templateData": "\n\n
\n\n\n\n \n
\n \n
\n \n\n\n\n\n
\n\n" + "templateData": "\r\n\r\n
\r\n\r\n\r\n\r\n \r\n
\r\n \r\n
\r\n \r\n\r\n\r\n\r\n\r\n
\r\n\r\n" }, { "name": "ouiTabNavPanel", - "id": "component-ouiTabNavPanel-9bae65d3c7ced1d19b2c9b521dc10b849a2def4e235b5b53918d1dfeb0d6e848284098bb20976a21d5cb589e2ebe3990b059964fdae21490b898a0aa8c60c4ad", + "id": "component-ouiTabNavPanel-6ce7108d054f1ce731fb3fdfd386c2252b009425dd05e2318aa5d6e1a34d06858b72f8ec2278d0b20e6242ef7a9e6be288d99d19c36c6712b85c978bf5907722", "file": "ui/src/components/tabs/tab-nav-bar/tab-nav-bar.ts", "changeDetection": "ChangeDetectionStrategy.OnPush", "encapsulation": [ @@ -47336,6 +48044,7 @@ "template": "", "templateUrl": [], "viewProviders": [], + "hostDirectives": [], "inputsClass": [ { "name": "id", @@ -47367,17 +48076,20 @@ "deprecationMessage": "", "hostBindings": [], "hostListeners": [], + "standalone": false, + "imports": [], "description": "

Tab panel component associated with OuiTabNav.

\n", "rawdescription": "\n\nTab panel component associated with OuiTabNav.\n", "type": "component", - "sourceCode": "import {\n AfterContentChecked,\n AfterContentInit,\n AfterViewInit,\n Attribute,\n ChangeDetectionStrategy,\n ChangeDetectorRef,\n Component,\n ContentChildren,\n ElementRef,\n forwardRef,\n Inject,\n Input,\n NgZone,\n OnDestroy,\n Optional,\n QueryList,\n ViewChild,\n ViewEncapsulation,\n} from '@angular/core';\nimport { ANIMATION_MODULE_TYPE } from '@angular/platform-browser/animations';\nimport {\n CanDisable,\n CanDisableRipple,\n HasTabIndex,\n mixinDisabled,\n mixinDisableRipple,\n mixinTabIndex,\n ThemePalette,\n} from '../../core';\nimport { FocusableOption, FocusMonitor } from '@angular/cdk/a11y';\nimport { Directionality } from '@angular/cdk/bidi';\nimport { ViewportRuler } from '@angular/cdk/scrolling';\nimport { Platform } from '@angular/cdk/platform';\nimport { OuiInkBar, mixinInkBarItem } from '../ink-bar';\nimport {\n BooleanInput,\n coerceBooleanProperty,\n NumberInput,\n} from '@angular/cdk/coercion';\nimport { BehaviorSubject, Subject } from 'rxjs';\nimport { startWith, takeUntil } from 'rxjs/operators';\nimport { ENTER, SPACE } from '@angular/cdk/keycodes';\nimport { OUI_TABS_CONFIG, OuiTabsConfig } from '../tab-config';\nimport { OuiPaginatedTabHeader } from '../paginated-tab-header';\nimport { isDevMode } from '@angular/core';\n\n// Increasing integer for generating unique ids for tab nav components.\nlet nextUniqueId = 0;\n\n/**\n * Navigation component matching the styles of the tab group header.\n * Provides anchored navigation with animated ink bar.\n */\n@Component({\n // eslint-disable-next-line @angular-eslint/component-selector\n selector: '[oui-tab-nav-bar]',\n exportAs: 'OuiTabNavBar, OuiTabNav',\n // eslint-disable-next-line @angular-eslint/no-inputs-metadata-property\n inputs: ['color'],\n templateUrl: 'tab-nav-bar.html',\n styleUrls: ['tab-nav-bar.scss'],\n // eslint-disable-next-line @angular-eslint/no-host-metadata-property\n host: {\n '[attr.role]': '_getRole()',\n class: 'oui-mdc-tab-nav-bar oui-mdc-tab-header',\n '[class.oui-mdc-tab-header-pagination-controls-enabled]':\n '_showPaginationControls',\n '[class.oui-mdc-tab-header-rtl]': \"_getLayoutDirection() == 'rtl'\",\n '[class.oui-mdc-tab-nav-bar-stretch-tabs]': 'stretchTabs',\n '[class.mat-primary]': 'color !== \"warn\" && color !== \"accent\"',\n '[class.mat-accent]': 'color === \"accent\"',\n '[class.mat-warn]': 'color === \"warn\"',\n '[class._oui-animation-noopable]': '_animationMode === \"NoopAnimations\"',\n '[style.--oui-tab-animation-duration]': 'animationDuration',\n },\n encapsulation: ViewEncapsulation.None,\n // tslint:disable-next-line:validate-decorators\n changeDetection: ChangeDetectionStrategy.Default,\n})\nexport class OuiTabNav\n extends OuiPaginatedTabHeader\n implements AfterContentChecked, AfterContentInit, OnDestroy, AfterViewInit\n{\n /** Whether the ink bar should fit its width to the size of the tab label content. */\n @Input()\n get fitInkBarToContent(): boolean {\n return this._fitInkBarToContent.value;\n }\n set fitInkBarToContent(v: BooleanInput) {\n this._fitInkBarToContent.next(coerceBooleanProperty(v));\n this._changeDetectorRef.markForCheck();\n }\n _fitInkBarToContent = new BehaviorSubject(false);\n\n /** Whether tabs should be stretched to fill the header. */\n @Input('oui-stretch-tabs')\n get stretchTabs(): boolean {\n return this._stretchTabs;\n }\n set stretchTabs(v: BooleanInput) {\n this._stretchTabs = coerceBooleanProperty(v);\n }\n private _stretchTabs = true;\n\n @Input()\n get animationDuration(): string {\n return this._animationDuration;\n }\n\n set animationDuration(value: NumberInput) {\n // eslint-disable-next-line @typescript-eslint/restrict-plus-operands\n this._animationDuration = /^\\d+$/.test(value + '') // eslint-disable-next-line @typescript-eslint/restrict-plus-operands\n ? value + 'ms'\n : (value as string);\n }\n\n private _animationDuration: string;\n\n /** Query list of all tab links of the tab navigation. */\n @ContentChildren(forwardRef(() => OuiTabLink), { descendants: true })\n _items: QueryList;\n\n /** Background color of the tab nav. */\n @Input()\n get backgroundColor(): ThemePalette {\n return this._backgroundColor;\n }\n\n set backgroundColor(value: ThemePalette) {\n const classList = this._elementRef.nativeElement.classList;\n classList.remove(\n 'oui-tabs-with-background',\n `oui-background-${this.backgroundColor}`\n );\n\n if (value) {\n classList.add('oui-tabs-with-background', `oui-background-${value}`);\n }\n\n this._backgroundColor = value;\n }\n\n private _backgroundColor: ThemePalette;\n\n /** Whether the ripple effect is disabled or not. */\n @Input()\n get disableRipple(): boolean {\n return this._disableRipple;\n }\n\n set disableRipple(value: BooleanInput) {\n this._disableRipple = coerceBooleanProperty(value);\n }\n\n private _disableRipple = false;\n\n /** Theme color of the nav bar. */\n @Input() color: ThemePalette = 'accent';\n\n /**\n * Associated tab panel controlled by the nav bar. If not provided, then the nav bar\n * follows the ARIA link / navigation landmark pattern. If provided, it follows the\n * ARIA tabs design pattern.\n */\n @Input() tabPanel?: ouiTabNavPanel;\n\n @ViewChild('tabListContainer', { static: true })\n _tabListContainer: ElementRef;\n @ViewChild('tabList', { static: true }) _tabList: ElementRef;\n @ViewChild('tabListInner', { static: true }) _tabListInner: ElementRef;\n @ViewChild('nextPaginator') _nextPaginator: ElementRef;\n @ViewChild('previousPaginator') _previousPaginator: ElementRef;\n _inkBar: OuiInkBar;\n\n constructor(\n elementRef: ElementRef,\n @Optional() dir: Directionality,\n ngZone: NgZone,\n changeDetectorRef: ChangeDetectorRef,\n viewportRuler: ViewportRuler,\n platform: Platform,\n @Optional() @Inject(ANIMATION_MODULE_TYPE) animationMode?: string,\n @Optional() @Inject(OUI_TABS_CONFIG) defaultConfig?: OuiTabsConfig\n ) {\n super(\n // eslint-disable-next-line @typescript-eslint/no-unsafe-argument\n elementRef,\n changeDetectorRef,\n viewportRuler,\n dir,\n ngZone,\n platform,\n animationMode\n );\n this.disablePagination =\n defaultConfig && defaultConfig.disablePagination != null\n ? defaultConfig.disablePagination\n : false;\n this.fitInkBarToContent =\n defaultConfig && defaultConfig.fitInkBarToContent != null\n ? defaultConfig.fitInkBarToContent\n : false;\n this.stretchTabs =\n defaultConfig && defaultConfig.stretchTabs != null\n ? defaultConfig.stretchTabs\n : true;\n }\n\n protected _itemSelected() {\n // noop\n }\n\n override ngAfterContentInit() {\n this._inkBar = new OuiInkBar(this._items);\n // We need this to run before the `changes` subscription in parent to ensure that the\n // selectedIndex is up-to-date by the time the super class starts looking for it.\n this._items.changes\n .pipe(startWith(null), takeUntil(this._destroyed))\n .subscribe(() => {\n this.updateActiveLink();\n });\n\n super.ngAfterContentInit();\n }\n\n override ngAfterViewInit() {\n if (!this.tabPanel && (typeof isDevMode === 'undefined' || isDevMode)) {\n throw new Error('A oui-tab-nav-panel must be specified via [tabPanel].');\n }\n super.ngAfterViewInit();\n }\n\n /** Notifies the component that the active link has been changed. */\n updateActiveLink() {\n if (!this._items) {\n return;\n }\n\n const items = this._items.toArray();\n\n for (let i = 0; i < items.length; i++) {\n if (items[i].active) {\n this.selectedIndex = i;\n this._changeDetectorRef.markForCheck();\n\n if (this.tabPanel) {\n this.tabPanel._activeTabId = items[i].id;\n }\n\n return;\n }\n }\n\n // The ink bar should hide itself if no items are active.\n this.selectedIndex = -1;\n this._inkBar.hide();\n }\n\n _getRole(): string | null {\n return this.tabPanel\n ? 'tablist'\n : this._elementRef.nativeElement.getAttribute('role');\n }\n}\n\n// Boilerplate for applying mixins to OuiTabLink.\nconst _OuiTabLinkMixinBase = mixinInkBarItem(\n mixinTabIndex(\n mixinDisableRipple(\n mixinDisabled(\n class {\n elementRef: ElementRef;\n }\n )\n )\n )\n);\n\n/**\n * Link inside a `oui-tab-nav-bar`.\n */\n@Component({\n // eslint-disable-next-line\n selector: '[oui-tab-link], [OuiTabLink]',\n exportAs: 'OuiTabLink',\n // eslint-disable-next-line\n inputs: ['disabled', 'disableRipple', 'tabIndex', 'active', 'id'],\n changeDetection: ChangeDetectionStrategy.OnPush,\n encapsulation: ViewEncapsulation.None,\n templateUrl: 'tab-link.html',\n styleUrls: ['tab-link.scss'],\n // eslint-disable-next-line\n host: {\n class: 'mdc-tab oui-mdc-tab-link oui-mdc-focus-indicator',\n '[attr.aria-controls]': '_getAriaControls()',\n '[attr.aria-current]': '_getAriaCurrent()',\n '[attr.aria-disabled]': 'disabled',\n '[attr.aria-selected]': '_getAriaSelected()',\n '[attr.id]': 'id',\n '[attr.tabIndex]': '_getTabIndex()',\n '[attr.role]': '_getRole()',\n '[class.oui-mdc-tab-disabled]': 'disabled',\n '[class.mdc-tab--active]': 'active',\n '(focus)': '_handleFocus()',\n '(keydown)': '_handleKeydown($event)',\n },\n})\nexport class OuiTabLink\n extends _OuiTabLinkMixinBase\n implements\n AfterViewInit,\n OnDestroy,\n CanDisable,\n CanDisableRipple,\n HasTabIndex,\n FocusableOption\n{\n private readonly _destroyed = new Subject();\n\n /** Whether the tab link is active or not. */\n protected _isActive = false;\n\n /** Whether the link is active. */\n @Input()\n get active(): boolean {\n return this._isActive;\n }\n\n set active(value: BooleanInput) {\n const newValue = coerceBooleanProperty(value);\n\n if (newValue !== this._isActive) {\n this._isActive = newValue;\n this._tabNavBar.updateActiveLink();\n }\n }\n\n /**\n * Whether ripples are disabled on interaction.\n * @docs-private\n */\n get rippleDisabled(): boolean {\n return this.disabled || this.disableRipple || this._tabNavBar.disableRipple;\n }\n\n /** Unique id for the tab. */\n @Input() id = `oui-tab-link-${nextUniqueId++}`;\n\n constructor(\n private _tabNavBar: OuiTabNav,\n /** @docs-private */\n override elementRef: ElementRef,\n @Attribute('tabindex') tabIndex: string,\n private _focusMonitor: FocusMonitor,\n @Optional() @Inject(ANIMATION_MODULE_TYPE) animationMode?: string\n ) {\n super();\n\n this.tabIndex = parseInt(tabIndex) || 0;\n\n if (animationMode === 'NoopAnimations') {\n // this.rippleConfig.animation = { enterDuration: 0, exitDuration: 0 };\n }\n\n _tabNavBar._fitInkBarToContent\n .pipe(takeUntil(this._destroyed))\n .subscribe((fitInkBarToContent) => {\n this.fitInkBarToContent = fitInkBarToContent;\n });\n }\n\n /** Focuses the tab link. */\n focus() {\n this.elementRef.nativeElement.focus();\n }\n\n ngAfterViewInit() {\n // eslint-disable-next-line @typescript-eslint/no-unsafe-argument\n this._focusMonitor.monitor(this.elementRef);\n }\n\n override ngOnDestroy() {\n this._destroyed.next();\n this._destroyed.complete();\n super.ngOnDestroy();\n // eslint-disable-next-line @typescript-eslint/no-unsafe-argument\n this._focusMonitor.stopMonitoring(this.elementRef);\n }\n\n _handleFocus() {\n // Since we allow navigation through tabbing in the nav bar, we\n // have to update the focused index whenever the link receives focus.\n this._tabNavBar.focusIndex = this._tabNavBar._items.toArray().indexOf(this);\n }\n\n _handleKeydown(event: KeyboardEvent) {\n if (this.disabled && (event.keyCode === SPACE || event.keyCode === ENTER)) {\n event.preventDefault();\n } else if (this._tabNavBar.tabPanel && event.keyCode === SPACE) {\n this.elementRef.nativeElement.click();\n }\n }\n\n _getAriaControls(): string | null {\n return this._tabNavBar.tabPanel\n ? this._tabNavBar.tabPanel?.id\n : this.elementRef.nativeElement.getAttribute('aria-controls');\n }\n\n _getAriaSelected(): string | null {\n if (this._tabNavBar.tabPanel) {\n return this.active ? 'true' : 'false';\n } else {\n return this.elementRef.nativeElement.getAttribute('aria-selected');\n }\n }\n\n _getAriaCurrent(): string | null {\n return this.active && !this._tabNavBar.tabPanel ? 'page' : null;\n }\n\n _getRole(): string | null {\n return this._tabNavBar.tabPanel\n ? 'tab'\n : this.elementRef.nativeElement.getAttribute('role');\n }\n\n _getTabIndex(): number {\n if (this._tabNavBar.tabPanel) {\n return this._isActive && !this.disabled ? 0 : -1;\n } else {\n return this.tabIndex;\n }\n }\n}\n\n/**\n * Tab panel component associated with OuiTabNav.\n */\n@Component({\n selector: 'oui-tab-nav-panel',\n exportAs: 'ouiTabNavPanel',\n template: '',\n // eslint-disable-next-line @angular-eslint/no-host-metadata-property\n host: {\n '[attr.aria-labelledby]': '_activeTabId',\n '[attr.id]': 'id',\n class: 'oui-mdc-tab-nav-panel',\n role: 'tabpanel',\n },\n encapsulation: ViewEncapsulation.None,\n changeDetection: ChangeDetectionStrategy.OnPush,\n})\nexport class ouiTabNavPanel {\n /** Unique id for the tab panel. */\n @Input() id = `oui-tab-nav-panel-${nextUniqueId++}`;\n\n /** Id of the active tab in the nav bar. */\n _activeTabId?: string;\n}\n", + "sourceCode": "import {\r\n AfterContentChecked,\r\n AfterContentInit,\r\n AfterViewInit,\r\n Attribute,\r\n ChangeDetectionStrategy,\r\n ChangeDetectorRef,\r\n Component,\r\n ContentChildren,\r\n ElementRef,\r\n forwardRef,\r\n Inject,\r\n Input,\r\n NgZone,\r\n OnDestroy,\r\n Optional,\r\n QueryList,\r\n ViewChild,\r\n ViewEncapsulation,\r\n} from '@angular/core';\r\nimport { ANIMATION_MODULE_TYPE } from '@angular/platform-browser/animations';\r\nimport {\r\n CanDisable,\r\n CanDisableRipple,\r\n HasTabIndex,\r\n mixinDisabled,\r\n mixinDisableRipple,\r\n mixinTabIndex,\r\n ThemePalette,\r\n} from '../../core';\r\nimport { FocusableOption, FocusMonitor } from '@angular/cdk/a11y';\r\nimport { Directionality } from '@angular/cdk/bidi';\r\nimport { ViewportRuler } from '@angular/cdk/scrolling';\r\nimport { Platform } from '@angular/cdk/platform';\r\nimport { OuiInkBar, mixinInkBarItem } from '../ink-bar';\r\nimport {\r\n BooleanInput,\r\n coerceBooleanProperty,\r\n NumberInput,\r\n} from '@angular/cdk/coercion';\r\nimport { BehaviorSubject, Subject } from 'rxjs';\r\nimport { startWith, takeUntil } from 'rxjs/operators';\r\nimport { ENTER, SPACE } from '@angular/cdk/keycodes';\r\nimport { OUI_TABS_CONFIG, OuiTabsConfig } from '../tab-config';\r\nimport { OuiPaginatedTabHeader } from '../paginated-tab-header';\r\nimport { isDevMode } from '@angular/core';\r\n\r\n// Increasing integer for generating unique ids for tab nav components.\r\nlet nextUniqueId = 0;\r\n\r\n/**\r\n * Navigation component matching the styles of the tab group header.\r\n * Provides anchored navigation with animated ink bar.\r\n */\r\n@Component({\r\n // eslint-disable-next-line @angular-eslint/component-selector\r\n selector: '[oui-tab-nav-bar]',\r\n exportAs: 'OuiTabNavBar, OuiTabNav',\r\n // eslint-disable-next-line @angular-eslint/no-inputs-metadata-property\r\n inputs: ['color'],\r\n templateUrl: 'tab-nav-bar.html',\r\n styleUrls: ['tab-nav-bar.scss'],\r\n // eslint-disable-next-line @angular-eslint/no-host-metadata-property\r\n host: {\r\n '[attr.role]': '_getRole()',\r\n class: 'oui-mdc-tab-nav-bar oui-mdc-tab-header',\r\n '[class.oui-mdc-tab-header-pagination-controls-enabled]':\r\n '_showPaginationControls',\r\n '[class.oui-mdc-tab-header-rtl]': \"_getLayoutDirection() == 'rtl'\",\r\n '[class.oui-mdc-tab-nav-bar-stretch-tabs]': 'stretchTabs',\r\n '[class.mat-primary]': 'color !== \"warn\" && color !== \"accent\"',\r\n '[class.mat-accent]': 'color === \"accent\"',\r\n '[class.mat-warn]': 'color === \"warn\"',\r\n '[class._oui-animation-noopable]': '_animationMode === \"NoopAnimations\"',\r\n '[style.--oui-tab-animation-duration]': 'animationDuration',\r\n },\r\n encapsulation: ViewEncapsulation.None,\r\n // tslint:disable-next-line:validate-decorators\r\n changeDetection: ChangeDetectionStrategy.Default,\r\n})\r\nexport class OuiTabNav\r\n extends OuiPaginatedTabHeader\r\n implements AfterContentChecked, AfterContentInit, OnDestroy, AfterViewInit\r\n{\r\n /** Whether the ink bar should fit its width to the size of the tab label content. */\r\n @Input()\r\n get fitInkBarToContent(): boolean {\r\n return this._fitInkBarToContent.value;\r\n }\r\n set fitInkBarToContent(v: BooleanInput) {\r\n this._fitInkBarToContent.next(coerceBooleanProperty(v));\r\n this._changeDetectorRef.markForCheck();\r\n }\r\n _fitInkBarToContent = new BehaviorSubject(false);\r\n\r\n /** Whether tabs should be stretched to fill the header. */\r\n @Input('oui-stretch-tabs')\r\n get stretchTabs(): boolean {\r\n return this._stretchTabs;\r\n }\r\n set stretchTabs(v: BooleanInput) {\r\n this._stretchTabs = coerceBooleanProperty(v);\r\n }\r\n private _stretchTabs = true;\r\n\r\n @Input()\r\n get animationDuration(): string {\r\n return this._animationDuration;\r\n }\r\n\r\n set animationDuration(value: NumberInput) {\r\n // eslint-disable-next-line @typescript-eslint/restrict-plus-operands\r\n this._animationDuration = /^\\d+$/.test(value + '') // eslint-disable-next-line @typescript-eslint/restrict-plus-operands\r\n ? value + 'ms'\r\n : (value as string);\r\n }\r\n\r\n private _animationDuration: string;\r\n\r\n /** Query list of all tab links of the tab navigation. */\r\n @ContentChildren(forwardRef(() => OuiTabLink), { descendants: true })\r\n _items: QueryList;\r\n\r\n /** Background color of the tab nav. */\r\n @Input()\r\n get backgroundColor(): ThemePalette {\r\n return this._backgroundColor;\r\n }\r\n\r\n set backgroundColor(value: ThemePalette) {\r\n const classList = this._elementRef.nativeElement.classList;\r\n classList.remove(\r\n 'oui-tabs-with-background',\r\n `oui-background-${this.backgroundColor}`\r\n );\r\n\r\n if (value) {\r\n classList.add('oui-tabs-with-background', `oui-background-${value}`);\r\n }\r\n\r\n this._backgroundColor = value;\r\n }\r\n\r\n private _backgroundColor: ThemePalette;\r\n\r\n /** Whether the ripple effect is disabled or not. */\r\n @Input()\r\n get disableRipple(): boolean {\r\n return this._disableRipple;\r\n }\r\n\r\n set disableRipple(value: BooleanInput) {\r\n this._disableRipple = coerceBooleanProperty(value);\r\n }\r\n\r\n private _disableRipple = false;\r\n\r\n /** Theme color of the nav bar. */\r\n @Input() color: ThemePalette = 'accent';\r\n\r\n /**\r\n * Associated tab panel controlled by the nav bar. If not provided, then the nav bar\r\n * follows the ARIA link / navigation landmark pattern. If provided, it follows the\r\n * ARIA tabs design pattern.\r\n */\r\n @Input() tabPanel?: ouiTabNavPanel;\r\n\r\n @ViewChild('tabListContainer', { static: true })\r\n _tabListContainer: ElementRef;\r\n @ViewChild('tabList', { static: true }) _tabList: ElementRef;\r\n @ViewChild('tabListInner', { static: true }) _tabListInner: ElementRef;\r\n @ViewChild('nextPaginator') _nextPaginator: ElementRef;\r\n @ViewChild('previousPaginator') _previousPaginator: ElementRef;\r\n _inkBar: OuiInkBar;\r\n\r\n constructor(\r\n elementRef: ElementRef,\r\n @Optional() dir: Directionality,\r\n ngZone: NgZone,\r\n changeDetectorRef: ChangeDetectorRef,\r\n viewportRuler: ViewportRuler,\r\n platform: Platform,\r\n @Optional() @Inject(ANIMATION_MODULE_TYPE) animationMode?: string,\r\n @Optional() @Inject(OUI_TABS_CONFIG) defaultConfig?: OuiTabsConfig\r\n ) {\r\n super(\r\n // eslint-disable-next-line @typescript-eslint/no-unsafe-argument\r\n elementRef,\r\n changeDetectorRef,\r\n viewportRuler,\r\n dir,\r\n ngZone,\r\n platform,\r\n animationMode\r\n );\r\n this.disablePagination =\r\n defaultConfig && defaultConfig.disablePagination != null\r\n ? defaultConfig.disablePagination\r\n : false;\r\n this.fitInkBarToContent =\r\n defaultConfig && defaultConfig.fitInkBarToContent != null\r\n ? defaultConfig.fitInkBarToContent\r\n : false;\r\n this.stretchTabs =\r\n defaultConfig && defaultConfig.stretchTabs != null\r\n ? defaultConfig.stretchTabs\r\n : true;\r\n }\r\n\r\n protected _itemSelected() {\r\n // noop\r\n }\r\n\r\n override ngAfterContentInit() {\r\n this._inkBar = new OuiInkBar(this._items);\r\n // We need this to run before the `changes` subscription in parent to ensure that the\r\n // selectedIndex is up-to-date by the time the super class starts looking for it.\r\n this._items.changes\r\n .pipe(startWith(null), takeUntil(this._destroyed))\r\n .subscribe(() => {\r\n this.updateActiveLink();\r\n });\r\n\r\n super.ngAfterContentInit();\r\n }\r\n\r\n override ngAfterViewInit() {\r\n if (!this.tabPanel && (typeof isDevMode === 'undefined' || isDevMode)) {\r\n throw new Error('A oui-tab-nav-panel must be specified via [tabPanel].');\r\n }\r\n super.ngAfterViewInit();\r\n }\r\n\r\n /** Notifies the component that the active link has been changed. */\r\n updateActiveLink() {\r\n if (!this._items) {\r\n return;\r\n }\r\n\r\n const items = this._items.toArray();\r\n\r\n for (let i = 0; i < items.length; i++) {\r\n if (items[i].active) {\r\n this.selectedIndex = i;\r\n this._changeDetectorRef.markForCheck();\r\n\r\n if (this.tabPanel) {\r\n this.tabPanel._activeTabId = items[i].id;\r\n }\r\n\r\n return;\r\n }\r\n }\r\n\r\n // The ink bar should hide itself if no items are active.\r\n this.selectedIndex = -1;\r\n this._inkBar.hide();\r\n }\r\n\r\n _getRole(): string | null {\r\n return this.tabPanel\r\n ? 'tablist'\r\n : this._elementRef.nativeElement.getAttribute('role');\r\n }\r\n}\r\n\r\n// Boilerplate for applying mixins to OuiTabLink.\r\nconst _OuiTabLinkMixinBase = mixinInkBarItem(\r\n mixinTabIndex(\r\n mixinDisableRipple(\r\n mixinDisabled(\r\n class {\r\n elementRef: ElementRef;\r\n }\r\n )\r\n )\r\n )\r\n);\r\n\r\n/**\r\n * Link inside a `oui-tab-nav-bar`.\r\n */\r\n@Component({\r\n // eslint-disable-next-line\r\n selector: '[oui-tab-link], [OuiTabLink]',\r\n exportAs: 'OuiTabLink',\r\n // eslint-disable-next-line\r\n inputs: ['disabled', 'disableRipple', 'tabIndex', 'active', 'id'],\r\n changeDetection: ChangeDetectionStrategy.OnPush,\r\n encapsulation: ViewEncapsulation.None,\r\n templateUrl: 'tab-link.html',\r\n styleUrls: ['tab-link.scss'],\r\n // eslint-disable-next-line\r\n host: {\r\n class: 'mdc-tab oui-mdc-tab-link oui-mdc-focus-indicator',\r\n '[attr.aria-controls]': '_getAriaControls()',\r\n '[attr.aria-current]': '_getAriaCurrent()',\r\n '[attr.aria-disabled]': 'disabled',\r\n '[attr.aria-selected]': '_getAriaSelected()',\r\n '[attr.id]': 'id',\r\n '[attr.tabIndex]': '_getTabIndex()',\r\n '[attr.role]': '_getRole()',\r\n '[class.oui-mdc-tab-disabled]': 'disabled',\r\n '[class.mdc-tab--active]': 'active',\r\n '(focus)': '_handleFocus()',\r\n '(keydown)': '_handleKeydown($event)',\r\n },\r\n})\r\nexport class OuiTabLink\r\n extends _OuiTabLinkMixinBase\r\n implements\r\n AfterViewInit,\r\n OnDestroy,\r\n CanDisable,\r\n CanDisableRipple,\r\n HasTabIndex,\r\n FocusableOption\r\n{\r\n private readonly _destroyed = new Subject();\r\n\r\n /** Whether the tab link is active or not. */\r\n protected _isActive = false;\r\n\r\n /** Whether the link is active. */\r\n @Input()\r\n get active(): boolean {\r\n return this._isActive;\r\n }\r\n\r\n set active(value: BooleanInput) {\r\n const newValue = coerceBooleanProperty(value);\r\n\r\n if (newValue !== this._isActive) {\r\n this._isActive = newValue;\r\n this._tabNavBar.updateActiveLink();\r\n }\r\n }\r\n\r\n /**\r\n * Whether ripples are disabled on interaction.\r\n * @docs-private\r\n */\r\n get rippleDisabled(): boolean {\r\n return this.disabled || this.disableRipple || this._tabNavBar.disableRipple;\r\n }\r\n\r\n /** Unique id for the tab. */\r\n @Input() id = `oui-tab-link-${nextUniqueId++}`;\r\n\r\n constructor(\r\n private _tabNavBar: OuiTabNav,\r\n /** @docs-private */\r\n override elementRef: ElementRef,\r\n @Attribute('tabindex') tabIndex: string,\r\n private _focusMonitor: FocusMonitor,\r\n @Optional() @Inject(ANIMATION_MODULE_TYPE) animationMode?: string\r\n ) {\r\n super();\r\n\r\n this.tabIndex = parseInt(tabIndex) || 0;\r\n\r\n if (animationMode === 'NoopAnimations') {\r\n // this.rippleConfig.animation = { enterDuration: 0, exitDuration: 0 };\r\n }\r\n\r\n _tabNavBar._fitInkBarToContent\r\n .pipe(takeUntil(this._destroyed))\r\n .subscribe((fitInkBarToContent) => {\r\n this.fitInkBarToContent = fitInkBarToContent;\r\n });\r\n }\r\n\r\n /** Focuses the tab link. */\r\n focus() {\r\n this.elementRef.nativeElement.focus();\r\n }\r\n\r\n ngAfterViewInit() {\r\n // eslint-disable-next-line @typescript-eslint/no-unsafe-argument\r\n this._focusMonitor.monitor(this.elementRef);\r\n }\r\n\r\n override ngOnDestroy() {\r\n this._destroyed.next();\r\n this._destroyed.complete();\r\n super.ngOnDestroy();\r\n // eslint-disable-next-line @typescript-eslint/no-unsafe-argument\r\n this._focusMonitor.stopMonitoring(this.elementRef);\r\n }\r\n\r\n _handleFocus() {\r\n // Since we allow navigation through tabbing in the nav bar, we\r\n // have to update the focused index whenever the link receives focus.\r\n this._tabNavBar.focusIndex = this._tabNavBar._items.toArray().indexOf(this);\r\n }\r\n\r\n _handleKeydown(event: KeyboardEvent) {\r\n if (this.disabled && (event.keyCode === SPACE || event.keyCode === ENTER)) {\r\n event.preventDefault();\r\n } else if (this._tabNavBar.tabPanel && event.keyCode === SPACE) {\r\n this.elementRef.nativeElement.click();\r\n }\r\n }\r\n\r\n _getAriaControls(): string | null {\r\n return this._tabNavBar.tabPanel\r\n ? this._tabNavBar.tabPanel?.id\r\n : this.elementRef.nativeElement.getAttribute('aria-controls');\r\n }\r\n\r\n _getAriaSelected(): string | null {\r\n if (this._tabNavBar.tabPanel) {\r\n return this.active ? 'true' : 'false';\r\n } else {\r\n return this.elementRef.nativeElement.getAttribute('aria-selected');\r\n }\r\n }\r\n\r\n _getAriaCurrent(): string | null {\r\n return this.active && !this._tabNavBar.tabPanel ? 'page' : null;\r\n }\r\n\r\n _getRole(): string | null {\r\n return this._tabNavBar.tabPanel\r\n ? 'tab'\r\n : this.elementRef.nativeElement.getAttribute('role');\r\n }\r\n\r\n _getTabIndex(): number {\r\n if (this._tabNavBar.tabPanel) {\r\n return this._isActive && !this.disabled ? 0 : -1;\r\n } else {\r\n return this.tabIndex;\r\n }\r\n }\r\n}\r\n\r\n/**\r\n * Tab panel component associated with OuiTabNav.\r\n */\r\n@Component({\r\n selector: 'oui-tab-nav-panel',\r\n exportAs: 'ouiTabNavPanel',\r\n template: '',\r\n // eslint-disable-next-line @angular-eslint/no-host-metadata-property\r\n host: {\r\n '[attr.aria-labelledby]': '_activeTabId',\r\n '[attr.id]': 'id',\r\n class: 'oui-mdc-tab-nav-panel',\r\n role: 'tabpanel',\r\n },\r\n encapsulation: ViewEncapsulation.None,\r\n changeDetection: ChangeDetectionStrategy.OnPush,\r\n})\r\nexport class ouiTabNavPanel {\r\n /** Unique id for the tab panel. */\r\n @Input() id = `oui-tab-nav-panel-${nextUniqueId++}`;\r\n\r\n /** Id of the active tab in the nav bar. */\r\n _activeTabId?: string;\r\n}\r\n", "assetsDirs": [], "styleUrlsData": "", - "stylesData": "" + "stylesData": "", + "extends": [] }, { "name": "OuiTabStorybook", - "id": "component-OuiTabStorybook-4826c889c695832f5994b7906333b44978af45ba140206e67d50876784e432180a396c0a0334557411bf498fcc1188da44774ce795be3962f8c5addf8323ee23", + "id": "component-OuiTabStorybook-f9856f14bebcb279e79e4f4062a35d5df5668ec4160537fd69ecb8b5e5f3997c6b97904ae2b1576d94db8e0ee178b4d1f0d1ada97c129bac4693f13181f277e8", "file": "ui/src/stories/tabs/tabs.component.ts", "encapsulation": [], "entryComponents": [], @@ -47387,9 +48099,10 @@ "selector": "oui-tab-storybook", "styleUrls": [], "styles": [], - "template": "\n \n BBBBB123\">\n CCCCCC123\">\n \n\n", + "template": "\n Content in tab 1\">\n Content in tab 2\">\n Content in tab 3\">\n\n", "templateUrl": [], "viewProviders": [], + "hostDirectives": [], "inputsClass": [], "outputsClass": [], "propertiesClass": [], @@ -47398,10 +48111,12 @@ "deprecationMessage": "", "hostBindings": [], "hostListeners": [], + "standalone": false, + "imports": [], "description": "", "rawdescription": "\n", "type": "component", - "sourceCode": "import { Component } from '@angular/core';\n\n@Component({\n selector: 'oui-tab-storybook',\n template: `\n \n \n BBBBB123\">\n CCCCCC123\">\n \n \n `,\n})\nexport class OuiTabStorybook {\n constructor() {}\n}\n", + "sourceCode": "import { Component } from '@angular/core';\r\n\r\n@Component({\r\n selector: 'oui-tab-storybook',\r\n template: `\r\n \r\n Content in tab 1\">\r\n Content in tab 2\">\r\n Content in tab 3\">\r\n \r\n `,\r\n})\r\nexport class OuiTabStorybook {\r\n constructor() {}\r\n}\r\n", "assetsDirs": [], "styleUrlsData": "", "stylesData": "", @@ -47411,8 +48126,9 @@ "deprecated": false, "deprecationMessage": "", "args": [], - "line": 15 - } + "line": 13 + }, + "extends": [] }, { "name": "OuiTooltipStorybook", @@ -47429,6 +48145,7 @@ "template": "\n", "templateUrl": [], "viewProviders": [], + "hostDirectives": [], "inputsClass": [ { "name": "_ouiTooltip", @@ -47465,6 +48182,8 @@ "deprecationMessage": "", "hostBindings": [], "hostListeners": [], + "standalone": false, + "imports": [], "description": "", "rawdescription": "\n", "type": "component", @@ -47512,7 +48231,8 @@ } } ] - } + }, + "extends": [] }, { "name": "OuiYearView", @@ -47534,6 +48254,7 @@ "year-view.html" ], "viewProviders": [], + "hostDirectives": [], "inputsClass": [ { "name": "activeDate", @@ -47628,7 +48349,7 @@ "description": "", "line": 65, "modifierKind": [ - 121 + 123 ] }, { @@ -47646,7 +48367,8 @@ } ], "modifierKind": [ - 123 + 170, + 125 ] }, { @@ -47658,7 +48380,7 @@ "description": "", "line": 102, "modifierKind": [ - 121 + 123 ] }, { @@ -47670,7 +48392,7 @@ "description": "", "line": 90, "modifierKind": [ - 121 + 123 ] }, { @@ -47697,6 +48419,9 @@ "name": "ViewChild", "stringifiedArguments": "OuiCalendarBody" } + ], + "modifierKind": [ + 170 ] }, { @@ -47708,7 +48433,7 @@ "description": "", "line": 78, "modifierKind": [ - 121 + 123 ] }, { @@ -47768,7 +48493,7 @@ "rawdescription": "\nCreates an OuiCalendarCell for the given month.", "description": "

Creates an OuiCalendarCell for the given month.

\n", "modifierKind": [ - 121 + 123 ], "jsdoctags": [ { @@ -47822,7 +48547,7 @@ "rawdescription": "\n\nGets the month in this year that the given Date falls on.\nReturns null if the given Date is in another year.\n", "description": "

Gets the month in this year that the given Date falls on.\nReturns null if the given Date is in another year.

\n", "modifierKind": [ - 121 + 123 ], "jsdoctags": [ { @@ -47855,17 +48580,17 @@ "rawdescription": "\n\n", "description": "", "modifierKind": [ - 121 + 123 ], "jsdoctags": [ { "name": { "pos": 10572, "end": 10575, - "flags": 4227072, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "obj" }, "type": "any", @@ -47874,10 +48599,10 @@ "tagName": { "pos": 10566, "end": 10571, - "flags": 4227072, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "param" }, "comment": "

The object to check.

\n" @@ -47886,10 +48611,10 @@ "tagName": { "pos": 10603, "end": 10610, - "flags": 4227072, + "flags": 16842752, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "returns" }, "comment": "

The given object if it is both a date instance and valid, otherwise null.

\n" @@ -47950,7 +48675,7 @@ "rawdescription": "\nDetermines whether the user has the RTL layout direction.", "description": "

Determines whether the user has the RTL layout direction.

\n", "modifierKind": [ - 121 + 123 ] }, { @@ -47978,7 +48703,7 @@ "rawdescription": "\n\nTests whether the combination month/year is after this.maxDate, considering\njust the month and year of this.maxDate\n", "description": "

Tests whether the combination month/year is after this.maxDate, considering\njust the month and year of this.maxDate

\n", "modifierKind": [ - 121 + 123 ], "jsdoctags": [ { @@ -48026,7 +48751,7 @@ "rawdescription": "\n\nTests whether the combination month/year is before this.minDate, considering\njust the month and year of this.minDate\n", "description": "

Tests whether the combination month/year is before this.minDate, considering\njust the month and year of this.minDate

\n", "modifierKind": [ - 121 + 123 ], "jsdoctags": [ { @@ -48098,7 +48823,7 @@ "rawdescription": "\nWhether the given month is enabled.", "description": "

Whether the given month is enabled.

\n", "modifierKind": [ - 121 + 123 ], "jsdoctags": [ { @@ -48127,6 +48852,8 @@ "deprecationMessage": "", "hostBindings": [], "hostListeners": [], + "standalone": false, + "imports": [], "description": "

An internal component used to display a single year in the datepicker.

\n", "rawdescription": "\n\nAn internal component used to display a single year in the datepicker.\n", "type": "component", @@ -48207,6 +48934,7 @@ } ] }, + "extends": [], "implements": [ "AfterContentInit" ], @@ -48388,6 +49116,7 @@ "tooltip.html" ], "viewProviders": [], + "hostDirectives": [], "inputsClass": [], "outputsClass": [], "propertiesClass": [ @@ -48402,7 +49131,7 @@ "line": 146, "rawdescription": "\nWhether interactions on the page should close the tooltip", "modifierKind": [ - 121 + 123 ] }, { @@ -48437,8 +49166,8 @@ "line": 149, "rawdescription": "\nSubject for notifying that the tooltip has been hidden from the view", "modifierKind": [ - 121, - 144 + 123, + 148 ] }, { @@ -48601,6 +49330,8 @@ "deprecationMessage": "", "hostBindings": [], "hostListeners": [], + "standalone": false, + "imports": [], "description": "

Internal component that wraps the tooltip's content.

\n", "rawdescription": "\n\nInternal component that wraps the tooltip's content.\n\n", "type": "component", @@ -48654,6 +49385,7 @@ } ] }, + "extends": [], "templateData": "
\n \n
{{message}}
\n
\n\n" } ], @@ -48853,7 +49585,7 @@ }, { "name": "OuiCommonModule", - "id": "module-OuiCommonModule-faf3c2d5fa6ebca28372c7cb5b8112d9d13108d2e2811f5e27b343cdad3e494640760104bebf9faa35deae7c62ab89021cce2b1ce16b785f1cd5bd3271ba0044", + "id": "module-OuiCommonModule-ef22db41367b2c08b13c523be66ebd594c90c986a94f6990f23d6414cbbfc4a9e9dfe943acf905441d9051e0e19202026192cb30f79f93da1f2c6830ab030985", "description": "

Module that captures anything that should be loaded and/or run for all Angular Material\ncomponents. This includes Bidi, etc.

\n

This module should be imported to each top-level component module (e.g., OuiTabsModule).

\n", "deprecationMessage": "", "deprecated": false, @@ -48878,7 +49610,7 @@ "rawdescription": "\nGets whether a specific sanity check is enabled.", "description": "

Gets whether a specific sanity check is enabled.

\n", "modifierKind": [ - 121 + 123 ], "jsdoctags": [ { @@ -48893,7 +49625,7 @@ ] } ], - "sourceCode": "/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport { HighContrastModeDetector } from '@angular/cdk/a11y';\nimport { BidiModule } from '@angular/cdk/bidi';\nimport {\n inject,\n Inject,\n InjectionToken,\n NgModule,\n Optional,\n} from '@angular/core';\nimport { VERSION as CDK_VERSION } from '@angular/cdk';\nimport { DOCUMENT } from '@angular/common';\nimport { Platform, _isTestEnvironment } from '@angular/cdk/platform';\nimport { VERSION } from '../version';\nimport { isDevMode } from '@angular/core';\n\n/** @docs-private */\nexport function MATERIAL_SANITY_CHECKS_FACTORY(): SanityChecks {\n return true;\n}\n\n/** Injection token that configures whether the Material sanity checks are enabled. */\nexport const MATERIAL_SANITY_CHECKS = new InjectionToken(\n 'mat-sanity-checks',\n {\n providedIn: 'root',\n factory: MATERIAL_SANITY_CHECKS_FACTORY,\n }\n);\n\n/**\n * Possible sanity checks that can be enabled. If set to\n * true/false, all checks will be enabled/disabled.\n */\nexport type SanityChecks = boolean | GranularSanityChecks;\n\n/** Object that can be used to configure the sanity checks granularly. */\nexport interface GranularSanityChecks {\n doctype: boolean;\n theme: boolean;\n version: boolean;\n}\n\n/**\n * Module that captures anything that should be loaded and/or run for *all* Angular Material\n * components. This includes Bidi, etc.\n *\n * This module should be imported to each top-level component module (e.g., OuiTabsModule).\n */\n@NgModule({\n imports: [BidiModule],\n exports: [BidiModule],\n})\nexport class OuiCommonModule {\n /** Whether we've done the global sanity checks (e.g. a theme is loaded, there is a doctype). */\n private _hasDoneGlobalChecks = false;\n\n constructor(\n highContrastModeDetector: HighContrastModeDetector,\n @Optional()\n @Inject(MATERIAL_SANITY_CHECKS)\n private _sanityChecks: SanityChecks,\n @Inject(DOCUMENT) private _document: Document\n ) {\n // While A11yModule also does this, we repeat it here to avoid importing A11yModule\n // in OuiCommonModule.\n highContrastModeDetector._applyBodyHighContrastModeCssClasses();\n\n if (!this._hasDoneGlobalChecks) {\n this._hasDoneGlobalChecks = true;\n\n if (typeof isDevMode === 'undefined' || isDevMode) {\n // Inject in here so the reference to `Platform` can be removed in production mode.\n const platform = inject(Platform, { optional: true });\n\n if (this._checkIsEnabled('doctype')) {\n _checkDoctypeIsDefined(this._document);\n }\n\n if (this._checkIsEnabled('theme')) {\n _checkThemeIsPresent(this._document, !!platform?.isBrowser);\n }\n\n if (this._checkIsEnabled('version')) {\n _checkCdkVersionMatch();\n }\n }\n }\n }\n\n /** Gets whether a specific sanity check is enabled. */\n private _checkIsEnabled(name: keyof GranularSanityChecks): boolean {\n if (_isTestEnvironment()) {\n return false;\n }\n\n if (typeof this._sanityChecks === 'boolean') {\n return this._sanityChecks;\n }\n\n return !!this._sanityChecks[name];\n }\n}\n\n/** Checks that the page has a doctype. */\nfunction _checkDoctypeIsDefined(doc: Document): void {\n if (!doc.doctype) {\n console.warn(\n 'Current document does not have a doctype. This may cause ' +\n 'some Angular Material components not to behave as expected.'\n );\n }\n}\n\n/** Checks that a theme has been included. */\nfunction _checkThemeIsPresent(doc: Document, isBrowser: boolean): void {\n // We need to assert that the `body` is defined, because these checks run very early\n // and the `body` won't be defined if the consumer put their scripts in the `head`.\n if (!doc.body || !isBrowser) {\n return;\n }\n\n const testElement = doc.createElement('div');\n testElement.classList.add('mat-theme-loaded-marker');\n doc.body.appendChild(testElement);\n\n const computedStyle = getComputedStyle(testElement);\n\n // In some situations the computed style of the test element can be null. For example in\n // Firefox, the computed style is null if an application is running inside of a hidden iframe.\n // See: https://bugzilla.mozilla.org/show_bug.cgi?id=548397\n if (computedStyle && computedStyle.display !== 'none') {\n console.warn(\n 'Could not find Angular Material core theme. Most Material ' +\n 'components may not work as expected. For more info refer ' +\n 'to the theming guide: https://material.angular.io/guide/theming'\n );\n }\n\n testElement.remove();\n}\n\n/** Checks whether the Material version matches the CDK version. */\nfunction _checkCdkVersionMatch(): void {\n if (VERSION.full !== CDK_VERSION.full) {\n console.warn(\n 'The Angular Material version (' +\n VERSION.full +\n ') does not match ' +\n 'the Angular CDK version (' +\n CDK_VERSION.full +\n ').\\n' +\n 'Please ensure the versions of these two packages exactly match.'\n );\n }\n}\n", + "sourceCode": "/**\r\n * @license\r\n * Copyright Google LLC All Rights Reserved.\r\n *\r\n * Use of this source code is governed by an MIT-style license that can be\r\n * found in the LICENSE file at https://angular.io/license\r\n */\r\n\r\nimport { HighContrastModeDetector } from '@angular/cdk/a11y';\r\nimport { BidiModule } from '@angular/cdk/bidi';\r\nimport {\r\n inject,\r\n Inject,\r\n InjectionToken,\r\n NgModule,\r\n Optional,\r\n} from '@angular/core';\r\nimport { VERSION as CDK_VERSION } from '@angular/cdk';\r\nimport { DOCUMENT } from '@angular/common';\r\nimport { Platform, _isTestEnvironment } from '@angular/cdk/platform';\r\nimport { VERSION } from '../version';\r\nimport { isDevMode } from '@angular/core';\r\n\r\n/** @docs-private */\r\nexport function MATERIAL_SANITY_CHECKS_FACTORY(): SanityChecks {\r\n return true;\r\n}\r\n\r\n/** Injection token that configures whether the Material sanity checks are enabled. */\r\nexport const MATERIAL_SANITY_CHECKS = new InjectionToken(\r\n 'mat-sanity-checks',\r\n {\r\n providedIn: 'root',\r\n factory: MATERIAL_SANITY_CHECKS_FACTORY,\r\n }\r\n);\r\n\r\n/**\r\n * Possible sanity checks that can be enabled. If set to\r\n * true/false, all checks will be enabled/disabled.\r\n */\r\nexport type SanityChecks = boolean | GranularSanityChecks;\r\n\r\n/** Object that can be used to configure the sanity checks granularly. */\r\nexport interface GranularSanityChecks {\r\n doctype: boolean;\r\n theme: boolean;\r\n version: boolean;\r\n}\r\n\r\n/**\r\n * Module that captures anything that should be loaded and/or run for *all* Angular Material\r\n * components. This includes Bidi, etc.\r\n *\r\n * This module should be imported to each top-level component module (e.g., OuiTabsModule).\r\n */\r\n@NgModule({\r\n imports: [BidiModule],\r\n exports: [BidiModule],\r\n})\r\nexport class OuiCommonModule {\r\n /** Whether we've done the global sanity checks (e.g. a theme is loaded, there is a doctype). */\r\n private _hasDoneGlobalChecks = false;\r\n\r\n constructor(\r\n highContrastModeDetector: HighContrastModeDetector,\r\n @Optional()\r\n @Inject(MATERIAL_SANITY_CHECKS)\r\n private _sanityChecks: SanityChecks,\r\n @Inject(DOCUMENT) private _document: Document\r\n ) {\r\n // While A11yModule also does this, we repeat it here to avoid importing A11yModule\r\n // in OuiCommonModule.\r\n highContrastModeDetector._applyBodyHighContrastModeCssClasses();\r\n\r\n if (!this._hasDoneGlobalChecks) {\r\n this._hasDoneGlobalChecks = true;\r\n\r\n if (typeof isDevMode === 'undefined' || isDevMode) {\r\n // Inject in here so the reference to `Platform` can be removed in production mode.\r\n const platform = inject(Platform, { optional: true });\r\n\r\n if (this._checkIsEnabled('doctype')) {\r\n _checkDoctypeIsDefined(this._document);\r\n }\r\n\r\n if (this._checkIsEnabled('theme')) {\r\n _checkThemeIsPresent(this._document, !!platform?.isBrowser);\r\n }\r\n\r\n if (this._checkIsEnabled('version')) {\r\n _checkCdkVersionMatch();\r\n }\r\n }\r\n }\r\n }\r\n\r\n /** Gets whether a specific sanity check is enabled. */\r\n private _checkIsEnabled(name: keyof GranularSanityChecks): boolean {\r\n if (_isTestEnvironment()) {\r\n return false;\r\n }\r\n\r\n if (typeof this._sanityChecks === 'boolean') {\r\n return this._sanityChecks;\r\n }\r\n\r\n return !!this._sanityChecks[name];\r\n }\r\n}\r\n\r\n/** Checks that the page has a doctype. */\r\nfunction _checkDoctypeIsDefined(doc: Document): void {\r\n if (!doc.doctype) {\r\n console.warn(\r\n 'Current document does not have a doctype. This may cause ' +\r\n 'some Angular Material components not to behave as expected.'\r\n );\r\n }\r\n}\r\n\r\n/** Checks that a theme has been included. */\r\nfunction _checkThemeIsPresent(doc: Document, isBrowser: boolean): void {\r\n // We need to assert that the `body` is defined, because these checks run very early\r\n // and the `body` won't be defined if the consumer put their scripts in the `head`.\r\n if (!doc.body || !isBrowser) {\r\n return;\r\n }\r\n\r\n const testElement = doc.createElement('div');\r\n testElement.classList.add('mat-theme-loaded-marker');\r\n doc.body.appendChild(testElement);\r\n\r\n const computedStyle = getComputedStyle(testElement);\r\n\r\n // In some situations the computed style of the test element can be null. For example in\r\n // Firefox, the computed style is null if an application is running inside of a hidden iframe.\r\n // See: https://bugzilla.mozilla.org/show_bug.cgi?id=548397\r\n if (computedStyle && computedStyle.display !== 'none') {\r\n console.warn(\r\n 'Could not find Angular Material core theme. Most Material ' +\r\n 'components may not work as expected. For more info refer ' +\r\n 'to the theming guide: https://material.angular.io/guide/theming'\r\n );\r\n }\r\n\r\n testElement.remove();\r\n}\r\n\r\n/** Checks whether the Material version matches the CDK version. */\r\nfunction _checkCdkVersionMatch(): void {\r\n if (VERSION.full !== CDK_VERSION.full) {\r\n console.warn(\r\n 'The Angular Material version (' +\r\n VERSION.full +\r\n ') does not match ' +\r\n 'the Angular CDK version (' +\r\n CDK_VERSION.full +\r\n ').\\n' +\r\n 'Please ensure the versions of these two packages exactly match.'\r\n );\r\n }\r\n}\r\n", "children": [ { "type": "providers", @@ -50169,13 +50901,13 @@ }, { "name": "OuiTabsModule", - "id": "module-OuiTabsModule-f3299d4f0f78dd7372a1f9f64d79165be29e4960e5b8ca975b7ab5352e24a9012ec17c5838afd27393cbd2d4ba5620a441a1b747ac70c8a2ec105526ef305c6d", + "id": "module-OuiTabsModule-bfa49801c59d126ca70f295adfca55a8db3e821ec755d268e3eb74900a718668b86e3356b088854d6b94c0203c43664807fce61ce7b3455b1c9a74153afa9ecd", "description": "", "deprecationMessage": "", "deprecated": false, "file": "ui/src/components/tabs/module.ts", "methods": [], - "sourceCode": "/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport { CommonModule } from '@angular/common';\nimport { NgModule } from '@angular/core';\nimport { PortalModule } from '@angular/cdk/portal';\nimport { ObserversModule } from '@angular/cdk/observers';\nimport { A11yModule } from '@angular/cdk/a11y';\nimport { OuiTabBodyPortal } from './tab-body';\nimport { OuiTabContent } from './tab-content';\nimport { OuiTabLabel } from './tab-label';\nimport { ouiTabLabelWrapper } from './tab-label-wrapper';\nimport { OuiTab } from './tab';\nimport { OuiTabHeader } from './tab-header';\nimport { ouiTabGroup } from './tab-group';\nimport {\n OuiTabNav,\n ouiTabNavPanel,\n OuiTabLink,\n} from './tab-nav-bar/tab-nav-bar';\nimport { OuiTabBody } from './tab-body';\n\n@NgModule({\n imports: [CommonModule, PortalModule, ObserversModule, A11yModule],\n exports: [\n OuiTabContent,\n OuiTabLabel,\n OuiTab,\n ouiTabGroup,\n OuiTabNav,\n ouiTabNavPanel,\n OuiTabLink,\n OuiTabBodyPortal,\n OuiTabBody,\n ],\n declarations: [\n OuiTabContent,\n OuiTabLabel,\n OuiTab,\n ouiTabGroup,\n OuiTabNav,\n ouiTabNavPanel,\n OuiTabLink,\n\n // Private directives, should not be exported.\n ouiTabLabelWrapper,\n OuiTabHeader,\n OuiTabBody,\n OuiTabBodyPortal,\n ],\n})\nexport class OuiTabsModule {}\n", + "sourceCode": "/**\r\n * @license\r\n * Copyright Google LLC All Rights Reserved.\r\n *\r\n * Use of this source code is governed by an MIT-style license that can be\r\n * found in the LICENSE file at https://angular.io/license\r\n */\r\n\r\nimport { CommonModule } from '@angular/common';\r\nimport { NgModule } from '@angular/core';\r\nimport { PortalModule } from '@angular/cdk/portal';\r\nimport { ObserversModule } from '@angular/cdk/observers';\r\nimport { A11yModule } from '@angular/cdk/a11y';\r\nimport { OuiTabBodyPortal } from './tab-body';\r\nimport { OuiTabContent } from './tab-content';\r\nimport { OuiTabLabel } from './tab-label';\r\nimport { ouiTabLabelWrapper } from './tab-label-wrapper';\r\nimport { OuiTab } from './tab';\r\nimport { OuiTabHeader } from './tab-header';\r\nimport { ouiTabGroup } from './tab-group';\r\nimport {\r\n OuiTabNav,\r\n ouiTabNavPanel,\r\n OuiTabLink,\r\n} from './tab-nav-bar/tab-nav-bar';\r\nimport { OuiTabBody } from './tab-body';\r\n\r\n@NgModule({\r\n imports: [CommonModule, PortalModule, ObserversModule, A11yModule],\r\n exports: [\r\n OuiTabContent,\r\n OuiTabLabel,\r\n OuiTab,\r\n ouiTabGroup,\r\n OuiTabNav,\r\n ouiTabNavPanel,\r\n OuiTabLink,\r\n OuiTabBodyPortal,\r\n OuiTabBody,\r\n ],\r\n declarations: [\r\n OuiTabContent,\r\n OuiTabLabel,\r\n OuiTab,\r\n ouiTabGroup,\r\n OuiTabNav,\r\n ouiTabNavPanel,\r\n OuiTabLink,\r\n\r\n // Private directives, should not be exported.\r\n ouiTabLabelWrapper,\r\n OuiTabHeader,\r\n OuiTabBody,\r\n OuiTabBodyPortal,\r\n ],\r\n})\r\nexport class OuiTabsModule {}\r\n", "children": [ { "type": "providers", @@ -50326,7 +51058,7 @@ "deprecated": false, "deprecationMessage": "", "type": "", - "defaultValue": "(opt: string[], value: string): string[] => {\n const filterValue = value.toLowerCase();\n\n return opt.filter((item) => item.toLowerCase().indexOf(filterValue) === 0);\n}" + "defaultValue": "(opt: string[], value: string): string[] => {\r\n const filterValue = value.toLowerCase();\r\n\r\n return opt.filter((item) => item.toLowerCase().indexOf(filterValue) === 0);\r\n}" }, { "name": "_OUI_INK_BAR_POSITIONER", @@ -50336,7 +51068,7 @@ "deprecated": false, "deprecationMessage": "", "type": "", - "defaultValue": "new InjectionToken<_OuiInkBarPositioner>(\n 'MatInkBarPositioner',\n {\n providedIn: 'root',\n factory: _OUI_INK_BAR_POSITIONER_FACTORY,\n }\n)", + "defaultValue": "new InjectionToken<_OuiInkBarPositioner>(\r\n 'MatInkBarPositioner',\r\n {\r\n providedIn: 'root',\r\n factory: _OUI_INK_BAR_POSITIONER_FACTORY,\r\n }\r\n)", "rawdescription": "Injection token for the OuiInkBar's Positioner.", "description": "

Injection token for the OuiInkBar's Positioner.

\n" }, @@ -50440,7 +51172,7 @@ "deprecated": false, "deprecationMessage": "", "type": "", - "defaultValue": "mixinTabIndex(\n mixinDisabled(mixinErrorState(OuiSelectBase))\n)" + "defaultValue": "mixinTabIndex(\r\n mixinDisabled(mixinErrorState(OuiSelectBase))\r\n)" }, { "name": "_OuiSlideToggleMixinBase", @@ -50480,7 +51212,7 @@ "deprecated": false, "deprecationMessage": "", "type": "", - "defaultValue": "mixinColor(\n mixinDisableRipple(\n class {\n constructor(public _elementRef: ElementRef) {}\n }\n ),\n 'primary'\n)" + "defaultValue": "mixinColor(\r\n mixinDisableRipple(\r\n class {\r\n constructor(public _elementRef: ElementRef) {}\r\n }\r\n ),\r\n 'primary'\r\n)" }, { "name": "_OuiTabLabelWrapperMixinBase", @@ -50490,7 +51222,7 @@ "deprecated": false, "deprecationMessage": "", "type": "", - "defaultValue": "mixinInkBarItem(\n mixinDisabled(\n class {\n elementRef: ElementRef;\n }\n )\n)" + "defaultValue": "mixinInkBarItem(\r\n mixinDisabled(\r\n class {\r\n elementRef: ElementRef;\r\n }\r\n )\r\n)" }, { "name": "_OuiTabLinkMixinBase", @@ -50500,7 +51232,7 @@ "deprecated": false, "deprecationMessage": "", "type": "", - "defaultValue": "mixinInkBarItem(\n mixinTabIndex(\n mixinDisableRipple(\n mixinDisabled(\n class {\n elementRef: ElementRef;\n }\n )\n )\n )\n)" + "defaultValue": "mixinInkBarItem(\r\n mixinTabIndex(\r\n mixinDisableRipple(\r\n mixinDisabled(\r\n class {\r\n elementRef: ElementRef;\r\n }\r\n )\r\n )\r\n )\r\n)" }, { "name": "_OuiTabMixinBase", @@ -50845,7 +51577,7 @@ "deprecationMessage": "", "type": "number", "defaultValue": "650", - "rawdescription": "Amount of milliseconds to wait before starting to scroll the header automatically.\nSet a little conservatively in order to handle fake events dispatched on touch devices.", + "rawdescription": "Amount of milliseconds to wait before starting to scroll the header automatically.\r\nSet a little conservatively in order to handle fake events dispatched on touch devices.", "description": "

Amount of milliseconds to wait before starting to scroll the header automatically.\nSet a little conservatively in order to handle fake events dispatched on touch devices.

\n" }, { @@ -50857,7 +51589,7 @@ "deprecationMessage": "", "type": "number", "defaultValue": "100", - "rawdescription": "Interval in milliseconds at which to scroll the header\nwhile the user is holding their pointer.", + "rawdescription": "Interval in milliseconds at which to scroll the header\r\nwhile the user is holding their pointer.", "description": "

Interval in milliseconds at which to scroll the header\nwhile the user is holding their pointer.

\n" }, { @@ -50932,7 +51664,7 @@ "deprecated": false, "deprecationMessage": "", "type": "", - "defaultValue": "new InjectionToken(\n 'mat-sanity-checks',\n {\n providedIn: 'root',\n factory: MATERIAL_SANITY_CHECKS_FACTORY,\n }\n)", + "defaultValue": "new InjectionToken(\r\n 'mat-sanity-checks',\r\n {\r\n providedIn: 'root',\r\n factory: MATERIAL_SANITY_CHECKS_FACTORY,\r\n }\r\n)", "rawdescription": "Injection token that configures whether the Material sanity checks are enabled.", "description": "

Injection token that configures whether the Material sanity checks are enabled.

\n" }, @@ -51150,7 +51882,7 @@ "deprecated": false, "deprecationMessage": "", "type": "OuiDateFormats", - "defaultValue": "{\n parse: {\n dateInput: null,\n },\n display: {\n dateInput: {\n year: 'numeric',\n day: '2-digit',\n month: '2-digit',\n },\n monthYearLabel: { year: 'numeric', month: 'short' },\n dateA11yLabel: { year: 'numeric', month: 'long', day: 'numeric' },\n monthYearA11yLabel: { year: 'numeric', month: 'long' },\n },\n}" + "defaultValue": "{\r\n parse: {\r\n dateInput: null,\r\n },\r\n display: {\r\n dateInput: {\r\n year: 'numeric',\r\n day: '2-digit',\r\n month: '2-digit',\r\n },\r\n monthYearLabel: { year: 'numeric', month: 'short' },\r\n dateA11yLabel: { year: 'numeric', month: 'long', day: 'numeric' },\r\n monthYearA11yLabel: { year: 'numeric', month: 'long' },\r\n },\r\n}" }, { "name": "OUI_DATE_FORMATS", @@ -51430,7 +52162,7 @@ "deprecated": false, "deprecationMessage": "", "type": "", - "defaultValue": "new InjectionToken<\n () => ScrollStrategy\n>('oui-panel-scroll-strategy')", + "defaultValue": "new InjectionToken<\r\n () => ScrollStrategy\r\n>('oui-panel-scroll-strategy')", "rawdescription": "Injection token that determines the scroll handling while the panel-overlay is open.", "description": "

Injection token that determines the scroll handling while the panel-overlay is open.

\n" }, @@ -51442,7 +52174,7 @@ "deprecated": false, "deprecationMessage": "", "type": "object", - "defaultValue": "{\n provide: OUI_PANEL_SCROLL_STRATEGY,\n deps: [Overlay],\n useFactory: OUI_PANEL_SCROLL_STRATEGY_FACTORY,\n}" + "defaultValue": "{\r\n provide: OUI_PANEL_SCROLL_STRATEGY,\r\n deps: [Overlay],\r\n useFactory: OUI_PANEL_SCROLL_STRATEGY_FACTORY,\r\n}" }, { "name": "OUI_RADIO_GROUP_CONTROL_VALUE_ACCESSOR", @@ -51498,8 +52230,8 @@ "deprecated": false, "deprecationMessage": "", "type": "", - "defaultValue": "new InjectionToken(\n 'OuiTabContent'\n)", - "rawdescription": "Injection token that can be used to reference instances of `OuiTabContent`. It serves as\nalternative token to the actual `OuiTabContent` class which could cause unnecessary\nretention of the class and its directive metadata.", + "defaultValue": "new InjectionToken(\r\n 'OuiTabContent'\r\n)", + "rawdescription": "Injection token that can be used to reference instances of `OuiTabContent`. It serves as\r\nalternative token to the actual `OuiTabContent` class which could cause unnecessary\r\nretention of the class and its directive metadata.", "description": "

Injection token that can be used to reference instances of OuiTabContent. It serves as\nalternative token to the actual OuiTabContent class which could cause unnecessary\nretention of the class and its directive metadata.

\n" }, { @@ -51523,7 +52255,7 @@ "deprecationMessage": "", "type": "", "defaultValue": "new InjectionToken('OuiTabLabel')", - "rawdescription": "Injection token that can be used to reference instances of `OuiTabLabel`. It serves as\nalternative token to the actual `OuiTabLabel` class which could cause unnecessary\nretention of the class and its directive metadata.", + "rawdescription": "Injection token that can be used to reference instances of `OuiTabLabel`. It serves as\r\nalternative token to the actual `OuiTabLabel` class which could cause unnecessary\r\nretention of the class and its directive metadata.", "description": "

Injection token that can be used to reference instances of OuiTabLabel. It serves as\nalternative token to the actual OuiTabLabel class which could cause unnecessary\nretention of the class and its directive metadata.

\n" }, { @@ -51534,7 +52266,7 @@ "deprecated": false, "deprecationMessage": "", "type": "", - "defaultValue": "new InjectionToken(\n 'OUI_TABS_CONFIG'\n)", + "defaultValue": "new InjectionToken(\r\n 'OUI_TABS_CONFIG'\r\n)", "rawdescription": "Injection token that can be used to provide the default options the tabs module.", "description": "

Injection token that can be used to provide the default options the tabs module.

\n" }, @@ -51644,7 +52376,7 @@ "deprecated": false, "deprecationMessage": "", "type": "literal type", - "defaultValue": "{\n /** Animation translates a tab along the X axis. */\n translateTab: trigger('translateTab', [\n // Transitions to `none` instead of 0, because some browsers might blur the content.\n state(\n 'center, void, left-origin-center, right-origin-center',\n style({ transform: 'none' })\n ),\n\n // If the tab is either on the left or right, we additionally add a `min-height` of 1px\n // in order to ensure that the element has a height before its state changes. This is\n // necessary because Chrome does seem to skip the transition in RTL mode if the element does\n // not have a static height and is not rendered. See related issue: #9465\n state(\n 'left',\n style({\n transform: 'translate3d(-100%, 0, 0)',\n minHeight: '1px',\n\n // Normally this is redundant since we detach the content from the DOM, but if the user\n // opted into keeping the content in the DOM, we have to hide it so it isn't focusable.\n visibility: 'hidden',\n })\n ),\n state(\n 'right',\n style({\n transform: 'translate3d(100%, 0, 0)',\n minHeight: '1px',\n visibility: 'hidden',\n })\n ),\n\n transition(\n '* => left, * => right, left => center, right => center',\n animate('{{animationDuration}} cubic-bezier(0.35, 0, 0.25, 1)')\n ),\n transition('void => left-origin-center', [\n style({ transform: 'translate3d(-100%, 0, 0)', visibility: 'hidden' }),\n animate('{{animationDuration}} cubic-bezier(0.35, 0, 0.25, 1)'),\n ]),\n transition('void => right-origin-center', [\n style({ transform: 'translate3d(100%, 0, 0)', visibility: 'hidden' }),\n animate('{{animationDuration}} cubic-bezier(0.35, 0, 0.25, 1)'),\n ]),\n ]),\n}", + "defaultValue": "{\r\n /** Animation translates a tab along the X axis. */\r\n translateTab: trigger('translateTab', [\r\n // Transitions to `none` instead of 0, because some browsers might blur the content.\r\n state(\r\n 'center, void, left-origin-center, right-origin-center',\r\n style({ transform: 'none' })\r\n ),\r\n\r\n // If the tab is either on the left or right, we additionally add a `min-height` of 1px\r\n // in order to ensure that the element has a height before its state changes. This is\r\n // necessary because Chrome does seem to skip the transition in RTL mode if the element does\r\n // not have a static height and is not rendered. See related issue: #9465\r\n state(\r\n 'left',\r\n style({\r\n transform: 'translate3d(-100%, 0, 0)',\r\n minHeight: '1px',\r\n\r\n // Normally this is redundant since we detach the content from the DOM, but if the user\r\n // opted into keeping the content in the DOM, we have to hide it so it isn't focusable.\r\n visibility: 'hidden',\r\n })\r\n ),\r\n state(\r\n 'right',\r\n style({\r\n transform: 'translate3d(100%, 0, 0)',\r\n minHeight: '1px',\r\n visibility: 'hidden',\r\n })\r\n ),\r\n\r\n transition(\r\n '* => left, * => right, left => center, right => center',\r\n animate('{{animationDuration}} cubic-bezier(0.35, 0, 0.25, 1)')\r\n ),\r\n transition('void => left-origin-center', [\r\n style({ transform: 'translate3d(-100%, 0, 0)', visibility: 'hidden' }),\r\n animate('{{animationDuration}} cubic-bezier(0.35, 0, 0.25, 1)'),\r\n ]),\r\n transition('void => right-origin-center', [\r\n style({ transform: 'translate3d(100%, 0, 0)', visibility: 'hidden' }),\r\n animate('{{animationDuration}} cubic-bezier(0.35, 0, 0.25, 1)'),\r\n ]),\r\n ]),\r\n}", "rawdescription": "Animations used by the Material tabs.", "description": "

Animations used by the Material tabs.

\n" }, @@ -51698,7 +52430,7 @@ "deprecated": false, "deprecationMessage": "", "type": "", - "defaultValue": "normalizePassiveListenerOptions({\n passive: true,\n}) as EventListenerOptions", + "defaultValue": "normalizePassiveListenerOptions({\r\n passive: true,\r\n}) as EventListenerOptions", "rawdescription": "Config used to bind passive event listeners", "description": "

Config used to bind passive event listeners

\n" }, @@ -51745,7 +52477,7 @@ "deprecationMessage": "", "type": "number", "defaultValue": "0", - "rawdescription": "Distance between the panel edge and the option text in\nmulti-selection mode.\n\nCalculated as:\n(SELECT_PANEL_PADDING_X * 1.5) + 20 = 44\nThe padding is multiplied by 1.5 because the checkbox's margin is half the padding.\nThe checkbox width is 16px.", + "rawdescription": "Distance between the panel edge and the option text in\r\nmulti-selection mode.\r\n\r\nCalculated as:\r\n(SELECT_PANEL_PADDING_X * 1.5) + 20 = 44\r\nThe padding is multiplied by 1.5 because the checkbox's margin is half the padding.\r\nThe checkbox width is 16px.", "description": "

Distance between the panel edge and the option text in\nmulti-selection mode.

\n

Calculated as:\n(SELECT_PANEL_PADDING_X * 1.5) + 20 = 44\nThe padding is multiplied by 1.5 because the checkbox's margin is half the padding.\nThe checkbox width is 16px.

\n" }, { @@ -51757,7 +52489,7 @@ "deprecationMessage": "", "type": "number", "defaultValue": "40", - "rawdescription": "The following style constants are necessary to save here in order\nto properly calculate the alignment of the selected option over\nthe trigger element.", + "rawdescription": "The following style constants are necessary to save here in order\r\nto properly calculate the alignment of the selected option over\r\nthe trigger element.", "description": "

The following style constants are necessary to save here in order\nto properly calculate the alignment of the selected option over\nthe trigger element.

\n" }, { @@ -51805,7 +52537,7 @@ "deprecationMessage": "", "type": "number", "defaultValue": "8", - "rawdescription": "The select panel will only \"fit\" inside the viewport if it is positioned at\nthis value or more away from the viewport boundary.", + "rawdescription": "The select panel will only \"fit\" inside the viewport if it is positioned at\r\nthis value or more away from the viewport boundary.", "description": "

The select panel will only "fit" inside the viewport if it is positioned at\nthis value or more away from the viewport boundary.

\n" }, { @@ -51986,10 +52718,10 @@ "name": { "pos": 13828, "end": 13834, - "flags": 4194304, + "flags": 16777216, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "config" }, "type": "OuiDialogConfig", @@ -51999,10 +52731,10 @@ "tagName": { "pos": 13822, "end": 13827, - "flags": 4194304, + "flags": 16777216, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "param" }, "comment": "

Config to be modified.

\n" @@ -52011,10 +52743,10 @@ "name": { "pos": 13868, "end": 13882, - "flags": 4194304, + "flags": 16777216, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "defaultOptions" }, "type": "OuiDialogConfig", @@ -52024,10 +52756,10 @@ "tagName": { "pos": 13862, "end": 13867, - "flags": 4194304, + "flags": 16777216, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "param" }, "comment": "

Default options provided.

\n" @@ -52036,10 +52768,10 @@ "tagName": { "pos": 13913, "end": 13920, - "flags": 4194304, + "flags": 16777216, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "returns" }, "comment": "

The new configuration object.

\n" @@ -52164,10 +52896,10 @@ "name": { "pos": 8577, "end": 8588, - "flags": 4194304, + "flags": 16777216, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "optionIndex" }, "type": "number", @@ -52176,10 +52908,10 @@ "tagName": { "pos": 8571, "end": 8576, - "flags": 4194304, + "flags": 16777216, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "param" }, "comment": "

Index of the option at which to start counting.

\n" @@ -52188,10 +52920,10 @@ "name": { "pos": 8647, "end": 8654, - "flags": 4194304, + "flags": 16777216, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "options" }, "type": "QueryList", @@ -52200,10 +52932,10 @@ "tagName": { "pos": 8641, "end": 8646, - "flags": 4194304, + "flags": 16777216, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "param" }, "comment": "

Flat list of all of the options.

\n" @@ -52212,10 +52944,10 @@ "name": { "pos": 8698, "end": 8710, - "flags": 4194304, + "flags": 16777216, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "optionGroups" }, "type": "QueryList", @@ -52224,10 +52956,10 @@ "tagName": { "pos": 8692, "end": 8697, - "flags": 4194304, + "flags": 16777216, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "param" }, "comment": "

Flat list of all of the option groups.

\n" @@ -52274,10 +53006,10 @@ "name": { "pos": 9417, "end": 9428, - "flags": 4194304, + "flags": 16777216, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "optionIndex" }, "type": "number", @@ -52286,10 +53018,10 @@ "tagName": { "pos": 9411, "end": 9416, - "flags": 4194304, + "flags": 16777216, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "param" }, "comment": "

Index of the option to be scrolled into the view.

\n" @@ -52298,10 +53030,10 @@ "name": { "pos": 9489, "end": 9501, - "flags": 4194304, + "flags": 16777216, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "optionHeight" }, "type": "number", @@ -52310,10 +53042,10 @@ "tagName": { "pos": 9483, "end": 9488, - "flags": 4194304, + "flags": 16777216, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "param" }, "comment": "

Height of the options.

\n" @@ -52322,10 +53054,10 @@ "name": { "pos": 9535, "end": 9556, - "flags": 4194304, + "flags": 16777216, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "currentScrollPosition" }, "type": "number", @@ -52334,10 +53066,10 @@ "tagName": { "pos": 9529, "end": 9534, - "flags": 4194304, + "flags": 16777216, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "param" }, "comment": "

Current scroll position of the panel.

\n" @@ -52346,10 +53078,10 @@ "name": { "pos": 9605, "end": 9616, - "flags": 4194304, + "flags": 16777216, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "panelHeight" }, "type": "number", @@ -52358,10 +53090,10 @@ "tagName": { "pos": 9599, "end": 9604, - "flags": 4194304, + "flags": 16777216, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "param" }, "comment": "

Height of the panel.

\n" @@ -52952,10 +53684,10 @@ "name": { "pos": 10099, "end": 10106, - "flags": 4194304, + "flags": 16777216, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "element" }, "type": "ElementRef", @@ -52964,10 +53696,10 @@ "tagName": { "pos": 10093, "end": 10098, - "flags": 4194304, + "flags": 16777216, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "param" }, "comment": "

Element relative to which to look for a dialog.

\n" @@ -52976,10 +53708,10 @@ "name": { "pos": 10165, "end": 10176, - "flags": 4194304, + "flags": 16777216, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "openDialogs" }, "deprecated": false, @@ -52987,10 +53719,10 @@ "tagName": { "pos": 10159, "end": 10164, - "flags": 4194304, + "flags": 16777216, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "param" }, "comment": "

References to the currently-open dialogs.

\n" @@ -53099,10 +53831,10 @@ "name": { "pos": 1649, "end": 1656, - "flags": 4194304, + "flags": 16777216, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "literal" }, "type": "SafeHtml", @@ -53111,10 +53843,10 @@ "tagName": { "pos": 1643, "end": 1648, - "flags": 4194304, + "flags": 16777216, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "param" }, "comment": "

HTML that was attempted to be sanitized.

\n" @@ -53143,10 +53875,10 @@ "name": { "pos": 1235, "end": 1238, - "flags": 4194304, + "flags": 16777216, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "url" }, "type": "SafeResourceUrl", @@ -53155,10 +53887,10 @@ "tagName": { "pos": 1229, "end": 1234, - "flags": 4194304, + "flags": 16777216, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "param" }, "comment": "

URL that was attempted to be sanitized.

\n" @@ -53201,7 +53933,7 @@ "subtype": "function", "deprecated": false, "deprecationMessage": "", - "description": "

Returns an exception to be thrown when the consumer attempts to use\n<oui-icon> without including @angular/http.

\n", + "description": "

Returns an exception to be thrown when the consumer attempts to use\n<oui-icon> without including

\n", "args": [], "returnType": "Error" }, @@ -54236,7 +54968,7 @@ "deprecated": false, "deprecationMessage": "", "description": "", - "kind": 179 + "kind": 185 }, { "name": "ArrowViewState", @@ -54247,7 +54979,7 @@ "deprecated": false, "deprecationMessage": "", "description": "

Valid positions for the arrow to be in for its opacity and translation. If the state is a\nsort direction, the position of the arrow will be above/below and opacity 0. If the state is\nhint, the arrow will be in the center with a slight opacity. Active state means the arrow will\nbe fully opaque in the center.

\n", - "kind": 186 + "kind": 192 }, { "name": "CanColorCtor", @@ -54258,7 +54990,7 @@ "deprecated": false, "deprecationMessage": "", "description": "", - "kind": 177 + "kind": 183 }, { "name": "CanDisableCtor", @@ -54269,7 +55001,7 @@ "deprecated": false, "deprecationMessage": "", "description": "", - "kind": 177 + "kind": 183 }, { "name": "CanDisableRippleCtor", @@ -54280,7 +55012,7 @@ "deprecated": false, "deprecationMessage": "", "description": "", - "kind": 187 + "kind": 193 }, { "name": "CanProgressCtor", @@ -54291,7 +55023,7 @@ "deprecated": false, "deprecationMessage": "", "description": "", - "kind": 177 + "kind": 183 }, { "name": "CanUpdateErrorStateCtor", @@ -54302,7 +55034,7 @@ "deprecated": false, "deprecationMessage": "", "description": "", - "kind": 177 + "kind": 183 }, { "name": "Constructor", @@ -54313,7 +55045,7 @@ "deprecated": false, "deprecationMessage": "", "description": "", - "kind": 179 + "kind": 185 }, { "name": "HasInitializedCtor", @@ -54324,7 +55056,7 @@ "deprecated": false, "deprecationMessage": "", "description": "", - "kind": 177 + "kind": 183 }, { "name": "HasTabIndexCtor", @@ -54335,7 +55067,7 @@ "deprecated": false, "deprecationMessage": "", "description": "", - "kind": 177 + "kind": 183 }, { "name": "MatPaginatedTabHeaderItem", @@ -54346,7 +55078,7 @@ "deprecated": false, "deprecationMessage": "", "description": "

Item inside a paginated tab header.

\n", - "kind": 187 + "kind": 193 }, { "name": "MenuPositionX", @@ -54357,7 +55089,7 @@ "deprecated": false, "deprecationMessage": "", "description": "", - "kind": 186 + "kind": 192 }, { "name": "MenuPositionY", @@ -54368,7 +55100,7 @@ "deprecated": false, "deprecationMessage": "", "description": "", - "kind": 186 + "kind": 192 }, { "name": "OuiCalendarCellCssClasses", @@ -54379,7 +55111,7 @@ "deprecated": false, "deprecationMessage": "", "description": "

Extra CSS classes that can be associated with a calendar cell.

\n", - "kind": 186 + "kind": 192 }, { "name": "OuiCalendarView", @@ -54390,7 +55122,7 @@ "deprecated": false, "deprecationMessage": "", "description": "

Possible views for the calendar.

\n", - "kind": 186 + "kind": 192 }, { "name": "OuiDateFormats", @@ -54401,7 +55133,7 @@ "deprecated": false, "deprecationMessage": "", "description": "", - "kind": 181 + "kind": 187 }, { "name": "OuiFormFieldAppearance", @@ -54412,7 +55144,7 @@ "deprecated": false, "deprecationMessage": "", "description": "

Possible appearance styles for the form field.

\n", - "kind": 186 + "kind": 192 }, { "name": "OuiPseudoCheckboxState", @@ -54423,7 +55155,7 @@ "deprecated": false, "deprecationMessage": "", "description": "

Possible states for a pseudo checkbox.

\n", - "kind": 186 + "kind": 192 }, { "name": "OuiTabBodyOriginState", @@ -54434,7 +55166,7 @@ "deprecated": false, "deprecationMessage": "", "description": "

The origin state is an internally used state that is set on a new tab body indicating if it\nbegan to the left or right of the prior selected index. For example, if the selected index was\nset to 1, and a new tab is created and selected at index 2, then the tab body would have an\norigin of right because its index was greater than the prior selected index.

\n", - "kind": 186 + "kind": 192 }, { "name": "OuiTabBodyPositionState", @@ -54445,7 +55177,7 @@ "deprecated": false, "deprecationMessage": "", "description": "

These position states are used internally as animation states for the tab body. Setting the\nposition state to left, right, or center will transition the tab body from its current\nposition to its respective state. If there is not current position (void, in the case of a new\ntab body), then there will be no transition animation to its state.

\n

In the case of a new tab body that should immediately be centered with an animating transition,\nthen left-origin-center or right-origin-center can be used, which will use left or right as its\npseudo-prior state.

\n", - "kind": 186 + "kind": 192 }, { "name": "OuiTabHeaderPosition", @@ -54456,7 +55188,7 @@ "deprecated": false, "deprecationMessage": "", "description": "

Possible positions for the tab header.

\n", - "kind": 186 + "kind": 192 }, { "name": "PanelPositionX", @@ -54467,7 +55199,7 @@ "deprecated": false, "deprecationMessage": "", "description": "", - "kind": 186 + "kind": 192 }, { "name": "PanelPositionY", @@ -54478,7 +55210,7 @@ "deprecated": false, "deprecationMessage": "", "description": "", - "kind": 186 + "kind": 192 }, { "name": "ProgressBarMode", @@ -54489,7 +55221,7 @@ "deprecated": false, "deprecationMessage": "", "description": "

Possible mode for a progress spinner.

\n", - "kind": 186 + "kind": 192 }, { "name": "ProgressSpinnerMode", @@ -54500,7 +55232,7 @@ "deprecated": false, "deprecationMessage": "", "description": "

Possible mode for a progress spinner.

\n", - "kind": 186 + "kind": 192 }, { "name": "PublicApi", @@ -54511,7 +55243,7 @@ "deprecated": false, "deprecationMessage": "", "description": "", - "kind": 194 + "kind": 200 }, { "name": "SanityChecks", @@ -54522,7 +55254,7 @@ "deprecated": false, "deprecationMessage": "", "description": "

Possible sanity checks that can be enabled. If set to\ntrue/false, all checks will be enabled/disabled.

\n", - "kind": 186 + "kind": 192 }, { "name": "ScrollDirection", @@ -54533,7 +55265,7 @@ "deprecated": false, "deprecationMessage": "", "description": "

The directions that scrolling can go in when the header's tabs exceed the header width. 'After'\nwill scroll the header towards the end of the tabs list and 'before' will scroll towards the\nbeginning of the list.

\n", - "kind": 186 + "kind": 192 }, { "name": "SortDirection", @@ -54544,7 +55276,7 @@ "deprecated": false, "deprecationMessage": "", "description": "", - "kind": 186 + "kind": 192 }, { "name": "ThemePalette", @@ -54555,7 +55287,7 @@ "deprecated": false, "deprecationMessage": "", "description": "

Possible color palette values.

\n", - "kind": 186 + "kind": 192 }, { "name": "TooltipPosition", @@ -54566,7 +55298,7 @@ "deprecated": false, "deprecationMessage": "", "description": "", - "kind": 186 + "kind": 192 }, { "name": "TooltipVisibility", @@ -54577,7 +55309,7 @@ "deprecated": false, "deprecationMessage": "", "description": "", - "kind": 186 + "kind": 192 } ], "enumerations": [ @@ -54659,7 +55391,7 @@ "deprecated": false, "deprecationMessage": "", "type": "", - "defaultValue": "(opt: string[], value: string): string[] => {\n const filterValue = value.toLowerCase();\n\n return opt.filter((item) => item.toLowerCase().indexOf(filterValue) === 0);\n}" + "defaultValue": "(opt: string[], value: string): string[] => {\r\n const filterValue = value.toLowerCase();\r\n\r\n return opt.filter((item) => item.toLowerCase().indexOf(filterValue) === 0);\r\n}" } ], "ui/src/components/tabs/ink-bar.ts": [ @@ -54671,7 +55403,7 @@ "deprecated": false, "deprecationMessage": "", "type": "", - "defaultValue": "new InjectionToken<_OuiInkBarPositioner>(\n 'MatInkBarPositioner',\n {\n providedIn: 'root',\n factory: _OUI_INK_BAR_POSITIONER_FACTORY,\n }\n)", + "defaultValue": "new InjectionToken<_OuiInkBarPositioner>(\r\n 'MatInkBarPositioner',\r\n {\r\n providedIn: 'root',\r\n factory: _OUI_INK_BAR_POSITIONER_FACTORY,\r\n }\r\n)", "rawdescription": "Injection token for the OuiInkBar's Positioner.", "description": "

Injection token for the OuiInkBar's Positioner.

\n" }, @@ -54963,7 +55695,7 @@ "deprecated": false, "deprecationMessage": "", "type": "", - "defaultValue": "mixinTabIndex(\n mixinDisabled(mixinErrorState(OuiSelectBase))\n)" + "defaultValue": "mixinTabIndex(\r\n mixinDisabled(mixinErrorState(OuiSelectBase))\r\n)" }, { "name": "nextUniqueId", @@ -54996,7 +55728,7 @@ "deprecationMessage": "", "type": "number", "defaultValue": "0", - "rawdescription": "Distance between the panel edge and the option text in\nmulti-selection mode.\n\nCalculated as:\n(SELECT_PANEL_PADDING_X * 1.5) + 20 = 44\nThe padding is multiplied by 1.5 because the checkbox's margin is half the padding.\nThe checkbox width is 16px.", + "rawdescription": "Distance between the panel edge and the option text in\r\nmulti-selection mode.\r\n\r\nCalculated as:\r\n(SELECT_PANEL_PADDING_X * 1.5) + 20 = 44\r\nThe padding is multiplied by 1.5 because the checkbox's margin is half the padding.\r\nThe checkbox width is 16px.", "description": "

Distance between the panel edge and the option text in\nmulti-selection mode.

\n

Calculated as:\n(SELECT_PANEL_PADDING_X * 1.5) + 20 = 44\nThe padding is multiplied by 1.5 because the checkbox's margin is half the padding.\nThe checkbox width is 16px.

\n" }, { @@ -55008,7 +55740,7 @@ "deprecationMessage": "", "type": "number", "defaultValue": "40", - "rawdescription": "The following style constants are necessary to save here in order\nto properly calculate the alignment of the selected option over\nthe trigger element.", + "rawdescription": "The following style constants are necessary to save here in order\r\nto properly calculate the alignment of the selected option over\r\nthe trigger element.", "description": "

The following style constants are necessary to save here in order\nto properly calculate the alignment of the selected option over\nthe trigger element.

\n" }, { @@ -55056,7 +55788,7 @@ "deprecationMessage": "", "type": "number", "defaultValue": "8", - "rawdescription": "The select panel will only \"fit\" inside the viewport if it is positioned at\nthis value or more away from the viewport boundary.", + "rawdescription": "The select panel will only \"fit\" inside the viewport if it is positioned at\r\nthis value or more away from the viewport boundary.", "description": "

The select panel will only "fit" inside the viewport if it is positioned at\nthis value or more away from the viewport boundary.

\n" } ], @@ -55127,7 +55859,7 @@ "deprecated": false, "deprecationMessage": "", "type": "", - "defaultValue": "mixinColor(\n mixinDisableRipple(\n class {\n constructor(public _elementRef: ElementRef) {}\n }\n ),\n 'primary'\n)" + "defaultValue": "mixinColor(\r\n mixinDisableRipple(\r\n class {\r\n constructor(public _elementRef: ElementRef) {}\r\n }\r\n ),\r\n 'primary'\r\n)" }, { "name": "nextId", @@ -55151,7 +55883,7 @@ "deprecated": false, "deprecationMessage": "", "type": "", - "defaultValue": "mixinInkBarItem(\n mixinDisabled(\n class {\n elementRef: ElementRef;\n }\n )\n)" + "defaultValue": "mixinInkBarItem(\r\n mixinDisabled(\r\n class {\r\n elementRef: ElementRef;\r\n }\r\n )\r\n)" } ], "ui/src/components/tabs/tab-nav-bar/tab-nav-bar.ts": [ @@ -55163,7 +55895,7 @@ "deprecated": false, "deprecationMessage": "", "type": "", - "defaultValue": "mixinInkBarItem(\n mixinTabIndex(\n mixinDisableRipple(\n mixinDisabled(\n class {\n elementRef: ElementRef;\n }\n )\n )\n )\n)" + "defaultValue": "mixinInkBarItem(\r\n mixinTabIndex(\r\n mixinDisableRipple(\r\n mixinDisabled(\r\n class {\r\n elementRef: ElementRef;\r\n }\r\n )\r\n )\r\n )\r\n)" }, { "name": "nextUniqueId", @@ -55698,7 +56430,7 @@ "deprecationMessage": "", "type": "number", "defaultValue": "650", - "rawdescription": "Amount of milliseconds to wait before starting to scroll the header automatically.\nSet a little conservatively in order to handle fake events dispatched on touch devices.", + "rawdescription": "Amount of milliseconds to wait before starting to scroll the header automatically.\r\nSet a little conservatively in order to handle fake events dispatched on touch devices.", "description": "

Amount of milliseconds to wait before starting to scroll the header automatically.\nSet a little conservatively in order to handle fake events dispatched on touch devices.

\n" }, { @@ -55710,7 +56442,7 @@ "deprecationMessage": "", "type": "number", "defaultValue": "100", - "rawdescription": "Interval in milliseconds at which to scroll the header\nwhile the user is holding their pointer.", + "rawdescription": "Interval in milliseconds at which to scroll the header\r\nwhile the user is holding their pointer.", "description": "

Interval in milliseconds at which to scroll the header\nwhile the user is holding their pointer.

\n" }, { @@ -55721,7 +56453,7 @@ "deprecated": false, "deprecationMessage": "", "type": "", - "defaultValue": "normalizePassiveListenerOptions({\n passive: true,\n}) as EventListenerOptions", + "defaultValue": "normalizePassiveListenerOptions({\r\n passive: true,\r\n}) as EventListenerOptions", "rawdescription": "Config used to bind passive event listeners", "description": "

Config used to bind passive event listeners

\n" } @@ -55747,7 +56479,7 @@ "deprecated": false, "deprecationMessage": "", "type": "", - "defaultValue": "new InjectionToken(\n 'mat-sanity-checks',\n {\n providedIn: 'root',\n factory: MATERIAL_SANITY_CHECKS_FACTORY,\n }\n)", + "defaultValue": "new InjectionToken(\r\n 'mat-sanity-checks',\r\n {\r\n providedIn: 'root',\r\n factory: MATERIAL_SANITY_CHECKS_FACTORY,\r\n }\r\n)", "rawdescription": "Injection token that configures whether the Material sanity checks are enabled.", "description": "

Injection token that configures whether the Material sanity checks are enabled.

\n" } @@ -55925,7 +56657,7 @@ "deprecated": false, "deprecationMessage": "", "type": "OuiDateFormats", - "defaultValue": "{\n parse: {\n dateInput: null,\n },\n display: {\n dateInput: {\n year: 'numeric',\n day: '2-digit',\n month: '2-digit',\n },\n monthYearLabel: { year: 'numeric', month: 'short' },\n dateA11yLabel: { year: 'numeric', month: 'long', day: 'numeric' },\n monthYearA11yLabel: { year: 'numeric', month: 'long' },\n },\n}" + "defaultValue": "{\r\n parse: {\r\n dateInput: null,\r\n },\r\n display: {\r\n dateInput: {\r\n year: 'numeric',\r\n day: '2-digit',\r\n month: '2-digit',\r\n },\r\n monthYearLabel: { year: 'numeric', month: 'short' },\r\n dateA11yLabel: { year: 'numeric', month: 'long', day: 'numeric' },\r\n monthYearA11yLabel: { year: 'numeric', month: 'long' },\r\n },\r\n}" } ], "ui/src/components/datepicker/date-formats.ts": [ @@ -56141,7 +56873,7 @@ "deprecated": false, "deprecationMessage": "", "type": "", - "defaultValue": "new InjectionToken<\n () => ScrollStrategy\n>('oui-panel-scroll-strategy')", + "defaultValue": "new InjectionToken<\r\n () => ScrollStrategy\r\n>('oui-panel-scroll-strategy')", "rawdescription": "Injection token that determines the scroll handling while the panel-overlay is open.", "description": "

Injection token that determines the scroll handling while the panel-overlay is open.

\n" }, @@ -56153,7 +56885,7 @@ "deprecated": false, "deprecationMessage": "", "type": "object", - "defaultValue": "{\n provide: OUI_PANEL_SCROLL_STRATEGY,\n deps: [Overlay],\n useFactory: OUI_PANEL_SCROLL_STRATEGY_FACTORY,\n}" + "defaultValue": "{\r\n provide: OUI_PANEL_SCROLL_STRATEGY,\r\n deps: [Overlay],\r\n useFactory: OUI_PANEL_SCROLL_STRATEGY_FACTORY,\r\n}" } ], "ui/src/components/sort/sort-header-intl.ts": [ @@ -56190,7 +56922,7 @@ "deprecationMessage": "", "type": "", "defaultValue": "new InjectionToken('OuiTabLabel')", - "rawdescription": "Injection token that can be used to reference instances of `OuiTabLabel`. It serves as\nalternative token to the actual `OuiTabLabel` class which could cause unnecessary\nretention of the class and its directive metadata.", + "rawdescription": "Injection token that can be used to reference instances of `OuiTabLabel`. It serves as\r\nalternative token to the actual `OuiTabLabel` class which could cause unnecessary\r\nretention of the class and its directive metadata.", "description": "

Injection token that can be used to reference instances of OuiTabLabel. It serves as\nalternative token to the actual OuiTabLabel class which could cause unnecessary\nretention of the class and its directive metadata.

\n" } ], @@ -56203,8 +56935,8 @@ "deprecated": false, "deprecationMessage": "", "type": "", - "defaultValue": "new InjectionToken(\n 'OuiTabContent'\n)", - "rawdescription": "Injection token that can be used to reference instances of `OuiTabContent`. It serves as\nalternative token to the actual `OuiTabContent` class which could cause unnecessary\nretention of the class and its directive metadata.", + "defaultValue": "new InjectionToken(\r\n 'OuiTabContent'\r\n)", + "rawdescription": "Injection token that can be used to reference instances of `OuiTabContent`. It serves as\r\nalternative token to the actual `OuiTabContent` class which could cause unnecessary\r\nretention of the class and its directive metadata.", "description": "

Injection token that can be used to reference instances of OuiTabContent. It serves as\nalternative token to the actual OuiTabContent class which could cause unnecessary\nretention of the class and its directive metadata.

\n" } ], @@ -56217,7 +56949,7 @@ "deprecated": false, "deprecationMessage": "", "type": "", - "defaultValue": "new InjectionToken(\n 'OUI_TABS_CONFIG'\n)", + "defaultValue": "new InjectionToken(\r\n 'OUI_TABS_CONFIG'\r\n)", "rawdescription": "Injection token that can be used to provide the default options the tabs module.", "description": "

Injection token that can be used to provide the default options the tabs module.

\n" } @@ -56329,7 +57061,7 @@ "deprecated": false, "deprecationMessage": "", "type": "literal type", - "defaultValue": "{\n /** Animation translates a tab along the X axis. */\n translateTab: trigger('translateTab', [\n // Transitions to `none` instead of 0, because some browsers might blur the content.\n state(\n 'center, void, left-origin-center, right-origin-center',\n style({ transform: 'none' })\n ),\n\n // If the tab is either on the left or right, we additionally add a `min-height` of 1px\n // in order to ensure that the element has a height before its state changes. This is\n // necessary because Chrome does seem to skip the transition in RTL mode if the element does\n // not have a static height and is not rendered. See related issue: #9465\n state(\n 'left',\n style({\n transform: 'translate3d(-100%, 0, 0)',\n minHeight: '1px',\n\n // Normally this is redundant since we detach the content from the DOM, but if the user\n // opted into keeping the content in the DOM, we have to hide it so it isn't focusable.\n visibility: 'hidden',\n })\n ),\n state(\n 'right',\n style({\n transform: 'translate3d(100%, 0, 0)',\n minHeight: '1px',\n visibility: 'hidden',\n })\n ),\n\n transition(\n '* => left, * => right, left => center, right => center',\n animate('{{animationDuration}} cubic-bezier(0.35, 0, 0.25, 1)')\n ),\n transition('void => left-origin-center', [\n style({ transform: 'translate3d(-100%, 0, 0)', visibility: 'hidden' }),\n animate('{{animationDuration}} cubic-bezier(0.35, 0, 0.25, 1)'),\n ]),\n transition('void => right-origin-center', [\n style({ transform: 'translate3d(100%, 0, 0)', visibility: 'hidden' }),\n animate('{{animationDuration}} cubic-bezier(0.35, 0, 0.25, 1)'),\n ]),\n ]),\n}", + "defaultValue": "{\r\n /** Animation translates a tab along the X axis. */\r\n translateTab: trigger('translateTab', [\r\n // Transitions to `none` instead of 0, because some browsers might blur the content.\r\n state(\r\n 'center, void, left-origin-center, right-origin-center',\r\n style({ transform: 'none' })\r\n ),\r\n\r\n // If the tab is either on the left or right, we additionally add a `min-height` of 1px\r\n // in order to ensure that the element has a height before its state changes. This is\r\n // necessary because Chrome does seem to skip the transition in RTL mode if the element does\r\n // not have a static height and is not rendered. See related issue: #9465\r\n state(\r\n 'left',\r\n style({\r\n transform: 'translate3d(-100%, 0, 0)',\r\n minHeight: '1px',\r\n\r\n // Normally this is redundant since we detach the content from the DOM, but if the user\r\n // opted into keeping the content in the DOM, we have to hide it so it isn't focusable.\r\n visibility: 'hidden',\r\n })\r\n ),\r\n state(\r\n 'right',\r\n style({\r\n transform: 'translate3d(100%, 0, 0)',\r\n minHeight: '1px',\r\n visibility: 'hidden',\r\n })\r\n ),\r\n\r\n transition(\r\n '* => left, * => right, left => center, right => center',\r\n animate('{{animationDuration}} cubic-bezier(0.35, 0, 0.25, 1)')\r\n ),\r\n transition('void => left-origin-center', [\r\n style({ transform: 'translate3d(-100%, 0, 0)', visibility: 'hidden' }),\r\n animate('{{animationDuration}} cubic-bezier(0.35, 0, 0.25, 1)'),\r\n ]),\r\n transition('void => right-origin-center', [\r\n style({ transform: 'translate3d(100%, 0, 0)', visibility: 'hidden' }),\r\n animate('{{animationDuration}} cubic-bezier(0.35, 0, 0.25, 1)'),\r\n ]),\r\n ]),\r\n}", "rawdescription": "Animations used by the Material tabs.", "description": "

Animations used by the Material tabs.

\n" } @@ -56449,10 +57181,10 @@ "name": { "pos": 13828, "end": 13834, - "flags": 4194304, + "flags": 16777216, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "config" }, "type": "OuiDialogConfig", @@ -56462,10 +57194,10 @@ "tagName": { "pos": 13822, "end": 13827, - "flags": 4194304, + "flags": 16777216, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "param" }, "comment": "

Config to be modified.

\n" @@ -56474,10 +57206,10 @@ "name": { "pos": 13868, "end": 13882, - "flags": 4194304, + "flags": 16777216, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "defaultOptions" }, "type": "OuiDialogConfig", @@ -56487,10 +57219,10 @@ "tagName": { "pos": 13862, "end": 13867, - "flags": 4194304, + "flags": 16777216, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "param" }, "comment": "

Default options provided.

\n" @@ -56499,10 +57231,10 @@ "tagName": { "pos": 13913, "end": 13920, - "flags": 4194304, + "flags": 16777216, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "returns" }, "comment": "

The new configuration object.

\n" @@ -56700,10 +57432,10 @@ "name": { "pos": 8577, "end": 8588, - "flags": 4194304, + "flags": 16777216, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "optionIndex" }, "type": "number", @@ -56712,10 +57444,10 @@ "tagName": { "pos": 8571, "end": 8576, - "flags": 4194304, + "flags": 16777216, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "param" }, "comment": "

Index of the option at which to start counting.

\n" @@ -56724,10 +57456,10 @@ "name": { "pos": 8647, "end": 8654, - "flags": 4194304, + "flags": 16777216, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "options" }, "type": "QueryList", @@ -56736,10 +57468,10 @@ "tagName": { "pos": 8641, "end": 8646, - "flags": 4194304, + "flags": 16777216, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "param" }, "comment": "

Flat list of all of the options.

\n" @@ -56748,10 +57480,10 @@ "name": { "pos": 8698, "end": 8710, - "flags": 4194304, + "flags": 16777216, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "optionGroups" }, "type": "QueryList", @@ -56760,10 +57492,10 @@ "tagName": { "pos": 8692, "end": 8697, - "flags": 4194304, + "flags": 16777216, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "param" }, "comment": "

Flat list of all of the option groups.

\n" @@ -56810,10 +57542,10 @@ "name": { "pos": 9417, "end": 9428, - "flags": 4194304, + "flags": 16777216, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "optionIndex" }, "type": "number", @@ -56822,10 +57554,10 @@ "tagName": { "pos": 9411, "end": 9416, - "flags": 4194304, + "flags": 16777216, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "param" }, "comment": "

Index of the option to be scrolled into the view.

\n" @@ -56834,10 +57566,10 @@ "name": { "pos": 9489, "end": 9501, - "flags": 4194304, + "flags": 16777216, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "optionHeight" }, "type": "number", @@ -56846,10 +57578,10 @@ "tagName": { "pos": 9483, "end": 9488, - "flags": 4194304, + "flags": 16777216, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "param" }, "comment": "

Height of the options.

\n" @@ -56858,10 +57590,10 @@ "name": { "pos": 9535, "end": 9556, - "flags": 4194304, + "flags": 16777216, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "currentScrollPosition" }, "type": "number", @@ -56870,10 +57602,10 @@ "tagName": { "pos": 9529, "end": 9534, - "flags": 4194304, + "flags": 16777216, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "param" }, "comment": "

Current scroll position of the panel.

\n" @@ -56882,10 +57614,10 @@ "name": { "pos": 9605, "end": 9616, - "flags": 4194304, + "flags": 16777216, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "panelHeight" }, "type": "number", @@ -56894,10 +57626,10 @@ "tagName": { "pos": 9599, "end": 9604, - "flags": 4194304, + "flags": 16777216, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "param" }, "comment": "

Height of the panel.

\n" @@ -56998,10 +57730,10 @@ "name": { "pos": 1649, "end": 1656, - "flags": 4194304, + "flags": 16777216, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "literal" }, "type": "SafeHtml", @@ -57010,10 +57742,10 @@ "tagName": { "pos": 1643, "end": 1648, - "flags": 4194304, + "flags": 16777216, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "param" }, "comment": "

HTML that was attempted to be sanitized.

\n" @@ -57042,10 +57774,10 @@ "name": { "pos": 1235, "end": 1238, - "flags": 4194304, + "flags": 16777216, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "url" }, "type": "SafeResourceUrl", @@ -57054,10 +57786,10 @@ "tagName": { "pos": 1229, "end": 1234, - "flags": 4194304, + "flags": 16777216, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "param" }, "comment": "

URL that was attempted to be sanitized.

\n" @@ -57100,7 +57832,7 @@ "subtype": "function", "deprecated": false, "deprecationMessage": "", - "description": "

Returns an exception to be thrown when the consumer attempts to use\n<oui-icon> without including @angular/http.

\n", + "description": "

Returns an exception to be thrown when the consumer attempts to use\n<oui-icon> without including

\n", "args": [], "returnType": "Error" }, @@ -57753,10 +58485,10 @@ "name": { "pos": 10099, "end": 10106, - "flags": 4194304, + "flags": 16777216, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "element" }, "type": "ElementRef", @@ -57765,10 +58497,10 @@ "tagName": { "pos": 10093, "end": 10098, - "flags": 4194304, + "flags": 16777216, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "param" }, "comment": "

Element relative to which to look for a dialog.

\n" @@ -57777,10 +58509,10 @@ "name": { "pos": 10165, "end": 10176, - "flags": 4194304, + "flags": 16777216, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "openDialogs" }, "deprecated": false, @@ -57788,10 +58520,10 @@ "tagName": { "pos": 10159, "end": 10164, - "flags": 4194304, + "flags": 16777216, "modifierFlagsCache": 0, "transformFlags": 0, - "kind": 79, + "kind": 80, "escapedText": "param" }, "comment": "

References to the currently-open dialogs.

\n" @@ -58846,7 +59578,7 @@ "deprecated": false, "deprecationMessage": "", "description": "", - "kind": 179 + "kind": 185 }, { "name": "Constructor", @@ -58857,7 +59589,7 @@ "deprecated": false, "deprecationMessage": "", "description": "", - "kind": 179 + "kind": 185 } ], "ui/src/components/sort/sort-header.ts": [ @@ -58870,7 +59602,7 @@ "deprecated": false, "deprecationMessage": "", "description": "

Valid positions for the arrow to be in for its opacity and translation. If the state is a\nsort direction, the position of the arrow will be above/below and opacity 0. If the state is\nhint, the arrow will be in the center with a slight opacity. Active state means the arrow will\nbe fully opaque in the center.

\n", - "kind": 186 + "kind": 192 } ], "ui/src/components/core/common-behaviors/color.ts": [ @@ -58883,7 +59615,7 @@ "deprecated": false, "deprecationMessage": "", "description": "", - "kind": 177 + "kind": 183 }, { "name": "ThemePalette", @@ -58894,7 +59626,7 @@ "deprecated": false, "deprecationMessage": "", "description": "

Possible color palette values.

\n", - "kind": 186 + "kind": 192 } ], "ui/src/components/core/common-behaviors/disabled.ts": [ @@ -58907,7 +59639,7 @@ "deprecated": false, "deprecationMessage": "", "description": "", - "kind": 177 + "kind": 183 } ], "ui/src/components/core/common-behaviors/disable-ripple.ts": [ @@ -58920,7 +59652,7 @@ "deprecated": false, "deprecationMessage": "", "description": "", - "kind": 187 + "kind": 193 } ], "ui/src/components/button/progress.ts": [ @@ -58933,7 +59665,7 @@ "deprecated": false, "deprecationMessage": "", "description": "", - "kind": 177 + "kind": 183 } ], "ui/src/components/core/common-behaviors/error-state.ts": [ @@ -58946,7 +59678,7 @@ "deprecated": false, "deprecationMessage": "", "description": "", - "kind": 177 + "kind": 183 } ], "ui/src/components/core/common-behaviors/initialized.ts": [ @@ -58959,7 +59691,7 @@ "deprecated": false, "deprecationMessage": "", "description": "", - "kind": 177 + "kind": 183 } ], "ui/src/components/core/common-behaviors/tabIndex.ts": [ @@ -58972,7 +59704,7 @@ "deprecated": false, "deprecationMessage": "", "description": "", - "kind": 177 + "kind": 183 } ], "ui/src/components/tabs/paginated-tab-header.ts": [ @@ -58985,7 +59717,7 @@ "deprecated": false, "deprecationMessage": "", "description": "

Item inside a paginated tab header.

\n", - "kind": 187 + "kind": 193 }, { "name": "ScrollDirection", @@ -58996,7 +59728,7 @@ "deprecated": false, "deprecationMessage": "", "description": "

The directions that scrolling can go in when the header's tabs exceed the header width. 'After'\nwill scroll the header towards the end of the tabs list and 'before' will scroll towards the\nbeginning of the list.

\n", - "kind": 186 + "kind": 192 } ], "ui/src/components/menu/menu-positions.ts": [ @@ -59009,7 +59741,7 @@ "deprecated": false, "deprecationMessage": "", "description": "", - "kind": 186 + "kind": 192 }, { "name": "MenuPositionY", @@ -59020,7 +59752,7 @@ "deprecated": false, "deprecationMessage": "", "description": "", - "kind": 186 + "kind": 192 } ], "ui/src/components/datepicker/calendar-body.ts": [ @@ -59033,7 +59765,7 @@ "deprecated": false, "deprecationMessage": "", "description": "

Extra CSS classes that can be associated with a calendar cell.

\n", - "kind": 186 + "kind": 192 } ], "ui/src/components/datepicker/calendar.ts": [ @@ -59046,7 +59778,7 @@ "deprecated": false, "deprecationMessage": "", "description": "

Possible views for the calendar.

\n", - "kind": 186 + "kind": 192 } ], "ui/src/components/datepicker/date-formats.ts": [ @@ -59059,7 +59791,7 @@ "deprecated": false, "deprecationMessage": "", "description": "", - "kind": 181 + "kind": 187 } ], "ui/src/components/form-field/form-field.ts": [ @@ -59072,7 +59804,7 @@ "deprecated": false, "deprecationMessage": "", "description": "

Possible appearance styles for the form field.

\n", - "kind": 186 + "kind": 192 } ], "ui/src/components/core/selection/pseudo-checkbox/pseudo-checkbox.ts": [ @@ -59085,7 +59817,7 @@ "deprecated": false, "deprecationMessage": "", "description": "

Possible states for a pseudo checkbox.

\n", - "kind": 186 + "kind": 192 } ], "ui/src/components/tabs/tab-body.ts": [ @@ -59098,7 +59830,7 @@ "deprecated": false, "deprecationMessage": "", "description": "

The origin state is an internally used state that is set on a new tab body indicating if it\nbegan to the left or right of the prior selected index. For example, if the selected index was\nset to 1, and a new tab is created and selected at index 2, then the tab body would have an\norigin of right because its index was greater than the prior selected index.

\n", - "kind": 186 + "kind": 192 }, { "name": "OuiTabBodyPositionState", @@ -59109,7 +59841,7 @@ "deprecated": false, "deprecationMessage": "", "description": "

These position states are used internally as animation states for the tab body. Setting the\nposition state to left, right, or center will transition the tab body from its current\nposition to its respective state. If there is not current position (void, in the case of a new\ntab body), then there will be no transition animation to its state.

\n

In the case of a new tab body that should immediately be centered with an animating transition,\nthen left-origin-center or right-origin-center can be used, which will use left or right as its\npseudo-prior state.

\n", - "kind": 186 + "kind": 192 } ], "ui/src/components/tabs/tab-group.ts": [ @@ -59122,7 +59854,7 @@ "deprecated": false, "deprecationMessage": "", "description": "

Possible positions for the tab header.

\n", - "kind": 186 + "kind": 192 } ], "ui/src/components/panel/panel-positions.ts": [ @@ -59135,7 +59867,7 @@ "deprecated": false, "deprecationMessage": "", "description": "", - "kind": 186 + "kind": 192 }, { "name": "PanelPositionY", @@ -59146,7 +59878,7 @@ "deprecated": false, "deprecationMessage": "", "description": "", - "kind": 186 + "kind": 192 } ], "ui/src/components/progress-bar/progress-bar.ts": [ @@ -59159,7 +59891,7 @@ "deprecated": false, "deprecationMessage": "", "description": "

Possible mode for a progress spinner.

\n", - "kind": 186 + "kind": 192 } ], "ui/src/components/progress-spinner/progress-spinner.ts": [ @@ -59172,7 +59904,7 @@ "deprecated": false, "deprecationMessage": "", "description": "

Possible mode for a progress spinner.

\n", - "kind": 186 + "kind": 192 } ], "ui/src/components/icon/testing/fake-icon-registry.ts": [ @@ -59185,7 +59917,7 @@ "deprecated": false, "deprecationMessage": "", "description": "", - "kind": 194 + "kind": 200 } ], "ui/src/components/core/common-behaviors/common-module.ts": [ @@ -59198,7 +59930,7 @@ "deprecated": false, "deprecationMessage": "", "description": "

Possible sanity checks that can be enabled. If set to\ntrue/false, all checks will be enabled/disabled.

\n", - "kind": 186 + "kind": 192 } ], "ui/src/components/sort/sort-direction.ts": [ @@ -59211,7 +59943,7 @@ "deprecated": false, "deprecationMessage": "", "description": "", - "kind": 186 + "kind": 192 } ], "ui/src/components/tooltip/tooltip.ts": [ @@ -59224,7 +59956,7 @@ "deprecated": false, "deprecationMessage": "", "description": "", - "kind": 186 + "kind": 192 }, { "name": "TooltipVisibility", @@ -59235,7 +59967,7 @@ "deprecated": false, "deprecationMessage": "", "description": "", - "kind": 186 + "kind": 192 } ] } @@ -61690,8 +62422,8 @@ }, { "filePath": "ui/src/components/select/select.component.ts", - "type": "component", - "linktype": "component", + "type": "directive", + "linktype": "directive", "name": "OuiSelectTrigger", "coveragePercent": 100, "coverageCount": "1/1", diff --git a/package-lock.json b/package-lock.json index 01540edf9..0935a1c3f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "oncehub-ui", - "version": "8.0.6", + "version": "8.0.8", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "oncehub-ui", - "version": "8.0.6", + "version": "8.0.8", "dependencies": { "@angular-devkit/architect": "0.1601.6", "@angular-devkit/core": "16.1.6", diff --git a/package.json b/package.json index 1b7763b22..58ae9b32c 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "oncehub-ui", - "version": "8.0.6", + "version": "8.0.8", "scripts": { "ng": "ng", "build": "ng build ui", diff --git a/ui/package-lock.json b/ui/package-lock.json index 4eb47cd20..6f783c4c8 100644 --- a/ui/package-lock.json +++ b/ui/package-lock.json @@ -1,12 +1,12 @@ { "name": "@oncehub/ui", - "version": "8.0.6", + "version": "8.0.8", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "@oncehub/ui", - "version": "8.0.6", + "version": "8.0.8", "dependencies": { "tslib": "^2.4.0" } diff --git a/ui/package.json b/ui/package.json index 072081539..12273e701 100644 --- a/ui/package.json +++ b/ui/package.json @@ -1,6 +1,6 @@ { "name": "@oncehub/ui", - "version": "8.0.6", + "version": "8.0.8", "description": "Oncehub UI", "peerDependencies": {}, "repository": { diff --git a/ui/src/components/panel/panel.ts b/ui/src/components/panel/panel.ts index 21695848b..a657ea1d3 100644 --- a/ui/src/components/panel/panel.ts +++ b/ui/src/components/panel/panel.ts @@ -162,7 +162,7 @@ export class OuiPanel implements OnInit, OuiPanelOverlay { @Component({ selector: 'oui-panel-icon', template: - '', + '', styleUrls: ['panel.scss'], changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, @@ -179,6 +179,7 @@ export class OuiPanelIcon implements OnDestroy { private _ngZone: NgZone, @Attribute('tabindex') tabIndex: string ) { + this._elementRef.nativeElement.setAttribute('tabindex', '0'); this.tabIndex = parseInt(tabIndex, 10) || 0; this._monitorSubscription = this._focusMonitor .monitor(this._elementRef, true) From f51db2e77fb1181f658fc3d83ccc01ba109c92e1 Mon Sep 17 00:00:00 2001 From: siddharth Date: Wed, 7 Feb 2024 14:53:45 +0530 Subject: [PATCH 5/7] Fixed, on searching the option the focus should scroll to the focused potion. --- package-lock.json | 4 ++-- package.json | 2 +- ui/package-lock.json | 4 ++-- ui/package.json | 2 +- ui/src/components/core/option/option.ts | 12 ++++++++++++ 5 files changed, 18 insertions(+), 6 deletions(-) diff --git a/package-lock.json b/package-lock.json index 03d0bfad6..e1d7804c7 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "oncehub-ui", - "version": "8.0.8", + "version": "8.0.9-beta.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "oncehub-ui", - "version": "8.0.8", + "version": "8.0.9-beta.0", "dependencies": { "@angular-devkit/architect": "0.1601.6", "@angular-devkit/core": "16.1.6", diff --git a/package.json b/package.json index 940e7a89a..8544c71c9 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "oncehub-ui", - "version": "8.0.8", + "version": "8.0.9-beta.0", "scripts": { "ng": "ng", "build": "ng build ui", diff --git a/ui/package-lock.json b/ui/package-lock.json index 6f783c4c8..9a2655269 100644 --- a/ui/package-lock.json +++ b/ui/package-lock.json @@ -1,12 +1,12 @@ { "name": "@oncehub/ui", - "version": "8.0.8", + "version": "8.0.9-beta.0", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "@oncehub/ui", - "version": "8.0.8", + "version": "8.0.9-beta.0", "dependencies": { "tslib": "^2.4.0" } diff --git a/ui/package.json b/ui/package.json index 12273e701..e8bfb640a 100644 --- a/ui/package.json +++ b/ui/package.json @@ -1,6 +1,6 @@ { "name": "@oncehub/ui", - "version": "8.0.8", + "version": "8.0.9-beta.0", "description": "Oncehub UI", "peerDependencies": {}, "repository": { diff --git a/ui/src/components/core/option/option.ts b/ui/src/components/core/option/option.ts index dd816101b..f1d36099b 100644 --- a/ui/src/components/core/option/option.ts +++ b/ui/src/components/core/option/option.ts @@ -200,6 +200,18 @@ export class OuiOption implements AfterViewChecked, OnDestroy { setActiveStyles(): void { if (!this._active) { this._active = true; + setTimeout((_) => { + const focusedElement = document.querySelector( + '.oui-active' + ) as HTMLElement; + const multiSelect = document.querySelector( + '.oui-option-pseudo-checkbox' + ) as HTMLElement; + const ouiSearch = document.querySelector('.oui-select-search-input'); + if (focusedElement && !multiSelect && !ouiSearch) { + focusedElement?.focus(); + } + }); this._changeDetectorRef.markForCheck(); } } From 00b9a762313ebb71c50de0cd86c2c02e4769a650 Mon Sep 17 00:00:00 2001 From: siddharth Date: Thu, 8 Feb 2024 19:12:30 +0530 Subject: [PATCH 6/7] oui-scrollbar look is broken in Chrome 121 --- CHANGELOG.md | 4 ++ package-lock.json | 4 +- package.json | 2 +- ui/package-lock.json | 4 +- ui/package.json | 2 +- ui/src/components/scrollbar/scrollbar.scss | 43 +++++++++++++--------- 6 files changed, 35 insertions(+), 24 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 300861c21..f6053dd76 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,10 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [8.0.9] - 2023-02-09 + +- [ONCEHUB-78061](https://scheduleonce.atlassian.net/browse/ONCEHUB-78061) Fixed the oui-scrollbar look is broken in Chrome 121 + ## [8.0.8] - 2023-02-02 - [ONCEHUB-60767](https://scheduleonce.atlassian.net/browse/ONCEHUB-77583) Add accessibility on oui-panel-icon diff --git a/package-lock.json b/package-lock.json index 03d0bfad6..65fad97d9 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "oncehub-ui", - "version": "8.0.8", + "version": "8.0.9", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "oncehub-ui", - "version": "8.0.8", + "version": "8.0.9", "dependencies": { "@angular-devkit/architect": "0.1601.6", "@angular-devkit/core": "16.1.6", diff --git a/package.json b/package.json index 940e7a89a..14f15a43e 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "oncehub-ui", - "version": "8.0.8", + "version": "8.0.9", "scripts": { "ng": "ng", "build": "ng build ui", diff --git a/ui/package-lock.json b/ui/package-lock.json index 6f783c4c8..270b24836 100644 --- a/ui/package-lock.json +++ b/ui/package-lock.json @@ -1,12 +1,12 @@ { "name": "@oncehub/ui", - "version": "8.0.8", + "version": "8.0.9", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "@oncehub/ui", - "version": "8.0.8", + "version": "8.0.9", "dependencies": { "tslib": "^2.4.0" } diff --git a/ui/package.json b/ui/package.json index 12273e701..665c95a54 100644 --- a/ui/package.json +++ b/ui/package.json @@ -1,6 +1,6 @@ { "name": "@oncehub/ui", - "version": "8.0.8", + "version": "8.0.9", "description": "Oncehub UI", "peerDependencies": {}, "repository": { diff --git a/ui/src/components/scrollbar/scrollbar.scss b/ui/src/components/scrollbar/scrollbar.scss index 083704e5b..c95e711d0 100644 --- a/ui/src/components/scrollbar/scrollbar.scss +++ b/ui/src/components/scrollbar/scrollbar.scss @@ -1,23 +1,30 @@ -.oui-scrollbar-container::-webkit-scrollbar { - width: 10px; -} -.oui-scrollbar-container::-webkit-scrollbar-track { - display: none; -} -.oui-scrollbar-container::-webkit-scrollbar-thumb { - background-color: #ccc !important; - border: 2px #fff solid; - border-radius: 15px; -} -.oui-scrollbar-container-large::-webkit-scrollbar { - width: 16px; +.oui-scrollbar-container { + overflow-y: auto; + &::-webkit-scrollbar { + width: 10px; + } + &::-webkit-scrollbar-track { + display: none; + } + &::-webkit-scrollbar-thumb { + background-color: #ccc !important; + border: 2px #fff solid; + border-radius: 15px; + } } -.oui-scrollbar-container-large::-webkit-scrollbar-thumb { - border: 4px #fff solid !important; +.oui-scrollbar-container-large { + &::-webkit-scrollbar { + width: 16px; + } + &::-webkit-scrollbar-thumb { + border: 4px #fff solid !important; + } } .oui-scrollbar-container { - overflow-y: auto; - scrollbar-color: #ccc transparent; - scrollbar-width: thin; + /* Standardized Properties */ + @supports not selector(::-webkit-scrollbar) { + scrollbar-color: #ccc transparent; + scrollbar-width: thin; + } } From fb707e82dacc697e47a9b75245d5e26862ca72e3 Mon Sep 17 00:00:00 2001 From: siddharth Date: Fri, 9 Feb 2024 14:40:17 +0530 Subject: [PATCH 7/7] Fixed select, on searching the option the focus should scroll to the focused potion. --- CHANGELOG.md | 4 ++++ package-lock.json | 4 ++-- package.json | 2 +- ui/package-lock.json | 4 ++-- ui/package.json | 2 +- 5 files changed, 10 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f6053dd76..bcd17908e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,10 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [8.0.10] - 2023-02-09 + +- [ONCEHUB-77842](https://scheduleonce.atlassian.net/browse/ONCEHUB-77842) Fixed, on searching the option the focus should scroll to the focused potion. + ## [8.0.9] - 2023-02-09 - [ONCEHUB-78061](https://scheduleonce.atlassian.net/browse/ONCEHUB-78061) Fixed the oui-scrollbar look is broken in Chrome 121 diff --git a/package-lock.json b/package-lock.json index 65fad97d9..f0462aa75 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "oncehub-ui", - "version": "8.0.9", + "version": "8.0.10", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "oncehub-ui", - "version": "8.0.9", + "version": "8.0.10", "dependencies": { "@angular-devkit/architect": "0.1601.6", "@angular-devkit/core": "16.1.6", diff --git a/package.json b/package.json index 14f15a43e..8190a713d 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "oncehub-ui", - "version": "8.0.9", + "version": "8.0.10", "scripts": { "ng": "ng", "build": "ng build ui", diff --git a/ui/package-lock.json b/ui/package-lock.json index 270b24836..aaa9a6f91 100644 --- a/ui/package-lock.json +++ b/ui/package-lock.json @@ -1,12 +1,12 @@ { "name": "@oncehub/ui", - "version": "8.0.9", + "version": "8.0.10", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "@oncehub/ui", - "version": "8.0.9", + "version": "8.0.10", "dependencies": { "tslib": "^2.4.0" } diff --git a/ui/package.json b/ui/package.json index 665c95a54..e0099d3ee 100644 --- a/ui/package.json +++ b/ui/package.json @@ -1,6 +1,6 @@ { "name": "@oncehub/ui", - "version": "8.0.9", + "version": "8.0.10", "description": "Oncehub UI", "peerDependencies": {}, "repository": {