refactor(item): remove deprecated apis (#29102)

BREAKING CHANGE:

- The `helper` slot has been removed. Developers should use the `helperText` property on `ion-input` and `ion-textarea`.
- The `error` slot has been removed. Developers should use the `errorText` property on `ion-input` and `ion-textarea`.
- Counter functionality has been removed including the `counter` and `counterFormatter` properties. Developers should use the properties of the same name on `ion-input` and `ion-textarea`.
- The `fill` property has been removed. Developers should use the property of the same name on `ion-input`, `ion-select`, and `ion-textarea`.
- The `shape` property has been removed. Developers should use the property of the same name on `ion-input`, `ion-select`, and `ion-textarea`.
This commit is contained in:
Liam DeBeasi
2024-03-07 11:37:40 +00:00
committed by GitHub
parent 6852719077
commit 743f517fec
60 changed files with 21 additions and 917 deletions

View File

@ -21,6 +21,7 @@ This is a comprehensive list of the breaking changes introduced in the major ver
- [Checkbox](#version-8x-checkbox)
- [Content](#version-8x-content)
- [Datetime](#version-8x-datetime)
- [Item](#version-8x-item)
- [Input](#version-8x-input)
- [Item](#version-8x-item)
- [Modal](#version-8x-modal)
@ -162,6 +163,13 @@ For more information on the dynamic font, refer to the [Dynamic Font Scaling doc
+ background: red;
}
```
<h4 id="version-8x-item">Item</h4>
- The `helper` slot has been removed. Developers should use the `helperText` property on `ion-input` and `ion-textarea`.
- The `error` slot has been removed. Developers should use the `errorText` property on `ion-input` and `ion-textarea`.
- Counter functionality has been removed including the `counter` and `counterFormatter` properties. Developers should use the properties of the same name on `ion-input` and `ion-textarea`.
- The `fill` property has been removed. Developers should use the property of the same name on `ion-input`, `ion-select`, and `ion-textarea`.
- The `shape` property has been removed. Developers should use the property of the same name on `ion-input`, `ion-select`, and `ion-textarea`.
<h4 id="version-8x-input">Input</h4>

View File

@ -608,20 +608,16 @@ ion-input,css-prop,--placeholder-opacity
ion-item,shadow
ion-item,prop,button,boolean,false,false,false
ion-item,prop,color,"danger" | "dark" | "light" | "medium" | "primary" | "secondary" | "success" | "tertiary" | "warning" | string & Record<never, never> | undefined,undefined,false,true
ion-item,prop,counter,boolean,false,false,false
ion-item,prop,counterFormatter,((inputLength: number, maxLength: number) => string) | undefined,undefined,false,false
ion-item,prop,detail,boolean | undefined,undefined,false,false
ion-item,prop,detailIcon,string,chevronForward,false,false
ion-item,prop,disabled,boolean,false,false,false
ion-item,prop,download,string | undefined,undefined,false,false
ion-item,prop,fill,"outline" | "solid" | undefined,undefined,false,false
ion-item,prop,href,string | undefined,undefined,false,false
ion-item,prop,lines,"full" | "inset" | "none" | undefined,undefined,false,false
ion-item,prop,mode,"ios" | "md",undefined,false,false
ion-item,prop,rel,string | undefined,undefined,false,false
ion-item,prop,routerAnimation,((baseEl: any, opts?: any) => Animation) | undefined,undefined,false,false
ion-item,prop,routerDirection,"back" | "forward" | "root",'forward',false,false
ion-item,prop,shape,"round" | undefined,undefined,false,false
ion-item,prop,target,string | undefined,undefined,false,false
ion-item,prop,type,"button" | "reset" | "submit",'button',false,false
ion-item,css-prop,--background

View File

@ -18,7 +18,6 @@ import { ScrollBaseDetail, ScrollDetail } from "./components/content/content-int
import { DatetimeChangeEventDetail, DatetimeHighlight, DatetimeHighlightCallback, DatetimeHourCycle, DatetimePresentation, TitleSelectedDatesFormatter } from "./components/datetime/datetime-interface";
import { SpinnerTypes } from "./components/spinner/spinner-configs";
import { InputChangeEventDetail, InputInputEventDetail } from "./components/input/input-interface";
import { CounterFormatter } from "./components/item/item-interface";
import { MenuChangeEventDetail, Side } from "./components/menu/menu-interface";
import { ModalBreakpointChangeEventDetail, ModalHandleBehavior } from "./components/modal/modal-interface";
import { NavComponent, NavComponentWithProps, NavOptions, RouterOutletOptions, SwipeGestureHandler, TransitionDoneFn, TransitionInstruction } from "./components/nav/nav-interface";
@ -54,7 +53,6 @@ export { ScrollBaseDetail, ScrollDetail } from "./components/content/content-int
export { DatetimeChangeEventDetail, DatetimeHighlight, DatetimeHighlightCallback, DatetimeHourCycle, DatetimePresentation, TitleSelectedDatesFormatter } from "./components/datetime/datetime-interface";
export { SpinnerTypes } from "./components/spinner/spinner-configs";
export { InputChangeEventDetail, InputInputEventDetail } from "./components/input/input-interface";
export { CounterFormatter } from "./components/item/item-interface";
export { MenuChangeEventDetail, Side } from "./components/menu/menu-interface";
export { ModalBreakpointChangeEventDetail, ModalHandleBehavior } from "./components/modal/modal-interface";
export { NavComponent, NavComponentWithProps, NavOptions, RouterOutletOptions, SwipeGestureHandler, TransitionDoneFn, TransitionInstruction } from "./components/nav/nav-interface";
@ -1294,16 +1292,6 @@ export namespace Components {
* The color to use from your application's color palette. Default options are: `"primary"`, `"secondary"`, `"tertiary"`, `"success"`, `"warning"`, `"danger"`, `"light"`, `"medium"`, and `"dark"`. For more information on colors, see [theming](/docs/theming/basics).
*/
"color"?: Color;
/**
* If `true`, a character counter will display the ratio of characters used and the total character limit. Only applies when the `maxlength` property is set on the inner `ion-input` or `ion-textarea`.
* @deprecated Use the `counter` property on `ion-input` or `ion-textarea` instead.
*/
"counter": boolean;
/**
* A callback used to format the counter text. By default the counter text is set to "itemLength / maxLength".
* @deprecated Use the `counterFormatter` property on `ion-input` or `ion-textarea` instead.
*/
"counterFormatter"?: CounterFormatter;
/**
* If `true`, a detail arrow will appear on the item. Defaults to `false` unless the `mode` is `ios` and an `href` or `button` property is present.
*/
@ -1320,11 +1308,6 @@ export namespace Components {
* This attribute instructs browsers to download a URL instead of navigating to it, so the user will be prompted to save it as a local file. If the attribute has a value, it is used as the pre-filled file name in the Save prompt (the user can still change the file name if they want).
*/
"download": string | undefined;
/**
* The fill for the item. If `"solid"` the item will have a background. If `"outline"` the item will be transparent with a border. Only available in `md` mode.
* @deprecated Use the `fill` property on `ion-input` or `ion-textarea` instead.
*/
"fill"?: 'outline' | 'solid';
/**
* Contains a URL or a URL fragment that the hyperlink points to. If this property is set, an anchor tag will be rendered.
*/
@ -1349,10 +1332,6 @@ export namespace Components {
* When using a router, it specifies the transition direction when navigating to another page using `href`.
*/
"routerDirection": RouterDirection;
/**
* The shape of the item. If "round" it will have increased border radius.
*/
"shape"?: 'round';
/**
* Specifies where to display the linked URL. Only applies when an `href` is provided. Special keywords: `"_blank"`, `"_self"`, `"_parent"`, `"_top"`.
*/
@ -6009,16 +5988,6 @@ declare namespace LocalJSX {
* The color to use from your application's color palette. Default options are: `"primary"`, `"secondary"`, `"tertiary"`, `"success"`, `"warning"`, `"danger"`, `"light"`, `"medium"`, and `"dark"`. For more information on colors, see [theming](/docs/theming/basics).
*/
"color"?: Color;
/**
* If `true`, a character counter will display the ratio of characters used and the total character limit. Only applies when the `maxlength` property is set on the inner `ion-input` or `ion-textarea`.
* @deprecated Use the `counter` property on `ion-input` or `ion-textarea` instead.
*/
"counter"?: boolean;
/**
* A callback used to format the counter text. By default the counter text is set to "itemLength / maxLength".
* @deprecated Use the `counterFormatter` property on `ion-input` or `ion-textarea` instead.
*/
"counterFormatter"?: CounterFormatter;
/**
* If `true`, a detail arrow will appear on the item. Defaults to `false` unless the `mode` is `ios` and an `href` or `button` property is present.
*/
@ -6035,11 +6004,6 @@ declare namespace LocalJSX {
* This attribute instructs browsers to download a URL instead of navigating to it, so the user will be prompted to save it as a local file. If the attribute has a value, it is used as the pre-filled file name in the Save prompt (the user can still change the file name if they want).
*/
"download"?: string | undefined;
/**
* The fill for the item. If `"solid"` the item will have a background. If `"outline"` the item will be transparent with a border. Only available in `md` mode.
* @deprecated Use the `fill` property on `ion-input` or `ion-textarea` instead.
*/
"fill"?: 'outline' | 'solid';
/**
* Contains a URL or a URL fragment that the hyperlink points to. If this property is set, an anchor tag will be rendered.
*/
@ -6064,10 +6028,6 @@ declare namespace LocalJSX {
* When using a router, it specifies the transition direction when navigating to another page using `href`.
*/
"routerDirection"?: RouterDirection;
/**
* The shape of the item. If "round" it will have increased border radius.
*/
"shape"?: 'round';
/**
* Specifies where to display the linked URL. Only applies when an `href` is provided. Special keywords: `"_blank"`, `"_self"`, `"_parent"`, `"_top"`.
*/

View File

@ -33,7 +33,6 @@
--highlight-color-focused: #{$item-ios-input-highlight-color};
--highlight-color-valid: #{$item-ios-input-highlight-color-valid};
--highlight-color-invalid: #{$item-ios-input-highlight-color-invalid};
--bottom-padding-start: 0px;
font-size: $item-ios-font-size;
}
@ -149,7 +148,6 @@
@include margin($item-ios-label-slot-end-margin-top, $item-ios-label-slot-end-margin-end, $item-ios-label-slot-end-margin-bottom, $item-ios-label-slot-end-margin-start);
}
// iOS Item Button
// --------------------------------------------------
@ -204,7 +202,6 @@
@include margin(10px, 8px, 10px, 0);
}
// iOS Stacked & Floating Inputs
// --------------------------------------------------
@ -212,10 +209,3 @@
:host(.item-label-stacked) {
--min-height: 68px;
}
// iOS Fixed Labels
// --------------------------------------------------
:host(.item-label-fixed) ::slotted(ion-datetime) {
--padding-start: 0;
}

View File

@ -32,68 +32,6 @@
text-transform: none;
}
:host(.item-fill-outline) {
--highlight-height: 2px;
}
// Item Fill: None
// --------------------------------------------------
:host(.item-fill-none.item-interactive.ion-focus) .item-highlight,
:host(.item-fill-none.item-interactive.item-has-focus) .item-highlight,
:host(.item-fill-none.item-interactive.ion-touched.ion-invalid) .item-highlight {
transform: scaleX(1);
border-width: 0 0 var(--full-highlight-height) 0;
border-style: var(--border-style);
border-color: var(--highlight-background);
}
:host(.item-fill-none.item-interactive.ion-focus) .item-native,
:host(.item-fill-none.item-interactive.item-has-focus) .item-native,
:host(.item-fill-none.item-interactive.ion-touched.ion-invalid) .item-native {
border-bottom-color: var(--highlight-background);
}
// Item Fill: Outline
// --------------------------------------------------
:host(.item-fill-outline.item-interactive.ion-focus) .item-highlight,
:host(.item-fill-outline.item-interactive.item-has-focus) .item-highlight {
transform: scaleX(1);
}
:host(.item-fill-outline.item-interactive.ion-focus) .item-highlight,
:host(.item-fill-outline.item-interactive.item-has-focus) .item-highlight,
:host(.item-fill-outline.item-interactive.ion-touched.ion-invalid) .item-highlight {
border-width: var(--full-highlight-height);
border-style: var(--border-style);
border-color: var(--highlight-background);
}
:host(.item-fill-outline.item-interactive.ion-touched.ion-invalid) .item-native {
border-color: var(--highlight-background);
}
// Item Fill: Solid
// --------------------------------------------------
:host(.item-fill-solid.item-interactive.ion-focus) .item-highlight,
:host(.item-fill-solid.item-interactive.item-has-focus) .item-highlight,
:host(.item-fill-solid.item-interactive.ion-touched.ion-invalid) .item-highlight {
transform: scaleX(1);
border-width: 0 0 var(--full-highlight-height) 0;
border-style: var(--border-style);
border-color: var(--highlight-background);
}
:host(.item-fill-solid.item-interactive.ion-focus) .item-native,
:host(.item-fill-solid.item-interactive.item-has-focus) .item-native,
:host(.item-fill-solid.item-interactive.ion-touched.ion-invalid) .item-native {
border-bottom-color: var(--highlight-background);
}
// Material Design Item: States
// --------------------------------------------------
@ -147,25 +85,6 @@
--show-inset-highlight: 0;
}
/**
* When `fill="outline"`, reposition the highlight element to cover everything but the `.item-bottom`
*/
:host(.item-fill-outline) .item-highlight {
--position-offset: calc(-1 * var(--border-width));
@include position(var(--position-offset), null, null, var(--position-offset));
width: calc(100% + 2 * var(--border-width));
height: calc(100% + 2 * var(--border-width));
transition: none;
}
:host(.item-fill-outline.ion-focused) .item-native,
:host(.item-fill-outline.item-has-focus) .item-native {
border-color: transparent;
}
// Material Design Multi-line Item
// --------------------------------------------------
@ -188,14 +107,6 @@
@include margin-horizontal($item-md-end-slot-margin-start, $item-md-end-slot-margin-end);
}
:host(.item-fill-solid) ::slotted([slot="start"]),
:host(.item-fill-solid) ::slotted([slot="end"]),
:host(.item-fill-outline) ::slotted([slot="start"]),
:host(.item-fill-outline) ::slotted([slot="end"]) {
align-self: center;
}
// Material Design Slotted Icon
// --------------------------------------------------
@ -211,7 +122,7 @@
font-size: math.div($item-md-icon-slot-font-size, $item-md-font-size) * 1em;
}
:host(.ion-color:not(.item-fill-solid):not(.item-fill-outline)) ::slotted(ion-icon) {
:host(.ion-color) ::slotted(ion-icon) {
color: current-color(contrast);
}
@ -227,12 +138,6 @@
@include margin-horizontal($item-md-icon-end-slot-margin-start, $item-md-icon-end-slot-margin-end);
}
:host(.item-fill-solid) ::slotted(ion-icon[slot="start"]),
:host(.item-fill-outline) ::slotted(ion-icon[slot="start"]) {
@include margin-horizontal($item-md-icon-start-slot-margin-start, $item-md-input-icon-start-slot-margin-end);
}
// Material Design Slotted Toggle
// --------------------------------------------------
@ -253,7 +158,7 @@
font-size: $item-md-note-slot-font-size;
}
::slotted(ion-note[slot]:not([slot="helper"]):not([slot="error"])) {
::slotted(ion-note[slot]) {
@include padding($item-md-note-slot-padding-top, $item-md-note-slot-padding-end, $item-md-note-slot-padding-bottom, $item-md-note-slot-padding-start);
}
@ -298,7 +203,6 @@
@include margin($item-md-label-margin-top, $item-md-label-margin-end, $item-md-label-margin-bottom, $item-md-label-margin-start);
}
// Material Design Floating/Stacked Label
// --------------------------------------------------
@ -307,15 +211,6 @@
@include margin($item-md-label-slot-end-margin-top, $item-md-label-slot-end-margin-end, $item-md-label-slot-end-margin-bottom, $item-md-label-slot-end-margin-start);
}
// Material Design Fixed Labels
// --------------------------------------------------
:host(.item-label-fixed) ::slotted(ion-datetime) {
--padding-start: 8px;
}
// Material Design Toggle/Radio Item
// --------------------------------------------------
@ -324,7 +219,6 @@
@include margin-horizontal(0, null);
}
// Material Design Item Button
// --------------------------------------------------
@ -339,15 +233,6 @@
font-size: dynamic-font(12px);
}
// Material Design Radio Item Label: Checked
// -----------------------------------------
// .item-radio-checked.item-md ion-label {
// color: $radio-md-color-on;
// }
// Material Design Stacked & Floating Inputs
// --------------------------------------------------
@ -373,94 +258,3 @@
:host(.item-label-color) {
--highlight-color-focused: #{current-color(base)};
}
:host(.item-fill-solid.ion-color),
:host(.item-fill-outline.ion-color) {
--highlight-color-focused: #{current-color(base)};
}
// Material Design Item: Fill Solid
// --------------------------------------------------
:host(.item-fill-solid) {
--background: #{$item-md-input-fill-solid-background-color};
--background-hover: #{$item-md-input-fill-solid-background-color-hover};
--background-focused: #{$item-md-input-fill-solid-background-color-focus};
--border-width: 0 0 #{$item-md-border-bottom-width} 0;
--inner-border-width: 0;
@include border-radius(4px, 4px, 0, 0);
}
:host(.item-fill-solid) .item-native {
--border-color: #{$item-md-input-fill-border-color};
}
:host(.item-fill-solid.ion-focused) .item-native,
:host(.item-fill-solid.item-has-focus) .item-native {
--background: var(--background-focused);
}
:host(.item-fill-solid.item-shape-round) {
@include border-radius(16px, 16px, 0, 0);
}
@media (any-hover: hover) {
:host(.item-fill-solid:hover) .item-native {
--background: var(--background-hover);
--border-color: #{$item-md-input-fill-border-color-hover};
}
}
// Material Design Item: Fill Outline
// --------------------------------------------------
:host(.item-fill-outline) {
--ripple-color: transparent;
--background-focused: transparent;
--background-hover: transparent;
--border-color: #{$item-md-input-fill-border-color};
--border-width: #{$item-md-border-bottom-width};
border: none;
overflow: visible;
}
:host(.item-fill-outline) .item-native {
--native-padding-left: 16px;
@include border-radius(4px);
}
:host(.item-fill-outline.item-shape-round) .item-native {
--inner-padding-start: 16px;
@include border-radius(28px);
}
:host(.item-fill-outline.item-shape-round) .item-bottom {
@include padding-horizontal(32px, null);
}
:host(.item-fill-outline.item-label-floating.ion-focused) .item-native ::slotted(ion-input:not(:first-child)),
:host(.item-fill-outline.item-label-floating.ion-focused) .item-native ::slotted(ion-textarea:not(:first-child)),
:host(.item-fill-outline.item-label-floating.item-has-focus) .item-native ::slotted(ion-input:not(:first-child)),
:host(.item-fill-outline.item-label-floating.item-has-focus) .item-native ::slotted(ion-textarea:not(:first-child)),
:host(.item-fill-outline.item-label-floating.item-has-value) .item-native ::slotted(ion-input:not(:first-child)),
:host(.item-fill-outline.item-label-floating.item-has-value) .item-native ::slotted(ion-textarea:not(:first-child)) {
transform: translateY(-14px);
}
@media (any-hover: hover) {
:host(.item-fill-outline:hover) .item-native {
--border-color: #{$item-md-input-fill-border-color-hover};
}
}
// Material Design Text Field Character Counter
// --------------------------------------------------
.item-counter {
letter-spacing: #{$item-md-input-counter-letter-spacing};
}

View File

@ -45,15 +45,6 @@ $item-md-border-bottom-color: $item-md-border-color !default;
// Item Input
// --------------------------------------------------
/// @prop - Color of the item input background
$item-md-input-fill-solid-background-color: $background-color-step-50 !default;
/// @prop - Color of the item input background when hovered
$item-md-input-fill-solid-background-color-hover: $background-color-step-100 !default;
/// @prop - Color of the item input background when focused
$item-md-input-fill-solid-background-color-focus: $background-color-step-150 !default;
/// @prop - Color of the item input highlight
$item-md-input-highlight-color: ion-color(primary, base) !default;
@ -63,15 +54,6 @@ $item-md-input-highlight-color-valid: ion-color(success, base) !default;
/// @prop - Color of the item input highlight when invalid
$item-md-input-highlight-color-invalid: ion-color(danger, base) !default;
/// @prop - Color of the item border when `fill` is set
$item-md-input-fill-border-color: $background-color-step-500 !default;
/// @prop - Color of the item border when `fill` is set and hovered
$item-md-input-fill-border-color-hover: $background-color-step-750 !default;
/// @prop - Letter spacing of the item input counter
$item-md-input-counter-letter-spacing: .0333333333em !default;
// Item Label
// --------------------------------------------------
@ -87,12 +69,6 @@ $item-md-label-margin-bottom: 10px !default;
/// @prop - Margin start of the label
$item-md-label-margin-start: 0 !default;
/// @prop - X translation for floating labels
$item-md-fill-outline-label-translate-x: -32px !default;
/// @prop - Padding for floating labels
$item-md-fill-outline-label-padding: 4px !default;
// Item Slots
// --------------------------------------------------

View File

@ -99,13 +99,13 @@
// Item: Color
// --------------------------------------------------
:host(.ion-color:not(.item-fill-solid):not(.item-fill-outline)) .item-native {
:host(.ion-color) .item-native {
background: current-color(base);
color: current-color(contrast);
}
:host(.ion-color:not(.item-fill-solid):not(.item-fill-outline)) .item-native,
:host(.ion-color:not(.item-fill-solid):not(.item-fill-outline)) .item-inner {
:host(.ion-color) .item-native,
:host(.ion-color) .item-inner {
border-color: current-color(shade);
}
@ -307,32 +307,6 @@ button, a {
box-sizing: border-box;
}
// Item Bottom
// --------------------------------------------------
.item-bottom {
@include margin(0);
@include padding(0, null);
/* stylelint-disable */
@include ltr() {
padding-left: calc(var(--padding-start) + var(--ion-safe-area-left, 0px));
padding-right: calc(var(--inner-padding-end) + var(--ion-safe-area-right, 0px));
}
@include rtl() {
padding-left: calc(var(--inner-padding-end) + var(--ion-safe-area-left, 0px));
padding-right: calc(var(--padding-start) + var(--ion-safe-area-right, 0px));
}
/* stylelint-enable */
display: flex;
justify-content: space-between;
}
// Item Detail Icon
// --------------------------------------------------
@ -424,7 +398,6 @@ button, a {
flex-direction: column;
}
// Item Input Highlight
// --------------------------------------------------
@ -485,15 +458,10 @@ button, a {
opacity: var(--show-inset-highlight);
}
:host(.ion-focused.item-fill-solid) .item-highlight,
:host(.item-has-focus.item-fill-solid) .item-highlight {
border-width: calc(var(--full-highlight-height) - 1px);
}
:host(.ion-focused) .item-inner-highlight,
:host(.ion-focused:not(.item-fill-outline)) .item-highlight,
:host(.ion-focused) .item-highlight,
:host(.item-has-focus) .item-inner-highlight,
:host(.item-has-focus:not(.item-fill-outline)) .item-highlight {
:host(.item-has-focus) .item-highlight {
border-top: none;
border-right: none;
border-left: none;
@ -522,35 +490,6 @@ button, a {
--highlight-background: var(--highlight-color-invalid);
}
:host(.item-interactive.ion-invalid) ::slotted([slot="helper"]) {
display: none;
}
::slotted([slot="error"]) {
display: none;
color: var(--highlight-color-invalid);
}
:host(.item-interactive.ion-invalid) ::slotted([slot="error"]) {
display: block;
}
// Item Datetime
// --------------------------------------------------
:host(:not(.item-label)) ::slotted(ion-datetime) {
--padding-start: 0;
}
:host(.item-label-stacked) ::slotted(ion-datetime),
:host(.item-label-floating) ::slotted(ion-datetime) {
--padding-start: 0;
width: 100%;
}
// Item w/ Multiple Inputs
// --------------------------------------------------
// Multiple inputs in an item should have the input
@ -585,36 +524,6 @@ ion-ripple-effect {
color: var(--ripple-color);
}
:host(.item-fill-solid) ::slotted([slot="start"]),
:host(.item-fill-solid) ::slotted([slot="end"]),
:host(.item-fill-outline) ::slotted([slot="start"]),
:host(.item-fill-outline) ::slotted([slot="end"]) {
align-self: center;
}
::slotted([slot="helper"]),
::slotted([slot="error"]),
.item-counter {
padding-top: 5px;
font-size: dynamic-font(12px);
z-index: 1;
}
// Item Max Length Counter
// --------------------------------------------------
.item-counter {
@include margin-horizontal(auto, null);
color: #{$background-color-step-550};
white-space: nowrap;
padding-inline-start: 16px;
}
// Item: Reduced Motion
// --------------------------------------------------

View File

@ -3,25 +3,19 @@ import { Component, Element, Host, Listen, Prop, State, Watch, forceUpdate, h }
import type { AnchorInterface, ButtonInterface } from '@utils/element-interface';
import type { Attributes } from '@utils/helpers';
import { inheritAttributes, raf } from '@utils/helpers';
import { printIonError, printIonWarning } from '@utils/logging';
import { createColorClasses, hostContext, openURL } from '@utils/theme';
import { chevronForward } from 'ionicons/icons';
import { getIonMode } from '../../global/ionic-global';
import type { AnimationBuilder, Color, CssClassMap, StyleEventDetail } from '../../interface';
import type { InputInputEventDetail } from '../input/input-interface';
import type { RouterDirection } from '../router/utils/interface';
import type { CounterFormatter } from './item-interface';
/**
* @virtualProp {"ios" | "md"} mode - The mode determines which platform styles to use.
*
* @slot - Content is placed between the named slots if provided without a slot.
* @slot start - Content is placed to the left of the item text in LTR, and to the right in RTL.
* @slot end - Content is placed to the right of the item text in LTR, and to the left in RTL.
* @slot helper - Content is placed under the item and displayed when no error is detected. **DEPRECATED** Use the "helperText" property on ion-input or ion-textarea instead.
* @slot error - Content is placed under the item and displayed when an error is detected. **DEPRECATED** Use the "errorText" property on ion-input or ion-textarea instead.
*
* @part native - The native HTML button, anchor or div element that wraps all child elements.
* @part detail-icon - The chevron icon for the item. Only applies when `detail="true"`.
@ -80,18 +74,6 @@ export class Item implements ComponentInterface, AnchorInterface, ButtonInterfac
*/
@Prop() download: string | undefined;
/**
* The fill for the item. If `"solid"` the item will have a background. If
* `"outline"` the item will be transparent with a border. Only available in `md` mode.
* @deprecated Use the `fill` property on `ion-input` or `ion-textarea` instead.
*/
@Prop() fill?: 'outline' | 'solid';
/**
* The shape of the item. If "round" it will have increased
* border radius.
*/
@Prop() shape?: 'round';
/**
* Contains a URL or a URL fragment that the hyperlink points to.
* If this property is set, an anchor tag will be rendered.
@ -109,12 +91,6 @@ export class Item implements ComponentInterface, AnchorInterface, ButtonInterfac
*/
@Prop() lines?: 'full' | 'inset' | 'none';
/**
* If `true`, a character counter will display the ratio of characters used and the total character limit. Only applies when the `maxlength` property is set on the inner `ion-input` or `ion-textarea`.
* @deprecated Use the `counter` property on `ion-input` or `ion-textarea` instead.
*/
@Prop() counter = false;
/**
* When using a router, it specifies the transition animation when navigating to
* another page using `href`.
@ -139,33 +115,12 @@ export class Item implements ComponentInterface, AnchorInterface, ButtonInterfac
*/
@Prop() type: 'submit' | 'reset' | 'button' = 'button';
/**
* A callback used to format the counter text.
* By default the counter text is set to "itemLength / maxLength".
* @deprecated Use the `counterFormatter` property on `ion-input` or `ion-textarea` instead.
*/
@Prop() counterFormatter?: CounterFormatter;
@State() counterString: string | null | undefined;
@Watch('button')
buttonChanged() {
// Update the focusable option when the button option is changed
this.focusable = this.isFocusable();
}
@Watch('counterFormatter')
counterFormatterChanged() {
this.updateCounterOutput(this.getFirstInput());
}
@Listen('ionInput')
handleIonInput(ev: CustomEvent<InputInputEventDetail>) {
if (this.counter && ev.target === this.getFirstInput()) {
this.updateCounterOutput(ev.target as HTMLIonInputElement | HTMLIonTextareaElement);
}
}
@Listen('ionColor')
labelColorChanged(ev: CustomEvent<string>) {
const { color } = this;
@ -207,10 +162,6 @@ export class Item implements ComponentInterface, AnchorInterface, ButtonInterfac
}
connectedCallback() {
if (this.counter) {
this.updateCounterOutput(this.getFirstInput());
}
this.hasStartEl();
}
@ -219,51 +170,6 @@ export class Item implements ComponentInterface, AnchorInterface, ButtonInterfac
}
componentDidLoad() {
const { el, counter, counterFormatter, fill, shape } = this;
const hasHelperSlot = el.querySelector('[slot="helper"]') !== null;
if (hasHelperSlot) {
printIonWarning(
'The "helper" slot has been deprecated in favor of using the "helperText" property on ion-input or ion-textarea.',
el
);
}
const hasErrorSlot = el.querySelector('[slot="error"]') !== null;
if (hasErrorSlot) {
printIonWarning(
'The "error" slot has been deprecated in favor of using the "errorText" property on ion-input or ion-textarea.',
el
);
}
if (counter === true) {
printIonWarning(
'The "counter" property has been deprecated in favor of using the "counter" property on ion-input or ion-textarea.',
el
);
}
if (counterFormatter !== undefined) {
printIonWarning(
'The "counterFormatter" property has been deprecated in favor of using the "counterFormatter" property on ion-input or ion-textarea.',
el
);
}
if (fill !== undefined) {
printIonWarning(
'The "fill" property has been deprecated in favor of using the "fill" property on ion-input or ion-textarea.',
el
);
}
if (shape !== undefined) {
printIonWarning(
'The "shape" property has been deprecated in favor of using the "shape" property on ion-input or ion-textarea.',
el
);
}
raf(() => {
this.setMultipleInputs();
this.focusable = this.isFocusable();
@ -319,35 +225,6 @@ export class Item implements ComponentInterface, AnchorInterface, ButtonInterfac
return this.canActivate() || focusableChild !== null;
}
private getFirstInput(): HTMLIonInputElement | HTMLIonTextareaElement {
const inputs = this.el.querySelectorAll('ion-input, ion-textarea') as NodeListOf<
HTMLIonInputElement | HTMLIonTextareaElement
>;
return inputs[0];
}
private updateCounterOutput(inputEl: HTMLIonInputElement | HTMLIonTextareaElement) {
const { counter, counterFormatter, defaultCounterFormatter } = this;
if (counter && !this.multipleInputs && inputEl?.maxlength !== undefined) {
const length = inputEl?.value?.toString().length ?? 0;
if (counterFormatter === undefined) {
this.counterString = defaultCounterFormatter(length, inputEl.maxlength);
} else {
try {
this.counterString = counterFormatter(length, inputEl.maxlength);
} catch (e) {
printIonError('Exception in provided `counterFormatter`.', e);
// Fallback to the default counter formatter when an exception happens
this.counterString = defaultCounterFormatter(length, inputEl.maxlength);
}
}
}
}
private defaultCounterFormatter(length: number, maxlength: number) {
return `${length} / ${maxlength}`;
}
private hasStartEl() {
const startEl = this.el.querySelector('[slot="start"]');
if (startEl !== null) {
@ -364,17 +241,14 @@ export class Item implements ComponentInterface, AnchorInterface, ButtonInterfac
render() {
const {
counterString,
detail,
detailIcon,
download,
fill,
labelColorStyles,
lines,
disabled,
href,
rel,
shape,
target,
routerAnimation,
routerDirection,
@ -445,7 +319,6 @@ export class Item implements ComponentInterface, AnchorInterface, ButtonInterfac
Object.assign(childStyles, value);
});
const ariaDisabled = disabled || childStyles['item-interactive-disabled'] ? 'true' : null;
const fillValue = fill || 'none';
const inList = hostContext('ion-list', this.el) && !hostContext('ion-radio-group', this.el);
/**
@ -466,8 +339,6 @@ export class Item implements ComponentInterface, AnchorInterface, ButtonInterfac
[mode]: true,
'item-lines-default': lines === undefined,
[`item-lines-${lines}`]: lines !== undefined,
[`item-fill-${fillValue}`]: true,
[`item-shape-${shape}`]: shape !== undefined,
'item-control-needs-pointer-cursor': firstInteractiveNeedsPointerCursor,
'item-disabled': disabled,
'in-list': inList,
@ -508,11 +379,6 @@ export class Item implements ComponentInterface, AnchorInterface, ButtonInterfac
{canActivate && mode === 'md' && <ion-ripple-effect></ion-ripple-effect>}
<div class="item-highlight"></div>
</TagType>
<div class="item-bottom">
<slot name="error"></slot>
<slot name="helper"></slot>
{counterString && <ion-note class="item-counter">{counterString}</ion-note>}
</div>
</Host>
);
}

View File

@ -25,11 +25,6 @@ configs().forEach(({ title, screenshot, config }) => {
}
</style>
<ion-list>
<ion-item>
<ion-label>Item with helper</ion-label>
<div slot="helper">Helper</div>
</ion-item>
<ion-item>
<ion-label class="ion-text-nowrap"> Single line text that should have ellipses when it doesn't all fit in the item</ion-label>
</ion-item>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.1 KiB

After

Width:  |  Height:  |  Size: 3.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.3 KiB

After

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.3 KiB

After

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.4 KiB

After

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.7 KiB

After

Width:  |  Height:  |  Size: 3.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.8 KiB

After

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.0 KiB

After

Width:  |  Height:  |  Size: 3.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.1 KiB

After

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.9 KiB

After

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.6 KiB

After

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.7 KiB

After

Width:  |  Height:  |  Size: 3.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.5 KiB

After

Width:  |  Height:  |  Size: 2.7 KiB

View File

@ -1,98 +0,0 @@
<!DOCTYPE html>
<html lang="en" dir="ltr">
<head>
<meta charset="UTF-8" />
<title>Item - Bottom</title>
<meta
name="viewport"
content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no"
/>
<link href="../../../../../css/ionic.bundle.css" rel="stylesheet" />
<link href="../../../../../scripts/testing/styles.css" rel="stylesheet" />
<script src="../../../../../scripts/testing/scripts.js"></script>
<script nomodule src="../../../../../dist/ionic/ionic.js"></script>
<script type="module" src="../../../../../dist/ionic/ionic.esm.js"></script>
</head>
<style>
ion-item.custom {
--border-width: 5px;
}
</style>
<body>
<ion-app>
<ion-header>
<ion-toolbar>
<ion-title>Item inputs</ion-title>
</ion-toolbar>
</ion-header>
<ion-content class="ion-padding-vertical">
<ion-list class="basic">
<ion-item>
<ion-input label="No Helper/Error" name="input" id="text"></ion-input>
</ion-item>
<ion-item>
<ion-input label="Helper and Error"></ion-input>
<ion-note slot="helper">Helper Text</ion-note>
<ion-note slot="error">Error Text</ion-note>
</ion-item>
<ion-item>
<ion-input label="Helper Only"></ion-input>
<ion-note slot="helper">Helper Text</ion-note>
</ion-item>
<ion-item>
<ion-input label="Error Only"></ion-input>
<ion-note slot="error">Error Text</ion-note>
</ion-item>
<ion-item class="custom">
<ion-input label="Both w/ Custom CSS"></ion-input>
<ion-note slot="helper">Helper Text</ion-note>
<ion-note slot="error">Error Text</ion-note>
</ion-item>
</ion-list>
<ion-grid>
<ion-row>
<ion-col>
<ion-item fill="solid">
<ion-input label="Helper and Error (Fill Solid)"></ion-input>
<ion-note slot="helper">Helper Text</ion-note>
<ion-note slot="error">Error Text</ion-note>
</ion-item>
</ion-col>
<ion-col>
<ion-item fill="outline">
<ion-input label="Helper and Error (Fill Outline)"></ion-input>
<ion-note slot="helper">Helper Text</ion-note>
<ion-note slot="error">Error Text</ion-note>
</ion-item>
</ion-col>
</ion-row>
<ion-row>
<ion-col>
<ion-item>
<ion-toggle id="error-toggle" color="danger">Toggle Error</ion-toggle>
</ion-item>
</ion-col>
</ion-row>
</ion-grid>
</ion-content>
</ion-app>
<script>
(function toggleHelperError() {
const toggle = document.getElementById('error-toggle');
toggle.addEventListener('ionChange', (ev) => {
const items = Array.from(document.querySelectorAll('ion-item'));
items.forEach((item) => item.classList.toggle('ion-invalid'));
});
})();
</script>
</body>
</html>

View File

@ -1,63 +0,0 @@
<!DOCTYPE html>
<html lang="en" dir="ltr">
<head>
<meta charset="UTF-8" />
<title>Item - Disabled</title>
<meta
name="viewport"
content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no"
/>
<link href="../../../../../css/ionic.bundle.css" rel="stylesheet" />
<link href="../../../../../scripts/testing/styles.css" rel="stylesheet" />
<script src="../../../../../scripts/testing/scripts.js"></script>
<script type="module" src="../../../../../dist/ionic/ionic.esm.js"></script>
</head>
<body>
<ion-app>
<ion-header>
<ion-toolbar>
<ion-title>Item: Disabled</ion-title>
</ion-toolbar>
</ion-header>
<ion-content class="ion-padding-vertical">
<ion-list>
<ion-list-header>
<ion-label>Single Input Disabled Items</ion-label>
</ion-list-header>
<ion-item disabled>
<ion-label>Disabled Item</ion-label>
</ion-item>
<ion-item disabled button>
<ion-label>Disabled Item Button</ion-label>
</ion-item>
<ion-item disabled href="#">
<ion-label>Disabled Item Anchor</ion-label>
</ion-item>
</ion-list>
</ion-content>
<ion-footer>
<ion-toolbar>
<ion-buttons slot="start">
<ion-button onClick="toggleDisabled()">Toggle</ion-button>
</ion-buttons>
</ion-toolbar>
</ion-footer>
</ion-app>
<script>
const disabledEls = document.querySelectorAll('[disabled]');
function toggleDisabled() {
for (var i = 0; i < disabledEls.length; i++) {
disabledEls[i].disabled = !disabledEls[i].disabled;
}
}
</script>
</body>
</html>

View File

@ -1,14 +0,0 @@
import { expect } from '@playwright/test';
import { configs, test } from '@utils/test/playwright';
configs().forEach(({ title, screenshot, config }) => {
test.describe(title('item: disabled state'), () => {
test('should not have visual regressions', async ({ page }) => {
await page.goto(`/src/components/item/test/legacy/disabled`, config);
await page.setIonViewport();
await expect(page).toHaveScreenshot(screenshot(`item-disabled-diff`));
});
});
});

View File

@ -52,65 +52,6 @@
@include transform(translateY(50%), scale(.75));
}
/**
* When translating the label inside of an ion-item with `fill="outline"`,
* add pseudo-elements to imitate fieldset-like padding without shifting the label
*/
:host-context(.item-fill-outline.ion-focused).label-floating,
:host-context(.item-fill-outline.item-has-focus).label-floating,
:host-context(.item-fill-outline.item-has-placeholder:not(.item-input)).label-floating,
:host-context(.item-fill-outline.item-has-value).label-floating {
@include transform(translateY(-6px), scale(.75));
position: relative;
max-width: min-content;
background-color: $item-md-background;
overflow: visible;
// Places the label on top of the item outline
z-index: 3;
&::before,
&::after {
position: absolute;
width: $item-md-fill-outline-label-padding;
height: 100%;
background-color: $item-md-background;
content: "";
}
&::before {
/* stylelint-disable property-disallowed-list */
left: calc(-1 * #{$item-md-fill-outline-label-padding});
/* stylelint-enable property-disallowed-list */
}
&::after {
/* stylelint-disable property-disallowed-list */
right: calc(-1 * #{$item-md-fill-outline-label-padding});
/* stylelint-enable property-disallowed-list */
}
}
:host-context(.item-fill-outline.ion-focused.item-has-start-slot).label-floating,
:host-context(.item-fill-outline.item-has-focus.item-has-start-slot).label-floating,
:host-context(.item-fill-outline.item-has-placeholder:not(.item-input).item-has-start-slot).label-floating,
:host-context(.item-fill-outline.item-has-value.item-has-start-slot).label-floating {
@include transform(translateX(#{$item-md-fill-outline-label-translate-x}), translateY(-6px), scale(.75));
}
:host-context(.item-fill-outline.ion-focused.item-has-start-slot).label-floating.label-rtl,
:host-context(.item-fill-outline.item-has-focus.item-has-start-slot).label-floating.label-rtl,
:host-context(.item-fill-outline.item-has-placeholder:not(.item-input).item-has-start-slot).label-floating.label-rtl,
:host-context(.item-fill-outline.item-has-value.item-has-start-slot).label-floating.label-rtl {
@include transform(translateX(calc(-1 * #{$item-md-fill-outline-label-translate-x})), translateY(-6px), scale(.75));
}
:host-context(.ion-focused).label-stacked:not(.ion-color),
:host-context(.ion-focused).label-floating:not(.ion-color),
:host-context(.item-has-focus).label-stacked:not(.ion-color),
@ -125,23 +66,11 @@
color: #{current-color(contrast)};
}
:host-context(.item-fill-solid.ion-focused.ion-color).label-stacked:not(.ion-color),
:host-context(.item-fill-solid.ion-focused.ion-color).label-floating:not(.ion-color),
:host-context(.item-fill-outline.ion-focused.ion-color).label-stacked:not(.ion-color),
:host-context(.item-fill-outline.ion-focused.ion-color).label-floating:not(.ion-color),
:host-context(.item-fill-solid.item-has-focus.ion-color).label-stacked:not(.ion-color),
:host-context(.item-fill-solid.item-has-focus.ion-color).label-floating:not(.ion-color),
:host-context(.item-fill-outline.item-has-focus.ion-color).label-stacked:not(.ion-color),
:host-context(.item-fill-outline.item-has-focus.ion-color).label-floating:not(.ion-color) {
color: #{current-color(base)};
}
:host-context(.ion-invalid.ion-touched).label-stacked:not(.ion-color),
:host-context(.ion-invalid.ion-touched).label-floating:not(.ion-color) {
color: var(--highlight-color-invalid);
}
// MD Typography
// --------------------------------------------------

View File

@ -22,13 +22,6 @@
box-sizing: border-box;
}
// TODO(FW-5289): remove
:host-context(.item-legacy) {
white-space: nowrap;
overflow: hidden;
}
:host(.ion-color) {
color: current-color(base);
}

View File

@ -98,31 +98,6 @@
color: var(--highlight-color);
}
/**
* Adjust the arrow so that it appears in the middle
* of the item. If the item has fill="outline" then
* we should adjust the entire ion-select rather than
* just the outline so the selected value appears centered too.
*/
:host-context(.item-label-stacked) .select-icon,
:host-context(.item-label-floating:not(.item-fill-outline)) .select-icon,
:host-context(.item-label-floating.item-fill-outline) {
@include transform(translate3d(0, -9px, 0));
}
:host-context(.item-has-focus):host(:not(.has-expanded-icon)) .select-icon {
@include transform(rotate(180deg));
}
/**
* Ensure that the translation we did
* above is preserved when we rotate the select icon.
*/
:host-context(.item-has-focus.item-label-stacked):host(:not(.has-expanded-icon)) .select-icon,
:host-context(.item-has-focus.item-label-floating:not(.item-fill-outline)):host(:not(.has-expanded-icon)) .select-icon {
@include transform(rotate(180deg), translate3d(0, -9px, 0));
}
// Select Shape Rounded
// ----------------------------------------------------------------

View File

@ -16,13 +16,6 @@
font-size: $textarea-ios-font-size;
}
:host-context(.item-label-stacked),
:host-context(.item-label-floating) {
--padding-top: 8px;
--padding-bottom: 8px;
--padding-start: 0px;
}
// Textarea - Disabled
// ----------------------------------------------------------------
// The textarea, label, helper text, char counter and placeholder

View File

@ -116,10 +116,6 @@
align-self: baseline;
}
:host-context(ion-item:not(.item-label)) {
--padding-start: 0;
}
:host-context(ion-item)[slot="start"],
:host-context(ion-item)[slot="end"] {
width: auto;
@ -238,20 +234,6 @@
overflow: hidden;
}
// Item Floating: Placeholder
// ----------------------------------------------------------------
// When used with a floating item the placeholder should hide
:host-context(.item-label-floating.item-has-placeholder:not(.item-has-value)) {
opacity: 0;
}
:host-context(.item-label-floating.item-has-placeholder:not(.item-has-value).item-has-focus) {
transition: opacity 0.15s cubic-bezier(0.4, 0, 0.2, 1);
opacity: 1;
}
// Textarea Wrapper
// ----------------------------------------------------------------

View File

@ -1,73 +0,0 @@
import { findItemLabel } from '@utils/helpers';
type HTMLLegacyFormControlElement = HTMLElement & { label?: string; legacy?: boolean };
/**
* Creates a controller that tracks whether a form control is using the legacy or modern syntax. This should be removed when the legacy form control syntax is removed.
*
* @internal
* @prop el: The Ionic form component to reference
*/
export const createLegacyFormController = (el: HTMLLegacyFormControlElement): LegacyFormController => {
const controlEl: HTMLLegacyFormControlElement = el;
let legacyControl: boolean | undefined;
const hasLegacyControl = () => {
if (legacyControl === undefined) {
/**
* Detect if developers are using the legacy form control syntax
* so a deprecation warning is logged. This warning can be disabled
* by either using the new `label` property or setting `aria-label`
* on the control.
* Alternatively, components that use a slot for the label
* can check to see if the component has slotted text
* in the light DOM.
*/
const hasLabelProp = controlEl.label !== undefined || hasLabelSlot(controlEl);
const hasAriaLabelAttribute =
controlEl.hasAttribute('aria-label') ||
// Shadow DOM form controls cannot use aria-labelledby
(controlEl.hasAttribute('aria-labelledby') && controlEl.shadowRoot === null);
const legacyItemLabel = findItemLabel(controlEl);
/**
* Developers can manually opt-out of the modern form markup
* by setting `legacy="true"` on components.
*/
legacyControl =
controlEl.legacy === true || (!hasLabelProp && !hasAriaLabelAttribute && legacyItemLabel !== null);
}
return legacyControl;
};
return { hasLegacyControl };
};
export type LegacyFormController = {
hasLegacyControl: () => boolean;
};
const hasLabelSlot = (controlEl: HTMLElement) => {
/**
* Components that have a named label slot
* also have other slots, so we need to query for
* anything that is explicitly passed to slot="label"
*/
if (NAMED_LABEL_SLOT_COMPONENTS.includes(controlEl.tagName) && controlEl.querySelector('[slot="label"]') !== null) {
return true;
}
/**
* Components that have an unnamed slot for the label
* have no other slots, so we can check the textContent
* of the element.
*/
if (UNNAMED_LABEL_SLOT_COMPONENTS.includes(controlEl.tagName) && controlEl.textContent !== '') {
return true;
}
return false;
};
const NAMED_LABEL_SLOT_COMPONENTS = ['ION-INPUT', 'ION-TEXTAREA', 'ION-SELECT', 'ION-RANGE'];
const UNNAMED_LABEL_SLOT_COMPONENTS = ['ION-TOGGLE', 'ION-CHECKBOX', 'ION-RADIO'];

View File

@ -1,3 +1,2 @@
export * from './form-controller';
export * from './notch-controller';
export * from './compare-with-utils';

View File

@ -254,14 +254,6 @@ export const hasShadowDom = (el: HTMLElement) => {
return !!el.shadowRoot && !!(el as any).attachShadow;
};
export const findItemLabel = (componentEl: HTMLElement): HTMLIonLabelElement | null => {
const itemEl = componentEl.closest('ion-item');
if (itemEl) {
return itemEl.querySelector('ion-label');
}
return null;
};
export const focusVisibleElement = (el: HTMLElement) => {
el.focus();
@ -310,8 +302,7 @@ export const getAriaLabel = (
let labelId = labelledBy !== null && labelledBy.trim() !== '' ? labelledBy : inputId + '-lbl';
let label =
labelledBy !== null && labelledBy.trim() !== '' ? document.getElementById(labelledBy) : findItemLabel(componentEl);
let label = labelledBy !== null && labelledBy.trim() !== '' ? document.getElementById(labelledBy) : null;
if (label) {
if (labelledBy === null) {

View File

@ -1015,14 +1015,14 @@ where the user's interaction is typing.
@ProxyCmp({
inputs: ['button', 'color', 'counter', 'counterFormatter', 'detail', 'detailIcon', 'disabled', 'download', 'fill', 'href', 'lines', 'mode', 'rel', 'routerAnimation', 'routerDirection', 'shape', 'target', 'type']
inputs: ['button', 'color', 'detail', 'detailIcon', 'disabled', 'download', 'href', 'lines', 'mode', 'rel', 'routerAnimation', 'routerDirection', 'target', 'type']
})
@Component({
selector: 'ion-item',
changeDetection: ChangeDetectionStrategy.OnPush,
template: '<ng-content></ng-content>',
// eslint-disable-next-line @angular-eslint/no-inputs-metadata-property
inputs: ['button', 'color', 'counter', 'counterFormatter', 'detail', 'detailIcon', 'disabled', 'download', 'fill', 'href', 'lines', 'mode', 'rel', 'routerAnimation', 'routerDirection', 'shape', 'target', 'type'],
inputs: ['button', 'color', 'detail', 'detailIcon', 'disabled', 'download', 'href', 'lines', 'mode', 'rel', 'routerAnimation', 'routerDirection', 'target', 'type'],
})
export class IonItem {
protected el: HTMLElement;

View File

@ -978,14 +978,14 @@ export declare interface IonInfiniteScrollContent extends Components.IonInfinite
@ProxyCmp({
defineCustomElementFn: defineIonItem,
inputs: ['button', 'color', 'counter', 'counterFormatter', 'detail', 'detailIcon', 'disabled', 'download', 'fill', 'href', 'lines', 'mode', 'rel', 'routerAnimation', 'routerDirection', 'shape', 'target', 'type']
inputs: ['button', 'color', 'detail', 'detailIcon', 'disabled', 'download', 'href', 'lines', 'mode', 'rel', 'routerAnimation', 'routerDirection', 'target', 'type']
})
@Component({
selector: 'ion-item',
changeDetection: ChangeDetectionStrategy.OnPush,
template: '<ng-content></ng-content>',
// eslint-disable-next-line @angular-eslint/no-inputs-metadata-property
inputs: ['button', 'color', 'counter', 'counterFormatter', 'detail', 'detailIcon', 'disabled', 'download', 'fill', 'href', 'lines', 'mode', 'rel', 'routerAnimation', 'routerDirection', 'shape', 'target', 'type'],
inputs: ['button', 'color', 'detail', 'detailIcon', 'disabled', 'download', 'href', 'lines', 'mode', 'rel', 'routerAnimation', 'routerDirection', 'target', 'type'],
standalone: true
})
export class IonItem {

View File

@ -443,17 +443,13 @@ export const IonItem = /*@__PURE__*/ defineContainer<JSX.IonItem>('ion-item', de
'detailIcon',
'disabled',
'download',
'fill',
'shape',
'href',
'rel',
'lines',
'counter',
'routerAnimation',
'routerDirection',
'target',
'type',
'counterFormatter'
'type'
]);