feat: support cross-root registration with form-element-register event
This commit is contained in:
parent
79a64674f8
commit
37deecd2a3
4 changed files with 85 additions and 3 deletions
5
.changeset/happy-jars-joke.md
Normal file
5
.changeset/happy-jars-joke.md
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
'@lion/ui': patch
|
||||
---
|
||||
|
||||
Added support for cross-root registration by adding a flag to composed property of form-element-register event.
|
||||
|
|
@ -28,6 +28,19 @@ const FormRegisteringMixinImplementation = superclass =>
|
|||
* @type {FormRegistrarHost | undefined}
|
||||
*/
|
||||
this._parentFormGroup = undefined;
|
||||
/**
|
||||
* To encourage accessibility best practices, `form-element-register` events
|
||||
* do not pierce through shadow roots. This forces the developer to create form groups and fieldsets that automatically allow the creation of accessible relationships in the same dom tree.
|
||||
Use this option if you know what you're doing. It will then be possible to nest FormControls
|
||||
inside shadow dom. See https://lion-web.netlify.app/fundamentals/rationales/accessibility/#shadow-roots-and-accessibility
|
||||
*/
|
||||
this.allowCrossRootRegistration = false;
|
||||
}
|
||||
|
||||
static get properties() {
|
||||
return {
|
||||
allowCrossRootRegistration: { type: Boolean, attribute: 'allow-cross-root-registration' },
|
||||
};
|
||||
}
|
||||
|
||||
connectedCallback() {
|
||||
|
|
@ -36,6 +49,7 @@ const FormRegisteringMixinImplementation = superclass =>
|
|||
new CustomEvent('form-element-register', {
|
||||
detail: { element: this },
|
||||
bubbles: true,
|
||||
composed: Boolean(this.allowCrossRootRegistration),
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,11 +1,12 @@
|
|||
import { LitElement } from 'lit';
|
||||
import { uuid } from '@lion/ui/core.js';
|
||||
import { defineCE, expect, fixture, html, unsafeStatic } from '@open-wc/testing';
|
||||
import {
|
||||
FormRegisteringMixin,
|
||||
FormRegistrarMixin,
|
||||
FormRegistrarPortalMixin,
|
||||
} from '@lion/ui/form-core.js';
|
||||
import { defineCE, expect, fixture, html, unsafeStatic } from '@open-wc/testing';
|
||||
import { LitElement } from 'lit';
|
||||
import sinon from 'sinon';
|
||||
|
||||
/**
|
||||
* @typedef {Object} customConfig
|
||||
|
|
@ -256,6 +257,60 @@ export const runRegistrationSuite = customConfig => {
|
|||
]);
|
||||
});
|
||||
|
||||
describe('FormRegisteringMixin', () => {
|
||||
it('propagates the form-element-register event through the shadowDom', async () => {
|
||||
const eventSpy = sinon.spy();
|
||||
const withShadowFormControlStr = defineCE(
|
||||
class extends FormRegistrarMixin(LitElement) {
|
||||
render() {
|
||||
return html`
|
||||
<${childTag}
|
||||
id="child"
|
||||
@form-element-register=${eventSpy}
|
||||
allow-cross-root-registration
|
||||
>
|
||||
</${childTag}>`;
|
||||
}
|
||||
},
|
||||
);
|
||||
const withShadowFormControlTag = unsafeStatic(withShadowFormControlStr);
|
||||
|
||||
const el = /** @type {RegistrarClass} */ (
|
||||
await fixture(html`
|
||||
<${withShadowFormControlTag}>
|
||||
</${withShadowFormControlTag}>
|
||||
`)
|
||||
);
|
||||
|
||||
expect(eventSpy).to.have.been.calledOnce;
|
||||
expect(eventSpy.getCall(0).args[0].composed).to.equal(true);
|
||||
expect(el.formElements).to.deep.equal([el.shadowRoot?.querySelector('#child')]);
|
||||
});
|
||||
it('dispatches the form-element-register event with compose true if allowCrossRootRegistration is set', async () => {
|
||||
const eventSpy = sinon.spy();
|
||||
/** @type {RegisteringClass} */ (
|
||||
await fixture(html`
|
||||
<${childTag}
|
||||
@form-element-register=${eventSpy}
|
||||
allow-cross-root-registration
|
||||
>
|
||||
</${childTag}>
|
||||
`)
|
||||
);
|
||||
expect(eventSpy).to.have.been.calledOnce;
|
||||
expect(eventSpy.getCall(0).args[0].composed).to.equal(true);
|
||||
});
|
||||
it('dispatches the form-element-register event with compose false if allowCrossRootRegistration is not set', async () => {
|
||||
const eventSpy = sinon.spy();
|
||||
/** @type {RegisteringClass} */ (
|
||||
await fixture(html`
|
||||
<${childTag} @form-element-register=${eventSpy}></${childTag}>
|
||||
`)
|
||||
);
|
||||
expect(eventSpy).to.have.been.calledOnce;
|
||||
expect(eventSpy.getCall(0).args[0].composed).to.equal(false);
|
||||
});
|
||||
});
|
||||
describe('FormRegistrarPortalMixin', () => {
|
||||
it('forwards registrations to the .registrationTarget', async () => {
|
||||
const el = /** @type {RegistrarClass} */ (
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import { LitElement } from 'lit';
|
||||
import { Constructor } from '@open-wc/dedupe-mixin';
|
||||
import { LitElement } from 'lit';
|
||||
|
||||
import { FormRegistrarHost } from './FormRegistrarMixinTypes.js';
|
||||
|
||||
|
|
@ -8,6 +8,14 @@ export declare class FormRegisteringHost {
|
|||
* The name the host is registered with to a parent
|
||||
*/
|
||||
name: string;
|
||||
/**
|
||||
* To encourage accessibility best practices, `form-element-register` events
|
||||
* do not pierce through shadow roots. This forces the developer to create form groups and fieldsets that
|
||||
* automatically allow the creation of accessible relationships in the same dom tree.
|
||||
* Use this option if you know what you're doing. It will then be possible to nest FormControls
|
||||
* inside shadow dom. See https://lion-web.netlify.app/fundamentals/rationales/accessibility#shadow-roots-and-accessibility
|
||||
*/
|
||||
allowCrossRootRegistration: boolean;
|
||||
|
||||
/**
|
||||
* The registrar this FormControl registers to, Usually a descendant of FormGroup or
|
||||
|
|
|
|||
Loading…
Reference in a new issue