From 1cd856658b2b701398f6b0b2c9512e8c59dd4161 Mon Sep 17 00:00:00 2001 From: Liam DeBeasi Date: Mon, 1 Apr 2024 10:55:11 -0400 Subject: [PATCH 1/4] test(input): add failing test --- core/src/components/input/test/input.spec.ts | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/core/src/components/input/test/input.spec.ts b/core/src/components/input/test/input.spec.ts index ce52d4540a7..e90b6c70a03 100644 --- a/core/src/components/input/test/input.spec.ts +++ b/core/src/components/input/test/input.spec.ts @@ -99,3 +99,18 @@ describe('input: label rendering', () => { expect(labelText.textContent).toBe('Label Prop Text'); }); }); + +describe.only('input: clear icon', () => { + it('should render custom icon', async () => { + const page = await newSpecPage({ + components: [Input], + html: ` + + `, + }); + + const icon = page.body.querySelector('ion-input ion-icon')!; + + expect(icon.icon).toBe('foo'); + }); +}); From ac8efc01f51f83c695e19e869fd768a301d40423 Mon Sep 17 00:00:00 2001 From: Liam DeBeasi Date: Mon, 1 Apr 2024 10:58:53 -0400 Subject: [PATCH 2/4] update test --- core/src/components/input/test/input.spec.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/src/components/input/test/input.spec.ts b/core/src/components/input/test/input.spec.ts index e90b6c70a03..ad05ecdf28c 100644 --- a/core/src/components/input/test/input.spec.ts +++ b/core/src/components/input/test/input.spec.ts @@ -111,6 +111,6 @@ describe.only('input: clear icon', () => { const icon = page.body.querySelector('ion-input ion-icon')!; - expect(icon.icon).toBe('foo'); + expect(icon.getAttribute('icon')).toBe('foo'); }); }); From e78efc449adb1be751bd460f5596aa8767b1f73b Mon Sep 17 00:00:00 2001 From: Liam DeBeasi Date: Mon, 1 Apr 2024 10:59:53 -0400 Subject: [PATCH 3/4] add annotation --- core/src/components/input/test/input.spec.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/core/src/components/input/test/input.spec.ts b/core/src/components/input/test/input.spec.ts index ad05ecdf28c..245e7dd492f 100644 --- a/core/src/components/input/test/input.spec.ts +++ b/core/src/components/input/test/input.spec.ts @@ -100,7 +100,8 @@ describe('input: label rendering', () => { }); }); -describe.only('input: clear icon', () => { +// https://github.com/ionic-team/ionic-framework/issues/26974 +describe('input: clear icon', () => { it('should render custom icon', async () => { const page = await newSpecPage({ components: [Input], From 2cebaac67bb79a488cb8516eb7282bae0842b222 Mon Sep 17 00:00:00 2001 From: Liam DeBeasi Date: Mon, 1 Apr 2024 11:00:03 -0400 Subject: [PATCH 4/4] feat(input): add clearInputIcon --- core/api.txt | 1 + core/src/components.d.ts | 8 ++++++++ core/src/components/input/input.tsx | 11 +++++++++-- packages/angular/src/directives/proxies.ts | 4 ++-- packages/vue/src/proxies.ts | 1 + 5 files changed, 21 insertions(+), 4 deletions(-) diff --git a/core/api.txt b/core/api.txt index 4b6ca421436..e91c256322e 100644 --- a/core/api.txt +++ b/core/api.txt @@ -553,6 +553,7 @@ ion-input,prop,autocomplete,"name" | "on" | "off" | "honorific-prefix" | "given- ion-input,prop,autocorrect,"off" | "on",'off',false,false ion-input,prop,autofocus,boolean,false,false,false ion-input,prop,clearInput,boolean,false,false,false +ion-input,prop,clearInputIcon,string | undefined,undefined,false,false ion-input,prop,clearOnEdit,boolean | undefined,undefined,false,false ion-input,prop,color,"danger" | "dark" | "light" | "medium" | "primary" | "secondary" | "success" | "tertiary" | "warning" | string & Record | undefined,undefined,false,true ion-input,prop,counter,boolean,false,false,false diff --git a/core/src/components.d.ts b/core/src/components.d.ts index 4b85721b497..1f736e6a0ef 100644 --- a/core/src/components.d.ts +++ b/core/src/components.d.ts @@ -1162,6 +1162,10 @@ export namespace Components { * If `true`, a clear icon will appear in the input when there is a value. Clicking it clears the input. */ "clearInput": boolean; + /** + * The icon to use for the clear button. Only applies when `clearInput` is set to `true`. + */ + "clearInputIcon"?: string; /** * If `true`, the value will be cleared after focus upon edit. Defaults to `true` when `type` is `"password"`, `false` for all other types. */ @@ -5886,6 +5890,10 @@ declare namespace LocalJSX { * If `true`, a clear icon will appear in the input when there is a value. Clicking it clears the input. */ "clearInput"?: boolean; + /** + * The icon to use for the clear button. Only applies when `clearInput` is set to `true`. + */ + "clearInputIcon"?: string; /** * If `true`, the value will be cleared after focus upon edit. Defaults to `true` when `type` is `"password"`, `false` for all other types. */ diff --git a/core/src/components/input/input.tsx b/core/src/components/input/input.tsx index 15727fe0e04..2594897fb1c 100644 --- a/core/src/components/input/input.tsx +++ b/core/src/components/input/input.tsx @@ -92,6 +92,11 @@ export class Input implements ComponentInterface { */ @Prop() clearInput = false; + /** + * The icon to use for the clear button. Only applies when `clearInput` is set to `true`. + */ + @Prop() clearInputIcon?: string; + /** * If `true`, the value will be cleared after focus upon edit. Defaults to `true` when `type` is `"password"`, `false` for all other types. */ @@ -681,11 +686,13 @@ export class Input implements ComponentInterface { } render() { - const { disabled, fill, readonly, shape, inputId, labelPlacement, el, hasFocus } = this; + const { disabled, fill, readonly, shape, inputId, labelPlacement, el, hasFocus, clearInputIcon } = this; const mode = getIonMode(this); const value = this.getValue(); const inItem = hostContext('ion-item', this.el); const shouldRenderHighlight = mode === 'md' && fill !== 'outline' && !inItem; + const defaultClearIcon = mode === 'ios' ? closeCircle : closeSharp; + const clearIconData = clearInputIcon ?? defaultClearIcon; const hasValue = this.hasValue(); const hasStartEndSlots = el.querySelector('[slot="start"], [slot="end"]') !== null; @@ -784,7 +791,7 @@ export class Input implements ComponentInterface { }} onClick={this.clearTextInput} > - + )} diff --git a/packages/angular/src/directives/proxies.ts b/packages/angular/src/directives/proxies.ts index 8253b0876f2..1fb566daacf 100644 --- a/packages/angular/src/directives/proxies.ts +++ b/packages/angular/src/directives/proxies.ts @@ -955,7 +955,7 @@ export declare interface IonInfiniteScrollContent extends Components.IonInfinite @ProxyCmp({ - inputs: ['autocapitalize', 'autocomplete', 'autocorrect', 'autofocus', 'clearInput', 'clearOnEdit', 'color', 'counter', 'counterFormatter', 'debounce', 'disabled', 'enterkeyhint', 'errorText', 'fill', 'helperText', 'inputmode', 'label', 'labelPlacement', 'max', 'maxlength', 'min', 'minlength', 'mode', 'multiple', 'name', 'pattern', 'placeholder', 'readonly', 'required', 'shape', 'spellcheck', 'step', 'type', 'value'], + inputs: ['autocapitalize', 'autocomplete', 'autocorrect', 'autofocus', 'clearInput', 'clearInputIcon', 'clearOnEdit', 'color', 'counter', 'counterFormatter', 'debounce', 'disabled', 'enterkeyhint', 'errorText', 'fill', 'helperText', 'inputmode', 'label', 'labelPlacement', 'max', 'maxlength', 'min', 'minlength', 'mode', 'multiple', 'name', 'pattern', 'placeholder', 'readonly', 'required', 'shape', 'spellcheck', 'step', 'type', 'value'], methods: ['setFocus', 'getInputElement'] }) @Component({ @@ -963,7 +963,7 @@ export declare interface IonInfiniteScrollContent extends Components.IonInfinite changeDetection: ChangeDetectionStrategy.OnPush, template: '', // eslint-disable-next-line @angular-eslint/no-inputs-metadata-property - inputs: ['autocapitalize', 'autocomplete', 'autocorrect', 'autofocus', 'clearInput', 'clearOnEdit', 'color', 'counter', 'counterFormatter', 'debounce', 'disabled', 'enterkeyhint', 'errorText', 'fill', 'helperText', 'inputmode', 'label', 'labelPlacement', 'max', 'maxlength', 'min', 'minlength', 'mode', 'multiple', 'name', 'pattern', 'placeholder', 'readonly', 'required', 'shape', 'spellcheck', 'step', 'type', 'value'], + inputs: ['autocapitalize', 'autocomplete', 'autocorrect', 'autofocus', 'clearInput', 'clearInputIcon', 'clearOnEdit', 'color', 'counter', 'counterFormatter', 'debounce', 'disabled', 'enterkeyhint', 'errorText', 'fill', 'helperText', 'inputmode', 'label', 'labelPlacement', 'max', 'maxlength', 'min', 'minlength', 'mode', 'multiple', 'name', 'pattern', 'placeholder', 'readonly', 'required', 'shape', 'spellcheck', 'step', 'type', 'value'], }) export class IonInput { protected el: HTMLElement; diff --git a/packages/vue/src/proxies.ts b/packages/vue/src/proxies.ts index 30d640d44f2..75e032378f9 100644 --- a/packages/vue/src/proxies.ts +++ b/packages/vue/src/proxies.ts @@ -402,6 +402,7 @@ export const IonInput = /*@__PURE__*/ defineContainer