mirror of
https://github.com/ionic-team/ionic-framework.git
synced 2025-11-08 23:58:13 +08:00
Merge branch 'main' into chore/update-next-from-main
This commit is contained in:
@ -2,7 +2,7 @@ import { NgZone } from '@angular/core';
|
||||
import type { Config, IonicWindow } from '@ionic/angular/common';
|
||||
import { raf } from '@ionic/angular/common';
|
||||
import { setupConfig } from '@ionic/core';
|
||||
import { applyPolyfills, defineCustomElements } from '@ionic/core/loader';
|
||||
import { defineCustomElements } from '@ionic/core/loader';
|
||||
|
||||
// TODO(FW-2827): types
|
||||
|
||||
@ -18,19 +18,17 @@ export const appInitialize = (config: Config, doc: Document, zone: NgZone) => {
|
||||
const aelFn =
|
||||
'__zone_symbol__addEventListener' in (doc.body as any) ? '__zone_symbol__addEventListener' : 'addEventListener';
|
||||
|
||||
return applyPolyfills().then(() => {
|
||||
return defineCustomElements(win, {
|
||||
exclude: ['ion-tabs'],
|
||||
syncQueue: true,
|
||||
raf,
|
||||
jmp: (h: any) => zone.runOutsideAngular(h),
|
||||
ael(elm, eventName, cb, opts) {
|
||||
(elm as any)[aelFn](eventName, cb, opts);
|
||||
},
|
||||
rel(elm, eventName, cb, opts) {
|
||||
elm.removeEventListener(eventName, cb, opts);
|
||||
},
|
||||
});
|
||||
return defineCustomElements(win, {
|
||||
exclude: ['ion-tabs'],
|
||||
syncQueue: true,
|
||||
raf,
|
||||
jmp: (h: any) => zone.runOutsideAngular(h),
|
||||
ael(elm, eventName, cb, opts) {
|
||||
(elm as any)[aelFn](eventName, cb, opts);
|
||||
},
|
||||
rel(elm, eventName, cb, opts) {
|
||||
elm.removeEventListener(eventName, cb, opts);
|
||||
},
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
@ -3,7 +3,7 @@ import { NG_VALUE_ACCESSOR } from '@angular/forms';
|
||||
import { ValueAccessor } from '@ionic/angular/common';
|
||||
|
||||
@Directive({
|
||||
selector: 'ion-input[type=number],ion-range',
|
||||
selector: 'ion-input[type=number],ion-input-otp:not([type=text]),ion-range',
|
||||
providers: [
|
||||
{
|
||||
provide: NG_VALUE_ACCESSOR,
|
||||
@ -18,12 +18,12 @@ export class NumericValueAccessorDirective extends ValueAccessor {
|
||||
}
|
||||
|
||||
@HostListener('ionInput', ['$event.target'])
|
||||
handleInputEvent(el: HTMLIonInputElement | HTMLIonRangeElement): void {
|
||||
handleInputEvent(el: HTMLIonInputElement | HTMLIonInputOtpElement | HTMLIonRangeElement): void {
|
||||
this.handleValueChange(el, el.value);
|
||||
}
|
||||
|
||||
registerOnChange(fn: (_: number | null) => void): void {
|
||||
if (this.el.nativeElement.tagName === 'ION-INPUT') {
|
||||
if (this.el.nativeElement.tagName === 'ION-INPUT' || this.el.nativeElement.tagName === 'ION-INPUT-OTP') {
|
||||
super.registerOnChange((value: string) => {
|
||||
fn(value === '' ? null : parseFloat(value));
|
||||
});
|
||||
|
||||
@ -3,7 +3,7 @@ import { NG_VALUE_ACCESSOR } from '@angular/forms';
|
||||
import { ValueAccessor } from '@ionic/angular/common';
|
||||
|
||||
@Directive({
|
||||
selector: 'ion-input:not([type=number]),ion-textarea,ion-searchbar',
|
||||
selector: 'ion-input:not([type=number]),ion-input-otp[type=text],ion-textarea,ion-searchbar',
|
||||
providers: [
|
||||
{
|
||||
provide: NG_VALUE_ACCESSOR,
|
||||
@ -18,7 +18,9 @@ export class TextValueAccessorDirective extends ValueAccessor {
|
||||
}
|
||||
|
||||
@HostListener('ionInput', ['$event.target'])
|
||||
_handleInputEvent(el: HTMLIonInputElement | HTMLIonTextareaElement | HTMLIonSearchbarElement): void {
|
||||
_handleInputEvent(
|
||||
el: HTMLIonInputElement | HTMLIonInputOtpElement | HTMLIonTextareaElement | HTMLIonSearchbarElement
|
||||
): void {
|
||||
this.handleValueChange(el, el.value);
|
||||
}
|
||||
}
|
||||
|
||||
@ -37,6 +37,7 @@ export const DIRECTIVES = [
|
||||
d.IonInfiniteScroll,
|
||||
d.IonInfiniteScrollContent,
|
||||
d.IonInput,
|
||||
d.IonInputOtp,
|
||||
d.IonInputPasswordToggle,
|
||||
d.IonItem,
|
||||
d.IonItemDivider,
|
||||
|
||||
@ -637,7 +637,7 @@ Set `scrollEvents` to `true` to enable.
|
||||
|
||||
|
||||
@ProxyCmp({
|
||||
inputs: ['cancelText', 'clearText', 'color', 'dayValues', 'disabled', 'doneText', 'firstDayOfWeek', 'formatOptions', 'highlightedDates', 'hourCycle', 'hourValues', 'isDateEnabled', 'locale', 'max', 'min', 'minuteValues', 'mode', 'monthValues', 'multiple', 'name', 'preferWheel', 'presentation', 'readonly', 'showClearButton', 'showDefaultButtons', 'showDefaultTimeLabel', 'showDefaultTitle', 'size', 'theme', 'titleSelectedDatesFormatter', 'value', 'yearValues'],
|
||||
inputs: ['cancelText', 'clearText', 'color', 'dayValues', 'disabled', 'doneText', 'firstDayOfWeek', 'formatOptions', 'highlightedDates', 'hourCycle', 'hourValues', 'isDateEnabled', 'locale', 'max', 'min', 'minuteValues', 'mode', 'monthValues', 'multiple', 'name', 'preferWheel', 'presentation', 'readonly', 'showAdjacentDays', 'showClearButton', 'showDefaultButtons', 'showDefaultTimeLabel', 'showDefaultTitle', 'size', 'theme', 'titleSelectedDatesFormatter', 'value', 'yearValues'],
|
||||
methods: ['confirm', 'reset', 'cancel']
|
||||
})
|
||||
@Component({
|
||||
@ -645,7 +645,7 @@ Set `scrollEvents` to `true` to enable.
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
template: '<ng-content></ng-content>',
|
||||
// eslint-disable-next-line @angular-eslint/no-inputs-metadata-property
|
||||
inputs: ['cancelText', 'clearText', 'color', 'dayValues', 'disabled', 'doneText', 'firstDayOfWeek', 'formatOptions', 'highlightedDates', 'hourCycle', 'hourValues', 'isDateEnabled', 'locale', 'max', 'min', 'minuteValues', 'mode', 'monthValues', 'multiple', 'name', 'preferWheel', 'presentation', 'readonly', 'showClearButton', 'showDefaultButtons', 'showDefaultTimeLabel', 'showDefaultTitle', 'size', 'theme', 'titleSelectedDatesFormatter', 'value', 'yearValues'],
|
||||
inputs: ['cancelText', 'clearText', 'color', 'dayValues', 'disabled', 'doneText', 'firstDayOfWeek', 'formatOptions', 'highlightedDates', 'hourCycle', 'hourValues', 'isDateEnabled', 'locale', 'max', 'min', 'minuteValues', 'mode', 'monthValues', 'multiple', 'name', 'preferWheel', 'presentation', 'readonly', 'showAdjacentDays', 'showClearButton', 'showDefaultButtons', 'showDefaultTimeLabel', 'showDefaultTitle', 'size', 'theme', 'titleSelectedDatesFormatter', 'value', 'yearValues'],
|
||||
})
|
||||
export class IonDatetime {
|
||||
protected el: HTMLIonDatetimeElement;
|
||||
@ -1042,6 +1042,69 @@ This event will not emit when programmatically setting the `value` property.
|
||||
}
|
||||
|
||||
|
||||
@ProxyCmp({
|
||||
inputs: ['autocapitalize', 'color', 'disabled', 'fill', 'inputmode', 'length', 'pattern', 'readonly', 'separators', 'shape', 'size', 'type', 'value'],
|
||||
methods: ['setFocus']
|
||||
})
|
||||
@Component({
|
||||
selector: 'ion-input-otp',
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
template: '<ng-content></ng-content>',
|
||||
// eslint-disable-next-line @angular-eslint/no-inputs-metadata-property
|
||||
inputs: ['autocapitalize', 'color', 'disabled', 'fill', 'inputmode', 'length', 'pattern', 'readonly', 'separators', 'shape', 'size', 'type', 'value'],
|
||||
})
|
||||
export class IonInputOtp {
|
||||
protected el: HTMLIonInputOtpElement;
|
||||
constructor(c: ChangeDetectorRef, r: ElementRef, protected z: NgZone) {
|
||||
c.detach();
|
||||
this.el = r.nativeElement;
|
||||
proxyOutputs(this, this.el, ['ionInput', 'ionChange', 'ionComplete', 'ionBlur', 'ionFocus']);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
import type { InputOtpInputEventDetail as IIonInputOtpInputOtpInputEventDetail } from '@ionic/core';
|
||||
import type { InputOtpChangeEventDetail as IIonInputOtpInputOtpChangeEventDetail } from '@ionic/core';
|
||||
import type { InputOtpCompleteEventDetail as IIonInputOtpInputOtpCompleteEventDetail } from '@ionic/core';
|
||||
|
||||
export declare interface IonInputOtp extends Components.IonInputOtp {
|
||||
/**
|
||||
* The `ionInput` event is fired each time the user modifies the input's value.
|
||||
Unlike the `ionChange` event, the `ionInput` event is fired for each alteration
|
||||
to the input's value. This typically happens for each keystroke as the user types.
|
||||
|
||||
For elements that accept text input (`type=text`, `type=tel`, etc.), the interface
|
||||
is [`InputEvent`](https://developer.mozilla.org/en-US/docs/Web/API/InputEvent); for others,
|
||||
the interface is [`Event`](https://developer.mozilla.org/en-US/docs/Web/API/Event). If
|
||||
the input is cleared on edit, the type is `null`.
|
||||
*/
|
||||
ionInput: EventEmitter<CustomEvent<IIonInputOtpInputOtpInputEventDetail>>;
|
||||
/**
|
||||
* The `ionChange` event is fired when the user modifies the input's value.
|
||||
Unlike the `ionInput` event, the `ionChange` event is only fired when changes
|
||||
are committed, not as the user types.
|
||||
|
||||
The `ionChange` event fires when the `<ion-input-otp>` component loses
|
||||
focus after its value has changed.
|
||||
|
||||
This event will not emit when programmatically setting the `value` property.
|
||||
*/
|
||||
ionChange: EventEmitter<CustomEvent<IIonInputOtpInputOtpChangeEventDetail>>;
|
||||
/**
|
||||
* Emitted when all input boxes have been filled with valid values.
|
||||
*/
|
||||
ionComplete: EventEmitter<CustomEvent<IIonInputOtpInputOtpCompleteEventDetail>>;
|
||||
/**
|
||||
* Emitted when the input group loses focus.
|
||||
*/
|
||||
ionBlur: EventEmitter<CustomEvent<FocusEvent>>;
|
||||
/**
|
||||
* Emitted when the input group has focus.
|
||||
*/
|
||||
ionFocus: EventEmitter<CustomEvent<FocusEvent>>;
|
||||
}
|
||||
|
||||
|
||||
@ProxyCmp({
|
||||
inputs: ['color', 'hideIcon', 'mode', 'showIcon']
|
||||
})
|
||||
|
||||
@ -86,6 +86,10 @@ export {
|
||||
InfiniteScrollCustomEvent,
|
||||
InputCustomEvent,
|
||||
InputChangeEventDetail,
|
||||
InputOtpCustomEvent,
|
||||
InputOtpChangeEventDetail,
|
||||
InputOtpCompleteEventDetail,
|
||||
InputOtpInputEventDetail,
|
||||
ItemReorderEventDetail,
|
||||
ItemReorderCustomEvent,
|
||||
ItemSlidingCustomEvent,
|
||||
|
||||
Reference in New Issue
Block a user