-
Notifications
You must be signed in to change notification settings - Fork 907
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
chore(behaviors): add ElementInternals mixin
PiperOrigin-RevId: 576657058
- Loading branch information
1 parent
0ebd7c7
commit 9137062
Showing
7 changed files
with
122 additions
and
56 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,62 @@ | ||
/** | ||
* @license | ||
* Copyright 2023 Google LLC | ||
* SPDX-License-Identifier: Apache-2.0 | ||
*/ | ||
|
||
import {LitElement} from 'lit'; | ||
|
||
import {MixinBase, MixinReturn} from './mixin.js'; | ||
|
||
/** | ||
* A unique symbol used for protected access to an instance's | ||
* `ElementInternals`. | ||
* | ||
* @example | ||
* ```ts | ||
* class MyElement extends mixinElementInternals(LitElement) { | ||
* constructor() { | ||
* super(); | ||
* this[internals].role = 'button'; | ||
* } | ||
* } | ||
* ``` | ||
*/ | ||
export const internals = Symbol('internals'); | ||
|
||
/** | ||
* An instance with an `internals` symbol property for the component's | ||
* `ElementInternals`. | ||
* | ||
* Use this when protected access is needed for an instance's `ElementInternals` | ||
* from other files. A unique symbol is used to access the internals. | ||
*/ | ||
export interface WithElementInternals { | ||
/** | ||
* An instance's `ElementInternals`. | ||
*/ | ||
[internals]: ElementInternals; | ||
} | ||
|
||
/** | ||
* Mixes in an attached `ElementInternals` instance. | ||
* | ||
* This mixin is only needed when other shared code needs access to a | ||
* component's `ElementInternals`, such as form-associated mixins. | ||
* | ||
* @param base The class to mix functionality into. | ||
* @return The provided class with `WithElementInternals` mixed in. | ||
*/ | ||
export function mixinElementInternals<T extends MixinBase<LitElement>>( | ||
base: T, | ||
): MixinReturn<T, WithElementInternals> { | ||
abstract class WithElementInternalsElement | ||
extends base | ||
implements WithElementInternals | ||
{ | ||
// Cast needed for closure | ||
[internals] = (this as HTMLElement).attachInternals(); | ||
} | ||
|
||
return WithElementInternalsElement; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
/** | ||
* @license | ||
* Copyright 2023 Google LLC | ||
* SPDX-License-Identifier: Apache-2.0 | ||
*/ | ||
|
||
// import 'jasmine'; (google3-only) | ||
|
||
import {html, LitElement} from 'lit'; | ||
import {customElement} from 'lit/decorators.js'; | ||
|
||
import {Environment} from '../../testing/environment.js'; | ||
|
||
import {internals, mixinElementInternals} from './element-internals.js'; | ||
|
||
describe('mixinElementInternals()', () => { | ||
@customElement('test-element-internals') | ||
class TestElementInternals extends mixinElementInternals(LitElement) {} | ||
|
||
const env = new Environment(); | ||
|
||
async function setupTest() { | ||
const root = env.render( | ||
html`<test-element-internals></test-element-internals>`, | ||
); | ||
const element = root.querySelector( | ||
'test-element-internals', | ||
) as TestElementInternals; | ||
await env.waitForStability(); | ||
return element; | ||
} | ||
|
||
it('should provide an `ElementInternals` instance', async () => { | ||
const element = await setupTest(); | ||
expect(element[internals]).toBeInstanceOf(ElementInternals); | ||
}); | ||
}); |