Compare commits

..

4 Commits

Author SHA1 Message Date
Bernardo Cardoso
36dfc50fa3 Merge branch 'next' into ionic-colors-support 2024-05-28 15:58:21 +01:00
Bernardo Cardoso
1ded2c5191 update iopnic clear button snapshots 2024-05-28 09:28:55 +01:00
Bernardo Cardoso
c8679f8b1b now color utilities affect variables 2024-05-28 07:21:55 +01:00
Bernardo Cardoso
6f089c0536 improve cretaeColorClasses function 2024-05-28 07:20:44 +01:00
2164 changed files with 25256 additions and 29612 deletions

1
.gitattributes vendored
View File

@@ -1 +0,0 @@
* text=auto eol=lf

View File

@@ -6,19 +6,11 @@ runs:
- uses: actions/setup-node@v4
with:
node-version: 18.x
- uses: ./.github/workflows/actions/download-archive
with:
name: ionic-core
path: ./core
filename: CoreBuild.zip
- name: Install Angular Server Dependencies
run: npm ci
shell: bash
working-directory: ./packages/angular-server
- name: Sync
run: npm run sync
shell: bash
working-directory: ./packages/angular-server
- name: Build
run: npm run build.prod
shell: bash

View File

@@ -29,7 +29,7 @@ runs:
shell: bash
working-directory: ./packages/angular/test
- name: Install Dependencies
run: npm install
run: npm install --legacy-peer-deps # TODO(FW-6227): Remove legacy-peer-deps flag
shell: bash
working-directory: ./packages/angular/test/build/${{ inputs.app }}
- name: Sync Built Changes

View File

@@ -11,8 +11,8 @@ jobs:
issues: write
steps:
- name: 'Auto-assign issue'
uses: pozil/auto-assign-issue@c5bca5027e680b9e8411b826d16947afd8c76b32 # v2.0.0
uses: pozil/auto-assign-issue@65947009a243e6b3993edeef4e64df3ca85d760c # v1.14.0
with:
assignees: brandyscarney, thetaPC, joselrio, rugoncalves, BenOsodrac, JoaoFerreira-FrontEnd, OS-giulianasilva, tanner-reits
assignees: brandyscarney, thetaPC
numOfAssignee: 1
allowSelfAssign: false

View File

