diff --git a/packages/core/src/button-inline/button-inline.element.ts b/packages/core/src/button-inline/button-inline.element.ts
index 6a433f0c5..0e5b130dc 100644
--- a/packages/core/src/button-inline/button-inline.element.ts
+++ b/packages/core/src/button-inline/button-inline.element.ts
@@ -49,9 +49,3 @@ export class CdsButtonInline extends CdsBaseButton {
return [baseStyles, styles];
}
}
-
-/**
- * @deprecated
- * renamed to `cds-button-inline` in 6.0 to align to rest of the `cds-button-*` APIs
- */
-export class CdsInlineButton extends CdsButtonInline {}
diff --git a/packages/core/src/button-inline/register.ts b/packages/core/src/button-inline/register.ts
index e2796f0d7..4bd77d4e0 100644
--- a/packages/core/src/button-inline/register.ts
+++ b/packages/core/src/button-inline/register.ts
@@ -5,7 +5,7 @@
*/
import { registerElementSafely } from '@cds/core/internal';
-import { CdsButtonInline, CdsInlineButton } from './button-inline.element.js';
+import { CdsButtonInline } from './button-inline.element.js';
registerElementSafely('cds-button-inline', CdsButtonInline);
@@ -14,12 +14,3 @@ declare global {
'cds-button-inline': CdsButtonInline;
}
}
-
-/** @deprecated */
-registerElementSafely('cds-inline-button', CdsInlineButton);
-
-declare global {
- interface HTMLElementTagNameMap {
- 'cds-inline-button': CdsInlineButton;
- }
-}
diff --git a/packages/core/src/internal/index.ts b/packages/core/src/internal/index.ts
index e9cb98ddf..990d84454 100644
--- a/packages/core/src/internal/index.ts
+++ b/packages/core/src/internal/index.ts
@@ -47,7 +47,6 @@ export * from './services/keycodes.service.js';
export * from './utils/conditional.js';
export * from './utils/enum.js';
export * from './utils/exists.js';
-export * from './utils/focus-trap.js';
export * from './utils/framework.js';
export * from './i18n/utils.js';
export * from './positioning/utils.js';
diff --git a/packages/core/src/internal/utils/focus-trap.spec.ts b/packages/core/src/internal/utils/focus-trap.spec.ts
deleted file mode 100644
index d13239607..000000000
--- a/packages/core/src/internal/utils/focus-trap.spec.ts
+++ /dev/null
@@ -1,441 +0,0 @@
-/*
- * Copyright (c) 2016-2021 VMware, Inc. All Rights Reserved.
- * This software is released under MIT license.
- * The full license information can be found in LICENSE in the root directory of this project.
- */
-
-import { html, LitElement } from 'lit';
-import { createTestElement, removeTestElement } from '@cds/core/test';
-import { createId, customElement, property, sleep, state } from '@cds/core/internal';
-import {
- addReboundElementsToFocusTrapElement,
- castHtmlElementToFocusTrapElement,
- createFocusTrapReboundElement,
- elementIsOutsideFocusTrapElement,
- FocusTrap,
- refocusIfOutsideFocusTrapElement,
- removeReboundElementsFromFocusTrapElement,
-} from './focus-trap.js';
-import { CDS_FOCUS_TRAP_DOCUMENT_ATTR, FocusTrapTrackerService } from '../services/focus-trap-tracker.service.js';
-
-@customElement('test-deprecated-focus-trap')
-class DeprecatedFocusTrap extends LitElement {
- focusTrap: FocusTrap;
-
- topReboundElement: HTMLElement;
- bottomReboundElement: HTMLElement;
-
- /**
- * Its recommended to remove or add a focus trap element from the DOM
- * some SSR systems can have technical constraints where the item can
- * only be removed via CSS/hidden.
- */
- @property({ type: Boolean }) hidden = false;
-
- @state({ type: Boolean, reflect: true })
- protected demoMode = false;
-
- @property({ type: String }) focusTrapId: string;
-
- constructor() {
- super();
- this.focusTrapId = createId();
- // if we see issues instantiating here, we should consider moving to
- // firstUpdated()
- this.focusTrap = new FocusTrap(this);
- }
-
- connectedCallback() {
- super.connectedCallback();
- this.toggleFocusTrap();
- }
-
- disconnectedCallback() {
- super.disconnectedCallback();
- this.focusTrap.removeFocusTrap();
- }
-
- attributeChangedCallback(name: string, old: string, value: string) {
- super.attributeChangedCallback(name, old, value);
-
- if (name === 'hidden' && old !== value) {
- this.toggleFocusTrap();
- }
- }
-
- protected render() {
- return html``;
- }
-
- private toggleFocusTrap() {
- if (!this.demoMode && !this.hasAttribute('hidden')) {
- this.focusTrap.enableFocusTrap();
- } else {
- this.focusTrap.removeFocusTrap();
- }
- }
-}
-
-@customElement('test-focus-trap')
-class TestFocusTrap extends DeprecatedFocusTrap {
- render() {
- return html``;
- }
-}
-
-describe('Focus Trap Utilities: ', () => {
- let focusedElement: HTMLElement;
- let noFocusElement: HTMLElement;
- let testElement: HTMLElement;
- let focusTrapElement: TestFocusTrap;
-
- beforeEach(async () => {
- testElement = await createTestElement(
- html``
- );
- focusTrapElement = testElement.querySelector('test-focus-trap');
- focusedElement = testElement.querySelector('.inside-focus');
- noFocusElement = testElement.querySelector('.outside-focus');
- });
-
- afterEach(() => {
- removeTestElement(testElement);
- });
-
- describe('Functional Helper: ', () => {
- afterEach(() => {
- removeReboundElementsFromFocusTrapElement(focusTrapElement);
- });
-
- describe('addReboundElementsToFocusTrapElement()', () => {
- it('adds rebound elements correctly when there are no siblings', () => {
- addReboundElementsToFocusTrapElement(focusTrapElement);
- const reboundElements = testElement.querySelectorAll('.offscreen-focus-rebounder');
- expect(reboundElements.length).toBe(2);
- expect(reboundElements[0].nextSibling).toEqual(focusTrapElement);
- expect(focusTrapElement.nextSibling).toEqual(reboundElements[1]);
- });
-
- it('does not double-add rebound elements if called twice by accident', () => {
- addReboundElementsToFocusTrapElement(focusTrapElement);
- addReboundElementsToFocusTrapElement(focusTrapElement);
- const reboundElements = testElement.querySelectorAll('.offscreen-focus-rebounder');
- expect(reboundElements.length).toBe(2);
- });
-
- it('adds rebound elements correctly when there are siblings ', () => {
- // this creates a sibling element to focusTrapElement
- const siblingEl = document.createElement('div');
- focusTrapElement.parentElement.appendChild(siblingEl);
-
- addReboundElementsToFocusTrapElement(focusTrapElement);
-
- const reboundElements = document.querySelectorAll('.offscreen-focus-rebounder');
- expect(reboundElements.length).toBe(2);
-
- expect(reboundElements[0].nextSibling).toEqual(focusTrapElement);
- expect(focusTrapElement.nextSibling).toEqual(reboundElements[1]);
- });
- });
-
- describe('removeReboundElementsFromFocusTrapElement()', () => {
- it('removes rebound elements correctly', () => {
- addReboundElementsToFocusTrapElement(focusTrapElement);
- removeReboundElementsFromFocusTrapElement(focusTrapElement);
- expect(document.querySelectorAll('.offscreen-focus-rebounder').length).toBe(0);
- });
-
- it('does not blow up if no rebound elements', () => {
- removeReboundElementsFromFocusTrapElement(focusTrapElement);
- expect(removeReboundElementsFromFocusTrapElement).not.toThrow();
- expect(document.querySelectorAll('.offscreen-focus-rebounder').length).toBe(0);
- });
- });
-
- describe('createFocusTrapReboundElement()', () => {
- let testElement: HTMLElement;
-
- beforeEach(() => {
- testElement = createFocusTrapReboundElement();
- });
-
- afterEach(() => {
- removeTestElement(testElement);
- });
-
- it('creates a focusable offscreen element', () => {
- expect(testElement.getAttribute('tabindex')).toBe('0');
- expect(testElement.classList).toContain('offscreen-focus-rebounder');
- });
- });
-
- describe('refocusIfOutsideFocusTrapElement()', () => {
- it('calls focus() if in current focus trap element', async () => {
- spyOn(focusedElement, 'focus');
- FocusTrapTrackerService.setCurrent(focusTrapElement);
- refocusIfOutsideFocusTrapElement(focusedElement, focusTrapElement);
- expect(focusedElement.focus).toHaveBeenCalled();
- });
-
- it('redirects focus() if focused element not in current focus trap element', async () => {
- spyOn(noFocusElement, 'focus');
- refocusIfOutsideFocusTrapElement(noFocusElement, focusTrapElement);
- expect(noFocusElement.focus).not.toHaveBeenCalled();
- });
-
- it('redirects focus() if it tries to focus a rebounder', async () => {
- const topReboundElement = focusTrapElement.topReboundElement;
- const bottomReboundElement = focusTrapElement.bottomReboundElement;
- spyOn(topReboundElement, 'focus');
- spyOn(bottomReboundElement, 'focus');
- refocusIfOutsideFocusTrapElement(topReboundElement, focusTrapElement);
- expect(topReboundElement.focus).not.toHaveBeenCalled();
- refocusIfOutsideFocusTrapElement(bottomReboundElement, focusTrapElement);
- expect(bottomReboundElement.focus).not.toHaveBeenCalled();
- });
- });
-
- describe('elementIsOutsideFocusTrapElement()', () => {
- let focusedElement: HTMLElement;
- let focusTrapElement: TestFocusTrap;
-
- beforeEach(async () => {
- focusTrapElement = (await createTestElement()) as TestFocusTrap;
- });
-
- afterEach(() => {
- removeTestElement(focusTrapElement);
- if (focusedElement) {
- focusedElement.remove();
- }
- });
-
- it('returns true if element is outside focus trap element', async () => {
- focusedElement = await createTestElement();
- expect(elementIsOutsideFocusTrapElement(focusedElement, focusTrapElement)).toBeTruthy();
- });
-
- it('returns true if focused element is top rebound element', async () => {
- const focusedElement = await createTestElement();
- focusTrapElement.topReboundElement = focusedElement;
- expect(elementIsOutsideFocusTrapElement(focusedElement, focusTrapElement)).toBeTruthy();
- });
-
- it('returns true if focused element is bottom rebound element', async () => {
- const focusedElement = await createTestElement();
- focusTrapElement.bottomReboundElement = focusedElement;
- expect(elementIsOutsideFocusTrapElement(focusedElement, focusTrapElement)).toBeTruthy();
- });
-
- it('returns false if element is inside focus trap element', () => {
- const focusedElement = document.createElement('div') as HTMLElement;
- focusTrapElement.appendChild(focusedElement);
- expect(elementIsOutsideFocusTrapElement(focusedElement, focusTrapElement)).toBeFalsy();
- });
-
- it('returns false if element is inside focus trap element shadow dom', async () => {
- const specialTestElement = await createTestElement(
- html``
- );
- const fte = testElement.querySelector('test-focus-trap');
- const elToFocus = fte.shadowRoot.querySelector('.shadow-button');
- expect(elementIsOutsideFocusTrapElement(elToFocus as HTMLElement, fte)).toBeFalsy();
- removeTestElement(specialTestElement);
- });
- });
- });
-});
-
-describe('FocusTrap Class: ', () => {
- describe('enableFocusTrap()', () => {
- let focusTrap: FocusTrap;
- let testElement: HTMLElement;
-
- function setUpFocusTrap(element: HTMLElement): FocusTrap {
- const ft = new FocusTrap(castHtmlElementToFocusTrapElement(element));
- ft.enableFocusTrap();
- return ft;
- }
-
- beforeEach(async () => {
- testElement = await createTestElement();
- });
-
- afterEach(() => {
- focusTrap.removeFocusTrap();
- removeTestElement(testElement);
- });
-
- it('set focus trap id', () => {
- focusTrap = setUpFocusTrap(testElement);
- expect(focusTrap.focusTrapElement.focusTrapId).toBeTruthy('needs to set focus trap id on plain html elements');
- });
-
- it('should add rebound elements', () => {
- focusTrap = setUpFocusTrap(testElement);
- expect(document.querySelectorAll('.offscreen-focus-rebounder').length).toBe(2);
- });
-
- it('should have a tabindex of -1 to be able to programatically focus', () => {
- focusTrap = setUpFocusTrap(testElement);
- expect(testElement.getAttribute('tabindex')).toBe('-1');
- });
-
- it('should not override tabindex if focus trap element already has a tabindex set', () => {
- testElement.setAttribute('tabindex', '1');
- focusTrap = setUpFocusTrap(testElement);
- expect(testElement.getAttribute('tabindex')).toBe('1');
- expect(testElement.getAttribute('tabindex')).not.toBe('-1');
- });
-
- it('should add to focus trap attr on root element (html) to prevent scrolling', () => {
- focusTrap = setUpFocusTrap(testElement);
- expect(document.documentElement.getAttribute(CDS_FOCUS_TRAP_DOCUMENT_ATTR)).toBe('');
- });
-
- it('should set itself to current on FocusTrapTracker service', () => {
- focusTrap = setUpFocusTrap(testElement);
- expect(FocusTrapTrackerService.getCurrent()).toEqual(testElement as any);
- });
-
- it('should be focused', async () => {
- focusTrap = setUpFocusTrap(testElement);
- // focus is not immediately set due to safari issue
- await sleep(23);
- expect(document.activeElement).toEqual(testElement, 'focus is set asynchronously after creation');
- });
-
- it('should be set to active', () => {
- focusTrap = setUpFocusTrap(testElement);
- expect(focusTrap.active).toBe(true);
- });
-
- it('should throw an error if enabledFocusTrap is called again', () => {
- focusTrap = setUpFocusTrap(testElement);
- const secondCall = () => focusTrap.enableFocusTrap();
- expect(secondCall).toThrow();
- });
- });
-
- describe('removeFocusTrap()', () => {
- let previousFocusedElement: HTMLElement;
- let focusTrap: FocusTrap;
- let testElement: HTMLElement;
-
- beforeEach(async () => {
- testElement = await createTestElement();
- focusTrap = new FocusTrap(testElement as any);
- previousFocusedElement = await createTestElement();
- previousFocusedElement.setAttribute('tabindex', '0');
- previousFocusedElement.focus();
- focusTrap.enableFocusTrap();
- focusTrap.removeFocusTrap();
- });
-
- afterEach(() => {
- removeTestElement(testElement);
- });
-
- it('should remove rebound elements', () => {
- expect(document.querySelectorAll('.offscreen-focus-rebounder').length).toBe(0);
- });
-
- it('should remove layout attribute to prevent scrolling on body', () => {
- expect(document.body.getAttribute('cds-layout')).toBeNull();
- });
-
- it('should not be set as current on FocusTrapTracker', () => {
- expect(FocusTrapTrackerService.getCurrent()).not.toEqual(testElement as any);
- });
-
- it('should not be set to active', () => {
- expect(focusTrap.active).toBe(false);
- });
-
- it('should restore previous focus', () => {
- expect(document.activeElement).toEqual(previousFocusedElement);
- });
- });
-});
-
-describe('Nested FocusTraps: ', () => {
- let outerFocusTrap: TestFocusTrap;
- let innerFocusTrap: TestFocusTrap;
- let testElement: HTMLElement;
- let outerFocusButton: HTMLElement;
- let innerFocusButton: HTMLElement;
- let noFocusButton: HTMLElement;
-
- beforeEach(async () => {
- testElement = await createTestElement(html`
-
-
-
-
-
- `);
- outerFocusTrap = testElement.querySelector('.outer-focus-trap');
- innerFocusTrap = testElement.querySelector('.inner-focus-trap');
- outerFocusButton = testElement.querySelector('.inside-outer-focus');
- innerFocusButton = testElement.querySelector('.inside-inner-focus');
- noFocusButton = testElement.querySelector('.outside-focus');
- });
-
- afterEach(() => {
- removeTestElement(testElement);
- });
-
- it('set multiple focus trap ids', () => {
- expect(
- FocusTrapTrackerService.getTrapElements()
- .map(e => e.focusTrapId)
- .indexOf(outerFocusTrap.focusTrapId) === 0
- ).toBe(true, 'sets focus trap ids as expected (1)');
- expect(
- FocusTrapTrackerService.getTrapElements()
- .map(e => e.focusTrapId)
- .indexOf(innerFocusTrap.focusTrapId) === 1
- ).toBe(true, 'sets focus trap ids as expected (2)');
- });
-
- it('keeps focus inside the inner trap', () => {
- noFocusButton.focus();
- let focused = document.activeElement;
- expect(focused).not.toBe(noFocusButton, 'should not focus elements outside of active focus trap (1)');
- expect(focused).toBe(
- innerFocusTrap,
- 'should apply focus to focus trap if trying to focus elements outside of active focus trap (1)'
- );
- outerFocusButton.focus();
- focused = document.activeElement;
- expect(focused).not.toBe(outerFocusButton, 'should not focus elements outside of active focus trap (2)');
- expect(focused).toBe(
- innerFocusTrap,
- 'should apply focus to focus trap if trying to focus elements outside of active focus trap (2)'
- );
- innerFocusButton.focus();
- focused = document.activeElement;
- expect(focused).toBe(innerFocusButton, 'should allow focus on elements inside of active focus trap (1)');
- });
-
- it('cancelling inner trap falls back to outer trap', () => {
- innerFocusTrap.focusTrap.removeFocusTrap();
- expect(FocusTrapTrackerService.getTrapElements().findIndex(e => e.focusTrapId === innerFocusTrap.focusTrapId)).toBe(
- -1,
- 'should remove focus trap from focus trap ids'
- );
-
- noFocusButton.focus();
- let focused = document.activeElement;
- expect(focused).not.toBe(noFocusButton, 'should not focus elements outside of active focus trap (3)');
- expect(focused).toBe(
- outerFocusTrap,
- 'should apply focus to focus trap if trying to focus elements outside of active focus trap (3)'
- );
-
- outerFocusButton.focus();
- focused = document.activeElement;
- expect(focused).toBe(outerFocusButton, 'should allow focus on elements inside of active focus trap (1)');
- });
-});
diff --git a/packages/core/src/internal/utils/focus-trap.ts b/packages/core/src/internal/utils/focus-trap.ts
deleted file mode 100644
index afb2bf81f..000000000
--- a/packages/core/src/internal/utils/focus-trap.ts
+++ /dev/null
@@ -1,253 +0,0 @@
-/*
- * Copyright (c) 2016-2021 VMware, Inc. All Rights Reserved.
- * This software is released under MIT license.
- * The full license information can be found in LICENSE in the root directory of this project.
- */
-
-import { FocusTrapTrackerService } from '../services/focus-trap-tracker.service.js';
-import { anyPassOrAnyFail } from './conditional.js';
-import { isHTMLElement, isFocusable, queryAllFocusable } from './dom.js';
-import { arrayHead, arrayTail } from './array.js';
-import { createId } from './identity.js';
-export interface FocusTrapElement extends HTMLElement {
- topReboundElement: HTMLElement | undefined;
- bottomReboundElement: HTMLElement | undefined;
- focusTrapId: string;
-}
-
-/* c8 ignore next 17 */
-/**
- * @deprecated since version 6.0
- */
-export function reorderCloseButtonSlot(elements: Element[]): Element[] {
- const closeButtonIndex = elements.findIndex(el => el.tagName.toLowerCase() === 'cds-internal-close-button');
-
- if (closeButtonIndex > 0 && elements[closeButtonIndex].hasAttribute('slot')) {
- // Put in the close button in a slot moves it around in the tab focus flow;
- // this helps to place it at the top of the modal where it is expected to be
- return [
- elements[closeButtonIndex],
- ...elements.filter(el => el.tagName.toLowerCase() !== 'cds-internal-close-button'),
- ];
- } else {
- return [...elements];
- }
-}
-
-/* c8 ignore next 27 */
-/**
- * @deprecated since version 6.0
- */
-export function refocusIfOutsideFocusTrapElement(
- focusedElement: HTMLElement,
- focusTrapElement: FocusTrapElement,
- elementToRefocus?: HTMLElement
-) {
- const focusTrapIsCurrent = FocusTrapTrackerService.getCurrent() === focusTrapElement;
- const elementToFocusIsOutsideFocusTrap = elementIsOutsideFocusTrapElement(focusedElement, focusTrapElement);
-
- if (focusTrapIsCurrent && elementToFocusIsOutsideFocusTrap) {
- const isReboundEl = whichReboundElement(focusedElement, focusTrapElement);
- const focusableChildren = queryAllFocusable(focusTrapElement);
- const orderedFocusableChildrenAsArray = reorderCloseButtonSlot(Array.from(focusableChildren));
-
- if (isReboundEl !== null) {
- if (isReboundEl === 'top') {
- elementToRefocus = arrayTail(orderedFocusableChildrenAsArray) as HTMLElement;
- } else if (isReboundEl === 'bottom') {
- elementToRefocus = arrayHead(orderedFocusableChildrenAsArray) as HTMLElement;
- }
- }
-
- (elementToRefocus || focusTrapElement).focus();
- } else {
- focusedElement.focus();
- }
-}
-
-/* c8 ignore next 9 */
-/**
- * @deprecated since version 6.0
- */
-export function whichReboundElement(el: HTMLElement, focusTrapElement: FocusTrapElement): 'top' | 'bottom' | null {
- if (el === focusTrapElement.topReboundElement) {
- return 'top';
- } else if (el === focusTrapElement.bottomReboundElement) {
- return 'bottom';
- } else {
- return null;
- }
-}
-
-/* c8 ignore next 13 */
-/**
- * @deprecated since version 6.0
- */
-export function elementIsOutsideFocusTrapElement(
- focusedElement: HTMLElement,
- focusTrapElement: FocusTrapElement
-): boolean {
- return anyPassOrAnyFail(
- [
- () => {
- return whichReboundElement(focusedElement, focusTrapElement) !== null;
- },
- ], // true if true
- [
- () => focusTrapElement.contains(focusedElement),
- () => focusTrapElement.shadowRoot !== null && focusTrapElement.shadowRoot.contains(focusedElement),
- ], // false if true
- true // fallthrough
- );
-}
-
-/* c8 ignore next 6 */
-/**
- * @deprecated since version 6.0
- */
-export function createFocusTrapReboundElement() {
- const offScreenSpan = document.createElement('span');
- offScreenSpan.setAttribute('tabindex', '0');
- offScreenSpan.classList.add('offscreen-focus-rebounder');
- return offScreenSpan;
-}
-
-/**
- * @deprecated since version 6.0
- */
-export function addReboundElementsToFocusTrapElement(focusTrapElement: FocusTrapElement) {
- if (focusTrapElement && !focusTrapElement.topReboundElement && !focusTrapElement.bottomReboundElement) {
- focusTrapElement.topReboundElement = createFocusTrapReboundElement();
- focusTrapElement.bottomReboundElement = createFocusTrapReboundElement();
-
- const parent = focusTrapElement.parentElement;
- const sibling = focusTrapElement.nextSibling;
-
- if (parent) {
- parent.insertBefore(focusTrapElement.topReboundElement, focusTrapElement);
- if (sibling) {
- parent.insertBefore(focusTrapElement.bottomReboundElement, sibling);
- } else {
- parent.appendChild(focusTrapElement.bottomReboundElement);
- }
- }
- }
-}
-
-/**
- * @deprecated since version 6.0
- */
-export function removeReboundElementsFromFocusTrapElement(focusTrapElement: FocusTrapElement) {
- if (focusTrapElement) {
- const parent = focusTrapElement.parentElement;
-
- if (parent) {
- const topRebound = focusTrapElement.topReboundElement;
- const bottomRebound = focusTrapElement.bottomReboundElement;
- if (topRebound) {
- parent.removeChild(topRebound);
- }
- if (bottomRebound) {
- parent.removeChild(bottomRebound);
- }
- }
- // These are here to to make sure that we completely delete all traces of the removed DOM objects.
- delete focusTrapElement.topReboundElement;
- delete focusTrapElement.bottomReboundElement;
- }
-}
-
-// this helper exists to enable the focus trap class to handle vanilla html elements
-// it's primary concern is to keep TS happy.
-// end users should prefer using the CdsBaseFocusTrap component to this method.
-// but it exists...
-/**
- * @deprecated since version 6.0
- */
-export function castHtmlElementToFocusTrapElement(el: HTMLElement): FocusTrapElement {
- return el as FocusTrapElement;
-}
-
-/**
- * @deprecated since version 6.0
- */
-export class FocusTrap {
- focusTrapElement: FocusTrapElement;
- previousFocus: HTMLElement;
- private onFocusInEvent: any;
-
- firstFocusElement: HTMLElement | FocusTrapElement;
-
- active = false;
-
- constructor(hostElement: FocusTrapElement) {
- hostElement = castHtmlElementToFocusTrapElement(hostElement);
-
- if (!hostElement.focusTrapId) {
- hostElement.focusTrapId = createId();
- }
-
- this.focusTrapElement = hostElement;
- }
-
- enableFocusTrap() {
- const fte = this.focusTrapElement;
- const firstFocusElement = fte.querySelector('[cds-first-focus]');
- const contentWrapper = fte.shadowRoot ? fte.shadowRoot.querySelector('.private-host[tabindex]') : null;
- const activeEl = document.activeElement;
-
- if (FocusTrapTrackerService.getCurrent() === fte) {
- throw new Error('Focus trap is already enabled for this instance.');
- }
-
- // Note that first-focus only shows a focus ring when an overlay is first opened
- // if the overlay is opened via keyboard navigation. This is a browser behavior, not a bug.
- this.firstFocusElement =
- (firstFocusElement as HTMLElement) || (contentWrapper as HTMLElement) || this.focusTrapElement;
-
- addReboundElementsToFocusTrapElement(fte);
-
- if (!isFocusable(this.firstFocusElement)) {
- this.firstFocusElement.setAttribute('tabindex', '-1');
- }
-
- if (activeEl && isHTMLElement(activeEl)) {
- this.previousFocus = activeEl as HTMLElement;
- }
-
- FocusTrapTrackerService.setCurrent(fte);
-
- // setTimeout here is required for Safari which may try to set focus on
- // element before it is visible...
- const focusTimer = setTimeout(() => {
- this.firstFocusElement.focus();
- clearTimeout(focusTimer);
- }, 1);
-
- this.onFocusInEvent = this.onFocusIn.bind(this);
- document.addEventListener('focusin', this.onFocusInEvent);
- this.active = true;
- }
-
- removeFocusTrap() {
- document.removeEventListener('focusin', this.onFocusInEvent);
- removeReboundElementsFromFocusTrapElement(this.focusTrapElement);
- FocusTrapTrackerService.activatePreviousCurrent();
- this.active = false;
- if (this.previousFocus) {
- // timeout here helps screen readers behave more consistently when focus traps are closed
- const focusTimer = setTimeout(() => {
- this.previousFocus.focus();
- clearTimeout(focusTimer);
- }, 1);
- }
- }
-
- private onFocusIn(event: FocusEvent) {
- refocusIfOutsideFocusTrapElement(
- event.composedPath()[0] as HTMLElement,
- this.focusTrapElement,
- this.firstFocusElement
- );
- }
-}
diff --git a/packages/react/src/button/index.tsx b/packages/react/src/button/index.tsx
index 84d3a76d7..5922f6f11 100644
--- a/packages/react/src/button/index.tsx
+++ b/packages/react/src/button/index.tsx
@@ -1,5 +1,4 @@
import { CdsButton as Button, CdsIconButton as IconButton } from '@cds/core/button';
-import { CdsButtonInline as InlineButton } from '@cds/core/button-inline';
import '@cds/core/button/register';
import { createComponent } from '@lit-labs/react';
import * as React from 'react';
@@ -7,6 +6,5 @@ import { logReactVersion } from '../utils/index';
export const CdsButton = createComponent(React, 'cds-button', Button, {}, 'CdsButton');
export const CdsIconButton = createComponent(React, 'cds-icon-button', IconButton, {}, 'CdsIconButton');
-export const CdsInlineButton = createComponent(React, 'cds-inline-button', InlineButton, {}, 'CdsInlineButton');
logReactVersion(React);