Compare commits

..

3 Commits

Author SHA1 Message Date
Sean Perkins
e8e075172b chore: set permissions 2023-12-04 15:01:10 -05:00
Liam DeBeasi
60d79103fd Update label.yml 2023-12-04 13:58:29 -05:00
Liam DeBeasi
27b4f86619 Update label.yml 2023-12-04 13:55:10 -05:00
359 changed files with 804 additions and 3301 deletions

15
.github/labeler.yml vendored
View File

@@ -6,17 +6,16 @@
# https://github.com/actions/labeler
'package: core':
- changed-files:
- any-glob-to-any-file: ['core/**/*']
- core/**/*
'package: angular':
- changed-files:
- any-glob-to-any-file: ['packages/angular/**/*', 'packages/angular-*/**/*']
- packages/angular/**/*
- packages/angular-*/**/*
'package: react':
- changed-files:
- any-glob-to-any-file: ['packages/react/**/*', 'packages/react-*/**/*']
- packages/react/**/*
- packages/react-*/**/*
'package: vue':
- changed-files:
- any-glob-to-any-file: ['packages/vue/**/*', 'packages/vue-*/**/*']
- packages/vue/**/*
- packages/vue-*/**/*

View File

@@ -11,9 +11,13 @@ on:
jobs:
triage:
permissions:
contents: read
pull-requests: write
runs-on: ubuntu-latest
steps:
- uses: actions/labeler@v5
- uses: actions/checkout@v4
- uses: actions/labeler@v4
with:
repo-token: "${{ secrets.GITHUB_TOKEN }}"
sync-labels: true

View File

