kopia lustrzana https://github.com/shoelace-style/shoelace
fixes #699
rodzic
eb18d759f1
commit
642de684e8
|
|
@ -35,7 +35,11 @@
|
||||||
"esbuild",
|
"esbuild",
|
||||||
"exportparts",
|
"exportparts",
|
||||||
"fieldsets",
|
"fieldsets",
|
||||||
|
"formaction",
|
||||||
"formdata",
|
"formdata",
|
||||||
|
"formmethod",
|
||||||
|
"formnovalidate",
|
||||||
|
"formtarget",
|
||||||
"FOUC",
|
"FOUC",
|
||||||
"FOUCE",
|
"FOUCE",
|
||||||
"fullscreen",
|
"fullscreen",
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,7 @@ _During the beta period, these restrictions may be relaxed in the event of a mis
|
||||||
|
|
||||||
## Next
|
## Next
|
||||||
|
|
||||||
|
- Added `form`, `formaction`, `formmethod`, `formnovalidate`, and `formtarget` attributes to `<sl-button>` [#699](https://github.com/shoelace-style/shoelace/issues/699)
|
||||||
- Improved `autofocus` behavior in Safari for `<sl-dialog>` and `<sl-drawer>` [#693](https://github.com/shoelace-style/shoelace/issues/693)
|
- Improved `autofocus` behavior in Safari for `<sl-dialog>` and `<sl-drawer>` [#693](https://github.com/shoelace-style/shoelace/issues/693)
|
||||||
- Removed feature detection for `focus({ preventScroll })` since it no longer works in Safari
|
- Removed feature detection for `focus({ preventScroll })` since it no longer works in Safari
|
||||||
- Removed path aliasing and third-party dependencies that it required
|
- Removed path aliasing and third-party dependencies that it required
|
||||||
|
|
|
||||||
|
|
@ -34,7 +34,20 @@ export default class SlButton extends LitElement {
|
||||||
|
|
||||||
@query('.button') button: HTMLButtonElement | HTMLLinkElement;
|
@query('.button') button: HTMLButtonElement | HTMLLinkElement;
|
||||||
|
|
||||||
private readonly formSubmitController = new FormSubmitController(this);
|
private readonly formSubmitController = new FormSubmitController(this, {
|
||||||
|
form: (input: HTMLInputElement) => {
|
||||||
|
// Buttons support a form attribute that points to an arbitrary form, so if this attribute it set we need to query
|
||||||
|
// the form from the same root using its id
|
||||||
|
if (input.hasAttribute('form')) {
|
||||||
|
const doc = input.getRootNode() as Document | ShadowRoot;
|
||||||
|
const formId = input.getAttribute('form')!;
|
||||||
|
return doc.getElementById(formId) as HTMLFormElement;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fall back to the closest containing form
|
||||||
|
return input.closest('form');
|
||||||
|
}
|
||||||
|
});
|
||||||
private readonly hasSlotController = new HasSlotController(this, '[default]', 'prefix', 'suffix');
|
private readonly hasSlotController = new HasSlotController(this, '[default]', 'prefix', 'suffix');
|
||||||
|
|
||||||
@state() private hasFocus = false;
|
@state() private hasFocus = false;
|
||||||
|
|
@ -85,6 +98,24 @@ export default class SlButton extends LitElement {
|
||||||
/** Tells the browser to download the linked file as this filename. Only used when `href` is set. */
|
/** Tells the browser to download the linked file as this filename. Only used when `href` is set. */
|
||||||
@property() download?: string;
|
@property() download?: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The "form owner" to associate the button with. If omitted, the closest containing form will be used instead. The
|
||||||
|
* value of this attribute must be an id of a form in the same document or shadow root as the button.
|
||||||
|
*/
|
||||||
|
@property() form: string;
|
||||||
|
|
||||||
|
/** Used to override the form owner's `action` attribute. */
|
||||||
|
@property({ attribute: 'formaction' }) formAction: string;
|
||||||
|
|
||||||
|
/** Used to override the form owner's `method` attribute. */
|
||||||
|
@property({ attribute: 'formmethod' }) formMethod: 'post' | 'get';
|
||||||
|
|
||||||
|
/** Used to override the form owner's `novalidate` attribute. */
|
||||||
|
@property({ attribute: 'formnovalidate', type: Boolean }) formNoValidate: boolean;
|
||||||
|
|
||||||
|
/** Used to override the form owner's `target` attribute. */
|
||||||
|
@property({ attribute: 'formtarget' }) formTarget: '_self' | '_blank' | '_parent' | '_top' | string;
|
||||||
|
|
||||||
/** Simulates a click on the button. */
|
/** Simulates a click on the button. */
|
||||||
click() {
|
click() {
|
||||||
this.button.click();
|
this.button.click();
|
||||||
|
|
@ -118,7 +149,7 @@ export default class SlButton extends LitElement {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.type === 'submit') {
|
if (this.type === 'submit') {
|
||||||
this.formSubmitController.submit();
|
this.formSubmitController.submit(this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@ import type { ReactiveController, ReactiveControllerHost, TemplateResult } from
|
||||||
import { html } from 'lit';
|
import { html } from 'lit';
|
||||||
import { classMap } from 'lit/directives/class-map.js';
|
import { classMap } from 'lit/directives/class-map.js';
|
||||||
import { ifDefined } from 'lit/directives/if-defined.js';
|
import { ifDefined } from 'lit/directives/if-defined.js';
|
||||||
|
import type SlButton from '../components/button/button';
|
||||||
import './formdata-event-polyfill';
|
import './formdata-event-polyfill';
|
||||||
|
|
||||||
export interface FormSubmitControllerOptions {
|
export interface FormSubmitControllerOptions {
|
||||||
|
|
@ -84,11 +85,11 @@ export class FormSubmitController implements ReactiveController {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
submit() {
|
submit(submitter?: HTMLInputElement | SlButton) {
|
||||||
// Calling form.submit() seems to bypass the submit event and constraint validation. Instead, we can inject a
|
// Calling form.submit() bypasses the submit event and constraint validation. To prevent this, we can inject a
|
||||||
// native submit button into the form, click it, then remove it to simulate a standard form submission.
|
// native submit button into the form, "click" it, then remove it to simulate a standard form submission.
|
||||||
const button = document.createElement('button');
|
|
||||||
if (this.form) {
|
if (this.form) {
|
||||||
|
const button = document.createElement('button');
|
||||||
button.type = 'submit';
|
button.type = 'submit';
|
||||||
button.style.position = 'absolute';
|
button.style.position = 'absolute';
|
||||||
button.style.width = '0';
|
button.style.width = '0';
|
||||||
|
|
@ -97,6 +98,15 @@ export class FormSubmitController implements ReactiveController {
|
||||||
button.style.clipPath = 'inset(50%)';
|
button.style.clipPath = 'inset(50%)';
|
||||||
button.style.overflow = 'hidden';
|
button.style.overflow = 'hidden';
|
||||||
button.style.whiteSpace = 'nowrap';
|
button.style.whiteSpace = 'nowrap';
|
||||||
|
|
||||||
|
// Pass form override properties through to the temporary button
|
||||||
|
if (submitter) {
|
||||||
|
button.formAction = submitter.formAction;
|
||||||
|
button.formMethod = submitter.formMethod;
|
||||||
|
button.formNoValidate = submitter.formNoValidate;
|
||||||
|
button.formTarget = submitter.formTarget;
|
||||||
|
}
|
||||||
|
|
||||||
this.form.append(button);
|
this.form.append(button);
|
||||||
button.click();
|
button.click();
|
||||||
button.remove();
|
button.remove();
|
||||||
|
|
|
||||||
Ładowanie…
Reference in New Issue