mirror of
https://github.com/shoelace-style/webawesome.git
synced 2026-01-12 12:09:26 +00:00
more fixes
This commit is contained in:
@@ -286,4 +286,4 @@ Mark a slider as required using the `required` attribute. Users must interact wi
|
||||
<br />
|
||||
<button type="submit">Submit</button>
|
||||
</form>
|
||||
```
|
||||
```
|
||||
@@ -12,9 +12,9 @@ import formControlStyles from '../../styles/component/form-control.css';
|
||||
import appearanceStyles from '../../styles/utilities/appearance.css';
|
||||
import sizeStyles from '../../styles/utilities/size.css';
|
||||
import { LocalizeController } from '../../utilities/localize.js';
|
||||
import type WaButton from '../button/button.js';
|
||||
import '../icon/icon.js';
|
||||
import styles from './input.css';
|
||||
import { submitOnEnter } from '../../internal/submit-on-enter.js';
|
||||
|
||||
/**
|
||||
* @summary Inputs collect data from the user.
|
||||
@@ -245,51 +245,7 @@ export default class WaInput extends WebAwesomeFormAssociatedElement {
|
||||
}
|
||||
|
||||
private handleKeyDown(event: KeyboardEvent) {
|
||||
const hasModifier = event.metaKey || event.ctrlKey || event.shiftKey || event.altKey;
|
||||
|
||||
// Pressing enter when focused on an input should submit the form like a native input, but we wait a tick before
|
||||
// submitting to allow users to cancel the keydown event if they need to
|
||||
if (event.key === 'Enter' && !hasModifier) {
|
||||
setTimeout(() => {
|
||||
//
|
||||
// When using an Input Method Editor (IME), pressing enter will cause the form to submit unexpectedly. One way
|
||||
// to check for this is to look at event.isComposing, which will be true when the IME is open.
|
||||
//
|
||||
// See https://github.com/shoelace-style/shoelace/pull/988
|
||||
//
|
||||
if (!event.defaultPrevented && !event.isComposing) {
|
||||
const form = this.getForm();
|
||||
|
||||
if (!form) {
|
||||
return;
|
||||
}
|
||||
|
||||
const formElements = [...form.elements];
|
||||
|
||||
// If we're the only formElement, we submit like a native input.
|
||||
if (formElements.length === 1) {
|
||||
form.requestSubmit(null);
|
||||
return;
|
||||
}
|
||||
|
||||
const button = formElements.find(
|
||||
(el: HTMLButtonElement) => el.type === 'submit' && !el.matches(':disabled'),
|
||||
) as undefined | HTMLButtonElement | WaButton;
|
||||
|
||||
// No button found, don't submit.
|
||||
if (!button) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (button.tagName.toLowerCase() === 'button') {
|
||||
form.requestSubmit(button);
|
||||
} else {
|
||||
// requestSubmit() wont work with `<wa-button>`
|
||||
button.click();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
submitOnEnter(event, this)
|
||||
}
|
||||
|
||||
private handlePasswordToggle() {
|
||||
|
||||
@@ -13,6 +13,7 @@ import { LocalizeController } from '../../utilities/localize.js';
|
||||
import '../tooltip/tooltip.js';
|
||||
import type WaTooltip from '../tooltip/tooltip.js';
|
||||
import styles from './slider.css';
|
||||
import { submitOnEnter } from '../../internal/submit-on-enter.js';
|
||||
|
||||
/**
|
||||
* <wa-slider>
|
||||
@@ -79,7 +80,7 @@ export default class WaSlider extends WebAwesomeFormAssociatedElement {
|
||||
private readonly hasSlotController = new HasSlotController(this, 'hint', 'label');
|
||||
private readonly localize = new LocalizeController(this);
|
||||
private trackBoundingClientRect: DOMRect;
|
||||
private valueWhenDraggingStarted: number | undefined;
|
||||
private valueWhenDraggingStarted: number | undefined | null;
|
||||
private activeThumb: 'min' | 'max' | null = null;
|
||||
private lastTrackPosition: number | null = null; // Track last position for direction detection
|
||||
|
||||
@@ -111,10 +112,20 @@ export default class WaSlider extends WebAwesomeFormAssociatedElement {
|
||||
/** The name of the slider. This will be submitted with the form as a name/value pair. */
|
||||
@property({ reflect: true }) name: string;
|
||||
|
||||
private _value: number | null = null;
|
||||
/** The minimum value of a range selection. Used only when range attribute is set. */
|
||||
@property({ type: Number, attribute: 'min-value' }) minValue = 0;
|
||||
|
||||
/** The maximum value of a range selection. Used only when range attribute is set. */
|
||||
@property({ type: Number, attribute: 'max-value' }) maxValue = 50;
|
||||
|
||||
/** The default value of the form control. Primarily used for resetting the form control. */
|
||||
@property({ attribute: 'value', reflect: true, type: Number }) defaultValue: number =
|
||||
this.getAttribute('value') == null ? this.minValue : Number(this.getAttribute("value"));
|
||||
|
||||
private _value: number = this.defaultValue;
|
||||
|
||||
/** The current value of the slider, submitted as a name/value pair with form data. */
|
||||
get value() {
|
||||
get value(): number {
|
||||
if (this.valueHasChanged) {
|
||||
return this._value;
|
||||
}
|
||||
@@ -124,7 +135,7 @@ export default class WaSlider extends WebAwesomeFormAssociatedElement {
|
||||
|
||||
@state()
|
||||
set value(val: number | null) {
|
||||
val = Number(val) ?? null;
|
||||
val = Number(val) ?? this.minValue;
|
||||
|
||||
if (this._value === val) {
|
||||
return;
|
||||
@@ -134,15 +145,6 @@ export default class WaSlider extends WebAwesomeFormAssociatedElement {
|
||||
this._value = val;
|
||||
}
|
||||
|
||||
/** The minimum value of a range selection. Used only when range attribute is set. */
|
||||
@property({ type: Number, attribute: 'min-value' }) minValue = 0;
|
||||
|
||||
/** The maximum value of a range selection. Used only when range attribute is set. */
|
||||
@property({ type: Number, attribute: 'max-value' }) maxValue = 50;
|
||||
|
||||
/** The default value of the form control. Primarily used for resetting the form control. */
|
||||
@property({ attribute: 'value', reflect: true, type: Number }) defaultValue: number | null =
|
||||
Number(this.getAttribute('value')) || this.minValue;
|
||||
|
||||
/** Converts the slider to a range slider with two thumbs. */
|
||||
@property({ type: Boolean, reflect: true }) range = false;
|
||||
@@ -210,16 +212,6 @@ export default class WaSlider extends WebAwesomeFormAssociatedElement {
|
||||
*/
|
||||
@property({ attribute: false }) valueFormatter: (value: number) => string;
|
||||
|
||||
connectedCallback() {
|
||||
super.connectedCallback();
|
||||
this.addEventListener('invalid', this.handleHostInvalid);
|
||||
}
|
||||
|
||||
disconnectedCallback() {
|
||||
super.disconnectedCallback();
|
||||
this.removeEventListener('invalid', this.handleHostInvalid);
|
||||
}
|
||||
|
||||
firstUpdated() {
|
||||
// Setup dragging based on range or single thumb mode
|
||||
if (this.isRange) {
|
||||
@@ -384,7 +376,9 @@ export default class WaSlider extends WebAwesomeFormAssociatedElement {
|
||||
} else {
|
||||
// Handle value for single thumb mode
|
||||
if (changedProperties.has('value')) {
|
||||
this.value = clamp(this.value, this.min, this.max);
|
||||
if (this.value != null) {
|
||||
this.value = clamp(this.value, this.min, this.max);
|
||||
}
|
||||
this.setValue(String(this.value));
|
||||
}
|
||||
}
|
||||
@@ -434,9 +428,7 @@ export default class WaSlider extends WebAwesomeFormAssociatedElement {
|
||||
} else {
|
||||
this.value = parseFloat(this.getAttribute('value') ?? String(this.min));
|
||||
}
|
||||
this.isInvalid = false;
|
||||
this.hasInteracted = false;
|
||||
this.wasSubmitted = false;
|
||||
super.formResetCallback();
|
||||
}
|
||||
|
||||
@@ -509,16 +501,6 @@ export default class WaSlider extends WebAwesomeFormAssociatedElement {
|
||||
this.dispatchEvent(new FocusEvent('focus', { bubbles: true, composed: true }));
|
||||
}
|
||||
|
||||
private handleHostInvalid() {
|
||||
//
|
||||
// We need to simulate the :user-invalid state when the form is submitted. Alas, there's no way to listen to form
|
||||
// submit because validation occurs before the `formdata` and `submit` events. The only way I've found to hook into
|
||||
// it is by listening to the `invalid` event on the host element, which is dispatched by the browser when the form
|
||||
// is submitted and the form-associated custom element is invalid.
|
||||
//
|
||||
this.wasSubmitted = true;
|
||||
}
|
||||
|
||||
private handleKeyDown(event: KeyboardEvent) {
|
||||
const isRtl = this.localize.dir() === 'rtl';
|
||||
const target = event.target as HTMLElement;
|
||||
@@ -591,15 +573,7 @@ export default class WaSlider extends WebAwesomeFormAssociatedElement {
|
||||
|
||||
// Handle form submission on Enter
|
||||
case 'Enter':
|
||||
if (this.internals.form) {
|
||||
const submitter = [...this.internals.form.elements].find((el: HTMLInputElement | HTMLButtonElement) => {
|
||||
// The first submit button associated with the form will be the submitter. At this time, only native buttons
|
||||
// can be submitters (see https://github.com/WICG/webcomponents/issues/814)
|
||||
return ['button', 'input'].includes(el.localName) && el.type === 'submit';
|
||||
}) as HTMLElement;
|
||||
|
||||
this.internals.form.requestSubmit(submitter);
|
||||
}
|
||||
submitOnEnter(event, this)
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
63
packages/webawesome/src/internal/submit-on-enter.ts
Normal file
63
packages/webawesome/src/internal/submit-on-enter.ts
Normal file
@@ -0,0 +1,63 @@
|
||||
import type WaButton from "../components/button/button.js";
|
||||
import type { WebAwesomeFormAssociatedElement } from "./webawesome-form-associated-element.js";
|
||||
|
||||
export function submitOnEnter<T extends HTMLElement>(event: KeyboardEvent, el: T) {
|
||||
const hasModifier = event.metaKey || event.ctrlKey || event.shiftKey || event.altKey;
|
||||
|
||||
// Pressing enter when focused on an input should submit the form like a native input, but we wait a tick before
|
||||
// submitting to allow users to cancel the keydown event if they need to
|
||||
if (event.key === 'Enter' && !hasModifier) {
|
||||
// setTimeout in case the event is caught higher up in the tree and defaultPrevented
|
||||
setTimeout(() => {
|
||||
//
|
||||
// When using an Input Method Editor (IME), pressing enter will cause the form to submit unexpectedly. One way
|
||||
// to check for this is to look at event.isComposing, which will be true when the IME is open.
|
||||
//
|
||||
// See https://github.com/shoelace-style/shoelace/pull/988
|
||||
//
|
||||
if (!event.defaultPrevented && !event.isComposing) {
|
||||
submitForm(el)
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export function submitForm (el: HTMLElement | WebAwesomeFormAssociatedElement) {
|
||||
let form: HTMLFormElement | null = null
|
||||
|
||||
if ("form" in el) {
|
||||
form = el.form as HTMLFormElement | null
|
||||
}
|
||||
|
||||
if (!form && "getForm" in el) {
|
||||
form = el.getForm()
|
||||
}
|
||||
|
||||
if (!form) {
|
||||
return;
|
||||
}
|
||||
|
||||
const formElements = [...form.elements];
|
||||
|
||||
// If we're the only formElement, we submit like a native input.
|
||||
if (formElements.length === 1) {
|
||||
form.requestSubmit(null);
|
||||
return;
|
||||
}
|
||||
|
||||
const button = formElements.find(
|
||||
(el: HTMLButtonElement) => el.type === 'submit' && !el.matches(':disabled'),
|
||||
) as undefined | HTMLButtonElement | WaButton;
|
||||
|
||||
// No button found, don't submit.
|
||||
if (!button) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (['input', 'button'].includes(button.localName)) {
|
||||
form.requestSubmit(button);
|
||||
} else {
|
||||
// requestSubmit() wont work with `<wa-button>`, so trigger a manual click.
|
||||
button.click();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user