@@ -3,109 +3,6 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [8.2.7](https://github.com/ionic-team/ionic-framework/compare/v8.2.5...v8.2.7) (2024-08-13)
### Bug Fixes
* **alert:** do not overwrite id set in htmlAttributes ([#29708](https://github.com/ionic-team/ionic-framework/issues/29708)) ([1295ced](https://github.com/ionic-team/ionic-framework/commit/1295cedae9ffbcc40389c19499e58e7e21fb424e)), closes [#29704](https://github.com/ionic-team/ionic-framework/issues/29704)
* **angular:** add focusTrap prop to modal and popover ([#29729](https://github.com/ionic-team/ionic-framework/issues/29729)) ([05913c3](https://github.com/ionic-team/ionic-framework/commit/05913c3cc3f2e8cb91f9a0944cd55e78392b0ba3)), closes [#29728](https://github.com/ionic-team/ionic-framework/issues/29728)
* **angular:** remove the tabindex set by routerLink from Ionic components ([#29744](https://github.com/ionic-team/ionic-framework/issues/29744)) ([20073e1](https://github.com/ionic-team/ionic-framework/commit/20073e10c934d3704734195c72f4281c9b9658e3)), closes [#20632](https://github.com/ionic-team/ionic-framework/issues/20632)
* **content:** allow custom roles and aria attributes to be set on content ([#29753](https://github.com/ionic-team/ionic-framework/issues/29753)) ([7b16397](https://github.com/ionic-team/ionic-framework/commit/7b16397714be773fda28658ab4009755f545b735))
* **item:** router-link remains clickable with item cover ([#29743](https://github.com/ionic-team/ionic-framework/issues/29743)) ([a9f278a](https://github.com/ionic-team/ionic-framework/commit/a9f278ad67758a19e0e12ce7ed6d13eb573b0765))
* **overlays:** do not overwrite id set in htmlAttributes ([#29722](https://github.com/ionic-team/ionic-framework/issues/29722)) ([92ce563](https://github.com/ionic-team/ionic-framework/commit/92ce563c402e557b08a622bd20f78459782312e2)), closes [#29712](https://github.com/ionic-team/ionic-framework/issues/29712)
* **react:** add onPointerDown, onTouchEnd, add onTouchMove ([#29736](https://github.com/ionic-team/ionic-framework/issues/29736)) ([bfee3cd](https://github.com/ionic-team/ionic-framework/commit/bfee3cd064a9b495489c2679ccfb762e622dbf09)), closes [#29174](https://github.com/ionic-team/ionic-framework/issues/29174)
* **vue:** pass router-link value to href to properly render clickable elements ([#29745](https://github.com/ionic-team/ionic-framework/issues/29745)) ([ab4f279](https://github.com/ionic-team/ionic-framework/commit/ab4f2791c1968adbb1d858c5f009fa251bb9101b))
## [8.2.6](https://github.com/ionic-team/ionic-framework/compare/v8.2.5...v8.2.6) (2024-07-24)
### Bug Fixes
* **alert:** do not overwrite id set in htmlAttributes ([#29708](https://github.com/ionic-team/ionic-framework/issues/29708)) ([1295ced](https://github.com/ionic-team/ionic-framework/commit/1295cedae9ffbcc40389c19499e58e7e21fb424e)), closes [#29704](https://github.com/ionic-team/ionic-framework/issues/29704)
* **angular:** add focusTrap prop to modal and popover ([#29729](https://github.com/ionic-team/ionic-framework/issues/29729)) ([05913c3](https://github.com/ionic-team/ionic-framework/commit/05913c3cc3f2e8cb91f9a0944cd55e78392b0ba3)), closes [#29728](https://github.com/ionic-team/ionic-framework/issues/29728)
* **overlays:** do not overwrite id set in htmlAttributes ([#29722](https://github.com/ionic-team/ionic-framework/issues/29722)) ([92ce563](https://github.com/ionic-team/ionic-framework/commit/92ce563c402e557b08a622bd20f78459782312e2)), closes [#29712](https://github.com/ionic-team/ionic-framework/issues/29712)
## [8.2.5](https://github.com/ionic-team/ionic-framework/compare/v8.2.4...v8.2.5) (2024-07-03)
### Bug Fixes
* **dependencies:** use latest @stencil/core to remove DOMException errors ([#29685](https://github.com/ionic-team/ionic-framework/issues/29685)) ([d70ea4](https://github.com/ionic-team/ionic/commit/d70ea400a4713bd091af1393e196e10844a190b6)), closes [#29681](https://github.com/ionic-team/ionic/issues/29681)
* **vue:** add optional IonicConfig type parameter to IonicVue plugin ([#29637](https://github.com/ionic-team/ionic-framework/issues/29637)) ([90893f4](https://github.com/ionic-team/ionic-framework/commit/90893f46c930dbccd4251fa2f56bdde30b669158)), closes [#29659](https://github.com/ionic-team/ionic-framework/issues/29659)
## [8.2.4](https://github.com/ionic-team/ionic-framework/compare/v8.2.2...v8.2.4) (2024-06-28)
### Bug Fixes
* **angular:** popover arrow navigation with disabled items ([#29662](https://github.com/ionic-team/ionic-framework/issues/29662)) ([ceb41f3](https://github.com/ionic-team/ionic-framework/commit/ceb41f31f382ff1bcf81de2b11680699d33d5077)), closes [#29640](https://github.com/ionic-team/ionic-framework/issues/29640)
## 8.2.3
This version should be skipped. Install 8.2.4 instead.
## [8.2.2](https://github.com/ionic-team/ionic-framework/compare/v8.2.1...v8.2.2) (2024-06-12)
### Bug Fixes
* **refresher:** show when content is fullscreen ([#29608](https://github.com/ionic-team/ionic-framework/issues/29608)) ([5cdfac8](https://github.com/ionic-team/ionic-framework/commit/5cdfac89f5389cb3009427183f7034ba05788bc2)), closes [#18714](https://github.com/ionic-team/ionic-framework/issues/18714)
## [8.2.1](https://github.com/ionic-team/ionic-framework/compare/v8.2.0...v8.2.1) (2024-06-05)
* **react:** export InputInputEventDetail type ([#29512](https://github.com/ionic-team/ionic-framework/issues/29512)) ([624ceba](https://github.com/ionic-team/ionic-framework/commit/624ceba2e128bb13a3afe4c35883f603f5488d0e)), closes [#29518](https://github.com/ionic-team/ionic-framework/issues/29518)
# [8.2.0](https://github.com/ionic-team/ionic-framework/compare/v8.1.3...v8.2.0) (2024-05-22)
### Features
* **angular:** setting props on a signal works ([#29453](https://github.com/ionic-team/ionic-framework/issues/29453)) ([4640e04](https://github.com/ionic-team/ionic-framework/commit/4640e046ebbd35bf92737368c6262f79a8803a59)), closes [#28876](https://github.com/ionic-team/ionic-framework/issues/28876)
## [8.1.3](https://github.com/ionic-team/ionic-framework/compare/v8.1.2...v8.1.3) (2024-05-22)
### Bug Fixes
* **core:** malformed URIs will not throw exception ([#29486](https://github.com/ionic-team/ionic-framework/issues/29486)) ([4a41983](https://github.com/ionic-team/ionic-framework/commit/4a41983098fe9bf83fdf05ce7ab28c79f414e11b)), closes [#29479](https://github.com/ionic-team/ionic-framework/issues/29479)
## [8.1.2](https://github.com/ionic-team/ionic-framework/compare/v8.1.1...v8.1.2) (2024-05-15)

View File

@@ -20,7 +20,7 @@
<a href="https://github.com/ionic-team/ionic-framework/blob/main/LICENSE">
<img src="https://img.shields.io/badge/license-MIT-blue.svg" alt="Ionic Framework is released under the MIT license." />
</a>
<a href="https://github.com/ionic-team/ionic-framework/blob/main/docs/CONTRIBUTING.md">
<a href="https://github.com/ionic-team/ionic/blob/main/docs/CONTRIBUTING.md">
<img src="https://img.shields.io/badge/PRs-welcome-brightgreen.svg" alt="PRs welcome!" />
</a>
<a href="https://twitter.com/Ionicframework">
@@ -38,7 +38,7 @@
Documentation
</a>
<span> · </span>
<a href="https://github.com/ionic-team/ionic-framework/blob/main/docs/CONTRIBUTING.md">Contribute</a>
<a href="https://github.com/ionic-team/ionic/blob/main/docs/CONTRIBUTING.md">Contribute</a>
<span> · </span>
<a href="https://blog.ionicframework.com/">Blog</a>
<br />
@@ -63,15 +63,14 @@ Looking for the `ionic-angular` package? Ionic 3 has been moved to the [`ionic-v
### Getting Started
Start a new project by following our [documentation](https://ionicframework.com/docs/).
Start a new project by following our quick [Getting Started guide](https://ionicframework.com/getting-started/).
We would love to hear from you! If you have any feedback or run into issues using our framework, please file
an [issue](https://github.com/ionic-team/ionic-framework/issues/new) on this repository.
an [issue](https://github.com/ionic-team/ionic/issues/new) on this repository.
### Migration Guides
Already have an Ionic app? These guides will help you migrate to the latest versions.
* [Migrate from v7 to v8](https://ionicframework.com/docs/updating/8-0)
* [Migrate from v6 to v7](https://ionicframework.com/docs/updating/7-0)
* [Migrate from v5 to v6](https://ionicframework.com/docs/updating/6-0)
* [Migrate from v4 to v5](https://ionicframework.com/docs/updating/5-0)
@@ -83,16 +82,21 @@ The Ionic Conference App is a full featured Ionic app. It is the perfect startin
- [Angular Ionic Conference App](https://github.com/ionic-team/ionic-conference-app)
- [React Ionic Conference App](https://github.com/ionic-team/ionic-react-conference-app)
- [Vue Ionic Conference App](https://github.com/ionic-team/ionic-vue-conference-app)
<!-- TODO(FW-3811): add this when the vue conference app is updated -->
<!-- - [Vue Ionic Conference App](https://github.com/ionic-team/ionic-vue-conference-app) -->
### Contributing
Thanks for your interest in contributing! Read up on our guidelines for
[contributing](https://github.com/ionic-team/ionic-framework/blob/main/docs/CONTRIBUTING.md)
and then look through our issues with a [help wanted](https://github.com/ionic-team/ionic-framework/issues?q=is%3Aopen+is%3Aissue+label%3A%22help+wanted%22)
[contributing](https://github.com/ionic-team/ionic/blob/main/docs/CONTRIBUTING.md)
and then look through our issues with a [help wanted](https://github.com/ionic-team/ionic/issues?q=is%3Aopen+is%3Aissue+label%3A%22help+wanted%22)
label.
Please note that this project is released with a [Contributor Code of Conduct](https://github.com/ionic-team/ionic-framework/blob/main/CODE_OF_CONDUCT.md). By participating in this project you agree to abide by its terms.
Please note that this project is released with a [Contributor Code of Conduct](https://github.com/ionic-team/ionic/blob/main/CODE_OF_CONDUCT.md). By participating in this project you agree to abide by its terms.
### Future Goals
As Ionic Framework components migrate to the web component standard, a goal of ours is to have Ionic Framework easily work within all of the popular frameworks.
### Earlier Versions

View File

@@ -3,98 +3,6 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [8.2.7](https://github.com/ionic-team/ionic-framework/compare/v8.2.5...v8.2.7) (2024-08-13)
### Bug Fixes
* **alert:** do not overwrite id set in htmlAttributes ([#29708](https://github.com/ionic-team/ionic-framework/issues/29708)) ([1295ced](https://github.com/ionic-team/ionic-framework/commit/1295cedae9ffbcc40389c19499e58e7e21fb424e)), closes [#29704](https://github.com/ionic-team/ionic-framework/issues/29704)
* **content:** allow custom roles and aria attributes to be set on content ([#29753](https://github.com/ionic-team/ionic-framework/issues/29753)) ([7b16397](https://github.com/ionic-team/ionic-framework/commit/7b16397714be773fda28658ab4009755f545b735))
* **item:** router-link remains clickable with item cover ([#29743](https://github.com/ionic-team/ionic-framework/issues/29743)) ([a9f278a](https://github.com/ionic-team/ionic-framework/commit/a9f278ad67758a19e0e12ce7ed6d13eb573b0765))
* **overlays:** do not overwrite id set in htmlAttributes ([#29722](https://github.com/ionic-team/ionic-framework/issues/29722)) ([92ce563](https://github.com/ionic-team/ionic-framework/commit/92ce563c402e557b08a622bd20f78459782312e2)), closes [#29712](https://github.com/ionic-team/ionic-framework/issues/29712)
* **vue:** pass router-link value to href to properly render clickable elements ([#29745](https://github.com/ionic-team/ionic-framework/issues/29745)) ([ab4f279](https://github.com/ionic-team/ionic-framework/commit/ab4f2791c1968adbb1d858c5f009fa251bb9101b))
## [8.2.6](https://github.com/ionic-team/ionic-framework/compare/v8.2.5...v8.2.6) (2024-07-24)
### Bug Fixes
* **alert:** do not overwrite id set in htmlAttributes ([#29708](https://github.com/ionic-team/ionic-framework/issues/29708)) ([1295ced](https://github.com/ionic-team/ionic-framework/commit/1295cedae9ffbcc40389c19499e58e7e21fb424e)), closes [#29704](https://github.com/ionic-team/ionic-framework/issues/29704)
* **overlays:** do not overwrite id set in htmlAttributes ([#29722](https://github.com/ionic-team/ionic-framework/issues/29722)) ([92ce563](https://github.com/ionic-team/ionic-framework/commit/92ce563c402e557b08a622bd20f78459782312e2)), closes [#29712](https://github.com/ionic-team/ionic-framework/issues/29712)
## [8.2.5](https://github.com/ionic-team/ionic-framework/compare/v8.2.4...v8.2.5) (2024-07-03)
**Note:** Version bump only for package @ionic/core
## [8.2.4](https://github.com/ionic-team/ionic-framework/compare/v8.2.2...v8.2.4) (2024-06-28)
### Bug Fixes
* **angular:** popover arrow navigation with disabled items ([#29662](https://github.com/ionic-team/ionic-framework/issues/29662)) ([ceb41f3](https://github.com/ionic-team/ionic-framework/commit/ceb41f31f382ff1bcf81de2b11680699d33d5077)), closes [#29640](https://github.com/ionic-team/ionic-framework/issues/29640)
## 8.2.3
This version should be skipped. Install 8.2.4 instead.
## [8.2.2](https://github.com/ionic-team/ionic-framework/compare/v8.2.1...v8.2.2) (2024-06-12)
### Bug Fixes
* **refresher:** show when content is fullscreen ([#29608](https://github.com/ionic-team/ionic-framework/issues/29608)) ([5cdfac8](https://github.com/ionic-team/ionic-framework/commit/5cdfac89f5389cb3009427183f7034ba05788bc2)), closes [#18714](https://github.com/ionic-team/ionic-framework/issues/18714)
## [8.2.1](https://github.com/ionic-team/ionic-framework/compare/v8.2.0...v8.2.1) (2024-06-05)
**Note:** Version bump only for package @ionic/core
# [8.2.0](https://github.com/ionic-team/ionic-framework/compare/v8.1.3...v8.2.0) (2024-05-22)
**Note:** Version bump only for package @ionic/core
## [8.1.3](https://github.com/ionic-team/ionic-framework/compare/v8.1.2...v8.1.3) (2024-05-22)
### Bug Fixes
* **core:** malformed URIs will not throw exception ([#29486](https://github.com/ionic-team/ionic-framework/issues/29486)) ([4a41983](https://github.com/ionic-team/ionic-framework/commit/4a41983098fe9bf83fdf05ce7ab28c79f414e11b)), closes [#29479](https://github.com/ionic-team/ionic-framework/issues/29479)
## [8.1.2](https://github.com/ionic-team/ionic-framework/compare/v8.1.1...v8.1.2) (2024-05-15)

View File

@@ -1,5 +1,5 @@
# Get Playwright
FROM mcr.microsoft.com/playwright:v1.46.0
FROM mcr.microsoft.com/playwright:v1.43.1
# Set the working directory
WORKDIR /ionic

View File

@@ -184,8 +184,7 @@ ion-app,prop,theme,"ios" | "md" | "ionic",undefined,false,false
ion-avatar,shadow
ion-avatar,prop,mode,"ios" | "md",undefined,false,false
ion-avatar,prop,shape,"rectangular" | "round" | "soft" | undefined,undefined,false,false
ion-avatar,prop,size,"large" | "medium" | "small" | "xlarge" | "xsmall" | "xxsmall" | undefined,undefined,false,false
ion-avatar,prop,size,"large" | "medium" | "small" | "xsmall" | undefined,undefined,false,false
ion-avatar,prop,theme,"ios" | "md" | "ionic",undefined,false,false
ion-avatar,css-prop,--border-radius,ionic
ion-avatar,css-prop,--border-radius,ios
@@ -312,8 +311,7 @@ ion-backdrop,event,ionBackdropTap,void,true
ion-badge,shadow
ion-badge,prop,color,"danger" | "dark" | "light" | "medium" | "primary" | "secondary" | "success" | "tertiary" | "warning" | string & Record<never, never> | undefined,undefined,false,true
ion-badge,prop,mode,"ios" | "md",undefined,false,false
ion-badge,prop,shape,"round | rectangular" | "soft" | undefined,undefined,false,false
ion-badge,prop,size,"large" | "medium" | "small" | "xlarge" | "xsmall" | "xxsmall" | undefined,undefined,false,false
ion-badge,prop,size,"large" | "medium" | "small" | "xlarge" | undefined,undefined,false,false
ion-badge,prop,theme,"ios" | "md" | "ionic",undefined,false,false
ion-badge,css-prop,--background,ionic
ion-badge,css-prop,--background,ios
@@ -488,13 +486,10 @@ ion-card,prop,shape,"rectangular" | "round" | "soft" | undefined,'round',false,t
ion-card,prop,target,string | undefined,undefined,false,false
ion-card,prop,theme,"ios" | "md" | "ionic",undefined,false,false
ion-card,prop,type,"button" | "reset" | "submit",'button',false,false
ion-card,css-prop,--background,ionic
ion-card,css-prop,--background,ios
ion-card,css-prop,--background,md
ion-card,css-prop,--border-radius,ionic
ion-card,css-prop,--border-radius,ios
ion-card,css-prop,--border-radius,md
ion-card,css-prop,--color,ionic
ion-card,css-prop,--color,ios
ion-card,css-prop,--color,md
ion-card,part,native
@@ -542,26 +537,37 @@ ion-checkbox,prop,value,any,'on',false,false
ion-checkbox,event,ionBlur,void,true
ion-checkbox,event,ionChange,CheckboxChangeEventDetail<any>,true
ion-checkbox,event,ionFocus,void,true
ion-checkbox,css-prop,--border-color,ionic
ion-checkbox,css-prop,--border-color,ios
ion-checkbox,css-prop,--border-color,md
ion-checkbox,css-prop,--border-color-checked,ionic
ion-checkbox,css-prop,--border-color-checked,ios
ion-checkbox,css-prop,--border-color-checked,md
ion-checkbox,css-prop,--border-radius,ionic
ion-checkbox,css-prop,--border-radius,ios
ion-checkbox,css-prop,--border-radius,md
ion-checkbox,css-prop,--border-style,ionic
ion-checkbox,css-prop,--border-style,ios
ion-checkbox,css-prop,--border-style,md
ion-checkbox,css-prop,--border-width,ionic
ion-checkbox,css-prop,--border-width,ios
ion-checkbox,css-prop,--border-width,md
ion-checkbox,css-prop,--checkbox-background,ionic
ion-checkbox,css-prop,--checkbox-background,ios
ion-checkbox,css-prop,--checkbox-background,md
ion-checkbox,css-prop,--checkbox-background-checked,ionic
ion-checkbox,css-prop,--checkbox-background-checked,ios
ion-checkbox,css-prop,--checkbox-background-checked,md
ion-checkbox,css-prop,--checkmark-color,ionic
ion-checkbox,css-prop,--checkmark-color,ios
ion-checkbox,css-prop,--checkmark-color,md
ion-checkbox,css-prop,--checkmark-width,ionic
ion-checkbox,css-prop,--checkmark-width,ios
ion-checkbox,css-prop,--checkmark-width,md
ion-checkbox,css-prop,--size,ionic
ion-checkbox,css-prop,--size,ios
ion-checkbox,css-prop,--size,md
ion-checkbox,css-prop,--transition,ionic
ion-checkbox,css-prop,--transition,ios
ion-checkbox,css-prop,--transition,md
ion-checkbox,part,container
@@ -691,16 +697,19 @@ ion-datetime,event,ionFocus,void,true
ion-datetime,css-prop,--background,ionic
ion-datetime,css-prop,--background,ios
ion-datetime,css-prop,--background,md
ion-datetime,css-prop,--background-rgb,ionic
ion-datetime,css-prop,--background-rgb,ios
ion-datetime,css-prop,--background-rgb,md
ion-datetime,css-prop,--focus-ring-color,ionic
ion-datetime,css-prop,--focus-ring-width,ionic
ion-datetime,css-prop,--title-color,ionic
ion-datetime,css-prop,--title-color,ios
ion-datetime,css-prop,--title-color,md
ion-datetime,css-prop,--wheel-fade-background-rgb,ionic
ion-datetime,css-prop,--wheel-fade-background-rgb,ios
ion-datetime,css-prop,--wheel-fade-background-rgb,md
ion-datetime,css-prop,--wheel-highlight-background,ionic
ion-datetime,css-prop,--wheel-highlight-background,ios
ion-datetime,css-prop,--wheel-highlight-background,md
ion-datetime,css-prop,--wheel-highlight-border-radius,ionic
ion-datetime,css-prop,--wheel-highlight-border-radius,ios
ion-datetime,css-prop,--wheel-highlight-border-radius,md
ion-datetime,part,calendar-day
@@ -852,7 +861,6 @@ ion-grid,css-prop,--ion-grid-width-xs
ion-header,none
ion-header,prop,collapse,"condense" | "fade" | undefined,undefined,false,false
ion-header,prop,divider,boolean,false,false,false
ion-header,prop,mode,"ios" | "md",undefined,false,false
ion-header,prop,theme,"ios" | "md" | "ionic",undefined,false,false
ion-header,prop,translucent,boolean,false,false,false
@@ -901,7 +909,7 @@ ion-input,prop,fill,"outline" | "solid" | undefined,undefined,false,false
ion-input,prop,helperText,string | undefined,undefined,false,false
ion-input,prop,inputmode,"decimal" | "email" | "none" | "numeric" | "search" | "tel" | "text" | "url" | undefined,undefined,false,false
ion-input,prop,label,string | undefined,undefined,false,false
ion-input,prop,labelPlacement,"end" | "fixed" | "floating" | "stacked" | "start" | undefined,undefined,false,false
ion-input,prop,labelPlacement,"end" | "fixed" | "floating" | "stacked" | "start",'start',false,false
ion-input,prop,max,number | string | undefined,undefined,false,false
ion-input,prop,maxlength,number | undefined,undefined,false,false
ion-input,prop,min,number | string | undefined,undefined,false,false
@@ -913,8 +921,7 @@ ion-input,prop,pattern,string | undefined,undefined,false,false
ion-input,prop,placeholder,string | undefined,undefined,false,false
ion-input,prop,readonly,boolean,false,false,true
ion-input,prop,required,boolean,false,false,false
ion-input,prop,shape,"rectangular" | "round" | "soft" | undefined,undefined,false,false
ion-input,prop,size,"large" | "medium" | "xlarge" | undefined,'medium',false,false
ion-input,prop,shape,"round" | undefined,undefined,false,false
ion-input,prop,spellcheck,boolean,false,false,false
ion-input,prop,step,string | undefined,undefined,false,false
ion-input,prop,theme,"ios" | "md" | "ionic",undefined,false,false
@@ -980,9 +987,6 @@ ion-input,css-prop,--placeholder-font-weight,md
ion-input,css-prop,--placeholder-opacity,ionic
ion-input,css-prop,--placeholder-opacity,ios
ion-input,css-prop,--placeholder-opacity,md
ion-input,css-prop,--text-color-invalid,ionic
ion-input,css-prop,--text-color-invalid,ios
ion-input,css-prop,--text-color-invalid,md
ion-input-password-toggle,shadow
ion-input-password-toggle,prop,color,"danger" | "dark" | "light" | "medium" | "primary" | "secondary" | "success" | "tertiary" | "warning" | string & Record<never, never> | undefined,undefined,false,true
@@ -995,7 +999,7 @@ 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,detail,boolean | undefined,undefined,false,false
ion-item,prop,detailIcon,string | undefined,undefined,false,false
ion-item,prop,disabled,boolean,false,false,true
ion-item,prop,disabled,boolean,false,false,false
ion-item,prop,download,string | undefined,undefined,false,false
ion-item,prop,href,string | undefined,undefined,false,false
ion-item,prop,lines,"full" | "inset" | "none" | undefined,undefined,false,false
@@ -1150,7 +1154,6 @@ ion-item-option,prop,expandable,boolean,false,false,false
ion-item-option,prop,href,string | undefined,undefined,false,false
ion-item-option,prop,mode,"ios" | "md",undefined,false,false
ion-item-option,prop,rel,string | undefined,undefined,false,false
ion-item-option,prop,shape,"rectangular" | "round" | "soft" | undefined,undefined,false,false
ion-item-option,prop,target,string | undefined,undefined,false,false
ion-item-option,prop,theme,"ios" | "md" | "ionic",undefined,false,false
ion-item-option,prop,type,"button" | "reset" | "submit",'button',false,false
@@ -1192,7 +1195,6 @@ ion-list,none
ion-list,prop,inset,boolean,false,false,false
ion-list,prop,lines,"full" | "inset" | "none" | undefined,undefined,false,false
ion-list,prop,mode,"ios" | "md",undefined,false,false
ion-list,prop,shape,"rectangular" | "round" | "soft" | undefined,undefined,false,false
ion-list,prop,theme,"ios" | "md" | "ionic",undefined,false,false
ion-list,method,closeSlidingItems,closeSlidingItems() => Promise<boolean>
@@ -2141,11 +2143,8 @@ ion-spinner,prop,duration,number | undefined,undefined,false,false
ion-spinner,prop,mode,"ios" | "md",undefined,false,false
ion-spinner,prop,name,"bubbles" | "circles" | "circular" | "crescent" | "dots" | "lines" | "lines-sharp" | "lines-sharp-small" | "lines-small" | undefined,undefined,false,false
ion-spinner,prop,paused,boolean,false,false,false
ion-spinner,prop,size,"large" | "medium" | "small" | "xlarge" | "xsmall" | undefined,undefined,false,false
ion-spinner,prop,theme,"ios" | "md" | "ionic",undefined,false,false
ion-spinner,css-prop,--color,ionic
ion-spinner,css-prop,--color,ios
ion-spinner,css-prop,--color,md
ion-spinner,css-prop,--color
ion-split-pane,shadow
ion-split-pane,prop,contentId,string | undefined,undefined,false,true
@@ -2276,8 +2275,7 @@ ion-textarea,prop,placeholder,string | undefined,undefined,false,false
ion-textarea,prop,readonly,boolean,false,false,false
ion-textarea,prop,required,boolean,false,false,false
ion-textarea,prop,rows,number | undefined,undefined,false,false
ion-textarea,prop,shape,"rectangular" | "round" | "soft" | undefined,undefined,false,false
ion-textarea,prop,size,"large" | "medium" | "small" | undefined,'medium',false,false
ion-textarea,prop,shape,"round" | undefined,undefined,false,false
ion-textarea,prop,spellcheck,boolean,false,false,false
ion-textarea,prop,theme,"ios" | "md" | "ionic",undefined,false,false
ion-textarea,prop,value,null | string | undefined,'',false,false

View File

@@ -67,5 +67,4 @@ const ASYNC_PLAYWRIGHT_ASSERTS = [
'toHaveTitle',
'toHaveURL',
'toBeOK',
'click'
];

12552
core/package-lock.json generated
View File

File diff suppressed because it is too large Load Diff

View File

@@ -1,6 +1,6 @@
{
"name": "@ionic/core",
"version": "8.2.7",
"version": "8.1.2",
"description": "Base components for Ionic",
"keywords": [
"ionic",
@@ -31,29 +31,27 @@
"loader/"
],
"dependencies": {
"@phosphor-icons/core": "^2.1.1",
"@stencil/core": "^4.19.2",
"@stencil/core": "^4.17.2",
"ionicons": "^7.2.2",
"tslib": "^2.1.0"
},
"devDependencies": {
"@axe-core/playwright": "^4.9.1",
"@axe-core/playwright": "^4.8.5",
"@capacitor/core": "^6.0.0",
"@capacitor/haptics": "^6.0.0",
"@capacitor/keyboard": "^6.0.0",
"@capacitor/status-bar": "^6.0.0",
"@clack/prompts": "^0.7.0",
"@ionic/eslint-config": "^0.3.0",
"@ionic/prettier-config": "^2.0.0",
"@playwright/test": "^1.46.0",
"@playwright/test": "^1.39.0",
"@rollup/plugin-node-resolve": "^8.4.0",
"@rollup/plugin-virtual": "^2.0.3",
"@stencil/angular-output-target": "^0.8.4",
"@stencil/react-output-target": "^0.6.0",
"@stencil/react-output-target": "^0.5.3",
"@stencil/sass": "^3.0.9",
"@stencil/vue-output-target": "^0.8.9",
"@stencil/vue-output-target": "^0.8.7",
"@types/jest": "^29.5.6",
"@types/node": "^18.19.47",
"@types/node": "^14.6.0",
"@typescript-eslint/eslint-plugin": "^6.7.2",
"@typescript-eslint/parser": "^6.7.2",
"chalk": "^5.3.0",
@@ -104,8 +102,7 @@
"docker.build": "docker build -t ionic-playwright .",
"test.e2e.docker": "npm run docker.build && node ./scripts/docker.mjs",
"test.e2e.docker.update-snapshots": "npm run test.e2e.docker -- --update-snapshots",
"test.e2e.docker.ci": "npm run docker.build && CI=true node ./scripts/docker.mjs",
"test.e2e.script": "node scripts/testing/e2e-script.mjs"
"test.e2e.docker.ci": "npm run docker.build && CI=true node ./scripts/docker.mjs"
},
"author": "Ionic Team",
"license": "MIT",
@@ -114,7 +111,7 @@
"url": "git+https://github.com/ionic-team/ionic-framework.git"
},
"bugs": {
"url": "https://github.com/ionic-team/ionic-framework/issues"
"url": "https://github.com/ionic-team/ionic/issues"
},
"homepage": "https://ionicframework.com/",
"jest": {

View File

@@ -1,260 +0,0 @@
// The purpose of this script is to provide a way run the E2E tests
// without having the developer to manually run multiple commands based
// on the desired end result.
// E.g. update the local ground truths for a specific component or
// open the Playwright report after running the E2E tests.
import {
intro,
outro,
confirm,
spinner,
isCancel,
cancel,
text,
log,
} from '@clack/prompts';
import { exec, spawn } from 'child_process';
import fs from 'node:fs';
import { setTimeout as sleep } from 'node:timers/promises';
import util from 'node:util';
import color from 'picocolors';
async function main() {
const execAsync = util.promisify(exec);
const cleanUpFiles = async () => {
// Clean up the local ground truths.
const cleanUp = spinner();
// Inform the user that the local ground truths are being cleaned up.
cleanUp.start('Restoring local ground truths');
// Reset the local ground truths.
await execAsync('git reset -- src/**/*-linux.png').catch((error) => {
cleanUp.stop('Failed to reset local ground truths');
console.error(error);
return process.exit(0);
});
// Restore the local ground truths.
await execAsync('git restore -- src/**/*-linux.png').catch((error) => {
cleanUp.stop('Failed to restore local ground truths');
console.error(error);
return process.exit(0);
});
// Inform the user that the local ground truths have been cleaned up.
cleanUp.stop('Local ground truths have been restored to their original state in order to avoid committing them.');
};
intro(color.inverse(' Update Local Ground Truths'));
// Ask user for the component name they want to test.
const componentValue = await text({
message: 'Enter the component or path you want to test (e.g. chip, src/components/chip)',
placeholder: 'Empty for all components',
});
// User cancelled the operation with `Ctrl+C` or `CMD+C`.
if (isCancel(componentValue)) {
cancel('Operation cancelled');
return process.exit(0);
}
// Ask user if they want to update their local ground truths.
const shouldUpdateTruths = await confirm({
message: 'Do you want to update your local ground truths?',
});
// User cancelled the operation with `Ctrl+C` or `CMD+C`.
if (isCancel(shouldUpdateTruths)) {
cancel('Operation cancelled');
return process.exit(0);
}
if (shouldUpdateTruths) {
const defaultBaseBranch = 'main';
// Ask user for the base branch.
let baseBranch = await text({
message: 'Enter the base branch name:',
placeholder: `default: ${defaultBaseBranch}`,
})
// User cancelled the operation with `Ctrl+C` or `CMD+C`.
if (isCancel(baseBranch)) {
cancel('Operation cancelled');
return process.exit(0);
}
// User didn't provide a base branch.
if (!baseBranch) {
baseBranch = defaultBaseBranch;
}
/**
* The provided base branch needs to be fetched.
* This ensures that the local base branch is up-to-date with the
* remote base branch. Otherwise, there might be errors stating that
* certain files don't exist in the local base branch.
*/
const fetchBaseBranch = spinner();
// Inform the user that the base branch is being fetched.
fetchBaseBranch.start(`Fetching "${baseBranch}" to have the latest changes`);
// Fetch the base branch.
await execAsync(`git fetch origin ${baseBranch}`).catch((error) => {
fetchBaseBranch.stop(`Failed to fetch "${baseBranch}"`);
console.error(error);
return process.exit(0);
});
// Inform the user that the base branch has been fetched.
fetchBaseBranch.stop(`Fetched "${baseBranch}"`);
const updateGroundTruth = spinner();
// Inform the user that the local ground truths are being updated.
updateGroundTruth.start('Updating local ground truths');
// Check if user provided an existing file or directory.
const isValidLocation = fs.existsSync(componentValue);
// User provided an existing file or directory.
if (isValidLocation) {
const stats = fs.statSync(componentValue);
// User provided a file as the component.
// ex: `componentValue` = `src/components/chip/test/basic/chip.e2e.ts`
if (stats.isFile()) {
// Update the local ground truths for the provided path.
await execAsync(`git checkout origin/${baseBranch} -- ${componentValue}-snapshots/*-linux.png`).catch((error) => {
updateGroundTruth.stop('Failed to update local ground truths');
console.error(error);
return process.exit(0);
});
}
// User provided a directory as the component.
// ex: `componentValue` = `src/components/chip`
if (stats.isDirectory()) {
// Update the local ground truths for the provided directory.
await execAsync(`git checkout origin/${baseBranch} -- ${componentValue}/test/*/*.e2e.ts-snapshots/*-linux.png`).catch((error) => {
updateGroundTruth.stop('Failed to update local ground truths');
console.error(error);
return process.exit(0);
});
}
}
// User provided a component name as the component.
// ex: `componentValue` = `chip`
else if (componentValue) {
// Update the local ground truths for the provided component.
await execAsync(`git checkout origin/${baseBranch} -- src/components/${componentValue}/test/*/${componentValue}.e2e.ts-snapshots/*-linux.png`).catch((error) => {
updateGroundTruth.stop('Failed to update local ground truths');
console.error(error);
return process.exit(0);
});
}
// User provided an empty string.
else {
// Update the local ground truths for all components.
await execAsync(`git checkout origin/${baseBranch} -- src/components/*/test/*/*.e2e.ts-snapshots/*-linux.png`).catch((error) => {
updateGroundTruth.stop('Failed to update local ground truths');
console.error(error);
return process.exit(0);
});
}
// Inform the user that the local ground truths have been updated.
updateGroundTruth.stop('Updated local ground truths');
}
const buildCore = spinner();
// Inform the user that the core is being built.
buildCore.start('Building core');
/**
* Build core
* Otherwise, the uncommitted changes will not be reflected in the tests because:
* - popping the stash doesn't trigger a re-render even if `npm start` is running
* - app is not running the `npm start` command
*/
await execAsync('npm run build').catch((error) => {
// Clean up the local ground truths.
cleanUpFiles();
buildCore.stop('Failed to build core');
console.error(error);
return process.exit(0);
});
buildCore.stop('Built core');
const runE2ETests = spinner();
// Inform the user that the E2E tests are being run.
runE2ETests.start('Running E2E tests');
// User provided a component value.
if (componentValue) {
await execAsync(`npm run test.e2e.docker.ci ${componentValue}`).catch((error) => {
// Clean up the local ground truths.
cleanUpFiles();
runE2ETests.stop('Failed to run E2E tests');
console.error(error);
return process.exit(0);
});
} else {
await execAsync('npm run test.e2e.docker.ci').catch((error) => {
// Clean up the local ground truths.
cleanUpFiles();
runE2ETests.stop('Failed to run E2E tests');
console.error(error);
return process.exit(0);
});
}
runE2ETests.stop('Ran E2E tests');
// Clean up the local ground truths.
await cleanUpFiles();
// Ask user if they want to open the Playwright report.
const shouldOpenReport = await confirm({
message: 'Do you want to open the Playwright report?',
});
// User cancelled the operation with `Ctrl+C` or `CMD+C`.
if (isCancel(shouldOpenReport)) {
cancel('Operation cancelled');
return process.exit(0);
}
// User chose to open the Playwright report.
if (shouldOpenReport) {
// Use spawn to display the server information and the key to quit the server.
spawn('npx', ['playwright', 'show-report'], {
stdio: 'inherit',
});
} else {
// Inform the user that the Playwright report can be opened by running the following command.
log.info('If you change your mind, you can open the Playwright report by running the following command:');
log.info(color.bold('npx playwright show-report'));
}
if (shouldOpenReport) {
outro("You're all set! Don't forget to quit serving the Playwright report when you're done.");
} else {
outro("You're all set!");
}
await sleep(1000);
}
main().catch(console.error);

View File

@@ -28,27 +28,6 @@
document.head.appendChild(linkTag);
}
/**
* The `ionic` theme uses a different stylesheet than the `iOS` and `md` themes.
* This is to ensure that the `ionic` theme is loaded when the `ionic:theme=ionic`
* or when the HTML tag has the `theme="ionic"` attribute. This is useful for
* the snapshot tests, where the `ionic` theme is not loaded by default.
*/
const themeQuery = window.location.search.match(/ionic:theme=([a-z]+)/);
const themeAttr = document.documentElement.getAttribute('theme');
if ((themeQuery && themeQuery[1] === 'ionic') || themeAttr === 'ionic') {
const ionicThemeLinkTag = document.querySelector('link[href*="css/ionic/bundle.ionic.css"]');
if (!ionicThemeLinkTag) {
const linkTag = document.createElement('link');
linkTag.setAttribute('rel', 'stylesheet');
linkTag.setAttribute('type', 'text/css');
linkTag.setAttribute('href', '/css/ionic/bundle.ionic.css');
document.head.appendChild(linkTag);
}
}
window.Ionic = window.Ionic || {};
window.Ionic.config = window.Ionic.config || {};

View File

@@ -16,7 +16,6 @@ const {
getRgbaValue,
hexToRgb,
generateShadowValue,
generateFontSizeValue,
generateFontFamilyValue,
generateTypographyValue,
generateRgbValue,
@@ -44,8 +43,6 @@ StyleDictionary.registerFormat({
return `--${variablesPrefix}-${prop.name}: ${cssShadow};`;
} else if (prop.attributes.category.match('font-family')) {
return generateFontFamilyValue(prop);
} else if (prop.attributes.category.match('font-size')) {
return generateFontSizeValue(prop);
} else {
const rgb = hexToRgb(prop.value);
prop.value = getRgbaValue(prop.value);
@@ -55,11 +52,7 @@ StyleDictionary.registerFormat({
}
});
return [
fileHeader({ file }),
'@use "../themes/functions.sizes" as font;\n',
':root {\n' + prefixedVariables.join('\n') + '\n}\n',
].join('\n');
return fileHeader({ file }) + ':root {\n' + prefixedVariables.join('\n') + '\n}\n';
},
});
@@ -79,8 +72,6 @@ StyleDictionary.registerFormat({
return `$${variablesPrefix}-${prop.name}: var(--${variablesPrefix}-${prop.name}, ${cssShadow});`;
} else if (prop.attributes.category.match('font-family')) {
return generateFontFamilyValue(prop, 'scss');
} else if (prop.attributes.category.match('font-size')) {
return generateFontSizeValue(prop, 'scss');
} else if (prop['$type'] === 'typography') {
return generateTypographyValue(prop, dictionary);
} else {
@@ -88,11 +79,7 @@ StyleDictionary.registerFormat({
}
});
return [
fileHeader({ file }),
'@use "../themes/functions.sizes" as font;\n',
prefixedVariables.join('\n') + '\n',
].join('\n');
return fileHeader({ file }) + prefixedVariables.join('\n') + '\n';
},
});

View File

@@ -44,15 +44,6 @@ function generateShadowValue(shadow) {
return `${shadow.offsetX} ${shadow.offsetY} ${shadow.blur} ${shadow.spread} ${color}`;
}
// Generates a valid font-size value from a font-size Design Token structure, while transforming the pixels to rem
function generateFontSizeValue(prop, variableType = 'css') {
return variableType === 'scss'
? `$${variablesPrefix}-${prop.name}: var(--${variablesPrefix}-${prop.name}, font.px-to-rem(${parseInt(
prop.value
)}));`
: `--${variablesPrefix}-${prop.name}: #{font.px-to-rem(${parseInt(prop.value)})};`;
}
// Generates a valid font-family value from a font-family Design Token structure
function generateFontFamilyValue(prop, variableType = 'css') {
// Remove the last word from the token, as it contains the name of the font, which we don't want to be included on the generated variables
@@ -69,13 +60,12 @@ function generateTypographyValue(prop, dictionary) {
const fontWeightMap = getTypeMap(dictionary, 'font-weight');
const lineHeightMap = getTypeMap(dictionary, 'line-height');
const letterSpacingMap = getTypeMap(dictionary, 'letter-spacing');
const fontStyle = prop.attributes.item?.toLowerCase() === 'italic' ? 'italic' : 'normal';
// This exact format is needed so that it compiles the tokens with the expected lint rules
return `
$${variablesPrefix}-${prop.name}: (
font-family: $ionic-font-family,
font-size: $ionic-font-size-${fontSizeMap[typography.fontSize]},
font-style: ${fontStyle},
font-weight: $ionic-font-weight-${fontWeightMap[typography.fontWeight]},
letter-spacing: $ionic-letter-spacing-${letterSpacingMap[typography.letterSpacing] || 0},
line-height: $ionic-line-height-${lineHeightMap[typography.lineHeight]},
@@ -115,13 +105,12 @@ function generateTypographyUtilityClass(prop, dictionary) {
const fontWeightMap = getTypeMap(dictionary, 'font-weight');
const lineHeightMap = getTypeMap(dictionary, 'line-height');
const letterSpacingMap = getTypeMap(dictionary, 'letter-spacing');
const fontStyle = prop.attributes.item?.toLowerCase() === 'italic' ? 'italic' : 'normal';
// This exact format is needed so that it compiles the tokens with the expected lint rules
return `
.${variablesPrefix}-${prop.name} {
font-family: $ionic-font-family;
font-size: $ionic-font-size-${fontSizeMap[typography.fontSize]};
font-style: ${fontStyle};
font-weight: $ionic-font-weight-${fontWeightMap[typography.fontWeight]};
letter-spacing: $ionic-letter-spacing-${letterSpacingMap[typography.letterSpacing] || 0};
line-height: $ionic-line-height-${lineHeightMap[typography.lineHeight]};
@@ -133,8 +122,8 @@ function generateTypographyUtilityClass(prop, dictionary) {
// Generates a color based css utility-class from a color Design Token structure
function generateColorUtilityClasses(prop, className) {
return `.${variablesPrefix}-${className} {\n color: $ionic-${prop.name};\n}
.${variablesPrefix}-background-${className} {\n background-color: $ionic-${prop.name};\n}`;
return `.${variablesPrefix}-${className} {\n --color: $ionic-${prop.name};\n}
.${variablesPrefix}-background-${className} {\n --background: $ionic-${prop.name};\n}`;
}
// Generates a font based css utility-class from a font Design Token structure
@@ -180,7 +169,6 @@ module.exports = {
hexToRgb,
hexToRgba,
generateShadowValue,
generateFontSizeValue,
generateFontFamilyValue,
generateTypographyValue,
generateRgbValue: generateValue,

View File

@@ -336,13 +336,9 @@ export namespace Components {
*/
"mode"?: "ios" | "md";
/**
* Set to `"soft"` for an avatar with slightly rounded corners, `"round"` for an avatar with fully rounded corners, or `"rectangular"` for an avatar without rounded corners. Defaults to `"round"` for the `ionic` theme, undefined for all other themes.
* Set to `"xsmall"` for the smallest size, `"small"` for a compact size, `"medium"` for the default height and width, or to `"large"` for a larger size. Defaults to `"medium"` for the `ionic` theme, undefined for all other themes.
*/
"shape"?: 'soft' | 'round' | 'rectangular';
/**
* Set to `"xxsmall"` for the smallest size. Set to `"xsmall"` for a very small size. Set to `"small"` for a compact size. Set to `"medium"` for the default height and width. Set to `"large"` for a larger size. Set to `"xlarge"` for the largest dimensions. Defaults to `"medium"` for the `ionic` theme, undefined for all other themes.
*/
"size"?: 'xxsmall' | 'xsmall' | 'small' | 'medium' | 'large' | 'xlarge';
"size"?: `xsmall` | 'small' | 'medium' | 'large';
/**
* The theme determines the visual appearance of the component.
*/
@@ -418,13 +414,9 @@ export namespace Components {
*/
"mode"?: "ios" | "md";
/**
* Set to `"rectangular"` for non-rounded corners. Set to `"soft"` for slightly rounded corners. Set to `"round"` for fully rounded corners. Defaults to `"round"` for the `ionic` theme, undefined for all other themes.
* Set to `"small"` for less height and width. Set to "medium" for slightly larger dimensions. Set to "large" for even greater height and width. Set to `"xlarge"` for the largest badge. Defaults to `"small"` for the `ionic` theme, undefined for all other themes.
*/
"shape"?: 'soft' | 'round | rectangular';
/**
* Set to `"xxsmall"` for the smallest badge. Set to "xsmall" for a very small badge. Set to `"small"` for a small badge. Set to "medium" for a medium badge. Set to "large" for a large badge. Set to `"xlarge"` for the largest badge. Defaults to `"small"` for the `ionic` theme, undefined for all other themes.
*/
"size"?: 'xxsmall' | 'xsmall' | 'small' | 'medium' | 'large' | 'xlarge';
"size"?: 'small' | 'medium' | 'large' | 'xlarge';
/**
* The theme determines the visual appearance of the component.
*/
@@ -1286,10 +1278,6 @@ export namespace Components {
* Describes the scroll effect that will be applied to the header. Only applies when the theme is `"ios"`. Typically used for [Collapsible Large Titles](https://ionicframework.com/docs/api/title#collapsible-large-titles)
*/
"collapse"?: 'condense' | 'fade';
/**
* If `true`, the header will have a line at the bottom. TODO(ROU-10855): add support for this prop on ios/md themes
*/
"divider": boolean;
/**
* The mode determines the platform behaviors of the component.
*/
@@ -1443,9 +1431,9 @@ export namespace Components {
*/
"label"?: string;
/**
* Where to place the label relative to the input. `"start"`: The label will appear to the left of the input in LTR and to the right in RTL. `"end"`: The label will appear to the right of the input in LTR and to the left in RTL. `"floating"`: The label will appear smaller and above the input when the input is focused or it has a value. Otherwise it will appear on top of the input. `"stacked"`: The label will appear smaller and above the input regardless even when the input is blurred or has no value. `"fixed"`: The label has the same behavior as `"start"` except it also has a fixed width. Long text will be truncated with ellipses ("..."). Defaults to "stacked" for the ionic theme, or "start" for all other themes. In the ionic theme, only the values "stacked" and "floating" are supported.
* Where to place the label relative to the input. `"start"`: The label will appear to the left of the input in LTR and to the right in RTL. `"end"`: The label will appear to the right of the input in LTR and to the left in RTL. `"floating"`: The label will appear smaller and above the input when the input is focused or it has a value. Otherwise it will appear on top of the input. `"stacked"`: The label will appear smaller and above the input regardless even when the input is blurred or has no value. `"fixed"`: The label has the same behavior as `"start"` except it also has a fixed width. Long text will be truncated with ellipses ("...").
*/
"labelPlacement"?: 'start' | 'end' | 'floating' | 'stacked' | 'fixed';
"labelPlacement": 'start' | 'end' | 'floating' | 'stacked' | 'fixed';
/**
* The maximum value, which must not be less than its minimum (min attribute) value.
*/
@@ -1495,13 +1483,9 @@ export namespace Components {
*/
"setFocus": () => Promise<void>;
/**
* Set to `"soft"` for an input with slightly rounded corners, `"round"` for an input with fully rounded corners, or `"rectangular"` for an input without rounded corners. Defaults to `"round"` for the ionic theme, and `undefined` for all other themes. Only applies when the fill is set to `"solid"` or `"outline"`.
* The shape of the input. If "round" it will have an increased border radius.
*/
"shape"?: 'soft' | 'round' | 'rectangular';
/**
* The size of the input. If "large", it will have an increased height. By default the size is medium. This property only applies to the `"ionic"` theme.
*/
"size"?: 'medium' | 'large' | 'xlarge';
"shape"?: 'round';
/**
* If `true`, the element will have its spelling and grammar checked.
*/
@@ -1661,10 +1645,6 @@ export namespace Components {
* Specifies the relationship of the target object to the link object. The value is a space-separated list of [link types](https://developer.mozilla.org/en-US/docs/Web/HTML/Link_types).
*/
"rel": string | undefined;
/**
* Set to `"rectangular"` for non-rounded corners. Set to `"soft"` for slightly rounded corners. Set to `"round"` for fully rounded corners. Defaults to `"round"` for the `ionic` theme, undefined for all other themes.
*/
"shape"?: 'soft' | 'round' | 'rectangular';
/**
* Specifies where to display the linked URL. Only applies when an `href` is provided. Special keywords: `"_blank"`, `"_self"`, `"_parent"`, `"_top"`.
*/
@@ -1763,10 +1743,6 @@ export namespace Components {
* The mode determines the platform behaviors of the component.
*/
"mode"?: "ios" | "md";
/**
* Set to `"soft"` for slightly rounded corners, `"round"` for fully rounded corners, or `"rectangular"` for no rounded corners. Defaults to `"round"` for the `ionic` theme when inset is `true` defaults to `"rectangular"` for the `ionic` theme when inset is `false`, undefined for all other themes.
*/
"shape"?: 'soft' | 'round' | 'rectangular';
/**
* The theme determines the visual appearance of the component.
*/
@@ -3346,10 +3322,6 @@ export namespace Components {
* If `true`, the spinner's animation will be paused.
*/
"paused": boolean;
/**
* Set to `"xsmall"` for the smallest size. Set to `"small"` for a smaller size. Set to `"medium"` for a medium size. Set to `"large"` for a large size. Set to `"xlarge"` for the largest size. Defaults to `"xsmall"` for the `ionic` theme, undefined for all other themes.
*/
"size"?: 'xsmall' | 'small' | 'medium' | 'large' | 'xlarge';
/**
* The theme determines the visual appearance of the component.
*/
@@ -3617,13 +3589,9 @@ export namespace Components {
*/
"setFocus": () => Promise<void>;
/**
* Set to `"soft"` for a textarea with slightly rounded corners, `"round"` for a textarea with fully rounded corners, or `"rectangular"` for a textarea without rounded corners. Defaults to `"round"` for the `ionic` theme, undefined for all other themes.
* The shape of the textarea. If "round" it will have an increased border radius.
*/
"shape"?: 'soft' | 'round' | 'rectangular';
/**
* The size of the textarea. If "large" it will increase the height of the textarea, while "small" and "medium" provide progressively smaller heights. The default size is "medium". This property only applies to the `"ionic"` theme.
*/
"size"?: 'small' | 'medium' | 'large';
"shape"?: 'round';
/**
* If `true`, the element will have its spelling and grammar checked.
*/
@@ -5600,13 +5568,9 @@ declare namespace LocalJSX {
*/
"mode"?: "ios" | "md";
/**
* Set to `"soft"` for an avatar with slightly rounded corners, `"round"` for an avatar with fully rounded corners, or `"rectangular"` for an avatar without rounded corners. Defaults to `"round"` for the `ionic` theme, undefined for all other themes.
* Set to `"xsmall"` for the smallest size, `"small"` for a compact size, `"medium"` for the default height and width, or to `"large"` for a larger size. Defaults to `"medium"` for the `ionic` theme, undefined for all other themes.
*/
"shape"?: 'soft' | 'round' | 'rectangular';
/**
* Set to `"xxsmall"` for the smallest size. Set to `"xsmall"` for a very small size. Set to `"small"` for a compact size. Set to `"medium"` for the default height and width. Set to `"large"` for a larger size. Set to `"xlarge"` for the largest dimensions. Defaults to `"medium"` for the `ionic` theme, undefined for all other themes.
*/
"size"?: 'xxsmall' | 'xsmall' | 'small' | 'medium' | 'large' | 'xlarge';
"size"?: `xsmall` | 'small' | 'medium' | 'large';
/**
* The theme determines the visual appearance of the component.
*/
@@ -5686,13 +5650,9 @@ declare namespace LocalJSX {
*/
"mode"?: "ios" | "md";
/**
* Set to `"rectangular"` for non-rounded corners. Set to `"soft"` for slightly rounded corners. Set to `"round"` for fully rounded corners. Defaults to `"round"` for the `ionic` theme, undefined for all other themes.
* Set to `"small"` for less height and width. Set to "medium" for slightly larger dimensions. Set to "large" for even greater height and width. Set to `"xlarge"` for the largest badge. Defaults to `"small"` for the `ionic` theme, undefined for all other themes.
*/
"shape"?: 'soft' | 'round | rectangular';
/**
* Set to `"xxsmall"` for the smallest badge. Set to "xsmall" for a very small badge. Set to `"small"` for a small badge. Set to "medium" for a medium badge. Set to "large" for a large badge. Set to `"xlarge"` for the largest badge. Defaults to `"small"` for the `ionic` theme, undefined for all other themes.
*/
"size"?: 'xxsmall' | 'xsmall' | 'small' | 'medium' | 'large' | 'xlarge';
"size"?: 'small' | 'medium' | 'large' | 'xlarge';
/**
* The theme determines the visual appearance of the component.
*/
@@ -6586,10 +6546,6 @@ declare namespace LocalJSX {
* Describes the scroll effect that will be applied to the header. Only applies when the theme is `"ios"`. Typically used for [Collapsible Large Titles](https://ionicframework.com/docs/api/title#collapsible-large-titles)
*/
"collapse"?: 'condense' | 'fade';
/**
* If `true`, the header will have a line at the bottom. TODO(ROU-10855): add support for this prop on ios/md themes
*/
"divider"?: boolean;
/**
* The mode determines the platform behaviors of the component.
*/
@@ -6751,7 +6707,7 @@ declare namespace LocalJSX {
*/
"label"?: string;
/**
* Where to place the label relative to the input. `"start"`: The label will appear to the left of the input in LTR and to the right in RTL. `"end"`: The label will appear to the right of the input in LTR and to the left in RTL. `"floating"`: The label will appear smaller and above the input when the input is focused or it has a value. Otherwise it will appear on top of the input. `"stacked"`: The label will appear smaller and above the input regardless even when the input is blurred or has no value. `"fixed"`: The label has the same behavior as `"start"` except it also has a fixed width. Long text will be truncated with ellipses ("..."). Defaults to "stacked" for the ionic theme, or "start" for all other themes. In the ionic theme, only the values "stacked" and "floating" are supported.
* Where to place the label relative to the input. `"start"`: The label will appear to the left of the input in LTR and to the right in RTL. `"end"`: The label will appear to the right of the input in LTR and to the left in RTL. `"floating"`: The label will appear smaller and above the input when the input is focused or it has a value. Otherwise it will appear on top of the input. `"stacked"`: The label will appear smaller and above the input regardless even when the input is blurred or has no value. `"fixed"`: The label has the same behavior as `"start"` except it also has a fixed width. Long text will be truncated with ellipses ("...").
*/
"labelPlacement"?: 'start' | 'end' | 'floating' | 'stacked' | 'fixed';
/**
@@ -6815,13 +6771,9 @@ declare namespace LocalJSX {
*/
"required"?: boolean;
/**
* Set to `"soft"` for an input with slightly rounded corners, `"round"` for an input with fully rounded corners, or `"rectangular"` for an input without rounded corners. Defaults to `"round"` for the ionic theme, and `undefined` for all other themes. Only applies when the fill is set to `"solid"` or `"outline"`.
* The shape of the input. If "round" it will have an increased border radius.
*/
"shape"?: 'soft' | 'round' | 'rectangular';
/**
* The size of the input. If "large", it will have an increased height. By default the size is medium. This property only applies to the `"ionic"` theme.
*/
"size"?: 'medium' | 'large' | 'xlarge';
"shape"?: 'round';
/**
* If `true`, the element will have its spelling and grammar checked.
*/
@@ -6981,10 +6933,6 @@ declare namespace LocalJSX {
* Specifies the relationship of the target object to the link object. The value is a space-separated list of [link types](https://developer.mozilla.org/en-US/docs/Web/HTML/Link_types).
*/
"rel"?: string | undefined;
/**
* Set to `"rectangular"` for non-rounded corners. Set to `"soft"` for slightly rounded corners. Set to `"round"` for fully rounded corners. Defaults to `"round"` for the `ionic` theme, undefined for all other themes.
*/
"shape"?: 'soft' | 'round' | 'rectangular';
/**
* Specifies where to display the linked URL. Only applies when an `href` is provided. Special keywords: `"_blank"`, `"_self"`, `"_parent"`, `"_top"`.
*/
@@ -7073,10 +7021,6 @@ declare namespace LocalJSX {
* The mode determines the platform behaviors of the component.
*/
"mode"?: "ios" | "md";
/**
* Set to `"soft"` for slightly rounded corners, `"round"` for fully rounded corners, or `"rectangular"` for no rounded corners. Defaults to `"round"` for the `ionic` theme when inset is `true` defaults to `"rectangular"` for the `ionic` theme when inset is `false`, undefined for all other themes.
*/
"shape"?: 'soft' | 'round' | 'rectangular';
/**
* The theme determines the visual appearance of the component.
*/
@@ -8697,10 +8641,6 @@ declare namespace LocalJSX {
* If `true`, the spinner's animation will be paused.
*/
"paused"?: boolean;
/**
* Set to `"xsmall"` for the smallest size. Set to `"small"` for a smaller size. Set to `"medium"` for a medium size. Set to `"large"` for a large size. Set to `"xlarge"` for the largest size. Defaults to `"xsmall"` for the `ionic` theme, undefined for all other themes.
*/
"size"?: 'xsmall' | 'small' | 'medium' | 'large' | 'xlarge';
/**
* The theme determines the visual appearance of the component.
*/
@@ -8977,13 +8917,9 @@ declare namespace LocalJSX {
*/
"rows"?: number;
/**
* Set to `"soft"` for a textarea with slightly rounded corners, `"round"` for a textarea with fully rounded corners, or `"rectangular"` for a textarea without rounded corners. Defaults to `"round"` for the `ionic` theme, undefined for all other themes.
* The shape of the textarea. If "round" it will have an increased border radius.
*/
"shape"?: 'soft' | 'round' | 'rectangular';
/**
* The size of the textarea. If "large" it will increase the height of the textarea, while "small" and "medium" provide progressively smaller heights. The default size is "medium". This property only applies to the `"ionic"` theme.
*/
"size"?: 'small' | 'medium' | 'large';
"shape"?: 'round';
/**
* If `true`, the element will have its spelling and grammar checked.
*/

View File

@@ -1,4 +1,3 @@
import caretDownRegular from '@phosphor-icons/core/assets/regular/caret-down.svg';
import type { ComponentInterface } from '@stencil/core';
import { Component, Element, Host, Prop, State, Watch, h } from '@stencil/core';
import { addEventListener, getElementRoot, raf, removeEventListener, transitionEndAsync } from '@utils/helpers';
@@ -188,34 +187,14 @@ export class Accordion implements ComponentInterface {
button.setAttribute('aria-expanded', `${expanded}`);
};
get accordionToggleIcon() {
// Return the icon if it is explicitly set
if (this.toggleIcon != null) {
return this.toggleIcon;
}
// Determine the theme and map to default icons
const theme = getIonTheme(this);
const defaultIcons = {
ios: chevronDown,
ionic: caretDownRegular,
md: chevronDown,
};
// Get the default icon based on the theme, falling back to 'md' icon if necessary
const defaultIcon = defaultIcons[theme] || defaultIcons.md;
// Return the configured accordion toggle icon or the default icon
return config.get('accordionToggleIcon', defaultIcon);
}
private slotToggleIcon = () => {
const ionItem = this.getSlottedHeaderIonItem();
if (!ionItem) {
return;
}
const { accordionToggleIcon, toggleIconSlot } = this;
const { toggleIconSlot } = this;
const accordionToggleIcon = this.toggleIcon ?? config.get('accordionToggleIcon', chevronDown);
/**
* Check if there already is a toggle icon.

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 88 KiB

After

Width:  |  Height:  |  Size: 85 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 88 KiB

After

Width:  |  Height:  |  Size: 85 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 88 KiB

After

Width:  |  Height:  |  Size: 87 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 89 KiB

After

Width:  |  Height:  |  Size: 87 KiB

View File

@@ -48,7 +48,7 @@ configs({ modes: ['md'], directions: ['ltr'] }).forEach(({ config, title }) => {
await expect(accordion).toHaveClass(/accordion-collapsed/);
await accordion.click();
accordion.click();
await page.waitForChanges();
await expect(accordion).toHaveClass(/accordion-collapsed/);
@@ -71,7 +71,7 @@ configs({ modes: ['md'], directions: ['ltr'] }).forEach(({ config, title }) => {
await expect(accordion).toHaveClass(/accordion-collapsed/);
await accordion.click();
accordion.click();
await page.waitForChanges();
await expect(accordion).toHaveClass(/accordion-collapsed/);

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 18 KiB

After

Width:  |  Height:  |  Size: 18 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 25 KiB

After

Width:  |  Height:  |  Size: 25 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 11 KiB

After

Width:  |  Height:  |  Size: 11 KiB

View File

@@ -48,7 +48,7 @@ configs({ modes: ['md'], directions: ['ltr'] }).forEach(({ config, title }) => {
await expect(accordion).toHaveClass(/accordion-collapsed/);
await accordion.click();
accordion.click();
await page.waitForChanges();
await expect(accordion).toHaveClass(/accordion-collapsed/);
@@ -71,7 +71,7 @@ configs({ modes: ['md'], directions: ['ltr'] }).forEach(({ config, title }) => {
await expect(accordion).toHaveClass(/accordion-collapsed/);
await accordion.click();
accordion.click();
await page.waitForChanges();
await expect(accordion).toHaveClass(/accordion-collapsed/);

View File

@@ -312,9 +312,7 @@ export class ActionSheet implements ComponentInterface, OverlayInterface {
}
componentWillLoad() {
if (!this.htmlAttributes?.id) {
setOverlayId(this.el);
}
setOverlayId(this.el);
}
componentDidLoad() {

View File

@@ -0,0 +1,41 @@
import { newSpecPage } from '@stencil/core/testing';
import { ActionSheet } from '../action-sheet';
it('action sheet should be assigned an incrementing id', async () => {
const page = await newSpecPage({
components: [ActionSheet],
html: `<ion-action-sheet is-open="true"></ion-action-sheet>`,
});
let actionSheet: HTMLIonActionSheetElement;
actionSheet = page.body.querySelector('ion-action-sheet')!;
expect(actionSheet).not.toBe(null);
expect(actionSheet.getAttribute('id')).toBe('ion-overlay-1');
// Remove the action sheet from the DOM
actionSheet.remove();
await page.waitForChanges();
// Create a new action sheet to verify the id is incremented
actionSheet = document.createElement('ion-action-sheet');
actionSheet.isOpen = true;
page.body.appendChild(actionSheet);
await page.waitForChanges();
actionSheet = page.body.querySelector('ion-action-sheet')!;
expect(actionSheet.getAttribute('id')).toBe('ion-overlay-2');
// Presenting the same action sheet again should reuse the existing id
actionSheet.isOpen = false;
await page.waitForChanges();
actionSheet.isOpen = true;
await page.waitForChanges();
actionSheet = page.body.querySelector('ion-action-sheet')!;
expect(actionSheet.getAttribute('id')).toBe('ion-overlay-2');
});

View File

@@ -1,55 +0,0 @@
import { newSpecPage } from '@stencil/core/testing';
import { ActionSheet } from '../action-sheet';
import { h } from '@stencil/core';
describe('action-sheet: id', () => {
it('action sheet should be assigned an incrementing id', async () => {
const page = await newSpecPage({
components: [ActionSheet],
html: `<ion-action-sheet is-open="true"></ion-action-sheet>`,
});
let actionSheet: HTMLIonActionSheetElement;
actionSheet = page.body.querySelector('ion-action-sheet')!;
expect(actionSheet).not.toBe(null);
expect(actionSheet.getAttribute('id')).toBe('ion-overlay-1');
// Remove the action sheet from the DOM
actionSheet.remove();
await page.waitForChanges();
// Create a new action sheet to verify the id is incremented
actionSheet = document.createElement('ion-action-sheet');
actionSheet.isOpen = true;
page.body.appendChild(actionSheet);
await page.waitForChanges();
actionSheet = page.body.querySelector('ion-action-sheet')!;
expect(actionSheet.getAttribute('id')).toBe('ion-overlay-2');
// Presenting the same action sheet again should reuse the existing id
actionSheet.isOpen = false;
await page.waitForChanges();
actionSheet.isOpen = true;
await page.waitForChanges();
actionSheet = page.body.querySelector('ion-action-sheet')!;
expect(actionSheet.getAttribute('id')).toBe('ion-overlay-2');
});
it('should not overwrite the id set in htmlAttributes', async () => {
const id = 'custom-id';
const page = await newSpecPage({
components: [ActionSheet],
template: () => <ion-action-sheet htmlAttributes={{ id }} overlayIndex={-1}></ion-action-sheet>,
});
const alert = page.body.querySelector('ion-action-sheet')!;
expect(alert.id).toBe(id);
});
});

View File

@@ -343,9 +343,7 @@ export class Alert implements ComponentInterface, OverlayInterface {
}
componentWillLoad() {
if (!this.htmlAttributes?.id) {
setOverlayId(this.el);
}
setOverlayId(this.el);
this.inputsChanged();
this.buttonsChanged();
}

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 32 KiB

After

Width:  |  Height:  |  Size: 36 KiB

View File

@@ -0,0 +1,41 @@
import { newSpecPage } from '@stencil/core/testing';
import { Alert } from '../alert';
it('alert should be assigned an incrementing id', async () => {
const page = await newSpecPage({
components: [Alert],
html: `<ion-alert is-open="true"></ion-alert>`,
});
let alert: HTMLIonAlertElement;
alert = page.body.querySelector('ion-alert')!;
expect(alert).not.toBe(null);
expect(alert.getAttribute('id')).toBe('ion-overlay-1');
// Remove the alert from the DOM
alert.remove();
await page.waitForChanges();
// Create a new alert to verify the id is incremented
alert = document.createElement('ion-alert');
alert.isOpen = true;
page.body.appendChild(alert);
await page.waitForChanges();
alert = page.body.querySelector('ion-alert')!;
expect(alert.getAttribute('id')).toBe('ion-overlay-2');
// Presenting the same alert again should reuse the existing id
alert.isOpen = false;
await page.waitForChanges();
alert.isOpen = true;
await page.waitForChanges();
alert = page.body.querySelector('ion-alert')!;
expect(alert.getAttribute('id')).toBe('ion-overlay-2');
});

View File

@@ -1,55 +0,0 @@
import { newSpecPage } from '@stencil/core/testing';
import { Alert } from '../alert';
import { h } from '@stencil/core';
describe('alert: id', () => {
it('alert should be assigned an incrementing id', async () => {
const page = await newSpecPage({
components: [Alert],
html: `<ion-alert is-open="true"></ion-alert>`,
});
let alert: HTMLIonAlertElement;
alert = page.body.querySelector('ion-alert')!;
expect(alert).not.toBe(null);
expect(alert.getAttribute('id')).toBe('ion-overlay-1');
// Remove the alert from the DOM
alert.remove();
await page.waitForChanges();
// Create a new alert to verify the id is incremented
alert = document.createElement('ion-alert');
alert.isOpen = true;
page.body.appendChild(alert);
await page.waitForChanges();
alert = page.body.querySelector('ion-alert')!;
expect(alert.getAttribute('id')).toBe('ion-overlay-2');
// Presenting the same alert again should reuse the existing id
alert.isOpen = false;
await page.waitForChanges();
alert.isOpen = true;
await page.waitForChanges();
alert = page.body.querySelector('ion-alert')!;
expect(alert.getAttribute('id')).toBe('ion-overlay-2');
});
it('should not overwrite the id set in htmlAttributes', async () => {
const id = 'custom-id';
const page = await newSpecPage({
components: [Alert],
template: () => <ion-alert htmlAttributes={{ id }} overlayIndex={-1}></ion-alert>,
});
const alert = page.body.querySelector('ion-alert')!;
expect(alert.id).toBe(id);
});
});

View File

@@ -1,5 +1,5 @@
@use "../../themes/ionic/ionic.globals.scss" as globals;
@import "./avatar.common";
@import "./avatar";
// Ionic Avatar
// --------------------------------------------------
@@ -16,34 +16,18 @@
background: globals.$ionic-color-neutral-100;
color: globals.$ionic-color-neutral-800;
font-weight: globals.$ionic-font-weight-medium;
font-weight: globals.$ionic-font-weight-regular;
line-height: globals.$ionic-line-height-700;
line-height: globals.$ionic-line-height-600;
}
:host(:not(.avatar-image)) {
@include padding(var(--padding-top), var(--padding-end), var(--padding-bottom), var(--padding-start));
border: globals.$ionic-border-size-025 globals.$ionic-border-style-solid globals.$ionic-color-neutral-800;
border: globals.$ionic-border-size-025 solid globals.$ionic-color-neutral-800;
}
// Avatar Sizes
// --------------------------------------------------
/* 2-Extra Small */
:host(.avatar-xxsmall) {
--padding-end: #{globals.$ionic-space-050};
--padding-start: #{globals.$ionic-space-050};
width: globals.$ionic-scale-400;
height: globals.$ionic-scale-400;
font-size: globals.$ionic-font-size-300;
line-height: globals.$ionic-line-height-500;
}
/* Extra Small */
:host(.avatar-xsmall) {
--padding-end: #{globals.$ionic-space-050};
--padding-start: #{globals.$ionic-space-050};
@@ -53,10 +37,11 @@
font-size: globals.$ionic-font-size-300;
font-weight: globals.$ionic-font-weight-medium;
line-height: globals.$ionic-line-height-500;
}
/* Small */
:host(.avatar-small) {
--padding-end: #{globals.$ionic-space-150};
--padding-start: #{globals.$ionic-space-150};
@@ -64,12 +49,9 @@
width: globals.$ionic-scale-800;
height: globals.$ionic-scale-800;
font-size: globals.$ionic-font-size-400;
line-height: globals.$ionic-line-height-600;
font-size: globals.$ionic-font-size-350;
}
/* Medium */
:host(.avatar-medium) {
--padding-end: #{globals.$ionic-space-200};
--padding-start: #{globals.$ionic-space-200};
@@ -77,10 +59,9 @@
width: globals.$ionic-scale-1000;
height: globals.$ionic-scale-1000;
font-size: globals.$ionic-font-size-450;
font-size: globals.$ionic-font-size-400;
}
/* Large */
:host(.avatar-large) {
--padding-end: #{globals.$ionic-space-250};
--padding-start: #{globals.$ionic-space-250};
@@ -88,69 +69,5 @@
width: globals.$ionic-scale-1200;
height: globals.$ionic-scale-1200;
font-size: globals.$ionic-font-size-500;
}
/* Extra Large */
:host(.avatar-xlarge) {
--padding-end: #{globals.$ionic-space-300};
--padding-start: #{globals.$ionic-space-300};
width: globals.$ionic-scale-1400;
height: globals.$ionic-scale-1400;
font-size: globals.$ionic-font-size-550;
}
// Avatar Shapes
// --------------------------------------------------
:host(.avatar-xxsmall.avatar-soft),
:host(.avatar-xsmall.avatar-soft),
:host(.avatar-small.avatar-soft) {
--border-radius: #{globals.$ionic-border-radius-100};
}
:host(.avatar-soft) {
--border-radius: #{globals.$ionic-border-radius-200};
}
:host(.avatar-round) {
--border-radius: #{globals.$ionic-border-radius-full};
}
:host(.avatar-rectangular) {
--border-radius: #{globals.$ionic-border-radius-0};
}
// Avatar Icon
// --------------------------------------------------
:host(.avatar-icon) {
@include padding(0);
}
:host(.avatar-xsmall) ::slotted(ion-icon) {
width: globals.$ionic-scale-400;
height: globals.$ionic-scale-400;
}
:host(.avatar-small) ::slotted(ion-icon) {
width: globals.$ionic-scale-500;
height: globals.$ionic-scale-500;
}
:host(.avatar-medium) ::slotted(ion-icon) {
width: globals.$ionic-scale-600;
height: globals.$ionic-scale-600;
}
:host(.avatar-large) ::slotted(ion-icon) {
width: globals.$ionic-scale-800;
height: globals.$ionic-scale-800;
}
:host(.avatar-xlarge) ::slotted(ion-icon) {
width: globals.$ionic-scale-1000;
height: globals.$ionic-scale-1000;
font-size: globals.$ionic-font-size-450;
}

View File

@@ -1,4 +1,4 @@
@import "./avatar.common";
@import "./avatar";
@import "./avatar.ios.vars";
// iOS Avatar

View File

@@ -1,4 +1,4 @@
@import "./avatar.common";
@import "./avatar";
@import "./avatar.md.vars";
// Material Design Avatar

View File

@@ -20,34 +20,17 @@ export class Avatar implements ComponentInterface {
@Element() el!: HTMLElement;
/**
* Set to `"xxsmall"` for the smallest size.
* Set to `"xsmall"` for a very small size.
* Set to `"small"` for a compact size.
* Set to `"medium"` for the default height and width.
* Set to `"large"` for a larger size.
* Set to `"xlarge"` for the largest dimensions.
* Set to `"xsmall"` for the smallest size, `"small"` for a compact size, `"medium"`
* for the default height and width, or to `"large"` for a larger size.
*
* Defaults to `"medium"` for the `ionic` theme, undefined for all other themes.
*/
@Prop() size?: 'xxsmall' | 'xsmall' | 'small' | 'medium' | 'large' | 'xlarge';
/**
* Set to `"soft"` for an avatar with slightly rounded corners,
* `"round"` for an avatar with fully rounded corners, or `"rectangular"`
* for an avatar without rounded corners.
*
* Defaults to `"round"` for the `ionic` theme, undefined for all other themes.
*/
@Prop() shape?: 'soft' | 'round' | 'rectangular';
@Prop() size?: `xsmall` | 'small' | 'medium' | 'large';
get hasImage() {
return !!this.el.querySelector('ion-img') || !!this.el.querySelector('img');
}
get hasIcon() {
return !!this.el.querySelector('ion-icon');
}
private getSize(): string | undefined {
const theme = getIonTheme(this);
const { size } = this;
@@ -64,35 +47,16 @@ export class Avatar implements ComponentInterface {
return size;
}
private getShape(): string | undefined {
const theme = getIonTheme(this);
const { shape } = this;
// TODO(ROU-10755): Remove theme check when shapes are defined for all themes.
if (theme !== 'ionic') {
return undefined;
}
if (shape === undefined) {
return 'round';
}
return shape;
}
render() {
const theme = getIonTheme(this);
const size = this.getSize();
const shape = this.getShape();
return (
<Host
class={{
[theme]: true,
[`avatar-${size}`]: size !== undefined,
[`avatar-${shape}`]: shape !== undefined,
[`avatar-image`]: this.hasImage,
[`avatar-icon`]: this.hasIcon,
}}
>
<slot></slot>

View File

@@ -1,192 +0,0 @@
import { expect } from '@playwright/test';
import { configs, test } from '@utils/test/playwright';
/**
* This behavior does not vary across directions.
*/
configs({ directions: ['ltr'], modes: ['ionic-md'] }).forEach(({ config, screenshot, title }) => {
test.describe(title('avatar: shape'), () => {
test.describe('round', () => {
test('should not have visual regressions when containing text', async ({ page }) => {
await page.setContent(
`
<ion-avatar shape="round">AB</ion-avatar>
`,
config
);
const avatar = page.locator('ion-avatar');
await expect(avatar).toHaveScreenshot(screenshot(`avatar-shape-round-text`));
});
test('should not have visual regressions when containing an icon', async ({ page }) => {
await page.setContent(
`
<ion-avatar shape="round">
<ion-icon name="person-outline"></ion-icon>
</ion-avatar>
`,
config
);
const avatar = page.locator('ion-avatar');
await expect(avatar).toHaveScreenshot(screenshot(`avatar-shape-round-icon`));
});
test('should not have visual regressions when containing an image', async ({ page }) => {
await page.setContent(
`
<ion-avatar shape="round">
<img src="/src/components/avatar/test/avatar.svg"/>
</ion-avatar>
`,
config
);
const avatar = page.locator('ion-avatar');
await expect(avatar).toHaveScreenshot(screenshot(`avatar-shape-round-image`));
});
});
test.describe('rectangular', () => {
test('should not have visual regressions when containing text', async ({ page }) => {
await page.setContent(
`
<ion-avatar shape="rectangular">AB</ion-avatar>
`,
config
);
const avatar = page.locator('ion-avatar');
await expect(avatar).toHaveScreenshot(screenshot(`avatar-shape-rectangular-text`));
});
test('should not have visual regressions when containing an icon', async ({ page }) => {
await page.setContent(
`
<ion-avatar shape="rectangular">
<ion-icon name="person-outline"></ion-icon>
</ion-avatar>
`,
config
);
const avatar = page.locator('ion-avatar');
await expect(avatar).toHaveScreenshot(screenshot(`avatar-shape-rectangular-icon`));
});
test('should not have visual regressions when containing an image', async ({ page }) => {
await page.setContent(
`
<ion-avatar shape="rectangular">
<img src="/src/components/avatar/test/avatar.svg"/>
</ion-avatar>
`,
config
);
const avatar = page.locator('ion-avatar');
await expect(avatar).toHaveScreenshot(screenshot(`avatar-shape-rectangular-image`));
});
});
test.describe('soft', () => {
test('should not have visual regressions when containing text', async ({ page }) => {
await page.setContent(
`
<style>
#container {
display: flex;
gap: 10px;
}
</style>
<div id="container">
<ion-avatar shape="soft" size="xxsmall">A</ion-avatar>
<ion-avatar shape="soft" size="xsmall">AB</ion-avatar>
<ion-avatar shape="soft" size="small">AB</ion-avatar>
<ion-avatar shape="soft">AB</ion-avatar>
</div>
`,
config
);
const container = page.locator('#container');
await expect(container).toHaveScreenshot(screenshot(`avatar-shape-soft-text`));
});
test('should not have visual regressions when containing an icon', async ({ page }) => {
await page.setContent(
`
<style>
#container {
display: flex;
gap: 10px;
}
</style>
<div id="container">
<ion-avatar shape="soft" size="xxsmall">
<ion-icon name="person-outline"></ion-icon>
</ion-avatar>
<ion-avatar shape="soft" size="xsmall">
<ion-icon name="person-outline"></ion-icon>
</ion-avatar>
<ion-avatar shape="soft" size="small">
<ion-icon name="person-outline"></ion-icon>
</ion-avatar>
<ion-avatar shape="soft">
<ion-icon name="person-outline"></ion-icon>
</ion-avatar>
</div>
`,
config
);
const container = page.locator('#container');
await expect(container).toHaveScreenshot(screenshot(`avatar-shape-soft-icon`));
});
test('should not have visual regressions when containing an image', async ({ page }) => {
await page.setContent(
`
<style>
#container {
display: flex;
gap: 10px;
}
</style>
<div id="container">
<ion-avatar shape="soft" size="xxsmall">
<img src="/src/components/avatar/test/avatar.svg"/>
</ion-avatar>
<ion-avatar shape="soft" size="xsmall">
<img src="/src/components/avatar/test/avatar.svg"/>
</ion-avatar>
<ion-avatar shape="soft" size="small">
<img src="/src/components/avatar/test/avatar.svg"/>
</ion-avatar>
<ion-avatar shape="soft">
<img src="/src/components/avatar/test/avatar.svg"/>
</ion-avatar>
</div>
`,
config
);
const container = page.locator('#container');
await expect(container).toHaveScreenshot(screenshot(`avatar-shape-soft-image`));
});
});
});
});

View File

@@ -1,76 +0,0 @@
<!DOCTYPE html>
<html lang="en" dir="ltr">
<head>
<meta charset="UTF-8" />
<title>Avatar - Shape</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>
.container {
display: flex;
gap: 10px;
}
</style>
</head>
<body>
<ion-app>
<ion-header>
<ion-toolbar>
<ion-title>Avatar - Shape</ion-title>
</ion-toolbar>
</ion-header>
<ion-content class="ion-padding" id="content" no-bounce>
<h2>Default</h2>
<div class="container">
<ion-avatar>AB</ion-avatar>
<ion-avatar>
<ion-icon name="person-outline"></ion-icon>
</ion-avatar>
<ion-avatar>
<img src="/src/components/avatar/test/avatar.svg" />
</ion-avatar>
</div>
<h2>Soft</h2>
<div class="container">
<ion-avatar shape="soft" size="xxsmall">A</ion-avatar>
<ion-avatar shape="soft" size="xsmall">AB</ion-avatar>
<ion-avatar shape="soft" size="small">AB</ion-avatar>
<ion-avatar shape="soft" size="medium">AB</ion-avatar>
<ion-avatar shape="soft" size="large">AB</ion-avatar>
<ion-avatar shape="soft" size="xlarge">AB</ion-avatar>
</div>
<h2>Round</h2>
<div class="container">
<ion-avatar shape="round" size="xxsmall">A</ion-avatar>
<ion-avatar shape="round" size="xsmall">AB</ion-avatar>
<ion-avatar shape="round" size="small">AB</ion-avatar>
<ion-avatar shape="round" size="medium">AB</ion-avatar>
<ion-avatar shape="round" size="large">AB</ion-avatar>
<ion-avatar shape="round" size="xlarge">AB</ion-avatar>
</div>
<h2>Rectangular</h2>
<div class="container">
<ion-avatar shape="rectangular" size="xxsmall">A</ion-avatar>
<ion-avatar shape="rectangular" size="xsmall">AB</ion-avatar>
<ion-avatar shape="rectangular" size="small">AB</ion-avatar>
<ion-avatar shape="rectangular" size="medium">AB</ion-avatar>
<ion-avatar shape="rectangular" size="large">AB</ion-avatar>
<ion-avatar shape="rectangular" size="xlarge">AB</ion-avatar>
</div>
</ion-content>
</ion-app>
</body>
</html>

View File

@@ -6,51 +6,6 @@ import { configs, test } from '@utils/test/playwright';
*/
configs({ directions: ['ltr'], modes: ['ionic-md'] }).forEach(({ config, screenshot, title }) => {
test.describe(title('avatar: size'), () => {
test.describe('xxsmall', () => {
test('should not have visual regressions when containing text', async ({ page }) => {
await page.setContent(
`
<ion-avatar size="xxsmall">A</ion-avatar>
`,
config
);
const avatar = page.locator('ion-avatar');
await expect(avatar).toHaveScreenshot(screenshot(`avatar-size-xxsmall-text`));
});
test('should not have visual regressions when containing an icon', async ({ page }) => {
await page.setContent(
`
<ion-avatar size="xxsmall">
<ion-icon name="person-outline"></ion-icon>
</ion-avatar>
`,
config
);
const avatar = page.locator('ion-avatar');
await expect(avatar).toHaveScreenshot(screenshot(`avatar-size-xxsmall-icon`));
});
test('should not have visual regressions when containing an image', async ({ page }) => {
await page.setContent(
`
<ion-avatar size="xxsmall">
<img src="/src/components/avatar/test/avatar.svg"/>
</ion-avatar>
`,
config
);
const avatar = page.locator('ion-avatar');
await expect(avatar).toHaveScreenshot(screenshot(`avatar-size-xxsmall-image`));
});
});
test.describe('xsmall', () => {
test('should not have visual regressions when containing text', async ({ page }) => {
await page.setContent(
@@ -230,50 +185,5 @@ configs({ directions: ['ltr'], modes: ['ionic-md'] }).forEach(({ config, screens
await expect(avatar).toHaveScreenshot(screenshot(`avatar-size-large-image`));
});
});
test.describe('xlarge', () => {
test('should not have visual regressions when containing text', async ({ page }) => {
await page.setContent(
`
<ion-avatar size="xlarge">AB</ion-avatar>
`,
config
);
const avatar = page.locator('ion-avatar');
await expect(avatar).toHaveScreenshot(screenshot(`avatar-size-xlarge-text`));
});
test('should not have visual regressions when containing an icon', async ({ page }) => {
await page.setContent(
`
<ion-avatar size="xlarge">
<ion-icon name="person-outline"></ion-icon>
</ion-avatar>
`,
config
);
const avatar = page.locator('ion-avatar');
await expect(avatar).toHaveScreenshot(screenshot(`avatar-size-xlarge-icon`));
});
test('should not have visual regressions when containing an image', async ({ page }) => {
await page.setContent(
`
<ion-avatar size="xlarge">
<img src="/src/components/avatar/test/avatar.svg"/>
</ion-avatar>
`,
config
);
const avatar = page.locator('ion-avatar');
await expect(avatar).toHaveScreenshot(screenshot(`avatar-size-xlarge-image`));
});
});
});
});

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.1 KiB

After

Width:  |  Height:  |  Size: 652 B

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 KiB

After

Width:  |  Height:  |  Size: 578 B

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.1 KiB

After

Width:  |  Height:  |  Size: 592 B

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 KiB

After

Width:  |  Height:  |  Size: 740 B

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

After

Width:  |  Height:  |  Size: 688 B

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 KiB

After

Width:  |  Height:  |  Size: 728 B

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.9 KiB

After

Width:  |  Height:  |  Size: 798 B

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.6 KiB

After

Width:  |  Height:  |  Size: 819 B

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.9 KiB

After

Width:  |  Height:  |  Size: 721 B

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.7 KiB

After

Width:  |  Height:  |  Size: 540 B

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 KiB

After

Width:  |  Height:  |  Size: 521 B

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.6 KiB

After

Width:  |  Height:  |  Size: 500 B

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

After

Width:  |  Height:  |  Size: 627 B

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.0 KiB

After

Width:  |  Height:  |  Size: 585 B

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

After

Width:  |  Height:  |  Size: 624 B

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.6 KiB

After

Width:  |  Height:  |  Size: 695 B

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 KiB

After

Width:  |  Height:  |  Size: 717 B

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.6 KiB

After

Width:  |  Height:  |  Size: 637 B

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 KiB

After

Width:  |  Height:  |  Size: 465 B

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1008 B

After

Width:  |  Height:  |  Size: 460 B

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 KiB

After

Width:  |  Height:  |  Size: 462 B

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 928 B

After

Width:  |  Height:  |  Size: 501 B

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 891 B

After

Width:  |  Height:  |  Size: 481 B

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 883 B

After

Width:  |  Height:  |  Size: 480 B

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 KiB

After

Width:  |  Height:  |  Size: 586 B

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

After

Width:  |  Height:  |  Size: 590 B

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 KiB

After

Width:  |  Height:  |  Size: 562 B

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