Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions BREAKING.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ This is a comprehensive list of the breaking changes introduced in the major ver
- [Card](#version-9x-card)
- [Chip](#version-9x-chip)
- [Grid](#version-9x-grid)
- [Input Otp](#version-9x-input-otp)
- [Radio Group](#version-9x-radio-group)
- [Textarea](#version-9x-textarea)

Expand Down Expand Up @@ -149,6 +150,12 @@ To reorder two columns where column 1 has `size="9" push="3"` and column 2 has `
</ion-grid>
```

<h4 id="version-9x-input-otp">Input Otp</h4>

Converted `ion-input-otp` to use [Shadow DOM](https://developer.mozilla.org/en-US/docs/Web/Web_Components/Using_shadow_DOM).

If you were targeting the internals of `ion-input-otp` in your CSS, you will need to target the `group`, `container`, `native`, `separator` or `description` [Shadow Parts](https://ionicframework.com/docs/theming/css-shadow-parts) instead, or use the provided CSS Variables.

<h4 id="version-9x-radio-group">Radio Group</h4>

Converted `ion-radio-group` to use [Shadow DOM](https://developer.mozilla.org/en-US/docs/Web/Web_Components/Using_shadow_DOM).
Expand Down
9 changes: 8 additions & 1 deletion core/api.txt
Original file line number Diff line number Diff line change
Expand Up @@ -1035,18 +1035,20 @@ ion-input,css-prop,--placeholder-opacity,ionic
ion-input,css-prop,--placeholder-opacity,ios
ion-input,css-prop,--placeholder-opacity,md

ion-input-otp,scoped
ion-input-otp,shadow
ion-input-otp,prop,autocapitalize,string,'off',false,false
ion-input-otp,prop,color,"danger" | "dark" | "light" | "medium" | "primary" | "secondary" | "success" | "tertiary" | "warning" | string & Record<never, never> | undefined,undefined,false,true
ion-input-otp,prop,disabled,boolean,false,false,true
ion-input-otp,prop,fill,"outline" | "solid" | undefined,'outline',false,false
ion-input-otp,prop,inputmode,"decimal" | "email" | "none" | "numeric" | "search" | "tel" | "text" | "url" | undefined,undefined,false,false
ion-input-otp,prop,length,number,4,false,false
ion-input-otp,prop,mode,"ios" | "md",undefined,false,false
ion-input-otp,prop,pattern,string | undefined,undefined,false,false
ion-input-otp,prop,readonly,boolean,false,false,true
ion-input-otp,prop,separators,number[] | string | undefined,undefined,false,false
ion-input-otp,prop,shape,"rectangular" | "round" | "soft",'round',false,false
ion-input-otp,prop,size,"large" | "medium" | "small",'medium',false,false
ion-input-otp,prop,theme,"ios" | "md" | "ionic",undefined,false,false
ion-input-otp,prop,type,"number" | "text",'number',false,false
ion-input-otp,prop,value,null | number | string | undefined,'',false,false
ion-input-otp,method,setFocus,setFocus(index?: number) => Promise<void>
Expand Down Expand Up @@ -1127,6 +1129,11 @@ ion-input-otp,css-prop,--separator-width,md
ion-input-otp,css-prop,--width,ionic
ion-input-otp,css-prop,--width,ios
ion-input-otp,css-prop,--width,md
ion-input-otp,part,container
ion-input-otp,part,description
ion-input-otp,part,group
ion-input-otp,part,native
ion-input-otp,part,separator

ion-input-password-toggle,shadow
ion-input-password-toggle,prop,color,"danger" | "dark" | "light" | "medium" | "primary" | "secondary" | "success" | "tertiary" | "warning" | string & Record<never, never> | undefined,undefined,false,true
Expand Down
16 changes: 16 additions & 0 deletions core/src/components.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1779,6 +1779,10 @@ export namespace Components {
* @default 4
*/
"length": number;
/**
* The mode determines the platform behaviors of the component.
*/
"mode"?: "ios" | "md";
/**
* A regex pattern string for allowed characters. Defaults based on type. For numbers (`type="number"`): `"[\p{N}]"` For text (`type="text"`): `"[\p{L}\p{N}]"`
*/
Expand Down Expand Up @@ -1807,6 +1811,10 @@ export namespace Components {
* @default 'medium'
*/
"size": 'small' | 'medium' | 'large';
/**
* The theme determines the visual appearance of the component.
*/
"theme"?: "ios" | "md" | "ionic";
/**
* The type of input allowed in the input boxes.
* @default 'number'
Expand Down Expand Up @@ -7762,6 +7770,10 @@ declare namespace LocalJSX {
* @default 4
*/
"length"?: number;
/**
* The mode determines the platform behaviors of the component.
*/
"mode"?: "ios" | "md";
/**
* Emitted when the input group loses focus.
*/
Expand Down Expand Up @@ -7805,6 +7817,10 @@ declare namespace LocalJSX {
* @default 'medium'
*/
"size"?: 'small' | 'medium' | 'large';
/**
* The theme determines the visual appearance of the component.
*/
"theme"?: "ios" | "md" | "ionic";
/**
* The type of input allowed in the input boxes.
* @default 'number'
Expand Down
3 changes: 3 additions & 0 deletions core/src/components/input-otp/input-otp.common.scss
Original file line number Diff line number Diff line change
Expand Up @@ -94,10 +94,13 @@
background: var(--background);
color: var(--color);

font-family: inherit;
font-size: inherit;

text-align: center;
appearance: none;

box-sizing: border-box;
}

:host(.has-focus) .native-input {
Expand Down
2 changes: 2 additions & 0 deletions core/src/components/input-otp/input-otp.native.scss
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@
--highlight-color-valid: #{ion-color(success, base)};
--highlight-color-invalid: #{ion-color(danger, base)};

font-family: $font-family-base;

font-size: dynamic-font(14px);
}

Expand Down
27 changes: 23 additions & 4 deletions core/src/components/input-otp/input-otp.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,14 +16,25 @@ import type {
InputOtpInputEventDetail,
} from './input-otp-interface';

/**
* @virtualProp {"ios" | "md"} mode - The mode determines the platform behaviors of the component.
* @virtualProp {"ios" | "md" | "ionic"} theme - The theme determines the visual appearance of the component.
*
* @part group - The container element that wraps all input boxes.
* @part container - The wrapper element for each individual input box.
* @part native - The native input element.
* @part separator - The separator element displayed between input boxes.
* @part description - The container element for the description text.
*/
@Component({
tag: 'ion-input-otp',
styleUrls: {
ios: 'input-otp.ios.scss',
md: 'input-otp.md.scss',
ionic: 'input-otp.ionic.scss',
},
scoped: true,
shadow: true,
formAssociated: true,
})
export class InputOTP implements ComponentInterface {
private inheritedAttributes: Attributes = {};
Expand Down Expand Up @@ -817,12 +828,19 @@ export class InputOTP implements ComponentInterface {
'input-otp-readonly': readonly,
})}
>
<div role="group" aria-label="One-time password input" class="input-otp-group" {...inheritedAttributes}>
<div
role="group"
aria-label="One-time password input"
class="input-otp-group"
part="group"
{...inheritedAttributes}
>
{Array.from({ length }).map((_, index) => (
<>
<div class="native-wrapper">
<div class="native-wrapper" part="container">
<input
class="native-input"
part="native"
id={`${inputId}-${index}`}
aria-label={`Input ${index + 1} of ${length}`}
type="text"
Expand All @@ -842,7 +860,7 @@ export class InputOTP implements ComponentInterface {
onPaste={this.onPaste}
/>
</div>
{this.showSeparator(index) && <div class="input-otp-separator" />}
{this.showSeparator(index) && <div class="input-otp-separator" part="separator" />}
</>
))}
</div>
Expand All @@ -851,6 +869,7 @@ export class InputOTP implements ComponentInterface {
'input-otp-description': true,
'input-otp-description-hidden': !hasDescription,
}}
part="description"
>
<slot></slot>
</div>
Expand Down
4 changes: 2 additions & 2 deletions packages/angular/src/directives/proxies.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1043,15 +1043,15 @@ 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'],
inputs: ['autocapitalize', 'color', 'disabled', 'fill', 'inputmode', 'length', 'mode', 'pattern', 'readonly', 'separators', 'shape', 'size', 'theme', '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'],
inputs: ['autocapitalize', 'color', 'disabled', 'fill', 'inputmode', 'length', 'mode', 'pattern', 'readonly', 'separators', 'shape', 'size', 'theme', 'type', 'value'],
})
export class IonInputOtp {
protected el: HTMLIonInputOtpElement;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ describe('Inputs', () => {
});

it('typing into input-otp should update ref', () => {
cy.get('ion-input-otp input').eq(0).type('1234', { scrollBehavior: false });
cy.get('ion-input-otp').shadow().find('input').eq(0).type('1234', { scrollBehavior: false });

cy.get('#input-otp-ref').should('have.text', '1234');
});
Expand Down
2 changes: 1 addition & 1 deletion packages/vue/test/base/tests/e2e/specs/inputs.cy.js
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ describe('Inputs', () => {
cy.get('#input-ref').should('have.text', 'Hello Input');
});
it('typing into input-otp should update ref', () => {
cy.get('ion-input-otp input').eq(0).type('1234', { scrollBehavior: false });
cy.get('ion-input-otp').shadow().find('input').eq(0).type('1234', { scrollBehavior: false });

cy.get('#input-otp-ref').should('have.text', '1234');
});
Expand Down
Loading