@@ -3,49 +3,6 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
# [7.6.0](https://github.com/ionic-team/ionic-framework/compare/v7.5.8...v7.6.0) (2023-12-06)
### Bug Fixes
* **angular,vue:** range form value updates while dragging knob ([#28422](https://github.com/ionic-team/ionic-framework/issues/28422)) ([0854a11](https://github.com/ionic-team/ionic-framework/commit/0854a11a25759d0201eae66c96a62fe138d486f8)), closes [#28256](https://github.com/ionic-team/ionic-framework/issues/28256)
* **animation:** add stronger types to Animation interface ([#28334](https://github.com/ionic-team/ionic-framework/issues/28334)) ([4a088d5](https://github.com/ionic-team/ionic-framework/commit/4a088d5d612ab0387064d388b37d46cdf15cf1ff))
* **animation:** progressEnd coercion is reset before onFinish ([#28394](https://github.com/ionic-team/ionic-framework/issues/28394)) ([eae8162](https://github.com/ionic-team/ionic-framework/commit/eae8162d0dc2e0bd7a9d56a3662a8e5f5d142b72)), closes [#28393](https://github.com/ionic-team/ionic-framework/issues/28393)
* **infinite-scroll:** remaining in threshold after ionInfinite can trigger event again on scroll ([#28569](https://github.com/ionic-team/ionic-framework/issues/28569)) ([8c235fd](https://github.com/ionic-team/ionic-framework/commit/8c235fd30c50f317de1f37f69068507aa0979068)), closes [#18071](https://github.com/ionic-team/ionic-framework/issues/18071)
* **item:** allow item to grow when it is used in a flex container ([#28594](https://github.com/ionic-team/ionic-framework/issues/28594)) ([1c1b567](https://github.com/ionic-team/ionic-framework/commit/1c1b567279dee44da70bb9b90c129946c9043987))
* **item:** wrap elements and label contents when the font size increases or the elements do not fit ([#28146](https://github.com/ionic-team/ionic-framework/issues/28146)) ([6438e3e](https://github.com/ionic-team/ionic-framework/commit/6438e3e919c665569b731a2d74fe1547b4f3c1cc))
* **select:** do not collapse to width: 0 when placed in flex container ([#28631](https://github.com/ionic-team/ionic-framework/issues/28631)) ([e71e7a0](https://github.com/ionic-team/ionic-framework/commit/e71e7a069000db8738abc304758de64286817442))
* **toast:** add swipeGesture to ToastOptions ([#28518](https://github.com/ionic-team/ionic-framework/issues/28518)) ([4ad6df6](https://github.com/ionic-team/ionic-framework/commit/4ad6df67f01cebce30d4da46c7541c4b14c5d4a4))
### Features
* **checkbox:** add shadow part for label ([#28604](https://github.com/ionic-team/ionic-framework/issues/28604)) ([f9f5654](https://github.com/ionic-team/ionic-framework/commit/f9f5654ab0e920bf97089fbabfb9eedbcf6fe8ae)), closes [#28300](https://github.com/ionic-team/ionic-framework/issues/28300)
* **input, textarea, select:** add start and end slots ([#28583](https://github.com/ionic-team/ionic-framework/issues/28583)) ([357b8b2](https://github.com/ionic-team/ionic-framework/commit/357b8b2beb29b95d53ef043af349067be1d32658)), closes [#26297](https://github.com/ionic-team/ionic-framework/issues/26297)
* **radio-group:** add compareWith property ([#28452](https://github.com/ionic-team/ionic-framework/issues/28452)) ([0ae327f](https://github.com/ionic-team/ionic-framework/commit/0ae327f0e09cd97d705f2d3051c215034381e226))
* **radio:** add shadow part for label ([#28607](https://github.com/ionic-team/ionic-framework/issues/28607)) ([b757970](https://github.com/ionic-team/ionic-framework/commit/b757970d23e87c59aa883ecb1bfa9b66bcae8de2)), closes [#28300](https://github.com/ionic-team/ionic-framework/issues/28300)
* **range:** expose label wrapper as shadow part ([#28601](https://github.com/ionic-team/ionic-framework/issues/28601)) ([52ed2bf](https://github.com/ionic-team/ionic-framework/commit/52ed2bf63777c764f57bb4c3a5d4a127bff46c50))
* **toast:** add swipe to dismiss functionality ([#28442](https://github.com/ionic-team/ionic-framework/issues/28442)) ([30c21aa](https://github.com/ionic-team/ionic-framework/commit/30c21aab3ed40d73c28e7d60d0952d8891b0a9d3)), closes [#21769](https://github.com/ionic-team/ionic-framework/issues/21769)
* **toggle:** expose label wrapper as shadow part ([#28585](https://github.com/ionic-team/ionic-framework/issues/28585)) ([a34188f](https://github.com/ionic-team/ionic-framework/commit/a34188f7dbec4a16e4f2043ed3dc096e337725a7))
## [7.5.8](https://github.com/ionic-team/ionic-framework/compare/v7.5.7...v7.5.8) (2023-12-06)
### Bug Fixes
* **angular:** add missing menu controller methods ([#28618](https://github.com/ionic-team/ionic-framework/issues/28618)) ([7871b56](https://github.com/ionic-team/ionic-framework/commit/7871b56eccfe63326b6dd4b56ade3b3afd444fce)), closes [#20053](https://github.com/ionic-team/ionic-framework/issues/20053)
* **overlays:** trigger is configured on load ([#28526](https://github.com/ionic-team/ionic-framework/issues/28526)) ([a3cd204](https://github.com/ionic-team/ionic-framework/commit/a3cd204f616606ccffc35082655e55fdfb19fe28)), closes [#28524](https://github.com/ionic-team/ionic-framework/issues/28524)
* **react:** router creates new view instances of parameterized routes ([#28616](https://github.com/ionic-team/ionic-framework/issues/28616)) ([1705d06](https://github.com/ionic-team/ionic-framework/commit/1705d064cc041e99f432a27207f3aab7fa62c778)), closes [#26524](https://github.com/ionic-team/ionic-framework/issues/26524)
* **vue:** nav component accepts kebab-case component properties ([#28615](https://github.com/ionic-team/ionic-framework/issues/28615)) ([60303aa](https://github.com/ionic-team/ionic-framework/commit/60303aad23f823488afc8f8824e9c72e3ab86acc)), closes [#28611](https://github.com/ionic-team/ionic-framework/issues/28611)
## [7.5.7](https://github.com/ionic-team/ionic-framework/compare/v7.5.6...v7.5.7) (2023-11-29)

View File

@@ -3,46 +3,6 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
# [7.6.0](https://github.com/ionic-team/ionic-framework/compare/v7.5.8...v7.6.0) (2023-12-06)
### Bug Fixes
* **angular,vue:** range form value updates while dragging knob ([#28422](https://github.com/ionic-team/ionic-framework/issues/28422)) ([0854a11](https://github.com/ionic-team/ionic-framework/commit/0854a11a25759d0201eae66c96a62fe138d486f8)), closes [#28256](https://github.com/ionic-team/ionic-framework/issues/28256)
* **animation:** add stronger types to Animation interface ([#28334](https://github.com/ionic-team/ionic-framework/issues/28334)) ([4a088d5](https://github.com/ionic-team/ionic-framework/commit/4a088d5d612ab0387064d388b37d46cdf15cf1ff))
* **animation:** progressEnd coercion is reset before onFinish ([#28394](https://github.com/ionic-team/ionic-framework/issues/28394)) ([eae8162](https://github.com/ionic-team/ionic-framework/commit/eae8162d0dc2e0bd7a9d56a3662a8e5f5d142b72)), closes [#28393](https://github.com/ionic-team/ionic-framework/issues/28393)
* **infinite-scroll:** remaining in threshold after ionInfinite can trigger event again on scroll ([#28569](https://github.com/ionic-team/ionic-framework/issues/28569)) ([8c235fd](https://github.com/ionic-team/ionic-framework/commit/8c235fd30c50f317de1f37f69068507aa0979068)), closes [#18071](https://github.com/ionic-team/ionic-framework/issues/18071)
* **item:** allow item to grow when it is used in a flex container ([#28594](https://github.com/ionic-team/ionic-framework/issues/28594)) ([1c1b567](https://github.com/ionic-team/ionic-framework/commit/1c1b567279dee44da70bb9b90c129946c9043987))
* **item:** wrap elements and label contents when the font size increases or the elements do not fit ([#28146](https://github.com/ionic-team/ionic-framework/issues/28146)) ([6438e3e](https://github.com/ionic-team/ionic-framework/commit/6438e3e919c665569b731a2d74fe1547b4f3c1cc))
* **select:** do not collapse to width: 0 when placed in flex container ([#28631](https://github.com/ionic-team/ionic-framework/issues/28631)) ([e71e7a0](https://github.com/ionic-team/ionic-framework/commit/e71e7a069000db8738abc304758de64286817442))
* **toast:** add swipeGesture to ToastOptions ([#28518](https://github.com/ionic-team/ionic-framework/issues/28518)) ([4ad6df6](https://github.com/ionic-team/ionic-framework/commit/4ad6df67f01cebce30d4da46c7541c4b14c5d4a4))
### Features
* **checkbox:** add shadow part for label ([#28604](https://github.com/ionic-team/ionic-framework/issues/28604)) ([f9f5654](https://github.com/ionic-team/ionic-framework/commit/f9f5654ab0e920bf97089fbabfb9eedbcf6fe8ae)), closes [#28300](https://github.com/ionic-team/ionic-framework/issues/28300)
* **input, textarea, select:** add start and end slots ([#28583](https://github.com/ionic-team/ionic-framework/issues/28583)) ([357b8b2](https://github.com/ionic-team/ionic-framework/commit/357b8b2beb29b95d53ef043af349067be1d32658)), closes [#26297](https://github.com/ionic-team/ionic-framework/issues/26297)
* **radio-group:** add compareWith property ([#28452](https://github.com/ionic-team/ionic-framework/issues/28452)) ([0ae327f](https://github.com/ionic-team/ionic-framework/commit/0ae327f0e09cd97d705f2d3051c215034381e226))
* **radio:** add shadow part for label ([#28607](https://github.com/ionic-team/ionic-framework/issues/28607)) ([b757970](https://github.com/ionic-team/ionic-framework/commit/b757970d23e87c59aa883ecb1bfa9b66bcae8de2)), closes [#28300](https://github.com/ionic-team/ionic-framework/issues/28300)
* **range:** expose label wrapper as shadow part ([#28601](https://github.com/ionic-team/ionic-framework/issues/28601)) ([52ed2bf](https://github.com/ionic-team/ionic-framework/commit/52ed2bf63777c764f57bb4c3a5d4a127bff46c50))
* **toast:** add swipe to dismiss functionality ([#28442](https://github.com/ionic-team/ionic-framework/issues/28442)) ([30c21aa](https://github.com/ionic-team/ionic-framework/commit/30c21aab3ed40d73c28e7d60d0952d8891b0a9d3)), closes [#21769](https://github.com/ionic-team/ionic-framework/issues/21769)
* **toggle:** expose label wrapper as shadow part ([#28585](https://github.com/ionic-team/ionic-framework/issues/28585)) ([a34188f](https://github.com/ionic-team/ionic-framework/commit/a34188f7dbec4a16e4f2043ed3dc096e337725a7))
## [7.5.8](https://github.com/ionic-team/ionic-framework/compare/v7.5.7...v7.5.8) (2023-12-06)
### Bug Fixes
* **overlays:** trigger is configured on load ([#28526](https://github.com/ionic-team/ionic-framework/issues/28526)) ([a3cd204](https://github.com/ionic-team/ionic-framework/commit/a3cd204f616606ccffc35082655e55fdfb19fe28)), closes [#28524](https://github.com/ionic-team/ionic-framework/issues/28524)
## [7.5.7](https://github.com/ionic-team/ionic-framework/compare/v7.5.6...v7.5.7) (2023-11-29)

View File

@@ -315,7 +315,6 @@ ion-checkbox,css-prop,--checkmark-width
ion-checkbox,css-prop,--size
ion-checkbox,css-prop,--transition
ion-checkbox,part,container
ion-checkbox,part,label
ion-checkbox,part,mark
ion-chip,shadow
@@ -1030,12 +1029,10 @@ ion-radio,css-prop,--color
ion-radio,css-prop,--color-checked
ion-radio,css-prop,--inner-border-radius
ion-radio,part,container
ion-radio,part,label
ion-radio,part,mark
ion-radio-group,none
ion-radio-group,prop,allowEmptySelection,boolean,false,false,false
ion-radio-group,prop,compareWith,((currentValue: any, compareValue: any) => boolean) | null | string | undefined,undefined,false,false
ion-radio-group,prop,name,string,this.inputId,false,false
ion-radio-group,prop,value,any,undefined,false,false
ion-radio-group,event,ionChange,RadioGroupChangeEventDetail<any>,true
@@ -1079,7 +1076,6 @@ ion-range,css-prop,--pin-color
ion-range,part,bar
ion-range,part,bar-active
ion-range,part,knob
ion-range,part,label
ion-range,part,pin
ion-range,part,tick
ion-range,part,tick-active
@@ -1450,7 +1446,6 @@ ion-toast,prop,message,IonicSafeString | string | undefined,undefined,false,fals
ion-toast,prop,mode,"ios" | "md",undefined,false,false
ion-toast,prop,position,"bottom" | "middle" | "top",'bottom',false,false
ion-toast,prop,positionAnchor,HTMLElement | string | undefined,undefined,false,false
ion-toast,prop,swipeGesture,"vertical" | undefined,undefined,false,false
ion-toast,prop,translucent,boolean,false,false,false
ion-toast,prop,trigger,string | undefined,undefined,false,false
ion-toast,method,dismiss,dismiss(data?: any, role?: string) => Promise<boolean>
@@ -1517,7 +1512,6 @@ ion-toggle,css-prop,--handle-width
ion-toggle,css-prop,--track-background
ion-toggle,css-prop,--track-background-checked
ion-toggle,part,handle
ion-toggle,part,label
ion-toggle,part,track
ion-toolbar,shadow

18
core/package-lock.json generated
View File

@@ -1,15 +1,15 @@
{
"name": "@ionic/core",
"version": "7.6.0",
"version": "7.5.7",
"lockfileVersion": 2,
"requires": true,
"packages": {
"": {
"name": "@ionic/core",
"version": "7.6.0",
"version": "7.5.7",
"license": "MIT",
"dependencies": {
"@stencil/core": "^4.8.1",
"@stencil/core": "^4.8.0",
"ionicons": "^7.2.1",
"tslib": "^2.1.0"
},
@@ -1825,9 +1825,9 @@
}
},
"node_modules/@stencil/core": {
"version": "4.8.1",
"resolved": "https://registry.npmjs.org/@stencil/core/-/core-4.8.1.tgz",
"integrity": "sha512-KG1H10j24rlyxIqOI4CG8/h9T7ObTv7giW2H3u1qXV4KKrLykDOpMcLzpqNXqL2Fki3s1QvHyl/oaRvi5waWVw==",
"version": "4.8.0",
"resolved": "https://registry.npmjs.org/@stencil/core/-/core-4.8.0.tgz",
"integrity": "sha512-iNEaMiEt9oFZXSjZ7qkdlBpPTzWzBgWM7go8nI8a7V6ZOkmdVhhT0xGQD7OY13v5ZuDoIw5IsGvbIAGefhIhhQ==",
"bin": {
"stencil": "bin/stencil"
},
@@ -12184,9 +12184,9 @@
"requires": {}
},
"@stencil/core": {
"version": "4.8.1",
"resolved": "https://registry.npmjs.org/@stencil/core/-/core-4.8.1.tgz",
"integrity": "sha512-KG1H10j24rlyxIqOI4CG8/h9T7ObTv7giW2H3u1qXV4KKrLykDOpMcLzpqNXqL2Fki3s1QvHyl/oaRvi5waWVw=="
"version": "4.8.0",
"resolved": "https://registry.npmjs.org/@stencil/core/-/core-4.8.0.tgz",
"integrity": "sha512-iNEaMiEt9oFZXSjZ7qkdlBpPTzWzBgWM7go8nI8a7V6ZOkmdVhhT0xGQD7OY13v5ZuDoIw5IsGvbIAGefhIhhQ=="
},
"@stencil/react-output-target": {
"version": "0.5.3",

View File

@@ -1,6 +1,6 @@
{
"name": "@ionic/core",
"version": "7.6.0",
"version": "7.5.7",
"description": "Base components for Ionic",
"keywords": [
"ionic",
@@ -31,7 +31,7 @@
"loader/"
],
"dependencies": {
"@stencil/core": "^4.8.1",
"@stencil/core": "^4.8.0",
"ionicons": "^7.2.1",
"tslib": "^2.1.0"
},

View File

@@ -1,21 +0,0 @@
expect.extend({
toHaveShadowPart(received, part) {
if (typeof part !== 'string') {
throw new Error('expected toHaveShadowPart to be called with a string of the CSS shadow part name');
}
if (received.shadowRoot === null) {
throw new Error('expected toHaveShadowPart to be called on an element with a shadow root');
}
const shadowPart = received.shadowRoot.querySelector(`[part="${part}"]`);
const pass = shadowPart !== null;
const message = `expected ${received.tagName.toLowerCase()} to have shadow part "${part}"`;
return {
pass,
message: () => message,
};
},
});

View File

@@ -27,7 +27,7 @@ import { PickerButton, PickerColumn } from "./components/picker/picker-interface
import { PickerColumnItem } from "./components/picker-column-internal/picker-column-internal-interfaces";
import { PickerInternalChangeEventDetail } from "./components/picker-internal/picker-internal-interfaces";
import { PopoverSize, PositionAlign, PositionReference, PositionSide, TriggerAction } from "./components/popover/popover-interface";
import { RadioGroupChangeEventDetail, RadioGroupCompareFn } from "./components/radio-group/radio-group-interface";
import { RadioGroupChangeEventDetail } from "./components/radio-group/radio-group-interface";
import { PinFormatter, RangeChangeEventDetail, RangeKnobMoveEndEventDetail, RangeKnobMoveStartEventDetail, RangeValue } from "./components/range/range-interface";
import { RefresherEventDetail } from "./components/refresher/refresher-interface";
import { ItemReorderEventDetail } from "./components/reorder-group/reorder-group-interface";
@@ -39,7 +39,7 @@ import { SelectChangeEventDetail, SelectCompareFn, SelectInterface } from "./com
import { SelectPopoverOption } from "./components/select-popover/select-popover-interface";
import { TabBarChangedEventDetail, TabButtonClickEventDetail, TabButtonLayout } from "./components/tab-bar/tab-bar-interface";
import { TextareaChangeEventDetail, TextareaInputEventDetail } from "./components/textarea/textarea-interface";
import { ToastButton, ToastDismissOptions, ToastLayout, ToastPosition, ToastPresentOptions, ToastSwipeGestureDirection } from "./components/toast/toast-interface";
import { ToastButton, ToastDismissOptions, ToastLayout, ToastPosition, ToastPresentOptions } from "./components/toast/toast-interface";
import { ToggleChangeEventDetail } from "./components/toggle/toggle-interface";
export { AccordionGroupChangeEventDetail } from "./components/accordion-group/accordion-group-interface";
export { AnimationBuilder, AutocompleteTypes, Color, ComponentProps, ComponentRef, FrameworkDelegate, StyleEventDetail, TextFieldTypes } from "./interface";
@@ -63,7 +63,7 @@ export { PickerButton, PickerColumn } from "./components/picker/picker-interface
export { PickerColumnItem } from "./components/picker-column-internal/picker-column-internal-interfaces";
export { PickerInternalChangeEventDetail } from "./components/picker-internal/picker-internal-interfaces";
export { PopoverSize, PositionAlign, PositionReference, PositionSide, TriggerAction } from "./components/popover/popover-interface";
export { RadioGroupChangeEventDetail, RadioGroupCompareFn } from "./components/radio-group/radio-group-interface";
export { RadioGroupChangeEventDetail } from "./components/radio-group/radio-group-interface";
export { PinFormatter, RangeChangeEventDetail, RangeKnobMoveEndEventDetail, RangeKnobMoveStartEventDetail, RangeValue } from "./components/range/range-interface";
export { RefresherEventDetail } from "./components/refresher/refresher-interface";
export { ItemReorderEventDetail } from "./components/reorder-group/reorder-group-interface";
@@ -75,7 +75,7 @@ export { SelectChangeEventDetail, SelectCompareFn, SelectInterface } from "./com
export { SelectPopoverOption } from "./components/select-popover/select-popover-interface";
export { TabBarChangedEventDetail, TabButtonClickEventDetail, TabButtonLayout } from "./components/tab-bar/tab-bar-interface";
export { TextareaChangeEventDetail, TextareaInputEventDetail } from "./components/textarea/textarea-interface";
export { ToastButton, ToastDismissOptions, ToastLayout, ToastPosition, ToastPresentOptions, ToastSwipeGestureDirection } from "./components/toast/toast-interface";
export { ToastButton, ToastDismissOptions, ToastLayout, ToastPosition, ToastPresentOptions } from "./components/toast/toast-interface";
export { ToggleChangeEventDetail } from "./components/toggle/toggle-interface";
export namespace Components {
interface IonAccordion {
@@ -2269,10 +2269,6 @@ export namespace Components {
* If `true`, the radios can be deselected.
*/
"allowEmptySelection": boolean;
/**
* This property allows developers to specify a custom function or property name for comparing objects when determining the selected option in the ion-radio-group. When not specified, the default behavior will use strict equality (===) for comparison.
*/
"compareWith"?: string | RadioGroupCompareFn | null;
/**
* The name of the control, which is submitted with the form data.
*/
@@ -2692,7 +2688,7 @@ export namespace Components {
*/
"color"?: Color;
/**
* This property allows developers to specify a custom function or property name for comparing objects when determining the selected option in the ion-select. When not specified, the default behavior will use strict equality (===) for comparison.
* A property name or function used to compare object values
*/
"compareWith"?: string | SelectCompareFn | null;
/**
@@ -3176,10 +3172,6 @@ export namespace Components {
* Present the toast overlay after it has been created.
*/
"present": () => Promise<void>;
/**
* If set to 'vertical', the Toast can be dismissed with a swipe gesture. The swipe direction is determined by the value of the `position` property: `top`: The Toast can be swiped up to dismiss. `bottom`: The Toast can be swiped down to dismiss. `middle`: The Toast can be swiped up or down to dismiss.
*/
"swipeGesture"?: ToastSwipeGestureDirection;
/**
* If `true`, the toast will be translucent. Only applies when the mode is `"ios"` and the device supports [`backdrop-filter`](https://developer.mozilla.org/en-US/docs/Web/CSS/backdrop-filter#Browser_compatibility).
*/
@@ -3398,10 +3390,6 @@ export interface IonSelectCustomEvent<T> extends CustomEvent<T> {
detail: T;
target: HTMLIonSelectElement;
}
export interface IonSkeletonTextCustomEvent<T> extends CustomEvent<T> {
detail: T;
target: HTMLIonSkeletonTextElement;
}
export interface IonSplitPaneCustomEvent<T> extends CustomEvent<T> {
detail: T;
target: HTMLIonSplitPaneElement;
@@ -4416,18 +4404,7 @@ declare global {
prototype: HTMLIonSelectPopoverElement;
new (): HTMLIonSelectPopoverElement;
};
interface HTMLIonSkeletonTextElementEventMap {
"ionStyle": StyleEventDetail;
}
interface HTMLIonSkeletonTextElement extends Components.IonSkeletonText, HTMLStencilElement {
addEventListener<K extends keyof HTMLIonSkeletonTextElementEventMap>(type: K, listener: (this: HTMLIonSkeletonTextElement, ev: IonSkeletonTextCustomEvent<HTMLIonSkeletonTextElementEventMap[K]>) => any, options?: boolean | AddEventListenerOptions): void;
addEventListener<K extends keyof DocumentEventMap>(type: K, listener: (this: Document, ev: DocumentEventMap[K]) => any, options?: boolean | AddEventListenerOptions): void;
addEventListener<K extends keyof HTMLElementEventMap>(type: K, listener: (this: HTMLElement, ev: HTMLElementEventMap[K]) => any, options?: boolean | AddEventListenerOptions): void;
addEventListener(type: string, listener: EventListenerOrEventListenerObject, options?: boolean | AddEventListenerOptions): void;
removeEventListener<K extends keyof HTMLIonSkeletonTextElementEventMap>(type: K, listener: (this: HTMLIonSkeletonTextElement, ev: IonSkeletonTextCustomEvent<HTMLIonSkeletonTextElementEventMap[K]>) => any, options?: boolean | EventListenerOptions): void;
removeEventListener<K extends keyof DocumentEventMap>(type: K, listener: (this: Document, ev: DocumentEventMap[K]) => any, options?: boolean | EventListenerOptions): void;
removeEventListener<K extends keyof HTMLElementEventMap>(type: K, listener: (this: HTMLElement, ev: HTMLElementEventMap[K]) => any, options?: boolean | EventListenerOptions): void;
removeEventListener(type: string, listener: EventListenerOrEventListenerObject, options?: boolean | EventListenerOptions): void;
}
var HTMLIonSkeletonTextElement: {
prototype: HTMLIonSkeletonTextElement;
@@ -6957,10 +6934,6 @@ declare namespace LocalJSX {
* If `true`, the radios can be deselected.
*/
"allowEmptySelection"?: boolean;
/**
* This property allows developers to specify a custom function or property name for comparing objects when determining the selected option in the ion-radio-group. When not specified, the default behavior will use strict equality (===) for comparison.
*/
"compareWith"?: string | RadioGroupCompareFn | null;
/**
* The name of the control, which is submitted with the form data.
*/
@@ -7443,7 +7416,7 @@ declare namespace LocalJSX {
*/
"color"?: Color;
/**
* This property allows developers to specify a custom function or property name for comparing objects when determining the selected option in the ion-select. When not specified, the default behavior will use strict equality (===) for comparison.
* A property name or function used to compare object values
*/
"compareWith"?: string | SelectCompareFn | null;
/**
@@ -7580,10 +7553,6 @@ declare namespace LocalJSX {
* If `true`, the skeleton text will animate.
*/
"animated"?: boolean;
/**
* Emitted when the styles change.
*/
"onIonStyle"?: (event: IonSkeletonTextCustomEvent<StyleEventDetail>) => void;
}
interface IonSpinner {
/**
@@ -7982,10 +7951,6 @@ declare namespace LocalJSX {
* The element to anchor the toast's position to. Can be set as a direct reference or the ID of the element. With `position="bottom"`, the toast will sit above the chosen element. With `position="top"`, the toast will sit below the chosen element. With `position="middle"`, the value of `positionAnchor` is ignored.
*/
"positionAnchor"?: HTMLElement | string;
/**
* If set to 'vertical', the Toast can be dismissed with a swipe gesture. The swipe direction is determined by the value of the `position` property: `top`: The Toast can be swiped up to dismiss. `bottom`: The Toast can be swiped down to dismiss. `middle`: The Toast can be swiped up or down to dismiss.
*/
"swipeGesture"?: ToastSwipeGestureDirection;
/**
* If `true`, the toast will be translucent. Only applies when the mode is `"ios"` and the device supports [`backdrop-filter`](https://developer.mozilla.org/en-US/docs/Web/CSS/backdrop-filter#Browser_compatibility).
*/

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.7 KiB

After

Width:  |  Height:  |  Size: 5.7 KiB

View File

@@ -90,6 +90,13 @@
}
.label-text-wrapper {
/**
* This ensures that double tapping this text
* clicks the <label> and focuses the checkbox
* when a screen reader is enabled.
*/
pointer-events: none;
text-overflow: ellipsis;
white-space: nowrap;
@@ -166,6 +173,7 @@ input {
opacity: 0;
}
// Justify Content
// ---------------------------------------------
@@ -192,6 +200,7 @@ input {
align-items: center;
}
// Label Placement - Start
// ----------------------------------------------------------------
@@ -212,6 +221,7 @@ input {
@include margin(null, $form-control-label-margin, null, 0);
}
// Label Placement - End
// ----------------------------------------------------------------
@@ -232,6 +242,7 @@ input {
@include margin(null, 0, null, $form-control-label-margin);
}
// Label Placement - Fixed
// ----------------------------------------------------------------
@@ -306,6 +317,7 @@ input {
opacity: 1;
}
// Disabled Checkbox
// ---------------------------------------------

View File

@@ -18,7 +18,6 @@ import type { CheckboxChangeEventDetail } from './checkbox-interface';
* @slot - The label text to associate with the checkbox. Use the "labelPlacement" property to control where the label is placed relative to the checkbox.
*
* @part container - The container for the checkbox mark.
* @part label - The label text describing the checkbox.
* @part mark - The checkmark used to indicate the checked state.
*/
@Component({
@@ -165,8 +164,6 @@ export class Checkbox implements ComponentInterface {
private emitStyle() {
const style: StyleEventDetail = {
'interactive-disabled': this.disabled,
// TODO(FW-3100): remove this
legacy: !!this.legacy,
};
// TODO(FW-3100): remove this
@@ -285,7 +282,6 @@ export class Checkbox implements ComponentInterface {
'label-text-wrapper': true,
'label-text-wrapper-hidden': el.textContent === '',
}}
part="label"
>
<slot></slot>
</div>

View File

@@ -2,23 +2,6 @@ import { newSpecPage } from '@stencil/core/testing';
import { Checkbox } from '../checkbox';
describe('ion-checkbox: shadow parts', () => {
it('should render the checkbox with shadow parts', async () => {
const page = await newSpecPage({
components: [Checkbox],
html: `
<ion-checkbox>Checkbox</ion-checkbox>
`,
});
const checkbox = page.body.querySelector('ion-checkbox')!;
expect(checkbox).toHaveShadowPart('container');
expect(checkbox).toHaveShadowPart('label');
expect(checkbox).toHaveShadowPart('mark');
});
});
describe('ion-checkbox: disabled', () => {
it('clicking disabled checkbox should not toggle checked state', async () => {
const page = await newSpecPage({

View File

@@ -267,9 +267,6 @@ ion-picker-column-internal {
justify-content: space-between;
}
// TODO(FW-3547): the styles targeting ion-item
// can be removed if we refactor datetime to
// not use an ion-item
:host .calendar-action-buttons ion-item,
:host .calendar-action-buttons ion-button {
--background: translucent;
@@ -279,11 +276,6 @@ ion-picker-column-internal {
display: flex;
align-items: center;
// Width is set to auto because it is set
// to min-content elsewhere and we want to
// prevent wrapping the label in datetime
width: auto;
}
:host .calendar-action-buttons ion-item ion-icon {

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 42 KiB

After

Width:  |  Height:  |  Size: 42 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 51 KiB

After

Width:  |  Height:  |  Size: 51 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 38 KiB

After

Width:  |  Height:  |  Size: 38 KiB

View File

@@ -12,14 +12,6 @@ export class InfiniteScroll implements ComponentInterface {
private thrPx = 0;
private thrPc = 0;
private scrollEl?: HTMLElement;
/**
* didFire exists so that ionInfinite
* does not fire multiple times if
* users continue to scroll after
* scrolling into the infinite
* scroll threshold.
*/
private didFire = false;
private isBusy = false;
@@ -135,6 +127,8 @@ export class InfiniteScroll implements ComponentInterface {
this.ionInfinite.emit();
return 3;
}
} else {
this.didFire = false;
}
return 4;
@@ -196,13 +190,10 @@ export class InfiniteScroll implements ComponentInterface {
writeTask(() => {
scrollEl.scrollTop = newScrollTop;
this.isBusy = false;
this.didFire = false;
});
});
});
});
} else {
this.didFire = false;
}
}

View File

@@ -1,63 +0,0 @@
<!DOCTYPE html>
<html lang="en" dir="ltr">
<head>
<meta charset="UTF-8" />
<title>Infinite Scroll - Small DOM Update</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>
<style>
#list .item {
width: 100%;
border-bottom: 1px solid gray;
padding: 10px;
}
</style>
</head>
<body>
<ion-app>
<ion-content class="ion-padding" id="content">
<div id="list"></div>
<ion-infinite-scroll threshold="100px" id="infinite-scroll">
<ion-infinite-scroll-content loading-spinner="crescent" loading-text="Loading more data...">
</ion-infinite-scroll-content>
</ion-infinite-scroll>
</ion-content>
</ion-app>
<script>
const list = document.getElementById('list');
const infiniteScroll = document.getElementById('infinite-scroll');
infiniteScroll.addEventListener('ionInfinite', () => {
setTimeout(() => {
appendItems();
infiniteScroll.complete();
// Custom event consumed in the e2e tests
window.dispatchEvent(new CustomEvent('ionInfiniteComplete'));
}, 500);
});
function appendItems(count = 3) {
for (var i = 0; i < count; i++) {
const el = document.createElement('div');
el.classList.add('item');
el.textContent = `${1 + i}`;
list.appendChild(el);
}
}
appendItems(30);
</script>
</body>
</html>

View File

@@ -1,34 +0,0 @@
import { expect } from '@playwright/test';
import { configs, test } from '@utils/test/playwright';
configs({ modes: ['md'], directions: ['ltr'] }).forEach(({ title, config }) => {
test.describe(title('infinite-scroll: appending small amounts to dom'), () => {
test('should load more after remaining in threshold', async ({ page }) => {
await page.goto('/src/components/infinite-scroll/test/small-dom-update', config);
const ionInfiniteComplete = await page.spyOnEvent('ionInfiniteComplete');
const content = page.locator('ion-content');
const items = page.locator('#list .item');
expect(await items.count()).toBe(30);
await content.evaluate((el: HTMLIonContentElement) => el.scrollToBottom(0));
await ionInfiniteComplete.next();
/**
* Even after appending we'll still be within
* the infinite scroll's threshold
*/
expect(await items.count()).toBe(33);
await content.evaluate((el: HTMLIonContentElement) => el.scrollToBottom(0));
await ionInfiniteComplete.next();
/**
* Scrolling down again without leaving
* the threshold should still trigger
* infinite scroll again.
*/
expect(await items.count()).toBe(36);
});
});
});

View File

@@ -89,7 +89,9 @@
/**
* This makes the label sit above the input.
*/
:host(.label-floating.input-fill-outline) .label-text-wrapper {
:host(.has-focus.input-fill-outline.input-label-placement-floating) .label-text-wrapper,
:host(.has-value.input-fill-outline.input-label-placement-floating) .label-text-wrapper,
:host(.input-fill-outline.input-label-placement-stacked) .label-text-wrapper {
@include transform(translateY(-32%), scale(#{$form-control-label-stacked-scale}));
@include margin(0);
@@ -214,6 +216,8 @@
* the floating/stacked label. We simulate this "cut out"
* by removing the top border from the notch fragment.
*/
:host(.label-floating.input-fill-outline) .input-outline-notch {
:host(.has-focus.input-fill-outline.input-label-placement-floating) .input-outline-notch,
:host(.has-value.input-fill-outline.input-label-placement-floating) .input-outline-notch,
:host(.input-fill-outline.input-label-placement-stacked) .input-outline-notch {
border-top: none;
}

View File

@@ -67,7 +67,9 @@
// Input Label
// ----------------------------------------------------------------
:host(.label-floating.input-fill-solid.input-label-placement-floating) .label-text-wrapper {
:host(.input-fill-solid.input-label-placement-stacked) .label-text-wrapper,
:host(.has-focus.input-fill-solid.input-label-placement-floating) .label-text-wrapper,
:host(.has-value.input-fill-solid.input-label-placement-floating) .label-text-wrapper {
/**
* Label text should not extend
* beyond the bounds of the input.

View File

@@ -322,9 +322,6 @@
flex-grow: 1;
// ensure start/end slot content is vertically centered
align-items: center;
width: 100%;
}
@@ -644,7 +641,9 @@
/**
* This makes the label sit above the input.
*/
:host(.label-floating) .label-text-wrapper {
:host(.input-label-placement-stacked) .label-text-wrapper,
:host(.has-focus.input-label-placement-floating) .label-text-wrapper,
:host(.has-value.input-label-placement-floating) .label-text-wrapper {
@include transform(translateY(50%), scale(#{$form-control-label-stacked-scale}));
/**
@@ -653,14 +652,3 @@
*/
max-width: calc(100% / #{$form-control-label-stacked-scale});
}
// Start/End Slots
// ----------------------------------------------------------------
::slotted([slot="start"]) {
margin-inline-end: $form-control-label-margin;
}
::slotted([slot="end"]) {
margin-inline-start: $form-control-label-margin;
}

View File

@@ -26,8 +26,6 @@ import { getCounterText } from './input.utils';
* @virtualProp {"ios" | "md"} mode - The mode determines which platform styles to use.
*
* @slot label - The label text to associate with the input. Use the `labelPlacement` property to control where the label is placed relative to the input. Use this if you need to render a label with custom HTML. (EXPERIMENTAL)
* @slot start - Content to display at the leading edge of the input. (EXPERIMENTAL)
* @slot end - Content to display at the trailing edge of the input. (EXPERIMENTAL)
*/
@Component({
tag: 'ion-input',
@@ -373,7 +371,7 @@ export class Input implements ComponentInterface {
const { el } = this;
this.legacyFormController = createLegacyFormController(el);
this.slotMutationController = createSlotMutationController(el, ['label', 'start', 'end'], () => forceUpdate(this));
this.slotMutationController = createSlotMutationController(el, 'label', () => forceUpdate(this));
this.notchController = createNotchController(
el,
() => this.notchSpacerEl,
@@ -498,8 +496,6 @@ export class Input implements ComponentInterface {
'has-value': this.hasValue(),
'has-focus': this.hasFocus,
'interactive-disabled': this.disabled,
// TODO(FW-2764): remove this
legacy: !!this.legacy,
});
}
}
@@ -703,42 +699,18 @@ export class Input implements ComponentInterface {
}
private renderInput() {
const { disabled, fill, readonly, shape, inputId, labelPlacement, el, hasFocus } = this;
const { disabled, fill, readonly, shape, inputId, labelPlacement } = this;
const mode = getIonMode(this);
const value = this.getValue();
const inItem = hostContext('ion-item', this.el);
const shouldRenderHighlight = mode === 'md' && fill !== 'outline' && !inItem;
const hasValue = this.hasValue();
const hasStartEndSlots = el.querySelector('[slot="start"], [slot="end"]') !== null;
/**
* If the label is stacked, it should always sit above the input.
* For floating labels, the label should move above the input if
* the input has a value, is focused, or has anything in either
* the start or end slot.
*
* If there is content in the start slot, the label would overlap
* it if not forced to float. This is also applied to the end slot
* because with the default or solid fills, the input is not
* vertically centered in the container, but the label is. This
* causes the slots and label to appear vertically offset from each
* other when the label isn't floating above the input. This doesn't
* apply to the outline fill, but this was not accounted for to keep
* things consistent.
*
* TODO(FW-5592): Remove hasStartEndSlots condition
*/
const labelShouldFloat =
labelPlacement === 'stacked' || (labelPlacement === 'floating' && (hasValue || hasFocus || hasStartEndSlots));
return (
<Host
class={createColorClasses(this.color, {
[mode]: true,
'has-value': hasValue,
'has-focus': hasFocus,
'label-floating': labelShouldFloat,
'has-value': this.hasValue(),
'has-focus': this.hasFocus,
[`input-fill-${fill}`]: fill !== undefined,
[`input-shape-${shape}`]: shape !== undefined,
[`input-label-placement-${labelPlacement}`]: true,
@@ -747,16 +719,9 @@ export class Input implements ComponentInterface {
'input-disabled': disabled,
})}
>
{/**
* htmlFor is needed so that clicking the label always focuses
* the input. Otherwise, if the start slot has something
* interactable, clicking the label would focus that instead
* since it comes before the input in the DOM.
*/}
<label class="input-wrapper" htmlFor={inputId}>
<label class="input-wrapper">
{this.renderLabelContainer()}
<div class="native-wrapper">
<slot name="start"></slot>
<input
class="native-input"
ref={(input) => (this.nativeInput = input)}
@@ -811,7 +776,6 @@ export class Input implements ComponentInterface {
<ion-icon aria-hidden="true" icon={mode === 'ios' ? closeCircle : closeSharp}></ion-icon>
</button>
)}
<slot name="end"></slot>
</div>
{shouldRenderHighlight && <div class="input-highlight"></div>}
</label>

View File

@@ -21,13 +21,7 @@
<ion-input label="Email" label-placement="stacked" value="hi@ionic.io"></ion-input><br />
<ion-input label="Email" label-placement="floating"></ion-input> <br />
<ion-input label="Email" label-placement="floating" fill="outline" value="hi@ionic.io"></ion-input> <br />
<ion-input label="Email" label-placement="floating" fill="solid" value="hi@ionic.io"></ion-input><br />
<ion-input label="Email" fill="solid" value="hi@ionic.io">
<ion-icon slot="start" name="lock-closed" aria-hidden="true"></ion-icon>
<ion-button slot="end" aria-label="button">
<ion-icon slot="icon-only" name="lock-closed" aria-hidden="true"></ion-icon>
</ion-button>
</ion-input>
<ion-input label="Email" label-placement="floating" fill="solid" value="hi@ionic.io"></ion-input>
</main>
</body>
</html>

View File

@@ -29,7 +29,7 @@
<h2>Inactive</h2>
<ion-item>
<ion-label position="floating">Label</ion-label>
<ion-input legacy="true" placeholder="Placeholder Text"></ion-input>
<ion-input placeholder="Placeholder Text"></ion-input>
</ion-item>
</div>
@@ -37,7 +37,7 @@
<h2>Focused</h2>
<ion-item class="item-has-focus">
<ion-label position="floating">Label</ion-label>
<ion-input legacy="true" placeholder="Placeholder Text"></ion-input>
<ion-input placeholder="Placeholder Text"></ion-input>
</ion-item>
</div>
@@ -45,7 +45,7 @@
<h2>Activated</h2>
<ion-item>
<ion-label position="floating">Label</ion-label>
<ion-input legacy="true" placeholder="Placeholder Text" value="Input Text"></ion-input>
<ion-input placeholder="Placeholder Text" value="Input Text"></ion-input>
</ion-item>
</div>
@@ -53,7 +53,7 @@
<h2>Hover</h2>
<ion-item class="item-hovered">
<ion-label position="floating">Label</ion-label>
<ion-input legacy="true"></ion-input>
<ion-input></ion-input>
</ion-item>
</div>
@@ -61,7 +61,7 @@
<h2>Disabled</h2>
<ion-item>
<ion-label position="floating">Label</ion-label>
<ion-input legacy="true" disabled></ion-input>
<ion-input disabled></ion-input>
</ion-item>
</div>
@@ -69,7 +69,7 @@
<h2>Toggle Placeholder</h2>
<ion-item>
<ion-label position="floating">Label</ion-label>
<ion-input legacy="true" id="floatingToggle" type="password"></ion-input>
<ion-input id="floatingToggle" type="password"></ion-input>
<ion-button
fill="clear"
slot="end"
@@ -89,7 +89,7 @@
<h2>Inactive</h2>
<ion-item>
<ion-label position="stacked">Label</ion-label>
<ion-input legacy="true"></ion-input>
<ion-input></ion-input>
</ion-item>
</div>
@@ -97,7 +97,7 @@
<h2>Focused</h2>
<ion-item class="item-has-focus">
<ion-label position="stacked">Label</ion-label>
<ion-input legacy="true" placeholder="Placeholder Text"></ion-input>
<ion-input placeholder="Placeholder Text"></ion-input>
</ion-item>
</div>
@@ -105,7 +105,7 @@
<h2>Activated</h2>
<ion-item>
<ion-label position="stacked">Label</ion-label>
<ion-input legacy="true" placeholder="Placeholder Text" value="Input Text"></ion-input>
<ion-input placeholder="Placeholder Text" value="Input Text"></ion-input>
</ion-item>
</div>
@@ -113,7 +113,7 @@
<h2>Hover</h2>
<ion-item class="item-hovered">
<ion-label position="stacked">Label</ion-label>
<ion-input legacy="true"></ion-input>
<ion-input></ion-input>
</ion-item>
</div>
@@ -121,7 +121,7 @@
<h2>Disabled</h2>
<ion-item>
<ion-label position="stacked">Label</ion-label>
<ion-input legacy="true" disabled></ion-input>
<ion-input disabled></ion-input>
</ion-item>
</div>
@@ -129,7 +129,7 @@
<h2>Toggle Placeholder</h2>
<ion-item>
<ion-label position="stacked">Label</ion-label>
<ion-input legacy="true" id="stackedToggle" type="password"></ion-input>
<ion-input id="stackedToggle" type="password"></ion-input>
<ion-button
fill="clear"
slot="end"

View File

@@ -49,125 +49,53 @@
</ion-header>
<ion-content id="content" class="ion-padding">
<h1>Label Slot</h1>
<div class="grid">
<div class="grid-item">
<h2>No Fill / Start Label</h2>
<h2>No Fill / Start</h2>
<ion-input label-placement="start" value="hi@ionic.io">
<div slot="label">Email <span class="required">*</span></div>
</ion-input>
</div>
<div class="grid-item">
<h2>Solid / Start Label</h2>
<h2>Solid / Start</h2>
<ion-input label-placement="start" fill="solid" value="hi@ionic.io">
<div slot="label">Email <span class="required">*</span></div>
</ion-input>
</div>
<div class="grid-item">
<h2>Outline / Start Label</h2>
<h2>Outline / Start</h2>
<ion-input label-placement="start" fill="outline" value="hi@ionic.io">
<div slot="label">Email <span class="required">*</span></div>
</ion-input>
</div>
<div class="grid-item">
<h2>No Fill / Floating Label</h2>
<h2>No Fill / Floating</h2>
<ion-input label-placement="floating" value="hi@ionic.io">
<div slot="label">Email <span class="required">*</span></div>
</ion-input>
</div>
<div class="grid-item">
<h2>Solid / Floating Label</h2>
<h2>Solid / Floating</h2>
<ion-input label-placement="floating" fill="solid" value="hi@ionic.io">
<div slot="label">Email <span class="required">*</span></div>
</ion-input>
</div>
<div class="grid-item">
<h2>Outline / Floating Label</h2>
<h2>Outline / Floating</h2>
<ion-input label-placement="floating" fill="outline" value="hi@ionic.io">
<div slot="label">Email <span class="required">*</span></div>
</ion-input>
</div>
</div>
<h1>Start/End Slots</h1>
<div class="grid">
<div class="grid-item">
<h2>No Fill / Start Label</h2>
<ion-input label-placement="start" value="hi@ionic.io" label="Email">
<ion-icon slot="start" name="lock-closed" aria-hidden="true"></ion-icon>
<ion-button fill="clear" slot="end" aria-label="Show/hide password">
<ion-icon slot="icon-only" name="eye" aria-hidden="true"></ion-icon>
</ion-button>
</ion-input>
</div>
<div class="grid-item">
<h2>Solid / Start Label</h2>
<ion-input label-placement="start" fill="solid" value="hi@ionic.io" label="Email">
<ion-icon slot="start" name="lock-closed" aria-hidden="true"></ion-icon>
<ion-button fill="clear" slot="end" aria-label="Show/hide password">
<ion-icon slot="icon-only" name="eye" aria-hidden="true"></ion-icon>
</ion-button>
</ion-input>
</div>
<div class="grid-item">
<h2>Outline / Start Label</h2>
<ion-input label-placement="start" fill="outline" value="hi@ionic.io" label="Email">
<ion-icon slot="start" name="lock-closed" aria-hidden="true"></ion-icon>
<ion-button fill="clear" slot="end" aria-label="Show/hide password">
<ion-icon slot="icon-only" name="eye" aria-hidden="true"></ion-icon>
</ion-button>
</ion-input>
</div>
<div class="grid-item">
<h2>No Fill / Floating Label</h2>
<ion-input label-placement="floating" value="hi@ionic.io" label="Email">
<ion-icon slot="start" name="lock-closed" aria-hidden="true"></ion-icon>
<ion-button fill="clear" slot="end" aria-label="Show/hide password">
<ion-icon slot="icon-only" name="eye" aria-hidden="true"></ion-icon>
</ion-button>
</ion-input>
</div>
<div class="grid-item">
<h2>Solid / Floating Label</h2>
<ion-input label-placement="floating" fill="solid" value="hi@ionic.io" label="Email">
<ion-icon slot="start" name="lock-closed" aria-hidden="true"></ion-icon>
<ion-button fill="clear" slot="end" aria-label="Show/hide password">
<ion-icon slot="icon-only" name="eye" aria-hidden="true"></ion-icon>
</ion-button>
</ion-input>
</div>
<div class="grid-item">
<h2>Outline / Floating Label</h2>
<ion-input label-placement="floating" fill="outline" value="hi@ionic.io" label="Email">
<ion-icon slot="start" name="lock-closed" aria-hidden="true"></ion-icon>
<ion-button fill="clear" slot="end" aria-label="Show/hide password">
<ion-icon slot="icon-only" name="eye" aria-hidden="true"></ion-icon>
</ion-button>
</ion-input>
</div>
</div>
<h1>Async Slot Content</h1>
<div class="grid">
<div class="grid-item">
<h2>Outline / Async Label</h2>
<h2>Outline / Floating / Async</h2>
<ion-input id="solid-async" label-placement="floating" fill="outline" value="hi@ionic.io"></ion-input>
</div>
<div class="grid-item">
<h2>Outline / Async Decorations</h2>
<ion-input id="async-decorations" label-placement="floating" fill="outline" label="Email"></ion-input>
</div>
</div>
<ion-button onclick="addSlot()">Add Slotted Content</ion-button>
@@ -178,65 +106,29 @@
<script>
const solidAsync = document.querySelector('#solid-async');
const asyncDecos = document.querySelector('#async-decorations');
const getSlottedLabel = () => {
const getSlottedContent = () => {
return solidAsync.querySelector('[slot="label"]');
};
const getSlottedStartDeco = () => {
return asyncDecos.querySelector('[slot="start"]');
};
const getSlottedEndDeco = () => {
return asyncDecos.querySelector('[slot="end"]');
};
const addSlot = () => {
if (getSlottedLabel() === null) {
if (getSlottedContent() === null) {
const labelEl = document.createElement('div');
labelEl.slot = 'label';
labelEl.innerHTML = 'Email <span class="required">*</span>';
solidAsync.appendChild(labelEl);
}
if (getSlottedStartDeco() === null) {
const startEl = document.createElement('div');
startEl.slot = 'start';
startEl.innerHTML = 'Start';
asyncDecos.insertAdjacentElement('afterbegin', startEl);
}
if (getSlottedEndDeco() === null) {
const endEl = document.createElement('div');
endEl.slot = 'end';
endEl.innerHTML = 'End';
asyncDecos.insertAdjacentElement('beforeend', endEl);
}
};
const removeSlot = () => {
const slottedLabel = getSlottedLabel();
if (slottedLabel !== null) {
slottedLabel.remove();
}
const slottedStartDeco = getSlottedStartDeco();
if (slottedStartDeco !== null) {
slottedStartDeco.remove();
}
const slottedEndDeco = getSlottedEndDeco();
if (slottedEndDeco !== null) {
slottedEndDeco.remove();
if (getSlottedContent() !== null) {
solidAsync.querySelector('[slot="label"]').remove();
}
};
const updateSlot = () => {
const slottedContent = getSlottedLabel();
const slottedContent = getSlottedContent();
if (slottedContent !== null) {
slottedContent.textContent = 'This is my really really really long text';

View File

@@ -1,68 +0,0 @@
import { expect } from '@playwright/test';
import { configs, test } from '@utils/test/playwright';
configs().forEach(({ title, screenshot, config }) => {
test.describe(title('input: start and end slots (visual checks)'), () => {
test('should not have visual regressions with a start-positioned label', async ({ page }) => {
await page.setContent(
`
<ion-input label-placement="start" fill="solid" value="100" label="Weight" clear-input="true">
<ion-icon slot="start" name="barbell" aria-hidden="true"></ion-icon>
<ion-label slot="end">lbs</ion-label>
</ion-input>
`,
config
);
const input = page.locator('ion-input');
await expect(input).toHaveScreenshot(screenshot(`input-slots-label-start`));
});
test('should not have visual regressions with a floating label', async ({ page }) => {
await page.setContent(
`
<ion-input label-placement="floating" fill="solid" value="100" label="Weight" clear-input="true">
<ion-icon slot="start" name="barbell" aria-hidden="true"></ion-icon>
<ion-label slot="end">lbs</ion-label>
</ion-input>
`,
config
);
const input = page.locator('ion-input');
await expect(input).toHaveScreenshot(screenshot(`input-slots-label-floating`));
});
});
});
configs({ modes: ['md'], directions: ['ltr'] }).forEach(({ title, config }) => {
test.describe(title('input: start and end slots (functionality checks)'), () => {
test('should raise floating label when there is content in the start slot', async ({ page }) => {
await page.setContent(
`
<ion-input label-placement="floating" fill="solid" label="Weight">
<ion-icon slot="start" name="barbell" aria-hidden="true"></ion-icon>
</ion-input>
`,
config
);
const input = page.locator('ion-input');
await expect(input).toHaveClass(/label-floating/);
});
test('should raise floating label when there is content in the end slot', async ({ page }) => {
await page.setContent(
`
<ion-input label-placement="floating" fill="solid" label="Weight">
<ion-icon slot="end" name="barbell" aria-hidden="true"></ion-icon>
</ion-input>
`,
config
);
const input = page.locator('ion-input');
await expect(input).toHaveClass(/label-floating/);
});
});
});

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.9 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.0 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.5 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.9 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.2 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.5 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.7 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.8 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.4 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.8 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.8 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.4 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.2 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.2 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.8 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.2 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.0 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.8 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.1 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.0 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.6 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.0 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.0 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.6 KiB

View File

@@ -51,15 +51,6 @@
* @prop --highlight-color-valid: The color of the highlight on the item when valid. Only applies to inputs and textareas using the legacy form syntax. DEPRECATED: Highlights can be styled on `ion-input` or `ion-textarea` when using the modern form syntax.
* @prop --highlight-color-invalid: The color of the highlight on the item when invalid. Only applies to inputs and textareas using the legacy form syntax. DEPRECATED: Highlights can be styled on `ion-input` or `ion-textarea` when using the modern form syntax.
*/
/**
* We change the minimum width as the
* font size changes. Using a fixed minimum
* width means that fewer and fewer characters
* can be displayed in the same space as the
* text grows.
*/
--inner-min-width: 4rem;
--border-radius: 0px;
--border-width: 0px;
--border-style: solid;
@@ -230,11 +221,6 @@
display: flex;
position: relative;
// Flex wrap is required here in order to wrap
// the start slot + .item-inner content that
// doesn't fit on the same line
flex-wrap: wrap;
align-items: inherit;
justify-content: inherit;
@@ -252,15 +238,9 @@
background: var(--background);
overflow: inherit;
box-sizing: border-box;
z-index: 1;
box-sizing: border-box;
}
// TODO(FW-5289): remove
:host(.item-legacy) .item-native {
flex-wrap: unset;
}
.item-native::-moz-focus-inner {
@@ -307,34 +287,11 @@ button, a {
// This is required to work with an inset highlight
position: relative;
// This flex property is required in order to make
// the elements wrap when there is a slotted start
// element and a label
flex: 1 0 0;
flex: 1;
flex-direction: inherit;
// Flex wrap is required here in order to wrap
// .input-wrapper content + the end slot that
// doesn't fit on the same line
flex-wrap: wrap;
align-items: inherit;
align-self: stretch;
/**
* The min-width defines when the
* content in the default slot should
* stop wrapping/truncating within its own
* container. At this point the entire
* container will wrap to the next line.
*/
min-width: var(--inner-min-width);
// Max width must be set to 100%, otherwise the
// elements will overflow this container instead
// of wrapping
max-width: 100%;
min-height: inherit;
border-width: var(--inner-border-width);
@@ -346,14 +303,6 @@ button, a {
box-sizing: border-box;
}
// TODO(FW-5289): remove
:host(.item-legacy) .item-inner {
flex: 1;
flex-wrap: unset;
max-width: unset;
}
// Item Bottom
// --------------------------------------------------
@@ -421,11 +370,6 @@ button, a {
::slotted(ion-label:not([slot="end"])) {
flex: 1;
// Setting width to min-content allows the label to
// shrink and wrap its text instead of moving to its
// own row if there are slotted elements next to it
width: min-content;
}
// Item Input
@@ -438,41 +382,18 @@ button, a {
.input-wrapper {
display: flex;
// This flex property is required in order to keep
// the label from shrinking when there are wide
// elements next to it
flex: 1 0 auto;
flex: 1;
flex-direction: inherit;
// Flex wrap is required here in order to wrap
// content in the default slot (such as a label
// and a button) that doesn't fit on the same line
flex-wrap: wrap;
align-items: inherit;
align-self: stretch;
// Max width must be set to 100%, otherwise the
// elements will overflow this container instead
// of wrapping
max-width: 100%;
text-overflow: ellipsis;
overflow: inherit;
box-sizing: border-box;
}
// TODO(FW-5289): remove
:host(.item-legacy) .input-wrapper {
flex: 1;
flex-wrap: unset;
max-width: unset;
}
:host(.item-label-stacked),
:host(.item-label-floating) {
align-items: start;

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

After

Width:  |  Height:  |  Size: 14 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 20 KiB

After

Width:  |  Height:  |  Size: 18 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 15 KiB

After

Width:  |  Height:  |  Size: 13 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 15 KiB

After

Width:  |  Height:  |  Size: 14 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 21 KiB

After

Width:  |  Height:  |  Size: 18 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

After

Width:  |  Height:  |  Size: 12 KiB

View File

@@ -43,13 +43,11 @@
</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-label> Single line text that should have ellipses when it doesn't all fit in the item</ion-label>
</ion-item>
<ion-item lines="none">
<ion-label>Single line item with no lines</ion-label>
<ion-label> Single line item with no lines</ion-label>
</ion-item>
<ion-item>
@@ -59,21 +57,21 @@
</ion-item>
<ion-item color="secondary">
<ion-label>
<ion-label class="ion-text-wrap">
<h1>H1 Title Text</h1>
<p>Paragraph line 1</p>
</ion-label>
</ion-item>
<ion-item>
<ion-label>
<ion-label class="ion-text-wrap">
<h2>H2 Title Text</h2>
<p>Paragraph line 1</p>
</ion-label>
</ion-item>
<ion-item>
<ion-label>
<ion-label class="ion-text-wrap">
<ion-text color="primary">
<h3>H3 Title Text</h3>
</ion-text>
@@ -85,7 +83,7 @@
</ion-item>
<ion-item>
<ion-label>
<ion-label class="ion-text-wrap">
<h4>H4 Title Text</h4>
<p>Paragraph line 1</p>
<p>Paragraph line 2</p>
@@ -94,7 +92,7 @@
</ion-item>
<ion-item>
<ion-label>Item using inner ion-label </ion-label>
<ion-label> Item using inner ion-label </ion-label>
</ion-item>
<ion-item class="overflow-visible">

View File

@@ -31,7 +31,7 @@ configs().forEach(({ title, screenshot, config }) => {
</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-label> Single line text that should have ellipses when it doesn't all fit in the item</ion-label>
</ion-item>
</ion-list>
`,

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 71 KiB

After

Width:  |  Height:  |  Size: 68 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 82 KiB

After

Width:  |  Height:  |  Size: 79 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 62 KiB

After

Width:  |  Height:  |  Size: 60 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 66 KiB

After

Width:  |  Height:  |  Size: 63 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 79 KiB

After

Width:  |  Height:  |  Size: 74 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 57 KiB

After

Width:  |  Height:  |  Size: 54 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 70 KiB

After

Width:  |  Height:  |  Size: 68 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 82 KiB

After

Width:  |  Height:  |  Size: 79 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 64 KiB

After

Width:  |  Height:  |  Size: 62 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 70 KiB

After

Width:  |  Height:  |  Size: 68 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 82 KiB

After

Width:  |  Height:  |  Size: 78 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 64 KiB

After

Width:  |  Height:  |  Size: 62 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 67 KiB

After

Width:  |  Height:  |  Size: 64 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 80 KiB

After

Width:  |  Height:  |  Size: 76 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 58 KiB

After

Width:  |  Height:  |  Size: 55 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 67 KiB

After

Width:  |  Height:  |  Size: 64 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 79 KiB

After

Width:  |  Height:  |  Size: 75 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 57 KiB

After

Width:  |  Height:  |  Size: 54 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 47 KiB

After

Width:  |  Height:  |  Size: 47 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 61 KiB

After

Width:  |  Height:  |  Size: 60 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 43 KiB

After

Width:  |  Height:  |  Size: 43 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 45 KiB

After

Width:  |  Height:  |  Size: 44 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 58 KiB

After

Width:  |  Height:  |  Size: 57 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 39 KiB

After

Width:  |  Height:  |  Size: 39 KiB

View File

@@ -144,7 +144,8 @@
<ion-item>
<ion-checkbox aria-label="Checkbox" slot="start"></ion-checkbox>
<ion-toggle disabled value="45">Checkbox + Toggle</ion-toggle>
<ion-label>Checkbox + Toggle</ion-label>
<ion-toggle aria-label="Checkbox" disabled value="45"></ion-toggle>
</ion-item>
<ion-item>

View File

@@ -11,6 +11,7 @@ configs({ directions: ['ltr'] }).forEach(({ title, screenshot, config }) => {
await page.setIonViewport();
// TODO: FW-4037 - Fix label color inconsistency between disabled controls
await expect(page).toHaveScreenshot(screenshot(`item-disabled-diff`));
});
});

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 85 KiB

After

Width:  |  Height:  |  Size: 81 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 87 KiB

After

Width:  |  Height:  |  Size: 83 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 77 KiB

After

Width:  |  Height:  |  Size: 74 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 77 KiB

After

Width:  |  Height:  |  Size: 73 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 79 KiB

After

Width:  |  Height:  |  Size: 75 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 68 KiB

After

Width:  |  Height:  |  Size: 64 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 49 KiB

After

Width:  |  Height:  |  Size: 46 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 56 KiB

After

Width:  |  Height:  |  Size: 59 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 40 KiB

After

Width:  |  Height:  |  Size: 38 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 50 KiB

After

Width:  |  Height:  |  Size: 47 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 58 KiB

After

Width:  |  Height:  |  Size: 60 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 41 KiB

After

Width:  |  Height:  |  Size: 39 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 61 KiB

After

Width:  |  Height:  |  Size: 60 KiB

Some files were not shown because too many files have changed in this diff Show More