Compare commits
1 Commits
workspace-
...
strength-i
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
243cf92600 |
167
.github/COMPONENT-GUIDE.md
vendored
@@ -2,10 +2,10 @@
|
||||
|
||||
- [Button States](#button-states)
|
||||
* [Component Structure](#component-structure)
|
||||
* [Activated](#activated)
|
||||
* [Disabled](#disabled)
|
||||
* [Focused](#focused)
|
||||
* [Hover](#hover)
|
||||
* [Activated](#activated)
|
||||
* [Ripple Effect](#ripple-effect)
|
||||
* [Example Components](#example-components)
|
||||
* [References](#references)
|
||||
@@ -21,7 +21,7 @@
|
||||
|
||||
## Button States
|
||||
|
||||
Any component that renders a button should have the following states: [`disabled`](#disabled), [`focused`](#focused), [`hover`](#hover), [`activated`](#activated). It should also have a [Ripple Effect](#ripple-effect) component added for Material Design.
|
||||
Any component that renders a button should have the following states: [`activated`](#activated), [`disabled`](#disabled), [`focused`](#focused), [`hover`](#hover). It should also have a [Ripple Effect](#ripple-effect) component added for Material Design.
|
||||
|
||||
### Component Structure
|
||||
|
||||
@@ -89,6 +89,73 @@ The following styles should be set for the CSS to work properly. Note that the `
|
||||
```
|
||||
|
||||
|
||||
### Activated
|
||||
|
||||
The activated state should be enabled for elements with actions on "press". It usually changes the opacity or background of an element.
|
||||
|
||||
> Make sure the component has the correct [component structure](#component-structure) before continuing.
|
||||
|
||||
#### JavaScript
|
||||
|
||||
The `ion-activatable` class needs to be set on an element that can be activated:
|
||||
|
||||
```jsx
|
||||
render() {
|
||||
return (
|
||||
<Host class='ion-activatable'>
|
||||
<slot></slot>
|
||||
</Host>
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
Once that is done, the element will get the `ion-activated` class added on press.
|
||||
|
||||
In addition to setting that class, `ion-activatable-instant` can be set in order to have an instant press with no delay:
|
||||
|
||||
```jsx
|
||||
<Host class='ion-activatable ion-activatable-instant'>
|
||||
```
|
||||
|
||||
#### CSS
|
||||
|
||||
```css
|
||||
/**
|
||||
* @prop --color-activated: Color of the button when pressed
|
||||
* @prop --background-activated: Background of the button when pressed
|
||||
* @prop --background-activated-opacity: Opacity of the background when pressed
|
||||
*/
|
||||
```
|
||||
|
||||
Style the `ion-activated` class based on the spec for that element:
|
||||
|
||||
```scss
|
||||
:host(.ion-activated) .button-native {
|
||||
color: var(--color-activated);
|
||||
|
||||
&::after {
|
||||
background: var(--background-activated);
|
||||
|
||||
opacity: var(--background-activated-opacity);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
> Order is important! Activated should be after the focused & hover states.
|
||||
|
||||
|
||||
#### User Customization
|
||||
|
||||
Setting the activated state on the `::after` pseudo-element allows the user to customize the activated state without knowing what the default opacity is set at. A user can customize in the following ways to have a solid red background on press, or they can leave out `--background-activated-opacity` and the button will use the default activated opacity to match the spec.
|
||||
|
||||
```css
|
||||
ion-button {
|
||||
--background-activated: red;
|
||||
--background-activated-opacity: 1;
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
### Disabled
|
||||
|
||||
The disabled state should be set via prop on all components that render a native button. Setting a disabled state will change the opacity or color of the button and remove click events from firing.
|
||||
@@ -125,8 +192,7 @@ render() {
|
||||
}
|
||||
```
|
||||
|
||||
> [!NOTE]
|
||||
> If the class being added was for `ion-back-button` it would be `back-button-disabled`.
|
||||
> Note: if the class being added was for `ion-back-button` it would be `back-button-disabled`.
|
||||
|
||||
#### CSS
|
||||
|
||||
@@ -144,18 +210,10 @@ The following CSS _at the bare minimum_ should be added for the disabled class,
|
||||
|
||||
TODO
|
||||
|
||||
|
||||
### Focused
|
||||
|
||||
The focused state should be enabled for elements with actions when tabbed to via the keyboard. This will only work inside of an `ion-app`. It usually changes the opacity or background of an element.
|
||||
|
||||
> [!WARNING]
|
||||
> Do not use `:focus` because that will cause the focus to apply even when an element is tapped (because the element is now focused). Instead, we only want the focus state to be shown when it makes sense which is what the `.ion-focusable` utility mentioned below does.
|
||||
|
||||
> [!NOTE]
|
||||
> The [`:focus-visible`](https://developer.mozilla.org/en-US/docs/Web/CSS/:focus-visible) pseudo-class mostly does the same thing as our JavaScript-driven utility. However, it does not work well with Shadow DOM components as the element that receives focus is typically inside of the Shadow DOM, but we usually want to set the `:focus-visible` state on the host so we can style other parts of the component. Using other combinations such as `:has(:focus-visible)` does not work because `:has` does not pierce the Shadow DOM (as that would leak implementation details about the Shadow DOM contents). `:focus-within` does work with the Shadow DOM, but that has the same problem as `:focus` that was mentioned before. Unfortunately, a [`:focus-visible-within` pseudo-class does not exist yet](https://github.com/WICG/focus-visible/issues/151).
|
||||
|
||||
> [!IMPORTANT]
|
||||
> Make sure the component has the correct [component structure](#component-structure) before continuing.
|
||||
|
||||
#### JavaScript
|
||||
@@ -165,7 +223,7 @@ The `ion-focusable` class needs to be set on an element that can be focused:
|
||||
```jsx
|
||||
render() {
|
||||
return (
|
||||
<Host class="ion-focusable">
|
||||
<Host class='ion-focusable'>
|
||||
<slot></slot>
|
||||
</Host>
|
||||
);
|
||||
@@ -200,8 +258,7 @@ Style the `ion-focused` class based on the spec for that element:
|
||||
}
|
||||
```
|
||||
|
||||
> [!IMPORTANT]
|
||||
> Order matters! Focused should be **before** the activated and hover states.
|
||||
> Order is important! Focused should be after the activated and before the hover state.
|
||||
|
||||
|
||||
#### User Customization
|
||||
@@ -220,10 +277,6 @@ ion-button {
|
||||
|
||||
The [hover state](https://developer.mozilla.org/en-US/docs/Web/CSS/:hover) happens when a user moves their cursor on top of an element without pressing on it. It should not happen on mobile, only on desktop devices that support hover.
|
||||
|
||||
> [!NOTE]
|
||||
> Some Android devices [incorrectly report their inputs](https://issues.chromium.org/issues/40855702) which can result in certain devices receiving hover events when they should not.
|
||||
|
||||
> [!IMPORTANT]
|
||||
> Make sure the component has the correct [component structure](#component-structure) before continuing.
|
||||
|
||||
#### CSS
|
||||
@@ -254,8 +307,7 @@ Style the `:hover` based on the spec for that element:
|
||||
}
|
||||
```
|
||||
|
||||
> [!IMPORTANT]
|
||||
> Order matters! Hover should be **before** the activated state.
|
||||
> Order is important! Hover should be before the activated state.
|
||||
|
||||
|
||||
#### User Customization
|
||||
@@ -270,79 +322,6 @@ ion-button {
|
||||
```
|
||||
|
||||
|
||||
### Activated
|
||||
|
||||
The activated state should be enabled for elements with actions on "press". It usually changes the opacity or background of an element.
|
||||
|
||||
> [!WARNING]
|
||||
>`:active` should not be used here as it is not received on mobile Safari unless the element has a `touchstart` listener (which we don't necessarily want to have to add to every element). From [Safari Web Content Guide](https://developer.apple.com/library/archive/documentation/AppleApplications/Reference/SafariWebContent/AdjustingtheTextSize/AdjustingtheTextSize.html):
|
||||
>
|
||||
>> On iOS, mouse events are sent so quickly that the down or active state is never received. Therefore, the `:active` pseudo state is triggered only when there is a touch event set on the HTML element
|
||||
|
||||
> [!IMPORTANT]
|
||||
> Make sure the component has the correct [component structure](#component-structure) before continuing.
|
||||
|
||||
#### JavaScript
|
||||
|
||||
The `ion-activatable` class needs to be set on an element that can be activated:
|
||||
|
||||
```jsx
|
||||
render() {
|
||||
return (
|
||||
<Host class="ion-activatable">
|
||||
<slot></slot>
|
||||
</Host>
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
Once that is done, the element will get the `ion-activated` class added on press after a small delay. This delay exists so that the active state does not show up when an activatable element is tapped while scrolling.
|
||||
|
||||
In addition to setting that class, `ion-activatable-instant` can be set in order to have an instant press with no delay:
|
||||
|
||||
```jsx
|
||||
<Host class="ion-activatable ion-activatable-instant">
|
||||
```
|
||||
|
||||
#### CSS
|
||||
|
||||
```css
|
||||
/**
|
||||
* @prop --color-activated: Color of the button when pressed
|
||||
* @prop --background-activated: Background of the button when pressed
|
||||
* @prop --background-activated-opacity: Opacity of the background when pressed
|
||||
*/
|
||||
```
|
||||
|
||||
Style the `ion-activated` class based on the spec for that element:
|
||||
|
||||
```scss
|
||||
:host(.ion-activated) .button-native {
|
||||
color: var(--color-activated);
|
||||
|
||||
&::after {
|
||||
background: var(--background-activated);
|
||||
|
||||
opacity: var(--background-activated-opacity);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
> [!IMPORTANT]
|
||||
> Order matters! Activated should be **after** the focused & hover states.
|
||||
|
||||
#### User Customization
|
||||
|
||||
Setting the activated state on the `::after` pseudo-element allows the user to customize the activated state without knowing what the default opacity is set at. A user can customize in the following ways to have a solid red background on press, or they can leave out `--background-activated-opacity` and the button will use the default activated opacity to match the spec.
|
||||
|
||||
```css
|
||||
ion-button {
|
||||
--background-activated: red;
|
||||
--background-activated-opacity: 1;
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
### Ripple Effect
|
||||
|
||||
The ripple effect should be added to elements for Material Design. It *requires* the `ion-activatable` class to be set on the parent element to work, and relative positioning on the parent.
|
||||
|
||||
285
.github/CONTRIBUTING.md
vendored
@@ -4,53 +4,56 @@ Thanks for your interest in contributing to the Ionic Framework! :tada:
|
||||
|
||||
- [Contributing Etiquette](#contributing-etiquette)
|
||||
- [Creating an Issue](#creating-an-issue)
|
||||
- [Creating a Good Code Reproduction](#creating-a-good-code-reproduction)
|
||||
* [Creating a Good Code Reproduction](#creating-a-good-code-reproduction)
|
||||
- [Creating a Pull Request](#creating-a-pull-request)
|
||||
- [Requirements](#requirements)
|
||||
- [Setup](#setup)
|
||||
- [Core](#core)
|
||||
- [Modifying Components](#modifying-components)
|
||||
- [Preview Changes](#preview-changes)
|
||||
- [Lint Changes](#lint-changes)
|
||||
- [Modifying Documentation](#modifying-documentation)
|
||||
- [Modifying Tests](#modifying-tests)
|
||||
* [Requirements](#requirements)
|
||||
* [Setup](#setup)
|
||||
* [Core](#core)
|
||||
+ [Modifying Components](#modifying-components)
|
||||
+ [Preview Changes](#preview-changes)
|
||||
+ [Lint Changes](#lint-changes)
|
||||
+ [Modifying Documentation](#modifying-documentation)
|
||||
+ [Modifying Tests](#modifying-tests)
|
||||
- [Screenshot Tests](#screenshot-tests)
|
||||
- [Building Changes](#building-changes)
|
||||
- [Angular, React, and Vue](#angular-react-and-vue)
|
||||
- [Modifying Files](#modifying-files)
|
||||
- [Preview Changes](#preview-changes-1)
|
||||
- [Lint Changes](#lint-changes-1)
|
||||
- [Modifying Tests](#modifying-tests-1)
|
||||
- [Building Changes](#building-changes-1)
|
||||
- [Submit Pull Request](#submit-pull-request)
|
||||
+ [Building Changes](#building-changes)
|
||||
* [Angular, React, and Vue](#angular-react-and-vue)
|
||||
+ [Modifying Files](#modifying-files)
|
||||
+ [Preview Changes](#preview-changes-1)
|
||||
+ [Lint Changes](#lint-changes-1)
|
||||
+ [Modifying Tests](#modifying-tests-1)
|
||||
+ [Building Changes](#building-changes-1)
|
||||
* [Submit Pull Request](#submit-pull-request)
|
||||
- [Commit Message Guidelines](#commit-message-guidelines)
|
||||
- [Commit Message Format](#commit-message-format)
|
||||
- [Revert](#revert)
|
||||
- [Type](#type)
|
||||
- [Scope](#scope)
|
||||
- [Subject](#subject)
|
||||
- [Body](#body)
|
||||
- [Footer](#footer)
|
||||
- [Examples](#examples)
|
||||
* [Commit Message Format](#commit-message-format)
|
||||
* [Revert](#revert)
|
||||
* [Type](#type)
|
||||
* [Scope](#scope)
|
||||
* [Subject](#subject)
|
||||
* [Body](#body)
|
||||
* [Footer](#footer)
|
||||
* [Examples](#examples)
|
||||
- [License](#license)
|
||||
|
||||
|
||||
## Contributing Etiquette
|
||||
|
||||
Please see our [Contributor Code of Conduct](https://github.com/ionic-team/ionic-framework/blob/main/CODE_OF_CONDUCT.md) for information on our rules of conduct.
|
||||
|
||||
|
||||
## Creating an Issue
|
||||
|
||||
- If you have a question about using the framework, please ask on the [Ionic Forum](http://forum.ionicframework.com/) or in the [Ionic Discord](https://ionic.link/discord).
|
||||
* If you have a question about using the framework, please ask on the [Ionic Forum](http://forum.ionicframework.com/) or in the [Ionic Discord](https://ionic.link/discord).
|
||||
|
||||
- It is required that you clearly describe the steps necessary to reproduce the issue you are running into. Although we would love to help our users as much as possible, diagnosing issues without clear reproduction steps is extremely time-consuming and simply not sustainable.
|
||||
* It is required that you clearly describe the steps necessary to reproduce the issue you are running into. Although we would love to help our users as much as possible, diagnosing issues without clear reproduction steps is extremely time-consuming and simply not sustainable.
|
||||
|
||||
- The issue list of this repository is exclusively for bug reports and feature requests. Non-conforming issues will be closed immediately.
|
||||
* The issue list of this repository is exclusively for bug reports and feature requests. Non-conforming issues will be closed immediately.
|
||||
|
||||
- Issues with no clear steps to reproduce will not be triaged. If an issue is labeled with "needs: reply" and receives no further replies from the author of the issue for more than 14 days, it will be closed.
|
||||
* Issues with no clear steps to reproduce will not be triaged. If an issue is labeled with "needs: reply" and receives no further replies from the author of the issue for more than 14 days, it will be closed.
|
||||
|
||||
- If you think you have found a bug, or have a new feature idea, please start by making sure it hasn't already been [reported](https://github.com/ionic-team/ionic-framework/issues?utf8=%E2%9C%93&q=is%3Aissue). You can search through existing issues to see if there is a similar one reported. Include closed issues as it may have been closed with a solution.
|
||||
* If you think you have found a bug, or have a new feature idea, please start by making sure it hasn't already been [reported](https://github.com/ionic-team/ionic-framework/issues?utf8=%E2%9C%93&q=is%3Aissue). You can search through existing issues to see if there is a similar one reported. Include closed issues as it may have been closed with a solution.
|
||||
|
||||
* Next, [create a new issue](https://github.com/ionic-team/ionic-framework/issues/new/choose) that thoroughly explains the problem. Please fill out the populated issue form before submitting the issue.
|
||||
|
||||
- Next, [create a new issue](https://github.com/ionic-team/ionic-framework/issues/new/choose) that thoroughly explains the problem. Please fill out the populated issue form before submitting the issue.
|
||||
|
||||
## Creating a Good Code Reproduction
|
||||
|
||||
@@ -66,43 +69,42 @@ Without a reliable code reproduction, it is unlikely we will be able to resolve
|
||||
|
||||
### How to Create a Reproduction
|
||||
|
||||
- Create a new Ionic application using one of our starter templates. The `blank` starter application is a great choice for this. You can create one using the following Ionic CLI command: `ionic start myApp blank`
|
||||
- Add the minimum amount of code needed to recreate the issue you are experiencing. Do not include anything that is not required to reproduce the issue. This includes any 3rd party plugins you have installed.
|
||||
- Publish the application on GitHub and include a link to it when [creating an issue](#creating-an-issue).
|
||||
- Be sure to include steps to reproduce the issue. These steps should be clear and easy to follow.
|
||||
* Create a new Ionic application using one of our starter templates. The `blank` starter application is a great choice for this. You can create one using the following Ionic CLI command: `ionic start myApp blank`
|
||||
* Add the minimum amount of code needed to recreate the issue you are experiencing. Do not include anything that is not required to reproduce the issue. This includes any 3rd party plugins you have installed.
|
||||
* Publish the application on GitHub and include a link to it when [creating an issue](#creating-an-issue).
|
||||
* Be sure to include steps to reproduce the issue. These steps should be clear and easy to follow.
|
||||
|
||||
### Benefits of Creating a Reproduction
|
||||
|
||||
- **Uses the latest version of Ionic:** By creating a new Ionic application, you are ensuring that you are testing against the latest version of the framework. Sometimes the issues you are experiencing have already been resolved in a newer version of the framework!
|
||||
- **Minimal surface area:** By removing code that is not needed in order to reproduce the issue, it makes it easier to identify the cause of the issue.
|
||||
- **No secret code needed:** Creating a minimal reproduction of the issue prevents you from having to publish any proprietary code used in your project.
|
||||
- **Get help fixing the issue:** If we can reliably reproduce an issue, there is a good chance we will be able to address it.
|
||||
* **Uses the latest version of Ionic:** By creating a new Ionic application, you are ensuring that you are testing against the latest version of the framework. Sometimes the issues you are experiencing have already been resolved in a newer version of the framework!
|
||||
* **Minimal surface area:** By removing code that is not needed in order to reproduce the issue, it makes it easier to identify the cause of the issue.
|
||||
* **No secret code needed:** Creating a minimal reproduction of the issue prevents you from having to publish any proprietary code used in your project.
|
||||
* **Get help fixing the issue:** If we can reliably reproduce an issue, there is a good chance we will be able to address it.
|
||||
|
||||
|
||||
## Creating a Pull Request
|
||||
|
||||
Before creating a pull request, please read our requirements that explains the minimal details to have your PR considered and merged into the codebase.
|
||||
|
||||
### Requirements
|
||||
|
||||
1. PRs must reference an existing issue that describes the issue or feature being submitted.
|
||||
2. PRs must have a reproduction app or the issue must include a reproduction app to verify changes against.
|
||||
3. PRs must include tests covering the changed behavior or a description of why tests cannot be written.
|
||||
|
||||
> Note: We appreciate you taking the time to contribute! Before submitting a pull request, please take the time to comment on the issue you are wanting to resolve. This helps us prevent duplicate effort or advise if the team is already addressing the issue.
|
||||
|
||||
- Looking for an issue to fix? Look through our issues with the [help wanted](https://github.com/ionic-team/ionic-framework/issues?q=is%3Aopen+is%3Aissue+label%3A%22help+wanted%22) label!
|
||||
* Looking for an issue to fix? Look through our issues with the [help wanted](https://github.com/ionic-team/ionic-framework/issues?q=is%3Aopen+is%3Aissue+label%3A%22help+wanted%22) label!
|
||||
|
||||
### Setup
|
||||
|
||||
1. [Download the installer](https://nodejs.org/) for the LTS version of Node.js.
|
||||
2. Install pnpm following the [installation instructions](https://pnpm.io/installation).
|
||||
3. Fork this repository.
|
||||
4. Clone your fork.
|
||||
5. Create a new branch from main for your change.
|
||||
6. Navigate into the directory of the package you wish to modify (core, angular, etc.).
|
||||
7. Run `pnpm install` to install dependencies for this package.
|
||||
- If you prefer to install all dependencies (core, angular, etc.) at once, run `pnpm -r install` from the root of the repository.
|
||||
8. Follow the steps for the specific package below.
|
||||
1. [Download the installer](https://nodejs.org/) for the LTS version of Node.js. This is the best way to also [install npm](https://blog.npmjs.org/post/85484771375/how-to-install-npm#_=_).
|
||||
2. Fork this repository.
|
||||
3. Clone your fork.
|
||||
4. Create a new branch from main for your change.
|
||||
5. Navigate into the directory of the package you wish to modify (core, angular, etc.).
|
||||
6. Run `npm install` to install dependencies for this package.
|
||||
7. Follow the steps for the specific package below.
|
||||
|
||||
|
||||
### Core
|
||||
|
||||
@@ -118,11 +120,12 @@ Before creating a pull request, please read our requirements that explains the m
|
||||
8. After the build is finished, commit the changes. Please follow the [commit message format](#commit-message-format) for every commit.
|
||||
9. [Submit a Pull Request](#submit-pull-request) of your changes.
|
||||
|
||||
|
||||
#### Preview Changes
|
||||
|
||||
##### Previewing in this repository
|
||||
|
||||
1. Run `pnpm start` from within the `core` directory.
|
||||
1. Run `npm start` from within the `core` directory.
|
||||
2. A browser should open at `http://localhost:3333/`.
|
||||
3. From here, navigate to one of the component's tests to preview your changes.
|
||||
4. If a test showing your change doesn't exist, [add a new test or update an existing one](#modifying-tests).
|
||||
@@ -130,7 +133,7 @@ Before creating a pull request, please read our requirements that explains the m
|
||||
|
||||
##### Previewing in an external app
|
||||
|
||||
We can use `pnpm pack` to test Ionic Framework changes in an external app outside of this repository. Follow the below steps based on your framework.
|
||||
We can use `npm pack` to test Ionic Framework changes in an external app outside of this repository. Follow the below steps based on your framework.
|
||||
|
||||
###### JavaScript
|
||||
|
||||
@@ -138,112 +141,128 @@ Run the following commands to build the core directory and pack the changes:
|
||||
|
||||
```bash
|
||||
cd core
|
||||
pnpm install
|
||||
pnpm build
|
||||
pnpm pack --pack-destination ~
|
||||
npm i
|
||||
npm run build
|
||||
npm pack --pack-destination ~
|
||||
```
|
||||
|
||||
Then, in your Ionic Framework JavaScript app, run the following command to use the built package with the `.tgz` file that was created:
|
||||
|
||||
```bash
|
||||
pnpm install file:/~/ionic-core-7.0.1.tgz
|
||||
npm install file:/~/ionic-core-7.0.1.tgz
|
||||
```
|
||||
|
||||
|
||||
###### Angular
|
||||
|
||||
Run the following commands to build the core & angular directories and pack the changes:
|
||||
|
||||
```bash
|
||||
cd core
|
||||
pnpm install
|
||||
pnpm build
|
||||
pnpm pack --pack-destination ~
|
||||
npm i
|
||||
npm run build
|
||||
npm pack --pack-destination ~
|
||||
|
||||
cd ../packages/angular
|
||||
pnpm build
|
||||
npm i
|
||||
npm run sync
|
||||
npm run build
|
||||
cd dist/
|
||||
pnpm pack --pack-destination ~
|
||||
npm pack --pack-destination ~
|
||||
```
|
||||
|
||||
Then, in your Ionic Framework Angular app, run the following commands to use the built packages with the `.tgz` files that were created:
|
||||
|
||||
```bash
|
||||
rm -rf .angular/
|
||||
pnpm install file:/~/ionic-core-7.0.1.tgz
|
||||
pnpm install file:/~/ionic-angular-7.0.1.tgz
|
||||
npm install file:/~/ionic-core-7.0.1.tgz
|
||||
npm install file:/~/ionic-angular-7.0.1.tgz
|
||||
```
|
||||
|
||||
|
||||
###### React
|
||||
|
||||
Run the following commands to build the core & react directories and pack the changes:
|
||||
|
||||
```bash
|
||||
cd core
|
||||
pnpm install
|
||||
pnpm build
|
||||
pnpm pack --pack-destination ~
|
||||
npm i
|
||||
npm run build
|
||||
npm pack --pack-destination ~
|
||||
|
||||
cd ../packages/react
|
||||
pnpm build
|
||||
pnpm pack --pack-destination ~
|
||||
npm i
|
||||
npm run sync
|
||||
npm run build
|
||||
npm pack --pack-destination ~
|
||||
|
||||
cd ../react-router
|
||||
pnpm build
|
||||
pnpm pack --pack-destination ~
|
||||
npm i
|
||||
npm run sync
|
||||
npm run build
|
||||
npm pack --pack-destination ~
|
||||
```
|
||||
|
||||
Then, in your Ionic Framework React app, run the following commands to use the built packages with the `.tgz` files that were created:
|
||||
|
||||
```bash
|
||||
pnpm install file:/~/ionic-core-7.0.1.tgz
|
||||
pnpm install file:/~/ionic-react-7.0.1.tgz
|
||||
pnpm install file:/~/ionic-react-router-7.0.1.tgz
|
||||
npm install file:/~/ionic-core-7.0.1.tgz
|
||||
npm install file:/~/ionic-react-7.0.1.tgz
|
||||
npm install file:/~/ionic-react-router-7.0.1.tgz
|
||||
```
|
||||
|
||||
|
||||
##### Vue
|
||||
|
||||
Run the following commands to build the core & vue directories and pack the changes:
|
||||
|
||||
```bash
|
||||
cd core
|
||||
pnpm install
|
||||
pnpm build
|
||||
pnpm pack --pack-destination ~
|
||||
npm i
|
||||
npm run build
|
||||
npm pack --pack-destination ~
|
||||
|
||||
cd ../packages/vue
|
||||
pnpm build
|
||||
pnpm pack --pack-destination ~
|
||||
npm i
|
||||
npm run sync
|
||||
npm run build
|
||||
npm pack --pack-destination ~
|
||||
|
||||
cd ../vue-router
|
||||
pnpm build
|
||||
pnpm pack --pack-destination ~
|
||||
npm i
|
||||
npm run sync
|
||||
npm run build
|
||||
npm pack --pack-destination ~
|
||||
```
|
||||
|
||||
Then, in your Ionic Framework Vue app, run the following commands to use the built packages with the `.tgz` files that were created:
|
||||
|
||||
```bash
|
||||
pnpm install file:/~/ionic-core-7.0.1.tgz
|
||||
pnpm install file:/~/ionic-vue-7.0.1.tgz
|
||||
pnpm install file:/~/ionic-vue-router-7.0.1.tgz
|
||||
npm install file:/~/ionic-core-7.0.1.tgz
|
||||
npm install file:/~/ionic-vue-7.0.1.tgz
|
||||
npm install file:/~/ionic-vue-router-7.0.1.tgz
|
||||
```
|
||||
|
||||
|
||||
#### Lint Changes
|
||||
|
||||
1. Run `pnpm lint` to lint the TypeScript and Sass.
|
||||
2. If there are lint errors, run `pnpm lint.fix` to automatically fix any errors. Repeat step 1 to ensure the errors have been fixed, and manually fix them if not.
|
||||
3. To lint and fix only TypeScript errors, run `pnpm lint.ts` and `pnpm lint.ts.fix`, respectively.
|
||||
4. To lint and fix only Sass errors, run `pnpm lint.sass` and `pnpm lint.sass.fix`, respectively.
|
||||
1. Run `npm run lint` to lint the TypeScript and Sass.
|
||||
2. If there are lint errors, run `npm run lint.fix` to automatically fix any errors. Repeat step 1 to ensure the errors have been fixed, and manually fix them if not.
|
||||
3. To lint and fix only TypeScript errors, run `npm run lint.ts` and `npm run lint.ts.fix`, respectively.
|
||||
4. To lint and fix only Sass errors, run `npm run lint.sass` and `npm run lint.sass.fix`, respectively.
|
||||
|
||||
|
||||
#### Modifying Documentation
|
||||
|
||||
- Changes to manually written documentation should be made in the `ionic-docs` repo: https://github.com/ionic-team/ionic-docs/tree/main/docs
|
||||
- In your `ionic-docs` PR, please add a link back to the related `ionic-framework` PR.
|
||||
- Changes to auto generated documentation should be made in the `ionic-framework` repo. These can be done in the same PR as your fix or feature.
|
||||
- Run `pnpm build` and commit all updates to ensure your changes make it into the generated documentation.
|
||||
- Run `npm run build` and commit all updates to ensure your changes make it into the generated documentation.
|
||||
- `Usage`: update the component's usage examples in the component's `usage/` directory.
|
||||
- `Properties`, `Events`, or `Methods`: update the component's TypeScript file (`*.tsx`).
|
||||
- `CSS Custom Properties`: update the component's main Sass file (`*.scss`).
|
||||
|
||||
|
||||
#### Modifying Tests
|
||||
|
||||
1. Locate the test to modify inside the `test/` folder in the component's directory.
|
||||
@@ -258,47 +277,43 @@ See [Ionic's E2E testing guide](../core/src/utils/test/playwright/docs/README.md
|
||||
1. If the test exists in screenshot, there will be a file named `e2e.ts` in the directory of the test.
|
||||
2. A screenshot test can be added by including this file and adding one or more `test()` calls that include a call to `page.compareScreenshot()`. See [Stencil end-to-end testing](https://stenciljs.com/docs/end-to-end-testing) and existing tests in `core/` for examples.
|
||||
3. **Important:** each `test()` should have only one screenshot (`page.compareScreenshot()`) call **or** it should check the expect at the end of each test. If there is a mismatch it will fail the test which will prevent the rest of the test from running, i.e. if the first screenshot fails the remaining screenshot calls would not be called _unless_ they are in a separate test or all of the expects are called at the end.
|
||||
4. To run screenshot locally, use the following command: `pnpm test.e2e`.
|
||||
- To run screenshot for a specific test, pass the path to the test or a string to search for.
|
||||
- For example, running all `alert` tests: `pnpm test.e2e alert`.
|
||||
- Or, running the basic `alert` tests: `pnpm test.e2e src/components/alert/test/basic/e2e.ts`.
|
||||
4. To run screenshot locally, use the following command: `npm run test.screenshot`.
|
||||
- To run screenshot for a specific test, pass the path to the test or a string to search for.
|
||||
- For example, running all `alert` tests: `npm run test.screenshot alert`.
|
||||
- Or, running the basic `alert` tests: `npm run test.screenshot src/components/alert/test/basic/e2e.ts`.
|
||||
|
||||
|
||||
#### Building Changes
|
||||
|
||||
1. Once all changes have been made and the documentation has been updated, run `pnpm build` inside of the `core` directory. This will add your changes to any auto-generated files, if necessary.
|
||||
1. Once all changes have been made and the documentation has been updated, run `npm run build` inside of the `core` directory. This will add your changes to any auto-generated files, if necessary.
|
||||
2. Review the changes and, if everything looks correct, [commit](#commit-message-format) the changes.
|
||||
3. Make sure the build has finished before committing. If you made changes to the documentation, properties, methods, or anything else that requires an update to a generate file, this needs to be committed.
|
||||
4. After the changes have been pushed, publish the branch and [create a pull request](#creating-a-pull-request).
|
||||
|
||||
> [!WARNING]
|
||||
> If you are receiving errors about missing packages, you may need to run `pnpm install --force` to force the installation of the missing packages.
|
||||
|
||||
### Angular, React, and Vue
|
||||
|
||||
#### Modifying Files
|
||||
|
||||
1. Locate the files inside the relevant root directory:
|
||||
|
||||
- Angular: [`/packages/angular/src`](/packages/angular/src)
|
||||
- React: [`/packages/react/src`](/packages/react/src)
|
||||
- Vue: [`/packages/vue/src`](/packages/vue/src)
|
||||
|
||||
- Angular: [`/packages/angular/src`](/packages/angular/src)
|
||||
- React: [`/packages/react/src`](/packages/react/src)
|
||||
- Vue: [`/packages/vue/src`](/packages/vue/src)
|
||||
2. Make your changes to the files. If the change is overly complex or out of the ordinary, add comments so we can understand the changes.
|
||||
3. Run lint on the directory and make sure there are no errors.
|
||||
4. Build the project with `pnpm build`.
|
||||
- If you prefer to build all packages (core, angular, etc.) at once, run `pnpm -r build` from the root of the repository.
|
||||
4. Build the project.
|
||||
5. After the build is finished, commit the changes. Please follow the [commit message format](#commit-message-format) for every commit.
|
||||
6. [Submit a Pull Request](#submit-pull-request) of your changes.
|
||||
|
||||
|
||||
|
||||
#### Preview Changes
|
||||
|
||||
##### Previewing in this repository
|
||||
|
||||
Follow the steps in the test directory for each framework:
|
||||
|
||||
- Angular: [`/packages/angular/test`](/packages/angular/test/README.md)
|
||||
- React: [`/packages/react/test`](/packages/react/test/README.md)
|
||||
- Vue: [`/packages/vue/test`](/packages/vue/test/README.md)
|
||||
- Angular: [`/packages/angular/test`](/packages/angular/test/README.md)
|
||||
- React: [`/packages/react/test`](/packages/react/test/README.md)
|
||||
- Vue: [`/packages/vue/test`](/packages/vue/test/README.md)
|
||||
|
||||
##### Previewing in an external app
|
||||
|
||||
@@ -306,29 +321,25 @@ Follow the steps to [preview changes in core](#preview-changes).
|
||||
|
||||
#### Lint Changes
|
||||
|
||||
1. Run `pnpm lint` to lint the TypeScript in the relevant directory:
|
||||
|
||||
- Angular: [`/packages/angular/src`](/packages/angular/src)
|
||||
- React: [`/packages/react/src`](/packages/react/src)
|
||||
- Vue: [`/packages/vue/src`](/packages/vue/src)
|
||||
|
||||
2. If there are lint errors, run `pnpm lint.fix` to automatically fix any errors. Repeat step 1 to ensure the errors have been fixed, and manually fix them if not.
|
||||
1. Run `npm run lint` to lint the TypeScript in the relevant directory:
|
||||
- Angular: [`/packages/angular/src`](/packages/angular/src)
|
||||
- React: [`/packages/react/src`](/packages/react/src)
|
||||
- Vue: [`/packages/vue/src`](/packages/vue/src)
|
||||
2. If there are lint errors, run `npm run lint.fix` to automatically fix any errors. Repeat step 1 to ensure the errors have been fixed, and manually fix them if not.
|
||||
|
||||
#### Modifying Tests
|
||||
|
||||
1. Locate the e2e test to modify inside the relevant test app directory:
|
||||
|
||||
- Angular: [`/packages/angular/test/base/e2e/src`](/packages/angular/test/base/e2e/src)
|
||||
- React: [`/packages/react/test/base/tests/e2e/specs`](/packages/react/test/base/tests/e2e/specs)
|
||||
- Vue: [`/packages/vue/test/base/tests/e2e/specs`](/packages/vue/test/base/tests/e2e/specs)
|
||||
|
||||
- Angular: [`/packages/angular/test/base/e2e/src`](/packages/angular/test/base/e2e/src)
|
||||
- React: [`/packages/react/test/base/tests/e2e/specs`](/packages/react/test/base/tests/e2e/specs)
|
||||
- Vue: [`/packages/vue/test/base/tests/e2e/specs`](/packages/vue/test/base/tests/e2e/specs)
|
||||
2. If a test exists, modify the test by adding an example to reproduce the problem fixed or feature added.
|
||||
3. If a new test is needed, copy an existing test, rename it, and edit the content in the test file.
|
||||
4. Run `pnpm test` to run your tests.
|
||||
4. Run `npm run test` to run your tests.
|
||||
|
||||
#### Building Changes
|
||||
|
||||
1. Once all changes have been made, run `pnpm build` inside of the package's root directory. This will add your changes to any auto-generated files, if necessary.
|
||||
1. Once all changes have been made, run `npm run build` inside of the package's root directory. This will add your changes to any auto-generated files, if necessary.
|
||||
2. Review the changes and, if everything looks correct, [commit](#commit-message-format) the changes.
|
||||
3. Make sure the build has finished before committing. If you made changes to the documentation, properties, methods, or anything else that requires an update to a generate file, this needs to be committed.
|
||||
4. After the changes have been pushed, publish the branch and [create a pull request](#creating-a-pull-request).
|
||||
@@ -345,13 +356,14 @@ The team has an internal design process for new Ionic features, which must be co
|
||||
|
||||
To expedite the process, please ensure that all feature PRs have an associated issue created, with a clear use case for why the feature should be added to Ionic.
|
||||
|
||||
|
||||
## Commit Message Guidelines
|
||||
|
||||
We have very precise rules over how our git commit messages should be formatted. This leads to readable messages that are easy to follow when looking through the project history. We also use the git commit messages to generate our [changelog](https://github.com/ionic-team/ionic-framework/blob/main/CHANGELOG.md). Our format closely resembles Angular's [commit message guidelines](https://github.com/angular/angular/blob/main/CONTRIBUTING.md#commit).
|
||||
|
||||
### Commit Message Format
|
||||
|
||||
We follow the [Conventional Commits specification](https://www.conventionalcommits.org/). A commit message consists of a **header**, **body** and **footer**. The header has a **type**, **scope** and **subject**:
|
||||
We follow the [Conventional Commits specification](https://www.conventionalcommits.org/). A commit message consists of a **header**, **body** and **footer**. The header has a **type**, **scope** and **subject**:
|
||||
|
||||
```
|
||||
<type>(<scope>): <subject>
|
||||
@@ -373,14 +385,14 @@ If the prefix is `feat`, `fix` or `perf`, it will appear in the changelog. Howev
|
||||
|
||||
Must be one of the following:
|
||||
|
||||
- **feat**: A new feature
|
||||
- **fix**: A bug fix
|
||||
- **docs**: Documentation only changes
|
||||
- **style**: Changes that do not affect the meaning of the code (white-space, formatting, missing semi-colons, etc)
|
||||
- **refactor**: A code change that neither fixes a bug nor adds a feature
|
||||
- **perf**: A code change that improves performance
|
||||
- **test**: Adding missing tests
|
||||
- **chore**: Changes to the build process or auxiliary tools and libraries such as documentation generation
|
||||
* **feat**: A new feature
|
||||
* **fix**: A bug fix
|
||||
* **docs**: Documentation only changes
|
||||
* **style**: Changes that do not affect the meaning of the code (white-space, formatting, missing semi-colons, etc)
|
||||
* **refactor**: A code change that neither fixes a bug nor adds a feature
|
||||
* **perf**: A code change that improves performance
|
||||
* **test**: Adding missing tests
|
||||
* **chore**: Changes to the build process or auxiliary tools and libraries such as documentation generation
|
||||
|
||||
### Scope
|
||||
|
||||
@@ -390,12 +402,12 @@ The scope can be anything specifying place of the commit change. Usually it will
|
||||
|
||||
The subject contains succinct description of the change:
|
||||
|
||||
- use the imperative, present tense: "change" not "changed" nor "changes"
|
||||
- do not capitalize first letter
|
||||
- do not place a period `.` at the end
|
||||
- entire length of the commit message must not go over 50 characters
|
||||
- describe what the commit does, not what issue it relates to or fixes
|
||||
- **be brief, yet descriptive** - we should have a good understanding of what the commit does by reading the subject
|
||||
* use the imperative, present tense: "change" not "changed" nor "changes"
|
||||
* do not capitalize first letter
|
||||
* do not place a period `.` at the end
|
||||
* entire length of the commit message must not go over 50 characters
|
||||
* describe what the commit does, not what issue it relates to or fixes
|
||||
* **be brief, yet descriptive** - we should have a good understanding of what the commit does by reading the subject
|
||||
|
||||
### Body
|
||||
|
||||
@@ -457,6 +469,7 @@ revert: feat(skeleton-text): add animated property
|
||||
This reverts commit 667ecc1654a317a13331b17617d973392f415f02.
|
||||
```
|
||||
|
||||
|
||||
## License
|
||||
|
||||
By contributing your code to the ionic-team/ionic GitHub Repository, you agree to license your contribution under the MIT license.
|
||||
|
||||
23
.github/ISSUE_TEMPLATE/bug_report.yml
vendored
@@ -20,10 +20,12 @@ body:
|
||||
id: affected-versions
|
||||
attributes:
|
||||
label: Ionic Framework Version
|
||||
description: Which version(s) of Ionic Framework does this issue impact? [Ionic Framework 1.x to 6.x are no longer supported](https://ionicframework.com/docs/reference/support#framework-maintenance-and-support-status). For extended support, considering visiting [Ionic's Enterprise offering](https://ionic.io/enterprise).
|
||||
description: Which version(s) of Ionic Framework does this issue impact? For Ionic Framework 1.x issues, please use https://github.com/ionic-team/ionic-v1. For Ionic Framework 2.x and 3.x issues, please use https://github.com/ionic-team/ionic-v3.
|
||||
options:
|
||||
- v4.x
|
||||
- v5.x
|
||||
- v6.x
|
||||
- v7.x
|
||||
- v8.x (Beta)
|
||||
- Nightly
|
||||
multiple: true
|
||||
validations:
|
||||
@@ -49,11 +51,11 @@ body:
|
||||
id: steps-to-reproduce
|
||||
attributes:
|
||||
label: Steps to Reproduce
|
||||
description: Explain the steps required to reproduce this issue.
|
||||
description: Please explain the steps required to duplicate this issue.
|
||||
placeholder: |
|
||||
1. Go to '...'
|
||||
2. Click on '...'
|
||||
3. Observe: '...'
|
||||
1.
|
||||
2.
|
||||
3.
|
||||
validations:
|
||||
required: true
|
||||
|
||||
@@ -61,15 +63,8 @@ body:
|
||||
id: reproduction-url
|
||||
attributes:
|
||||
label: Code Reproduction URL
|
||||
description: |
|
||||
Reproduce this issue in a blank [Ionic Framework starter application](https://ionicframework.com/start#basics) or a Stackblitz example.
|
||||
|
||||
You can use the Stackblitz button available on any of the [component playgrounds](https://ionicframework.com/docs/components) to open an editable example. Remember to save your changes to obtain a link to copy.
|
||||
|
||||
Reproductions cases must be minimal and focused around the specific problem you are experiencing. This is the best way to ensure this issue is triaged quickly. Issues without a code reproduction may be closed if the Ionic Team cannot reproduce the issue you are reporting.
|
||||
description: Please reproduce this issue in a blank Ionic Framework starter application and provide a link to the repo. Try out our [Getting Started Wizard](https://ionicframework.com/start#basics) to quickly spin up an Ionic Framework starter app. This is the best way to ensure this issue is triaged quickly. Issues without a code reproduction may be closed if the Ionic Team cannot reproduce the issue you are reporting.
|
||||
placeholder: https://github.com/...
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
id: ionic-info
|
||||
|
||||
20
.github/dependabot.yml
vendored
Normal file
@@ -0,0 +1,20 @@
|
||||
version: 2
|
||||
updates:
|
||||
- package-ecosystem: "npm"
|
||||
directory: "/core"
|
||||
schedule:
|
||||
interval: "daily"
|
||||
versioning-strategy: increase
|
||||
allow:
|
||||
- dependency-name: "@playwright/test"
|
||||
- dependency-name: "@axe-core/playwright"
|
||||
- dependency-name: "@stencil/angular-output-target"
|
||||
- dependency-name: "@stencil/core"
|
||||
- dependency-name: "@stencil/react-output-target"
|
||||
- dependency-name: "@stencil/sass"
|
||||
- dependency-name: "@stencil/vue-output-target"
|
||||
- dependency-name: "ionicons"
|
||||
- dependency-name: "@capacitor/core"
|
||||
- dependency-name: "@capacitor/keyboard"
|
||||
- dependency-name: "@capacitor/haptics"
|
||||
- dependency-name: "@capacitor/status-bar"
|
||||
@@ -3,23 +3,16 @@ description: 'Build Ionic Angular Server'
|
||||
runs:
|
||||
using: 'composite'
|
||||
steps:
|
||||
- uses: actions/setup-node@v4
|
||||
- uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: 18.x
|
||||
- uses: pnpm/action-setup@v2
|
||||
with:
|
||||
version: 8
|
||||
- uses: ./.github/workflows/actions/download-archive
|
||||
with:
|
||||
name: ionic-core
|
||||
path: ./core
|
||||
filename: CoreBuild.zip
|
||||
|
||||
- name: Install Angular Server Dependencies
|
||||
run: pnpm install
|
||||
run: npm ci
|
||||
shell: bash
|
||||
working-directory: ./packages/angular-server
|
||||
- name: Build
|
||||
run: pnpm run build.prod
|
||||
run: npm run build.prod
|
||||
shell: bash
|
||||
working-directory: ./packages/angular-server
|
||||
- uses: ./.github/workflows/actions/upload-archive
|
||||
|
||||
@@ -3,27 +3,28 @@ description: 'Build Ionic Angular'
|
||||
runs:
|
||||
using: 'composite'
|
||||
steps:
|
||||
- uses: actions/setup-node@v4
|
||||
- uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: 18.x
|
||||
- uses: pnpm/action-setup@v2
|
||||
with:
|
||||
version: 8
|
||||
- uses: ./.github/workflows/actions/download-archive
|
||||
with:
|
||||
name: ionic-core
|
||||
path: ./core
|
||||
filename: CoreBuild.zip
|
||||
- name: Install Angular Dependencies
|
||||
run: pnpm install
|
||||
run: npm ci
|
||||
shell: bash
|
||||
working-directory: ./packages/angular
|
||||
- name: Sync
|
||||
run: npm run sync
|
||||
shell: bash
|
||||
working-directory: ./packages/angular
|
||||
- name: Lint
|
||||
run: pnpm run lint
|
||||
run: npm run lint
|
||||
shell: bash
|
||||
working-directory: ./packages/angular
|
||||
- name: Build
|
||||
run: pnpm run build
|
||||
run: npm run build
|
||||
shell: bash
|
||||
working-directory: ./packages/angular
|
||||
- name: Check Diff
|
||||
|
||||
@@ -8,23 +8,21 @@ inputs:
|
||||
runs:
|
||||
using: 'composite'
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-node@v4
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: 18.x
|
||||
- uses: pnpm/action-setup@v2
|
||||
with:
|
||||
version: 8
|
||||
|
||||
- name: Install Dependencies
|
||||
run: pnpm install
|
||||
run: npm ci
|
||||
working-directory: ./core
|
||||
shell: bash
|
||||
- name: Install Stencil ${{ inputs.stencil-version }}
|
||||
working-directory: ./core
|
||||
run: pnpm i @stencil/core@${{ inputs.stencil-version }}
|
||||
run: npm i @stencil/core@${{ inputs.stencil-version }}
|
||||
shell: bash
|
||||
- name: Build Core
|
||||
run: pnpm npm run build -- --ci --debug --verbose
|
||||
run: npm run build -- --ci
|
||||
working-directory: ./core
|
||||
shell: bash
|
||||
- uses: ./.github/workflows/actions/upload-archive
|
||||
|
||||
13
.github/workflows/actions/build-core/action.yml
vendored
@@ -8,26 +8,23 @@ inputs:
|
||||
runs:
|
||||
using: 'composite'
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-node@v4
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: 18.x
|
||||
- uses: pnpm/action-setup@v2
|
||||
with:
|
||||
version: 8
|
||||
- name: Install Dependencies
|
||||
run: pnpm install
|
||||
run: npm install
|
||||
working-directory: ./core
|
||||
shell: bash
|
||||
# If an Ionicons version was specified install that.
|
||||
# Otherwise just use the version defined in the package.json.
|
||||
- name: Install Ionicons Version
|
||||
if: inputs.ionicons-version != ''
|
||||
run: pnpm install ionicons@${{ inputs.ionicons-version }}
|
||||
run: npm install ionicons@${{ inputs.ionicons-version }}
|
||||
working-directory: ./core
|
||||
shell: bash
|
||||
- name: Build Core
|
||||
run: pnpm run build --ci
|
||||
run: npm run build -- --ci
|
||||
working-directory: ./core
|
||||
shell: bash
|
||||
- uses: ./.github/workflows/actions/upload-archive
|
||||
|
||||
@@ -3,12 +3,9 @@ description: 'Build Ionic React Router'
|
||||
runs:
|
||||
using: 'composite'
|
||||
steps:
|
||||
- uses: actions/setup-node@v4
|
||||
- uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: 18.x
|
||||
- uses: pnpm/action-setup@v2
|
||||
with:
|
||||
version: 8
|
||||
- uses: ./.github/workflows/actions/download-archive
|
||||
with:
|
||||
name: ionic-core
|
||||
@@ -20,15 +17,19 @@ runs:
|
||||
path: ./packages/react
|
||||
filename: ReactBuild.zip
|
||||
- name: Install Dependencies
|
||||
run: pnpm install
|
||||
run: npm ci
|
||||
shell: bash
|
||||
working-directory: ./packages/react-router
|
||||
- name: Sync
|
||||
run: npm run sync
|
||||
shell: bash
|
||||
working-directory: ./packages/react-router
|
||||
- name: Lint
|
||||
run: pnpm run lint
|
||||
run: npm run lint
|
||||
shell: bash
|
||||
working-directory: ./packages/react-router
|
||||
- name: Build
|
||||
run: pnpm run build
|
||||
run: npm run build
|
||||
shell: bash
|
||||
working-directory: ./packages/react-router
|
||||
- uses: ./.github/workflows/actions/upload-archive
|
||||
|
||||
17
.github/workflows/actions/build-react/action.yml
vendored
@@ -3,31 +3,32 @@ description: 'Build Ionic React'
|
||||
runs:
|
||||
using: 'composite'
|
||||
steps:
|
||||
- uses: actions/setup-node@v4
|
||||
- uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: 18.x
|
||||
- uses: pnpm/action-setup@v2
|
||||
with:
|
||||
version: 8
|
||||
- uses: ./.github/workflows/actions/download-archive
|
||||
with:
|
||||
name: ionic-core
|
||||
path: ./core
|
||||
filename: CoreBuild.zip
|
||||
- name: Install React Dependencies
|
||||
run: pnpm install
|
||||
run: npm ci
|
||||
shell: bash
|
||||
working-directory: ./packages/react
|
||||
- name: Sync
|
||||
run: npm run sync
|
||||
shell: bash
|
||||
working-directory: ./packages/react
|
||||
- name: Lint
|
||||
run: pnpm run lint
|
||||
run: npm run lint
|
||||
shell: bash
|
||||
working-directory: ./packages/react
|
||||
- name: Build
|
||||
run: pnpm run build
|
||||
run: npm run build
|
||||
shell: bash
|
||||
working-directory: ./packages/react
|
||||
- name: Test Spec
|
||||
run: pnpm run test.spec
|
||||
run: npm run test.spec
|
||||
shell: bash
|
||||
working-directory: ./packages/react
|
||||
- name: Check Diff
|
||||
|
||||
@@ -3,12 +3,9 @@ description: 'Builds Ionic Vue Router'
|
||||
runs:
|
||||
using: 'composite'
|
||||
steps:
|
||||
- uses: actions/setup-node@v4
|
||||
- uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: 18.x
|
||||
- uses: pnpm/action-setup@v2
|
||||
with:
|
||||
version: 8
|
||||
- uses: ./.github/workflows/actions/download-archive
|
||||
with:
|
||||
name: ionic-core
|
||||
@@ -20,19 +17,23 @@ runs:
|
||||
path: ./packages/vue
|
||||
filename: VueBuild.zip
|
||||
- name: Install Vue Router Dependencies
|
||||
run: pnpm install
|
||||
run: npm ci
|
||||
shell: bash
|
||||
working-directory: ./packages/vue-router
|
||||
- name: Sync
|
||||
run: npm run sync
|
||||
shell: bash
|
||||
working-directory: ./packages/vue-router
|
||||
- name: Lint
|
||||
run: pnpm run lint
|
||||
run: npm run lint
|
||||
shell: bash
|
||||
working-directory: ./packages/vue-router
|
||||
- name: Build
|
||||
run: pnpm run build
|
||||
run: npm run build
|
||||
shell: bash
|
||||
working-directory: ./packages/vue-router
|
||||
- name: Test Spec
|
||||
run: pnpm run test.spec
|
||||
run: npm run test.spec
|
||||
shell: bash
|
||||
working-directory: ./packages/vue-router
|
||||
- uses: ./.github/workflows/actions/upload-archive
|
||||
|
||||
15
.github/workflows/actions/build-vue/action.yml
vendored
@@ -3,27 +3,28 @@ description: 'Build Ionic Vue'
|
||||
runs:
|
||||
using: 'composite'
|
||||
steps:
|
||||
- uses: actions/setup-node@v4
|
||||
- uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: 18.x
|
||||
- uses: pnpm/action-setup@v2
|
||||
with:
|
||||
version: 8
|
||||
- uses: ./.github/workflows/actions/download-archive
|
||||
with:
|
||||
name: ionic-core
|
||||
path: ./core
|
||||
filename: CoreBuild.zip
|
||||
- name: Install Vue Dependencies
|
||||
run: pnpm install
|
||||
run: npm ci
|
||||
shell: bash
|
||||
working-directory: ./packages/vue
|
||||
- name: Sync
|
||||
run: npm run sync
|
||||
shell: bash
|
||||
working-directory: ./packages/vue
|
||||
- name: Lint
|
||||
run: pnpm run lint
|
||||
run: npm run lint
|
||||
shell: bash
|
||||
working-directory: ./packages/vue
|
||||
- name: Build
|
||||
run: pnpm run build
|
||||
run: npm run build
|
||||
shell: bash
|
||||
working-directory: ./packages/vue
|
||||
- name: Check Diff
|
||||
|
||||
@@ -10,7 +10,7 @@ inputs:
|
||||
runs:
|
||||
using: 'composite'
|
||||
steps:
|
||||
- uses: actions/download-artifact@v4
|
||||
- uses: actions/download-artifact@v3
|
||||
with:
|
||||
name: ${{ inputs.name }}
|
||||
path: ${{ inputs.path }}
|
||||
|
||||
20
.github/workflows/actions/publish-npm/action.yml
vendored
@@ -19,12 +19,9 @@ inputs:
|
||||
runs:
|
||||
using: 'composite'
|
||||
steps:
|
||||
- uses: actions/setup-node@v4
|
||||
- uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: 18.x
|
||||
- uses: pnpm/action-setup@v2
|
||||
with:
|
||||
version: 8
|
||||
# Provenance requires npm 9.5.0+
|
||||
- name: Install latest npm
|
||||
run: npm install -g npm@latest
|
||||
@@ -32,26 +29,27 @@ runs:
|
||||
# This ensures the local version of Lerna is installed
|
||||
# and that we do not use the global Lerna version
|
||||
- name: Install root dependencies
|
||||
run: pnpm install
|
||||
run: npm ci
|
||||
shell: bash
|
||||
- name: Install project dependencies
|
||||
run: pnpm install
|
||||
- name: Install Dependencies
|
||||
run: npx lerna bootstrap --include-dependencies --scope ${{ inputs.scope }} --ignore-scripts -- --legacy-peer-deps
|
||||
shell: bash
|
||||
working-directory: ${{ inputs.working-directory }}
|
||||
- name: Update Version
|
||||
run: pnpm exec lerna version ${{ inputs.version }} --yes --exact --no-changelog --no-push --no-git-tag-version --preid=${{ inputs.preid }}
|
||||
run: npx lerna version ${{ inputs.version }} --yes --exact --no-changelog --no-push --no-git-tag-version --preid=${{ inputs.preid }}
|
||||
shell: bash
|
||||
working-directory: ${{ inputs.working-directory }}
|
||||
- name: Run Build
|
||||
run: pnpm run build
|
||||
run: npm run build
|
||||
shell: bash
|
||||
working-directory: ${{ inputs.working-directory }}
|
||||
- name: Prepare NPM Token
|
||||
run: pnpm config set //registry.npmjs.org/:_authToken ${NPM_TOKEN}
|
||||
run: echo //registry.npmjs.org/:_authToken=${NPM_TOKEN} > .npmrc
|
||||
working-directory: ${{ inputs.working-directory }}
|
||||
shell: bash
|
||||
env:
|
||||
NPM_TOKEN: ${{ inputs.token }}
|
||||
- name: Publish to NPM
|
||||
run: pnpm publish ${{ inputs.folder }} --tag ${{ inputs.tag }} --provenance --no-git-checks
|
||||
run: npm publish ${{ inputs.folder }} --tag ${{ inputs.tag }} --provenance
|
||||
shell: bash
|
||||
working-directory: ${{ inputs.working-directory }}
|
||||
|
||||
@@ -6,12 +6,9 @@ inputs:
|
||||
runs:
|
||||
using: 'composite'
|
||||
steps:
|
||||
- uses: actions/setup-node@v4
|
||||
- uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: 18
|
||||
- uses: pnpm/action-setup@v2
|
||||
with:
|
||||
version: 8
|
||||
- uses: ./.github/workflows/actions/download-archive
|
||||
with:
|
||||
name: ionic-core
|
||||
@@ -32,10 +29,14 @@ runs:
|
||||
shell: bash
|
||||
working-directory: ./packages/angular/test
|
||||
- name: Install Dependencies
|
||||
run: pnpm install
|
||||
run: npm install
|
||||
shell: bash
|
||||
working-directory: ./packages/angular/test/build/${{ inputs.app }}
|
||||
- name: Sync Built Changes
|
||||
run: npm run sync
|
||||
shell: bash
|
||||
working-directory: ./packages/angular/test/build/${{ inputs.app }}
|
||||
- name: Run Tests
|
||||
run: pnpm run test
|
||||
run: npm run test
|
||||
shell: bash
|
||||
working-directory: ./packages/angular/test/build/${{ inputs.app }}
|
||||
|
||||
@@ -3,7 +3,7 @@ description: 'Test Core Clean Build'
|
||||
runs:
|
||||
using: 'composite'
|
||||
steps:
|
||||
- uses: actions/setup-node@v4
|
||||
- uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: 18.x
|
||||
|
||||
|
||||
@@ -3,18 +3,15 @@ description: 'Test Core Lint'
|
||||
runs:
|
||||
using: 'composite'
|
||||
steps:
|
||||
- uses: actions/setup-node@v4
|
||||
- uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: 18.x
|
||||
- uses: pnpm/action-setup@v2
|
||||
with:
|
||||
version: 8
|
||||
- name: Install Dependencies
|
||||
run: pnpm install
|
||||
run: npm ci
|
||||
working-directory: ./core
|
||||
shell: bash
|
||||
- name: Lint
|
||||
run: pnpm run lint
|
||||
run: npm run lint
|
||||
shell: bash
|
||||
working-directory: ./core
|
||||
# Lint changes should be pushed
|
||||
|
||||
@@ -13,24 +13,41 @@ inputs:
|
||||
runs:
|
||||
using: 'composite'
|
||||
steps:
|
||||
- uses: actions/setup-node@v4
|
||||
- uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: 18.x
|
||||
- uses: pnpm/action-setup@v2
|
||||
with:
|
||||
version: 8
|
||||
- uses: ./.github/workflows/actions/download-archive
|
||||
with:
|
||||
name: ionic-core
|
||||
path: ./core
|
||||
filename: CoreBuild.zip
|
||||
- name: Install Dependencies
|
||||
run: pnpm install
|
||||
- name: Install Playwright Dependencies
|
||||
run: npm install && npx playwright install && npx playwright install-deps
|
||||
shell: bash
|
||||
working-directory: ./core
|
||||
- id: clean-component-name
|
||||
name: Clean Component Name
|
||||
# Remove `ion-` prefix from the `component` variable if it exists.
|
||||
run: |
|
||||
echo "component=$(echo ${{ inputs.component }} | sed 's/ion-//g')" >> $GITHUB_OUTPUT
|
||||
shell: bash
|
||||
- id: set-test-file
|
||||
name: Set Test File
|
||||
# Screenshots can be updated for all components or specified component(s).
|
||||
# If the `component` variable is set, then the test has the option to
|
||||
# - run all the file paths that are in a component folder.
|
||||
# -- For example: if the `component` value is "item", then the test will run all the file paths that are in the "src/components/item" folder.
|
||||
# -- For example: if the `component` value is "item chip", then the test will run all the file paths that are in the "src/components/item" and "src/components/chip" folders.
|
||||
run: |
|
||||
if [ -n "${{ steps.clean-component-name.outputs.component }}" ]; then
|
||||
echo "testFile=\$(echo '${{ steps.clean-component-name.outputs.component }}' | awk '{for(i=1;i<=NF;i++) \$i=\"src/components/\"\$i}1')" >> $GITHUB_OUTPUT
|
||||
else
|
||||
echo "testFile=$(echo '')" >> $GITHUB_OUTPUT
|
||||
fi
|
||||
shell: bash
|
||||
- name: Test
|
||||
if: inputs.update != 'true'
|
||||
run: pnpm run test.e2e.docker.ci ${{ inputs.component }} -- --shard=${{ inputs.shard }}/${{ inputs.totalShards }}
|
||||
run: npm run test.e2e ${{ steps.set-test-file.outputs.testFile }} -- --shard=${{ inputs.shard }}/${{ inputs.totalShards }}
|
||||
shell: bash
|
||||
working-directory: ./core
|
||||
- name: Test and Update
|
||||
@@ -52,7 +69,7 @@ runs:
|
||||
# which is why we not using the upload-archive
|
||||
# composite step here.
|
||||
run: |
|
||||
pnpm run test.e2e.docker.ci ${{ inputs.component }} -- --shard=${{ inputs.shard }}/${{ inputs.totalShards }} --update-snapshots
|
||||
npm run test.e2e ${{ steps.set-test-file.outputs.testFile }} -- --shard=${{ inputs.shard }}/${{ inputs.totalShards }} --update-snapshots
|
||||
git add src/\*.png --force
|
||||
mkdir updated-screenshots
|
||||
cd ../ && rsync -R --progress $(git diff --name-only --cached) core/updated-screenshots
|
||||
@@ -65,7 +82,7 @@ runs:
|
||||
working-directory: ./core
|
||||
- name: Archive Updated Screenshots
|
||||
if: inputs.update == 'true' && steps.test-and-update.outputs.hasUpdatedScreenshots == 'true'
|
||||
uses: actions/upload-artifact@v4
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: updated-screenshots-${{ inputs.shard }}-${{ inputs.totalShards }}
|
||||
path: UpdatedScreenshots-${{ inputs.shard }}-${{ inputs.totalShards }}.zip
|
||||
|
||||
@@ -6,18 +6,15 @@ inputs:
|
||||
runs:
|
||||
using: 'composite'
|
||||
steps:
|
||||
- uses: actions/setup-node@v4
|
||||
- uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: 18.x
|
||||
- uses: pnpm/action-setup@v2
|
||||
with:
|
||||
version: 8
|
||||
- name: Install Dependencies
|
||||
run: pnpm install
|
||||
run: npm ci
|
||||
working-directory: ./core
|
||||
shell: bash
|
||||
- name: Install Stencil ${{ inputs.stencil-version }}
|
||||
run: pnpm install @stencil/core@${{ inputs.stencil-version }}
|
||||
run: npm install @stencil/core@${{ inputs.stencil-version }}
|
||||
shell: bash
|
||||
working-directory: ./core
|
||||
if: ${{ inputs.stencil-version != '' }}
|
||||
@@ -27,6 +24,6 @@ runs:
|
||||
path: ./core
|
||||
filename: CoreBuild.zip
|
||||
- name: Test
|
||||
run: pnpm run test.spec --ci
|
||||
run: npm run test.spec -- --ci
|
||||
shell: bash
|
||||
working-directory: ./core
|
||||
|
||||
@@ -6,12 +6,9 @@ inputs:
|
||||
runs:
|
||||
using: 'composite'
|
||||
steps:
|
||||
- uses: actions/setup-node@v4
|
||||
- uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: 18.x
|
||||
- uses: pnpm/action-setup@v2
|
||||
with:
|
||||
version: 8
|
||||
- uses: ./.github/workflows/actions/download-archive
|
||||
with:
|
||||
name: ionic-core
|
||||
@@ -32,15 +29,19 @@ runs:
|
||||
shell: bash
|
||||
working-directory: ./packages/react/test
|
||||
- name: Install Dependencies
|
||||
run: pnpm install
|
||||
run: npm install
|
||||
shell: bash
|
||||
working-directory: ./packages/react/test/build/${{ inputs.app }}
|
||||
- name: Sync Built Changes
|
||||
run: npm run sync
|
||||
shell: bash
|
||||
working-directory: ./packages/react/test/build/${{ inputs.app }}
|
||||
- name: Build
|
||||
run: pnpm run build
|
||||
run: npm run build
|
||||
shell: bash
|
||||
working-directory: ./packages/react/test/build/${{ inputs.app }}
|
||||
- name: Run Tests
|
||||
run: pnpm run e2e
|
||||
run: npm run e2e
|
||||
shell: bash
|
||||
working-directory: ./packages/react/test/build/${{ inputs.app }}
|
||||
|
||||
|
||||
@@ -6,12 +6,9 @@ inputs:
|
||||
runs:
|
||||
using: 'composite'
|
||||
steps:
|
||||
- uses: actions/setup-node@v4
|
||||
- uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: 18.x
|
||||
- uses: pnpm/action-setup@v2
|
||||
with:
|
||||
version: 8
|
||||
- uses: ./.github/workflows/actions/download-archive
|
||||
with:
|
||||
name: ionic-core
|
||||
@@ -32,14 +29,18 @@ runs:
|
||||
shell: bash
|
||||
working-directory: ./packages/react-router/test
|
||||
- name: Install Dependencies
|
||||
run: pnpm install
|
||||
run: npm install
|
||||
shell: bash
|
||||
working-directory: ./packages/react-router/test/build/${{ inputs.app }}
|
||||
- name: Sync Built Changes
|
||||
run: npm run sync
|
||||
shell: bash
|
||||
working-directory: ./packages/react-router/test/build/${{ inputs.app }}
|
||||
- name: Build
|
||||
run: pnpm run build
|
||||
run: npm run build
|
||||
shell: bash
|
||||
working-directory: ./packages/react-router/test/build/${{ inputs.app }}
|
||||
- name: Run Tests
|
||||
run: pnpm run e2e
|
||||
run: npm run e2e
|
||||
shell: bash
|
||||
working-directory: ./packages/react-router/test/build/${{ inputs.app }}
|
||||
|
||||
@@ -6,12 +6,9 @@ inputs:
|
||||
runs:
|
||||
using: 'composite'
|
||||
steps:
|
||||
- uses: actions/setup-node@v4
|
||||
- uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: 18.x
|
||||
- uses: pnpm/action-setup@v2
|
||||
with:
|
||||
version: 8
|
||||
- uses: ./.github/workflows/actions/download-archive
|
||||
with:
|
||||
name: ionic-core
|
||||
@@ -32,14 +29,18 @@ runs:
|
||||
shell: bash
|
||||
working-directory: ./packages/vue/test
|
||||
- name: Install Dependencies
|
||||
run: pnpm install
|
||||
run: npm install
|
||||
shell: bash
|
||||
working-directory: ./packages/vue/test/build/${{ inputs.app }}
|
||||
- name: Sync
|
||||
run: npm run sync
|
||||
shell: bash
|
||||
working-directory: ./packages/vue/test/build/${{ inputs.app }}
|
||||
- name: Run Spec Tests
|
||||
run: pnpm run test:unit
|
||||
run: npm run test:unit
|
||||
shell: bash
|
||||
working-directory: ./packages/vue/test/build/${{ inputs.app }}
|
||||
- name: Run E2E Tests
|
||||
run: pnpm run test:e2e
|
||||
run: npm run test:e2e
|
||||
shell: bash
|
||||
working-directory: ./packages/vue/test/build/${{ inputs.app }}
|
||||
|
||||
@@ -7,10 +7,10 @@ on:
|
||||
runs:
|
||||
using: 'composite'
|
||||
steps:
|
||||
- uses: actions/setup-node@v4
|
||||
- uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: 18.x
|
||||
- uses: actions/download-artifact@v4
|
||||
- uses: actions/download-artifact@v3
|
||||
with:
|
||||
path: ./artifacts
|
||||
- name: Extract Archives
|
||||
@@ -25,9 +25,12 @@ runs:
|
||||
# Configure user as Ionitron
|
||||
# and push only the changed .png snapshots
|
||||
# to the remote branch.
|
||||
# Non-Linux screenshots are in .gitignore
|
||||
# Screenshots are in .gitignore
|
||||
# to prevent local screenshots from getting
|
||||
# pushed to Git.
|
||||
# pushed to Git. As a result, we need --force
|
||||
# here so that CI generated screenshots can
|
||||
# get added to git. Screenshot ground truths
|
||||
# should only be added via this CI process.
|
||||
run: |
|
||||
git config user.name ionitron
|
||||
git config user.email hi@ionicframework.com
|
||||
@@ -35,7 +38,7 @@ runs:
|
||||
# This adds an empty entry for new
|
||||
# screenshot files so we can track them with
|
||||
# git diff
|
||||
git add src/\*.png -N
|
||||
git add src/\*.png --force -N
|
||||
|
||||
if git diff --exit-code; then
|
||||
echo -e "\033[1;31m⚠️ Error: No new screenshots generated ⚠️\033[0m"
|
||||
@@ -45,7 +48,7 @@ runs:
|
||||
else
|
||||
# This actually adds the contents
|
||||
# of the screenshots (including new ones)
|
||||
git add src/\*.png
|
||||
git add src/\*.png --force
|
||||
git commit -m "chore(): add updated snapshots"
|
||||
git push
|
||||
fi
|
||||
|
||||
@@ -13,7 +13,7 @@ runs:
|
||||
- name: Create Archive
|
||||
run: zip -q -r ${{ inputs.output }} ${{ inputs.paths }}
|
||||
shell: bash
|
||||
- uses: actions/upload-artifact@v4
|
||||
- uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: ${{ inputs.name }}
|
||||
path: ${{ inputs.output }}
|
||||
|
||||
30
.github/workflows/build.yml
vendored
@@ -22,7 +22,7 @@ jobs:
|
||||
build-core:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@v3
|
||||
- uses: ./.github/workflows/actions/build-core
|
||||
with:
|
||||
ionicons-version: ${{ inputs.ionicons_npm_release_tag }}
|
||||
@@ -31,21 +31,21 @@ jobs:
|
||||
needs: [build-core]
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@v3
|
||||
- uses: ./.github/workflows/actions/test-core-clean-build
|
||||
|
||||
test-core-lint:
|
||||
needs: [build-core]
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@v3
|
||||
- uses: ./.github/workflows/actions/test-core-lint
|
||||
|
||||
test-core-spec:
|
||||
needs: [build-core]
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@v3
|
||||
- uses: ./.github/workflows/actions/test-core-spec
|
||||
|
||||
test-core-screenshot:
|
||||
@@ -62,7 +62,7 @@ jobs:
|
||||
needs: [build-core]
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@v3
|
||||
- uses: ./.github/workflows/actions/test-core-screenshot
|
||||
with:
|
||||
shard: ${{ matrix.shard }}
|
||||
@@ -90,14 +90,14 @@ jobs:
|
||||
needs: [build-core]
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@v3
|
||||
- uses: ./.github/workflows/actions/build-vue
|
||||
|
||||
build-vue-router:
|
||||
needs: [build-vue]
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@v3
|
||||
- uses: ./.github/workflows/actions/build-vue-router
|
||||
|
||||
test-vue-e2e:
|
||||
@@ -108,7 +108,7 @@ jobs:
|
||||
needs: [build-vue, build-vue-router]
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@v3
|
||||
- uses: ./.github/workflows/actions/test-vue-e2e
|
||||
with:
|
||||
app: ${{ matrix.apps }}
|
||||
@@ -126,14 +126,14 @@ jobs:
|
||||
needs: [build-core]
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@v3
|
||||
- uses: ./.github/workflows/actions/build-angular
|
||||
|
||||
build-angular-server:
|
||||
needs: [build-core]
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@v3
|
||||
- uses: ./.github/workflows/actions/build-angular-server
|
||||
|
||||
test-angular-e2e:
|
||||
@@ -144,7 +144,7 @@ jobs:
|
||||
needs: [build-angular, build-angular-server]
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@v3
|
||||
- uses: ./.github/workflows/actions/test-angular-e2e
|
||||
with:
|
||||
app: ${{ matrix.apps }}
|
||||
@@ -162,14 +162,14 @@ jobs:
|
||||
needs: [build-core]
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@v3
|
||||
- uses: ./.github/workflows/actions/build-react
|
||||
|
||||
build-react-router:
|
||||
needs: [build-react]
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@v3
|
||||
- uses: ./.github/workflows/actions/build-react-router
|
||||
|
||||
test-react-router-e2e:
|
||||
@@ -180,7 +180,7 @@ jobs:
|
||||
needs: [build-react, build-react-router]
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@v3
|
||||
- uses: ./.github/workflows/actions/test-react-router-e2e
|
||||
with:
|
||||
app: ${{ matrix.apps }}
|
||||
@@ -202,7 +202,7 @@ jobs:
|
||||
needs: [build-react, build-react-router]
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@v3
|
||||
- uses: ./.github/workflows/actions/test-react-e2e
|
||||
with:
|
||||
app: ${{ matrix.apps }}
|
||||
|
||||
6
.github/workflows/codeql-analysis.yml
vendored
@@ -14,8 +14,8 @@ jobs:
|
||||
permissions:
|
||||
security-events: write
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: github/codeql-action/init@v3
|
||||
- uses: actions/checkout@v3
|
||||
- uses: github/codeql-action/init@v2
|
||||
with:
|
||||
languages: javascript
|
||||
- uses: github/codeql-action/analyze@v3
|
||||
- uses: github/codeql-action/analyze@v2
|
||||
|
||||
7
.github/workflows/dev-build.yml
vendored
@@ -9,15 +9,12 @@ jobs:
|
||||
outputs:
|
||||
dev-hash: ${{ steps.create-dev-hash.outputs.DEV_HASH }}
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: pnpm/action-setup@v2
|
||||
with:
|
||||
version: 8
|
||||
- uses: actions/checkout@v3
|
||||
# A 1 is required before the timestamp
|
||||
# as lerna will fail when there is a leading 0
|
||||
# See https://github.com/lerna/lerna/issues/2840
|
||||
- name: Install Dependencies
|
||||
run: pnpm install
|
||||
run: npm ci
|
||||
shell: bash
|
||||
- id: create-dev-hash
|
||||
name: Create Dev Hash
|
||||
|
||||
7
.github/workflows/nightly.yml
vendored
@@ -12,15 +12,12 @@ jobs:
|
||||
outputs:
|
||||
nightly-hash: ${{ steps.create-nightly-hash.outputs.NIGHTLY_HASH }}
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: pnpm/action-setup@v2
|
||||
with:
|
||||
version: 8
|
||||
- uses: actions/checkout@v3
|
||||
# A 1 is required before the timestamp
|
||||
# as lerna will fail when there is a leading 0
|
||||
# See https://github.com/lerna/lerna/issues/2840
|
||||
- name: Install Dependencies
|
||||
run: pnpm install
|
||||
run: npm ci
|
||||
shell: bash
|
||||
- id: create-nightly-hash
|
||||
name: Create Nightly Hash
|
||||
|
||||
17
.github/workflows/release-ionic.yml
vendored
@@ -22,7 +22,7 @@ jobs:
|
||||
release-core:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@v3
|
||||
- uses: ./.github/workflows/actions/publish-npm
|
||||
with:
|
||||
scope: '@ionic/core'
|
||||
@@ -48,7 +48,7 @@ jobs:
|
||||
needs: [release-core]
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@v3
|
||||
- name: Restore @ionic/docs built cache
|
||||
uses: ./.github/workflows/actions/download-archive
|
||||
with:
|
||||
@@ -68,7 +68,7 @@ jobs:
|
||||
needs: [release-core]
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@v3
|
||||
- name: Restore @ionic/core built cache
|
||||
uses: ./.github/workflows/actions/download-archive
|
||||
with:
|
||||
@@ -95,7 +95,7 @@ jobs:
|
||||
needs: [release-core]
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@v3
|
||||
- name: Restore @ionic/core built cache
|
||||
uses: ./.github/workflows/actions/download-archive
|
||||
with:
|
||||
@@ -121,7 +121,7 @@ jobs:
|
||||
needs: [release-core]
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@v3
|
||||
- name: Restore @ionic/core built cache
|
||||
uses: ./.github/workflows/actions/download-archive
|
||||
with:
|
||||
@@ -147,7 +147,7 @@ jobs:
|
||||
needs: [release-core]
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@v3
|
||||
- name: Restore @ionic/core built cache
|
||||
uses: ./.github/workflows/actions/download-archive
|
||||
with:
|
||||
@@ -161,13 +161,14 @@ jobs:
|
||||
version: ${{ inputs.version }}
|
||||
preid: ${{ inputs.preid }}
|
||||
working-directory: 'packages/angular-server'
|
||||
folder: './dist'
|
||||
token: ${{ secrets.NPM_TOKEN }}
|
||||
|
||||
release-react-router:
|
||||
needs: [release-react]
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@v3
|
||||
- name: Restore @ionic/core built cache
|
||||
uses: ./.github/workflows/actions/download-archive
|
||||
with:
|
||||
@@ -193,7 +194,7 @@ jobs:
|
||||
needs: [release-vue]
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@v3
|
||||
- name: Restore @ionic/core built cache
|
||||
uses: ./.github/workflows/actions/download-archive
|
||||
with:
|
||||
|
||||
9
.github/workflows/release.yml
vendored
@@ -50,13 +50,10 @@ jobs:
|
||||
needs: [release-ionic]
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@v3
|
||||
with:
|
||||
token: ${{ secrets.IONITRON_TOKEN }}
|
||||
fetch-depth: 0
|
||||
- uses: pnpm/action-setup@v2
|
||||
with:
|
||||
version: 8
|
||||
- name: Configure Identity
|
||||
# Commits from github-actions do not
|
||||
# trigger other GitHub Actions. As a result,
|
||||
@@ -81,7 +78,7 @@ jobs:
|
||||
needs: [finalize-release]
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@v3
|
||||
# Pull the latest version of the reference
|
||||
# branch instead of the revision that triggered
|
||||
# the workflow otherwise we won't get the commit
|
||||
@@ -104,7 +101,7 @@ jobs:
|
||||
# so we do that here.
|
||||
- name: Bump Package Lock
|
||||
run: |
|
||||
pnpm install --lockfile-only
|
||||
lerna exec "npm install --package-lock-only"
|
||||
git add .
|
||||
git commit -m "chore(): update package lock files"
|
||||
git push
|
||||
|
||||
30
.github/workflows/stencil-nightly.yml
vendored
@@ -26,7 +26,7 @@ jobs:
|
||||
build-core-with-stencil-nightly:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@v3
|
||||
- uses: ./.github/workflows/actions/build-core-stencil-prerelease
|
||||
with:
|
||||
stencil-version: ${{ inputs.npm_release_tag || 'nightly' }}
|
||||
@@ -35,21 +35,21 @@ jobs:
|
||||
needs: [build-core-with-stencil-nightly]
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@v3
|
||||
- uses: ./.github/workflows/actions/test-core-clean-build
|
||||
|
||||
test-core-lint:
|
||||
needs: [build-core-with-stencil-nightly]
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@v3
|
||||
- uses: ./.github/workflows/actions/test-core-lint
|
||||
|
||||
test-core-spec:
|
||||
needs: [build-core-with-stencil-nightly]
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@v3
|
||||
- uses: ./.github/workflows/actions/test-core-spec
|
||||
with:
|
||||
stencil-version: ${{ inputs.npm_release_tag || 'nightly' }}
|
||||
@@ -72,7 +72,7 @@ jobs:
|
||||
needs: [build-core-with-stencil-nightly]
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@v3
|
||||
- uses: ./.github/workflows/actions/test-core-screenshot
|
||||
with:
|
||||
shard: ${{ matrix.shard }}
|
||||
@@ -100,14 +100,14 @@ jobs:
|
||||
needs: [build-core-with-stencil-nightly]
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@v3
|
||||
- uses: ./.github/workflows/actions/build-vue
|
||||
|
||||
build-vue-router:
|
||||
needs: [build-vue]
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@v3
|
||||
- uses: ./.github/workflows/actions/build-vue-router
|
||||
|
||||
test-vue-e2e:
|
||||
@@ -118,7 +118,7 @@ jobs:
|
||||
needs: [build-vue, build-vue-router]
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@v3
|
||||
- uses: ./.github/workflows/actions/test-vue-e2e
|
||||
with:
|
||||
app: ${{ matrix.apps }}
|
||||
@@ -136,14 +136,14 @@ jobs:
|
||||
needs: [build-core-with-stencil-nightly]
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@v3
|
||||
- uses: ./.github/workflows/actions/build-angular
|
||||
|
||||
build-angular-server:
|
||||
needs: [build-core-with-stencil-nightly]
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@v3
|
||||
- uses: ./.github/workflows/actions/build-angular-server
|
||||
|
||||
test-angular-e2e:
|
||||
@@ -154,7 +154,7 @@ jobs:
|
||||
needs: [build-angular, build-angular-server]
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@v3
|
||||
- uses: ./.github/workflows/actions/test-angular-e2e
|
||||
with:
|
||||
app: ${{ matrix.apps }}
|
||||
@@ -172,14 +172,14 @@ jobs:
|
||||
needs: [build-core-with-stencil-nightly]
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@v3
|
||||
- uses: ./.github/workflows/actions/build-react
|
||||
|
||||
build-react-router:
|
||||
needs: [build-react]
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@v3
|
||||
- uses: ./.github/workflows/actions/build-react-router
|
||||
|
||||
test-react-router-e2e:
|
||||
@@ -190,7 +190,7 @@ jobs:
|
||||
needs: [build-react, build-react-router]
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@v3
|
||||
- uses: ./.github/workflows/actions/test-react-router-e2e
|
||||
with:
|
||||
app: ${{ matrix.apps }}
|
||||
@@ -212,7 +212,7 @@ jobs:
|
||||
needs: [build-react, build-react-router]
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@v3
|
||||
- uses: ./.github/workflows/actions/test-react-e2e
|
||||
with:
|
||||
app: ${{ matrix.apps }}
|
||||
|
||||
20
.github/workflows/update-screenshots.yml
vendored
@@ -3,20 +3,6 @@ name: 'Update Reference Screenshots'
|
||||
on:
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
# Screenshots can be updated for all components or specified component(s).
|
||||
# If the `component` variable is set, then the test has the option to
|
||||
# - run all the instances of the specified component(s) in the `src/components` folder
|
||||
# -- For example: if the `component` value is "item", then the following command will be: `npm run test.e2e item`
|
||||
# - run the specified file path
|
||||
# -- For example: if the `component` value is "src/components/item/test/basic", then the following command will be: `npm run test.e2e src/components/item/test/basic`
|
||||
# - run multiple specified components based on the space-separated value
|
||||
# -- For example: if the `component` value is "item basic", then the following command will be: `npm run test.e2e item basic`
|
||||
# -- For example: if the `component` value is "src/components/item/test/basic src/components/item/test/a11y", then the following command will be: `npm run test.e2e src/components/item/test/basic src/components/item/test/a11y`
|
||||
#
|
||||
# If the `component` variable is not set, then the test will run all the instances of the components in the `src/components` folder.
|
||||
# - For example: `npm run test.e2e`
|
||||
#
|
||||
# More common options can be found at the Playwright Command line page: https://playwright.dev/docs/test-cli
|
||||
component:
|
||||
description: 'What component(s) should be updated? (leave blank to update all or use a space-separated list for multiple components)'
|
||||
required: false
|
||||
@@ -26,7 +12,7 @@ jobs:
|
||||
build-core:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@v3
|
||||
- uses: ./.github/workflows/actions/build-core
|
||||
|
||||
test-core-screenshot:
|
||||
@@ -47,7 +33,7 @@ jobs:
|
||||
needs: [build-core]
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@v3
|
||||
- uses: ./.github/workflows/actions/test-core-screenshot
|
||||
with:
|
||||
shard: ${{ matrix.shard }}
|
||||
@@ -59,7 +45,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
needs: [test-core-screenshot]
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@v3
|
||||
# Normally, we could just push with the
|
||||
# default GITHUB_TOKEN, but that will
|
||||
# not cause the build workflow
|
||||
|
||||
11
.gitignore
vendored
@@ -68,16 +68,7 @@ core/www/
|
||||
# playwright
|
||||
core/test-results/
|
||||
core/playwright-report/
|
||||
|
||||
# ground truths generated outside of docker should not be committed to the repo
|
||||
core/**/*-snapshots/*
|
||||
|
||||
# new ground truths should only be generated inside of docker which will result in -linux.png screenshots
|
||||
!core/**/*-snapshots/*-linux.png
|
||||
|
||||
# these files are going to be different per-developer environment so do not add them to the repo
|
||||
core/docker-display.txt
|
||||
core/docker-display-volume.txt
|
||||
core/**/*-snapshots
|
||||
|
||||
# angular
|
||||
packages/angular/css/
|
||||
|
||||
90
CHANGELOG.md
@@ -3,96 +3,6 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [7.8.2](https://github.com/ionic-team/ionic-framework/compare/v7.8.1...v7.8.2) (2024-03-27)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **searchbar:** autocapitalize is initialized correctly ([#29197](https://github.com/ionic-team/ionic-framework/issues/29197)) ([8ad66c0](https://github.com/ionic-team/ionic-framework/commit/8ad66c03d777edcab19c97cba696b171acc2d2e8)), closes [#29193](https://github.com/ionic-team/ionic-framework/issues/29193)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## [7.8.1](https://github.com/ionic-team/ionic-framework/compare/v7.8.0...v7.8.1) (2024-03-20)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **datetime:** wheel picker shows consistently in overlays ([#29147](https://github.com/ionic-team/ionic-framework/issues/29147)) ([19c1bc1](https://github.com/ionic-team/ionic-framework/commit/19c1bc16cbc6725463890382365203824b7fd353)), closes [#26234](https://github.com/ionic-team/ionic-framework/issues/26234)
|
||||
* **header:** iOS headers in MD app are not hidden ([#29164](https://github.com/ionic-team/ionic-framework/issues/29164)) ([fdfecd3](https://github.com/ionic-team/ionic-framework/commit/fdfecd32c33c41cf202d3b30c073bfb1b077e2d6)), closes [#28867](https://github.com/ionic-team/ionic-framework/issues/28867)
|
||||
* **react:** avoid definitely typed errors with @types/react@18 ([#29182](https://github.com/ionic-team/ionic-framework/issues/29182)) ([58d217d](https://github.com/ionic-team/ionic-framework/commit/58d217d0cf6b716da855c71c169fb1870d4067d3)), closes [#29178](https://github.com/ionic-team/ionic-framework/issues/29178)
|
||||
|
||||
|
||||
### Performance Improvements
|
||||
|
||||
* **datetime:** calendar body shows immediately in modal on ios ([#29163](https://github.com/ionic-team/ionic-framework/issues/29163)) ([f759776](https://github.com/ionic-team/ionic-framework/commit/f75977699dae5aeea3d97d4318377633e935afb9)), closes [#24542](https://github.com/ionic-team/ionic-framework/issues/24542)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [7.8.0](https://github.com/ionic-team/ionic-framework/compare/v7.7.5...v7.8.0) (2024-03-13)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **datetime:** formatOptions property for Datetime ([#29065](https://github.com/ionic-team/ionic-framework/issues/29065)) ([7cdbc1b](https://github.com/ionic-team/ionic-framework/commit/7cdbc1b5ad004e17a7c51363653e0e67f50e6860))
|
||||
* **searchbar:** autocapitalize, dir, lang, maxlength, and minlength are inherited to native input ([#29098](https://github.com/ionic-team/ionic-framework/issues/29098)) ([a0a77f7](https://github.com/ionic-team/ionic-framework/commit/a0a77f799df0732d9f7182f15866035a3ce5a1eb)), closes [#27606](https://github.com/ionic-team/ionic-framework/issues/27606)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## [7.7.5](https://github.com/ionic-team/ionic-framework/compare/v7.7.4...v7.7.5) (2024-03-13)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **angular:** add ionNavWillChange and ionNavDidChange types for nav ([#29122](https://github.com/ionic-team/ionic-framework/issues/29122)) ([85b9d5c](https://github.com/ionic-team/ionic-framework/commit/85b9d5c35f626ffc273d220549b0126ddc1f7e4b)), closes [#29114](https://github.com/ionic-team/ionic-framework/issues/29114)
|
||||
* **checkbox:** set aria-checked of indeterminate checkbox to 'mixed' ([#29115](https://github.com/ionic-team/ionic-framework/issues/29115)) ([b2d636f](https://github.com/ionic-team/ionic-framework/commit/b2d636f14dcd33313f6604cfd4a64b542c831b34))
|
||||
* **overlay:** do not hide overlay if toast is presented ([#29140](https://github.com/ionic-team/ionic-framework/issues/29140)) ([c0f5e5e](https://github.com/ionic-team/ionic-framework/commit/c0f5e5ebc0c9d45d71e10e09903b00b3ba8e6bba)), closes [#29139](https://github.com/ionic-team/ionic-framework/issues/29139)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## [7.7.4](https://github.com/ionic-team/ionic-framework/compare/v7.7.3...v7.7.4) (2024-03-06)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **modal:** ariaLabel and role are inherited when set via htmlAttributes ([#29099](https://github.com/ionic-team/ionic-framework/issues/29099)) ([de13633](https://github.com/ionic-team/ionic-framework/commit/de13633a182d963876434db773aa346833f956fd))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## [7.7.3](https://github.com/ionic-team/ionic-framework/compare/v7.7.2...v7.7.3) (2024-02-21)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **label:** do not grow when in end slot ([#29036](https://github.com/ionic-team/ionic-framework/issues/29036)) ([1fc4b76](https://github.com/ionic-team/ionic-framework/commit/1fc4b76f5940b38fd89e19561d6b4738dfb8ae5d)), closes [#29033](https://github.com/ionic-team/ionic-framework/issues/29033)
|
||||
* **overlays:** focus is returned to last focus element when focusing toast ([#28950](https://github.com/ionic-team/ionic-framework/issues/28950)) ([2ed0ada](https://github.com/ionic-team/ionic-framework/commit/2ed0ada9237b3f4dbf5959746ce2d1744936eebe)), closes [#28261](https://github.com/ionic-team/ionic-framework/issues/28261)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## [7.7.2](https://github.com/ionic-team/ionic-framework/compare/v7.7.1...v7.7.2) (2024-02-14)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **overlays:** do not return focus if application has already moved focus manually ([#28850](https://github.com/ionic-team/ionic-framework/issues/28850)) ([a016670](https://github.com/ionic-team/ionic-framework/commit/a016670a8a46e101d23235b17bc8a2081fb992eb)), closes [#28849](https://github.com/ionic-team/ionic-framework/issues/28849)
|
||||
* **overlays:** ensure that only topmost overlay is announced by screen readers ([#28997](https://github.com/ionic-team/ionic-framework/issues/28997)) ([ba4ba61](https://github.com/ionic-team/ionic-framework/commit/ba4ba6161c1a6c67f7804b07f49c64ac9ad2b14c)), closes [#23472](https://github.com/ionic-team/ionic-framework/issues/23472)
|
||||
* **popover:** render arrow above backdrop ([#28986](https://github.com/ionic-team/ionic-framework/issues/28986)) ([0a8964d](https://github.com/ionic-team/ionic-framework/commit/0a8964d30c76218fe62f7f4aed4f81df7bb80cd0)), closes [#28985](https://github.com/ionic-team/ionic-framework/issues/28985)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## [7.7.1](https://github.com/ionic-team/ionic-framework/compare/v7.7.0...v7.7.1) (2024-02-07)
|
||||
|
||||
|
||||
|
||||
@@ -3,94 +3,6 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [7.8.2](https://github.com/ionic-team/ionic-framework/compare/v7.8.1...v7.8.2) (2024-03-27)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **searchbar:** autocapitalize is initialized correctly ([#29197](https://github.com/ionic-team/ionic-framework/issues/29197)) ([8ad66c0](https://github.com/ionic-team/ionic-framework/commit/8ad66c03d777edcab19c97cba696b171acc2d2e8)), closes [#29193](https://github.com/ionic-team/ionic-framework/issues/29193)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## [7.8.1](https://github.com/ionic-team/ionic-framework/compare/v7.8.0...v7.8.1) (2024-03-20)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **datetime:** wheel picker shows consistently in overlays ([#29147](https://github.com/ionic-team/ionic-framework/issues/29147)) ([19c1bc1](https://github.com/ionic-team/ionic-framework/commit/19c1bc16cbc6725463890382365203824b7fd353)), closes [#26234](https://github.com/ionic-team/ionic-framework/issues/26234)
|
||||
* **header:** iOS headers in MD app are not hidden ([#29164](https://github.com/ionic-team/ionic-framework/issues/29164)) ([fdfecd3](https://github.com/ionic-team/ionic-framework/commit/fdfecd32c33c41cf202d3b30c073bfb1b077e2d6)), closes [#28867](https://github.com/ionic-team/ionic-framework/issues/28867)
|
||||
|
||||
|
||||
### Performance Improvements
|
||||
|
||||
* **datetime:** calendar body shows immediately in modal on ios ([#29163](https://github.com/ionic-team/ionic-framework/issues/29163)) ([f759776](https://github.com/ionic-team/ionic-framework/commit/f75977699dae5aeea3d97d4318377633e935afb9)), closes [#24542](https://github.com/ionic-team/ionic-framework/issues/24542)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [7.8.0](https://github.com/ionic-team/ionic-framework/compare/v7.7.5...v7.8.0) (2024-03-13)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **datetime:** formatOptions property for Datetime ([#29065](https://github.com/ionic-team/ionic-framework/issues/29065)) ([7cdbc1b](https://github.com/ionic-team/ionic-framework/commit/7cdbc1b5ad004e17a7c51363653e0e67f50e6860))
|
||||
* **searchbar:** autocapitalize, dir, lang, maxlength, and minlength are inherited to native input ([#29098](https://github.com/ionic-team/ionic-framework/issues/29098)) ([a0a77f7](https://github.com/ionic-team/ionic-framework/commit/a0a77f799df0732d9f7182f15866035a3ce5a1eb)), closes [#27606](https://github.com/ionic-team/ionic-framework/issues/27606)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## [7.7.5](https://github.com/ionic-team/ionic-framework/compare/v7.7.4...v7.7.5) (2024-03-13)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **checkbox:** set aria-checked of indeterminate checkbox to 'mixed' ([#29115](https://github.com/ionic-team/ionic-framework/issues/29115)) ([b2d636f](https://github.com/ionic-team/ionic-framework/commit/b2d636f14dcd33313f6604cfd4a64b542c831b34))
|
||||
* **overlay:** do not hide overlay if toast is presented ([#29140](https://github.com/ionic-team/ionic-framework/issues/29140)) ([c0f5e5e](https://github.com/ionic-team/ionic-framework/commit/c0f5e5ebc0c9d45d71e10e09903b00b3ba8e6bba)), closes [#29139](https://github.com/ionic-team/ionic-framework/issues/29139)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## [7.7.4](https://github.com/ionic-team/ionic-framework/compare/v7.7.3...v7.7.4) (2024-03-06)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **modal:** ariaLabel and role are inherited when set via htmlAttributes ([#29099](https://github.com/ionic-team/ionic-framework/issues/29099)) ([de13633](https://github.com/ionic-team/ionic-framework/commit/de13633a182d963876434db773aa346833f956fd))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## [7.7.3](https://github.com/ionic-team/ionic-framework/compare/v7.7.2...v7.7.3) (2024-02-21)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **label:** do not grow when in end slot ([#29036](https://github.com/ionic-team/ionic-framework/issues/29036)) ([1fc4b76](https://github.com/ionic-team/ionic-framework/commit/1fc4b76f5940b38fd89e19561d6b4738dfb8ae5d)), closes [#29033](https://github.com/ionic-team/ionic-framework/issues/29033)
|
||||
* **overlays:** focus is returned to last focus element when focusing toast ([#28950](https://github.com/ionic-team/ionic-framework/issues/28950)) ([2ed0ada](https://github.com/ionic-team/ionic-framework/commit/2ed0ada9237b3f4dbf5959746ce2d1744936eebe)), closes [#28261](https://github.com/ionic-team/ionic-framework/issues/28261)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## [7.7.2](https://github.com/ionic-team/ionic-framework/compare/v7.7.1...v7.7.2) (2024-02-14)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **overlays:** do not return focus if application has already moved focus manually ([#28850](https://github.com/ionic-team/ionic-framework/issues/28850)) ([a016670](https://github.com/ionic-team/ionic-framework/commit/a016670a8a46e101d23235b17bc8a2081fb992eb)), closes [#28849](https://github.com/ionic-team/ionic-framework/issues/28849)
|
||||
* **overlays:** ensure that only topmost overlay is announced by screen readers ([#28997](https://github.com/ionic-team/ionic-framework/issues/28997)) ([ba4ba61](https://github.com/ionic-team/ionic-framework/commit/ba4ba6161c1a6c67f7804b07f49c64ac9ad2b14c)), closes [#23472](https://github.com/ionic-team/ionic-framework/issues/23472)
|
||||
* **popover:** render arrow above backdrop ([#28986](https://github.com/ionic-team/ionic-framework/issues/28986)) ([0a8964d](https://github.com/ionic-team/ionic-framework/commit/0a8964d30c76218fe62f7f4aed4f81df7bb80cd0)), closes [#28985](https://github.com/ionic-team/ionic-framework/issues/28985)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## [7.7.1](https://github.com/ionic-team/ionic-framework/compare/v7.7.0...v7.7.1) (2024-02-07)
|
||||
|
||||
|
||||
|
||||
@@ -1,5 +0,0 @@
|
||||
# Get Playwright
|
||||
FROM mcr.microsoft.com/playwright:v1.42.1
|
||||
|
||||
# Set the working directory
|
||||
WORKDIR /ionic
|
||||
@@ -394,7 +394,6 @@ ion-datetime,prop,dayValues,number | number[] | string | undefined,undefined,fal
|
||||
ion-datetime,prop,disabled,boolean,false,false,false
|
||||
ion-datetime,prop,doneText,string,'Done',false,false
|
||||
ion-datetime,prop,firstDayOfWeek,number,0,false,false
|
||||
ion-datetime,prop,formatOptions,undefined | { date: DateTimeFormatOptions; time?: DateTimeFormatOptions | undefined; } | { date?: DateTimeFormatOptions | undefined; time: DateTimeFormatOptions; },undefined,false,false
|
||||
ion-datetime,prop,highlightedDates,((dateIsoString: string) => DatetimeHighlightStyle | undefined) | DatetimeHighlight[] | undefined,undefined,false,false
|
||||
ion-datetime,prop,hourCycle,"h11" | "h12" | "h23" | "h24" | undefined,undefined,false,false
|
||||
ion-datetime,prop,hourValues,number | number[] | string | undefined,undefined,false,false
|
||||
@@ -1158,7 +1157,6 @@ ion-row,shadow
|
||||
|
||||
ion-searchbar,scoped
|
||||
ion-searchbar,prop,animated,boolean,false,false,false
|
||||
ion-searchbar,prop,autocapitalize,string,'default',false,false
|
||||
ion-searchbar,prop,autocomplete,"name" | "email" | "tel" | "url" | "on" | "off" | "honorific-prefix" | "given-name" | "additional-name" | "family-name" | "honorific-suffix" | "nickname" | "username" | "new-password" | "current-password" | "one-time-code" | "organization-title" | "organization" | "street-address" | "address-line1" | "address-line2" | "address-line3" | "address-level4" | "address-level3" | "address-level2" | "address-level1" | "country" | "country-name" | "postal-code" | "cc-name" | "cc-given-name" | "cc-additional-name" | "cc-family-name" | "cc-number" | "cc-exp" | "cc-exp-month" | "cc-exp-year" | "cc-csc" | "cc-type" | "transaction-currency" | "transaction-amount" | "language" | "bday" | "bday-day" | "bday-month" | "bday-year" | "sex" | "tel-country-code" | "tel-national" | "tel-area-code" | "tel-local" | "tel-extension" | "impp" | "photo",'off',false,false
|
||||
ion-searchbar,prop,autocorrect,"off" | "on",'off',false,false
|
||||
ion-searchbar,prop,cancelButtonIcon,string,config.get('backButtonIcon', arrowBackSharp) as string,false,false
|
||||
@@ -1169,8 +1167,6 @@ ion-searchbar,prop,debounce,number | undefined,undefined,false,false
|
||||
ion-searchbar,prop,disabled,boolean,false,false,false
|
||||
ion-searchbar,prop,enterkeyhint,"done" | "enter" | "go" | "next" | "previous" | "search" | "send" | undefined,undefined,false,false
|
||||
ion-searchbar,prop,inputmode,"decimal" | "email" | "none" | "numeric" | "search" | "tel" | "text" | "url" | undefined,undefined,false,false
|
||||
ion-searchbar,prop,maxlength,number | undefined,undefined,false,false
|
||||
ion-searchbar,prop,minlength,number | undefined,undefined,false,false
|
||||
ion-searchbar,prop,mode,"ios" | "md",undefined,false,false
|
||||
ion-searchbar,prop,name,string,this.inputId,false,false
|
||||
ion-searchbar,prop,placeholder,string,'Search',false,false
|
||||
|
||||
18826
core/package-lock.json
generated
Normal file
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@ionic/core",
|
||||
"version": "7.8.2",
|
||||
"version": "7.7.1",
|
||||
"description": "Base components for Ionic",
|
||||
"keywords": [
|
||||
"ionic",
|
||||
@@ -31,19 +31,18 @@
|
||||
"loader/"
|
||||
],
|
||||
"dependencies": {
|
||||
"@stencil/core": "^4.12.2",
|
||||
"@stencil/core": "^4.12.1",
|
||||
"ionicons": "^7.2.2",
|
||||
"tslib": "^2.1.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@axe-core/playwright": "^4.8.5",
|
||||
"@capacitor/core": "^5.7.0",
|
||||
"@axe-core/playwright": "^4.8.4",
|
||||
"@capacitor/core": "^5.6.0",
|
||||
"@capacitor/haptics": "^5.0.7",
|
||||
"@capacitor/keyboard": "^5.0.8",
|
||||
"@capacitor/status-bar": "^5.0.7",
|
||||
"@ionic/eslint-config": "^0.3.0",
|
||||
"@ionic/prettier-config": "^2.0.0",
|
||||
"@jest/core": "^27.5.1",
|
||||
"@playwright/test": "^1.39.0",
|
||||
"@rollup/plugin-node-resolve": "^8.4.0",
|
||||
"@rollup/plugin-virtual": "^2.0.3",
|
||||
@@ -51,7 +50,7 @@
|
||||
"@stencil/react-output-target": "^0.5.3",
|
||||
"@stencil/sass": "^3.0.9",
|
||||
"@stencil/vue-output-target": "^0.8.7",
|
||||
"@types/jest": "^27.5.2",
|
||||
"@types/jest": "^29.5.6",
|
||||
"@types/node": "^14.6.0",
|
||||
"@typescript-eslint/eslint-plugin": "^6.7.2",
|
||||
"@typescript-eslint/parser": "^6.7.2",
|
||||
@@ -61,11 +60,11 @@
|
||||
"eslint-config-prettier": "^8.5.0",
|
||||
"eslint-plugin-custom-rules": "file:custom-rules",
|
||||
"execa": "^5.0.0",
|
||||
"fast-deep-equal": "^3.1.3",
|
||||
"fs-extra": "^9.0.1",
|
||||
"jest": "^27.5.1",
|
||||
"jest-cli": "^27.5.1",
|
||||
"jest": "^29.7.0",
|
||||
"jest-cli": "^29.7.0",
|
||||
"prettier": "^2.6.1",
|
||||
"puppeteer": "21.1.1",
|
||||
"rollup": "^2.26.4",
|
||||
"sass": "^1.33.0",
|
||||
"serve": "^14.0.1",
|
||||
@@ -73,35 +72,30 @@
|
||||
"stylelint-order": "^4.1.0"
|
||||
},
|
||||
"scripts": {
|
||||
"build": "pnpm run clean && pnpm run build.css && stencil build --es5 --docs-json dist/docs.json",
|
||||
"build.css": "pnpm run css.sass && pnpm run css.minify",
|
||||
"build.debug": "pnpm run clean && stencil build --debug",
|
||||
"build": "npm run clean && npm run build.css && stencil build --es5 --docs-json dist/docs.json",
|
||||
"build.css": "npm run css.sass && npm run css.minify",
|
||||
"build.debug": "npm run clean && stencil build --debug",
|
||||
"build.docs.json": "stencil build --docs-json dist/docs.json",
|
||||
"clean": "node scripts/clean.js",
|
||||
"css.minify": "cleancss -O2 -o ./css/ionic.bundle.css ./css/ionic.bundle.css",
|
||||
"css.sass": "sass --embed-sources src/css:./css",
|
||||
"eslint": "eslint src",
|
||||
"lint": "pnpm run lint.ts && pnpm run lint.sass && pnpm run prettier --write --cache",
|
||||
"lint.fix": "pnpm run lint.ts.fix && pnpm run lint.sass.fix && pnpm run prettier --write --cache",
|
||||
"lint": "npm run lint.ts && npm run lint.sass && npm run prettier -- --write --cache",
|
||||
"lint.fix": "npm run lint.ts.fix && npm run lint.sass.fix && npm run prettier -- --write --cache",
|
||||
"lint.sass": "stylelint \"src/**/*.scss\"",
|
||||
"lint.sass.fix": "pnpm run lint.sass --fix",
|
||||
"lint.ts": "pnpm run eslint",
|
||||
"lint.ts.fix": "pnpm run eslint --fix",
|
||||
"lint.sass.fix": "npm run lint.sass -- --fix",
|
||||
"lint.ts": "npm run eslint",
|
||||
"lint.ts.fix": "npm run eslint -- --fix",
|
||||
"prerender.e2e": "node scripts/testing/prerender.js",
|
||||
"prettier": "prettier \"./src/**/*.{html,ts,tsx,js,jsx}\"",
|
||||
"start": "pnpm run build.css && stencil build --dev --watch --serve",
|
||||
"test": "pnpm run test.spec && pnpm run test.e2e",
|
||||
"start": "npm run build.css && stencil build --dev --watch --serve",
|
||||
"test": "npm run test.spec && npm run test.e2e",
|
||||
"test.spec": "stencil test --spec --max-workers=2",
|
||||
"test.e2e": "pnpm exec playwright test",
|
||||
"test.e2e.update-snapshots": "pnpm run test.e2e --update-snapshots",
|
||||
"test.e2e": "npx playwright test",
|
||||
"test.e2e.update-snapshots": "npm run test.e2e -- --update-snapshots",
|
||||
"test.watch": "jest --watch --no-cache",
|
||||
"test.treeshake": "node scripts/treeshaking.js dist/index.js",
|
||||
"validate": "pnpm run lint && pnpm run test && pnpm run build && pnpm run test.treeshake",
|
||||
"docker.build": "docker build -t ionic-playwright .",
|
||||
"test.e2e.docker": "pnpm run docker.build && docker run -it --rm -e DISPLAY=$(cat docker-display.txt) -v $(cat docker-display-volume.txt) --ipc=host --mount=type=bind,source=./,target=/ionic ionic-playwright pnpm run test.e2e --",
|
||||
"test.e2e.docker.update-snapshots": "pnpm run test.e2e.docker -- --update-snapshots",
|
||||
"test.e2e.docker.ci": "pnpm run docker.build && docker run -e CI='true' --rm --ipc=host --mount=type=bind,source=./,target=/ionic ionic-playwright pnpm run test.e2e --",
|
||||
"test.report": "pnpm exec playwright show-report"
|
||||
"validate": "npm run lint && npm run test && npm run build && npm run test.treeshake"
|
||||
},
|
||||
"author": "Ionic Team",
|
||||
"license": "MIT",
|
||||
|
||||
55
core/src/components.d.ts
vendored
@@ -15,7 +15,7 @@ import { RouteID, RouterDirection, RouterEventDetail, RouteWrite } from "./compo
|
||||
import { BreadcrumbCollapsedClickEventDetail } from "./components/breadcrumb/breadcrumb-interface";
|
||||
import { CheckboxChangeEventDetail } from "./components/checkbox/checkbox-interface";
|
||||
import { ScrollBaseDetail, ScrollDetail } from "./components/content/content-interface";
|
||||
import { DatetimeChangeEventDetail, DatetimeHighlight, DatetimeHighlightCallback, DatetimeHourCycle, DatetimePresentation, FormatOptions, TitleSelectedDatesFormatter } from "./components/datetime/datetime-interface";
|
||||
import { DatetimeChangeEventDetail, DatetimeHighlight, DatetimeHighlightCallback, DatetimeHourCycle, DatetimePresentation, TitleSelectedDatesFormatter } from "./components/datetime/datetime-interface";
|
||||
import { SpinnerTypes } from "./components/spinner/spinner-configs";
|
||||
import { InputChangeEventDetail, InputInputEventDetail } from "./components/input/input-interface";
|
||||
import { CounterFormatter } from "./components/item/item-interface";
|
||||
@@ -51,7 +51,7 @@ export { RouteID, RouterDirection, RouterEventDetail, RouteWrite } from "./compo
|
||||
export { BreadcrumbCollapsedClickEventDetail } from "./components/breadcrumb/breadcrumb-interface";
|
||||
export { CheckboxChangeEventDetail } from "./components/checkbox/checkbox-interface";
|
||||
export { ScrollBaseDetail, ScrollDetail } from "./components/content/content-interface";
|
||||
export { DatetimeChangeEventDetail, DatetimeHighlight, DatetimeHighlightCallback, DatetimeHourCycle, DatetimePresentation, FormatOptions, TitleSelectedDatesFormatter } from "./components/datetime/datetime-interface";
|
||||
export { DatetimeChangeEventDetail, DatetimeHighlight, DatetimeHighlightCallback, DatetimeHourCycle, DatetimePresentation, TitleSelectedDatesFormatter } from "./components/datetime/datetime-interface";
|
||||
export { SpinnerTypes } from "./components/spinner/spinner-configs";
|
||||
export { InputChangeEventDetail, InputInputEventDetail } from "./components/input/input-interface";
|
||||
export { CounterFormatter } from "./components/item/item-interface";
|
||||
@@ -858,10 +858,6 @@ export namespace Components {
|
||||
* The first day of the week to use for `ion-datetime`. The default value is `0` and represents Sunday.
|
||||
*/
|
||||
"firstDayOfWeek": number;
|
||||
/**
|
||||
* Formatting options for dates and times. Should include a 'date' and/or 'time' object, each of which is of type [Intl.DateTimeFormatOptions](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/DateTimeFormat/DateTimeFormat#options).
|
||||
*/
|
||||
"formatOptions"?: FormatOptions;
|
||||
/**
|
||||
* Used to apply custom text and background colors to specific dates. Can be either an array of objects containing ISO strings and colors, or a callback that receives an ISO string and returns the colors. Only applies to the `date`, `date-time`, and `time-date` presentations, with `preferWheel="false"`.
|
||||
*/
|
||||
@@ -1952,6 +1948,9 @@ export namespace Components {
|
||||
*/
|
||||
"mode"?: "ios" | "md";
|
||||
}
|
||||
interface IonPasswordStrength {
|
||||
"strength"?: 'weak' | 'medium' | 'strong';
|
||||
}
|
||||
interface IonPicker {
|
||||
/**
|
||||
* If `true`, the picker will animate.
|
||||
@@ -2552,10 +2551,6 @@ export namespace Components {
|
||||
* If `true`, enable searchbar animation.
|
||||
*/
|
||||
"animated": boolean;
|
||||
/**
|
||||
* Indicates whether and how the text value should be automatically capitalized as it is entered/edited by the user. Available options: `"off"`, `"none"`, `"on"`, `"sentences"`, `"words"`, `"characters"`.
|
||||
*/
|
||||
"autocapitalize": string;
|
||||
/**
|
||||
* Set the input's autocomplete property.
|
||||
*/
|
||||
@@ -2600,14 +2595,6 @@ export namespace Components {
|
||||
* A hint to the browser for which keyboard to display. Possible values: `"none"`, `"text"`, `"tel"`, `"url"`, `"email"`, `"numeric"`, `"decimal"`, and `"search"`.
|
||||
*/
|
||||
"inputmode"?: 'none' | 'text' | 'tel' | 'url' | 'email' | 'numeric' | 'decimal' | 'search';
|
||||
/**
|
||||
* This attribute specifies the maximum number of characters that the user can enter.
|
||||
*/
|
||||
"maxlength"?: number;
|
||||
/**
|
||||
* This attribute specifies the minimum number of characters that the user can enter.
|
||||
*/
|
||||
"minlength"?: number;
|
||||
/**
|
||||
* The mode determines which platform styles to use.
|
||||
*/
|
||||
@@ -3211,7 +3198,7 @@ export namespace Components {
|
||||
}
|
||||
interface IonToggle {
|
||||
/**
|
||||
* How to control the alignment of the toggle and label on the cross axis. `"start"`: The label and control will appear on the left of the cross axis in LTR, and on the right side in RTL. `"center"`: The label and control will appear at the center of the cross axis in both LTR and RTL.
|
||||
* How to control the alignment of the toggle and label on the cross axis. ``"start"`: The label and control will appear on the left of the cross axis in LTR, and on the right side in RTL. `"center"`: The label and control will appear at the center of the cross axis in both LTR and RTL.
|
||||
*/
|
||||
"alignment": 'start' | 'center';
|
||||
/**
|
||||
@@ -4051,6 +4038,12 @@ declare global {
|
||||
prototype: HTMLIonNoteElement;
|
||||
new (): HTMLIonNoteElement;
|
||||
};
|
||||
interface HTMLIonPasswordStrengthElement extends Components.IonPasswordStrength, HTMLStencilElement {
|
||||
}
|
||||
var HTMLIonPasswordStrengthElement: {
|
||||
prototype: HTMLIonPasswordStrengthElement;
|
||||
new (): HTMLIonPasswordStrengthElement;
|
||||
};
|
||||
interface HTMLIonPickerElementEventMap {
|
||||
"ionPickerDidPresent": void;
|
||||
"ionPickerWillPresent": void;
|
||||
@@ -4688,6 +4681,7 @@ declare global {
|
||||
"ion-nav": HTMLIonNavElement;
|
||||
"ion-nav-link": HTMLIonNavLinkElement;
|
||||
"ion-note": HTMLIonNoteElement;
|
||||
"ion-password-strength": HTMLIonPasswordStrengthElement;
|
||||
"ion-picker": HTMLIonPickerElement;
|
||||
"ion-picker-column": HTMLIonPickerColumnElement;
|
||||
"ion-picker-column-internal": HTMLIonPickerColumnInternalElement;
|
||||
@@ -5557,10 +5551,6 @@ declare namespace LocalJSX {
|
||||
* The first day of the week to use for `ion-datetime`. The default value is `0` and represents Sunday.
|
||||
*/
|
||||
"firstDayOfWeek"?: number;
|
||||
/**
|
||||
* Formatting options for dates and times. Should include a 'date' and/or 'time' object, each of which is of type [Intl.DateTimeFormatOptions](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/DateTimeFormat/DateTimeFormat#options).
|
||||
*/
|
||||
"formatOptions"?: FormatOptions;
|
||||
/**
|
||||
* Used to apply custom text and background colors to specific dates. Can be either an array of objects containing ISO strings and colors, or a callback that receives an ISO string and returns the colors. Only applies to the `date`, `date-time`, and `time-date` presentations, with `preferWheel="false"`.
|
||||
*/
|
||||
@@ -6626,6 +6616,9 @@ declare namespace LocalJSX {
|
||||
*/
|
||||
"mode"?: "ios" | "md";
|
||||
}
|
||||
interface IonPasswordStrength {
|
||||
"strength"?: 'weak' | 'medium' | 'strong';
|
||||
}
|
||||
interface IonPicker {
|
||||
/**
|
||||
* If `true`, the picker will animate.
|
||||
@@ -7292,10 +7285,6 @@ declare namespace LocalJSX {
|
||||
* If `true`, enable searchbar animation.
|
||||
*/
|
||||
"animated"?: boolean;
|
||||
/**
|
||||
* Indicates whether and how the text value should be automatically capitalized as it is entered/edited by the user. Available options: `"off"`, `"none"`, `"on"`, `"sentences"`, `"words"`, `"characters"`.
|
||||
*/
|
||||
"autocapitalize"?: string;
|
||||
/**
|
||||
* Set the input's autocomplete property.
|
||||
*/
|
||||
@@ -7336,14 +7325,6 @@ declare namespace LocalJSX {
|
||||
* A hint to the browser for which keyboard to display. Possible values: `"none"`, `"text"`, `"tel"`, `"url"`, `"email"`, `"numeric"`, `"decimal"`, and `"search"`.
|
||||
*/
|
||||
"inputmode"?: 'none' | 'text' | 'tel' | 'url' | 'email' | 'numeric' | 'decimal' | 'search';
|
||||
/**
|
||||
* This attribute specifies the maximum number of characters that the user can enter.
|
||||
*/
|
||||
"maxlength"?: number;
|
||||
/**
|
||||
* This attribute specifies the minimum number of characters that the user can enter.
|
||||
*/
|
||||
"minlength"?: number;
|
||||
/**
|
||||
* The mode determines which platform styles to use.
|
||||
*/
|
||||
@@ -8037,7 +8018,7 @@ declare namespace LocalJSX {
|
||||
}
|
||||
interface IonToggle {
|
||||
/**
|
||||
* How to control the alignment of the toggle and label on the cross axis. `"start"`: The label and control will appear on the left of the cross axis in LTR, and on the right side in RTL. `"center"`: The label and control will appear at the center of the cross axis in both LTR and RTL.
|
||||
* How to control the alignment of the toggle and label on the cross axis. ``"start"`: The label and control will appear on the left of the cross axis in LTR, and on the right side in RTL. `"center"`: The label and control will appear at the center of the cross axis in both LTR and RTL.
|
||||
*/
|
||||
"alignment"?: 'start' | 'center';
|
||||
/**
|
||||
@@ -8159,6 +8140,7 @@ declare namespace LocalJSX {
|
||||
"ion-nav": IonNav;
|
||||
"ion-nav-link": IonNavLink;
|
||||
"ion-note": IonNote;
|
||||
"ion-password-strength": IonPasswordStrength;
|
||||
"ion-picker": IonPicker;
|
||||
"ion-picker-column": IonPickerColumn;
|
||||
"ion-picker-column-internal": IonPickerColumnInternal;
|
||||
@@ -8256,6 +8238,7 @@ declare module "@stencil/core" {
|
||||
"ion-nav": LocalJSX.IonNav & JSXBase.HTMLAttributes<HTMLIonNavElement>;
|
||||
"ion-nav-link": LocalJSX.IonNavLink & JSXBase.HTMLAttributes<HTMLIonNavLinkElement>;
|
||||
"ion-note": LocalJSX.IonNote & JSXBase.HTMLAttributes<HTMLIonNoteElement>;
|
||||
"ion-password-strength": LocalJSX.IonPasswordStrength & JSXBase.HTMLAttributes<HTMLIonPasswordStrengthElement>;
|
||||
"ion-picker": LocalJSX.IonPicker & JSXBase.HTMLAttributes<HTMLIonPickerElement>;
|
||||
"ion-picker-column": LocalJSX.IonPickerColumn & JSXBase.HTMLAttributes<HTMLIonPickerColumnElement>;
|
||||
"ion-picker-column-internal": LocalJSX.IonPickerColumnInternal & JSXBase.HTMLAttributes<HTMLIonPickerColumnInternalElement>;
|
||||
|
||||
@@ -288,10 +288,6 @@ configs({ directions: ['ltr'] }).forEach(({ title, screenshot, config }) => {
|
||||
await alert.evaluate((el: HTMLIonAlertElement) => el.present());
|
||||
await ionAlertDidPresent.next();
|
||||
|
||||
/**
|
||||
* The borders on the text fields may not be visible in the screenshot
|
||||
* when using Safari, this is due to a WebKit rendering quirk.
|
||||
*/
|
||||
await expect(page).toHaveScreenshot(screenshot(`alert-text-fields-scale`));
|
||||
});
|
||||
});
|
||||
|
||||
|
Before Width: | Height: | Size: 33 KiB After Width: | Height: | Size: 23 KiB |
|
Before Width: | Height: | Size: 21 KiB After Width: | Height: | Size: 21 KiB |
|
Before Width: | Height: | Size: 20 KiB After Width: | Height: | Size: 20 KiB |
|
Before Width: | Height: | Size: 20 KiB After Width: | Height: | Size: 20 KiB |
|
Before Width: | Height: | Size: 27 KiB After Width: | Height: | Size: 26 KiB |
|
Before Width: | Height: | Size: 19 KiB After Width: | Height: | Size: 18 KiB |
|
Before Width: | Height: | Size: 27 KiB After Width: | Height: | Size: 26 KiB |
|
Before Width: | Height: | Size: 19 KiB After Width: | Height: | Size: 18 KiB |
|
Before Width: | Height: | Size: 35 KiB After Width: | Height: | Size: 33 KiB |
|
Before Width: | Height: | Size: 21 KiB After Width: | Height: | Size: 22 KiB |
|
Before Width: | Height: | Size: 35 KiB After Width: | Height: | Size: 33 KiB |
|
Before Width: | Height: | Size: 21 KiB After Width: | Height: | Size: 22 KiB |
@@ -1,7 +1,7 @@
|
||||
import type { ComponentInterface } from '@stencil/core';
|
||||
import { Build, Component, Element, Host, Method, h } from '@stencil/core';
|
||||
import type { FocusVisibleUtility } from '@utils/focus-visible';
|
||||
import { shouldUseCloseWatcher } from '@utils/hardware-back-button';
|
||||
import { shoudUseCloseWatcher } from '@utils/hardware-back-button';
|
||||
import { printIonWarning } from '@utils/logging';
|
||||
import { isPlatform } from '@utils/platform';
|
||||
|
||||
@@ -36,7 +36,7 @@ export class App implements ComponentInterface {
|
||||
import('../../utils/input-shims/input-shims').then((module) => module.startInputShims(config, platform));
|
||||
}
|
||||
const hardwareBackButtonModule = await import('../../utils/hardware-back-button');
|
||||
const supportsHardwareBackButtonEvents = isHybrid || shouldUseCloseWatcher();
|
||||
const supportsHardwareBackButtonEvents = isHybrid || shoudUseCloseWatcher();
|
||||
if (config.getBoolean('hardwareBackButton', supportsHardwareBackButtonEvents)) {
|
||||
hardwareBackButtonModule.startHardwareBackButton();
|
||||
} else {
|
||||
@@ -44,7 +44,7 @@ export class App implements ComponentInterface {
|
||||
* If an app sets hardwareBackButton: false and experimentalCloseWatcher: true
|
||||
* then the close watcher will not be used.
|
||||
*/
|
||||
if (shouldUseCloseWatcher()) {
|
||||
if (shoudUseCloseWatcher()) {
|
||||
printIonWarning(
|
||||
'experimentalCloseWatcher was set to `true`, but hardwareBackButton was set to `false`. Both config options must be `true` for the Close Watcher API to be used.'
|
||||
);
|
||||
|
||||
|
Before Width: | Height: | Size: 2.2 KiB After Width: | Height: | Size: 2.2 KiB |
|
Before Width: | Height: | Size: 2.1 KiB After Width: | Height: | Size: 2.0 KiB |
|
Before Width: | Height: | Size: 89 KiB After Width: | Height: | Size: 89 KiB |
|
Before Width: | Height: | Size: 89 KiB After Width: | Height: | Size: 89 KiB |
|
Before Width: | Height: | Size: 83 KiB After Width: | Height: | Size: 86 KiB |
|
Before Width: | Height: | Size: 83 KiB After Width: | Height: | Size: 86 KiB |
|
Before Width: | Height: | Size: 26 KiB After Width: | Height: | Size: 26 KiB |
|
Before Width: | Height: | Size: 25 KiB After Width: | Height: | Size: 26 KiB |
|
Before Width: | Height: | Size: 27 KiB After Width: | Height: | Size: 27 KiB |
|
Before Width: | Height: | Size: 27 KiB After Width: | Height: | Size: 27 KiB |
|
Before Width: | Height: | Size: 110 KiB After Width: | Height: | Size: 111 KiB |
|
Before Width: | Height: | Size: 110 KiB After Width: | Height: | Size: 110 KiB |
@@ -251,7 +251,6 @@ export class Checkbox implements ComponentInterface {
|
||||
|
||||
return (
|
||||
<Host
|
||||
aria-checked={indeterminate ? 'mixed' : `${checked}`}
|
||||
class={createColorClasses(color, {
|
||||
[mode]: true,
|
||||
'in-item': hostContext('ion-item', el),
|
||||
|
||||
@@ -39,18 +39,3 @@ describe('ion-checkbox: disabled', () => {
|
||||
expect(checkbox.checked).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe('ion-checkbox: indeterminate', () => {
|
||||
it('should have a mixed value for aria-checked', async () => {
|
||||
const page = await newSpecPage({
|
||||
components: [Checkbox],
|
||||
html: `
|
||||
<ion-checkbox indeterminate="true">Checkbox</ion-checkbox>
|
||||
`,
|
||||
});
|
||||
|
||||
const checkbox = page.body.querySelector('ion-checkbox')!;
|
||||
|
||||
expect(checkbox.getAttribute('aria-checked')).toBe('mixed');
|
||||
});
|
||||
});
|
||||
|
||||
@@ -8,7 +8,7 @@ import { getIonMode } from '../../global/ionic-global';
|
||||
import type { Color } from '../../interface';
|
||||
import type { DatetimePresentation } from '../datetime/datetime-interface';
|
||||
import { getToday } from '../datetime/utils/data';
|
||||
import { getLocalizedDateTime, getLocalizedTime } from '../datetime/utils/format';
|
||||
import { getMonthAndYear, getMonthDayAndYear, getLocalizedDateTime, getLocalizedTime } from '../datetime/utils/format';
|
||||
import { getHourCycle } from '../datetime/utils/helpers';
|
||||
import { parseDate } from '../datetime/utils/parse';
|
||||
/**
|
||||
@@ -196,7 +196,7 @@ export class DatetimeButton implements ComponentInterface {
|
||||
return;
|
||||
}
|
||||
|
||||
const { value, locale, formatOptions, hourCycle, preferWheel, multiple, titleSelectedDatesFormatter } = datetimeEl;
|
||||
const { value, locale, hourCycle, preferWheel, multiple, titleSelectedDatesFormatter } = datetimeEl;
|
||||
|
||||
const parsedValues = this.getParsedDateValues(value);
|
||||
|
||||
@@ -225,12 +225,8 @@ export class DatetimeButton implements ComponentInterface {
|
||||
switch (datetimePresentation) {
|
||||
case 'date-time':
|
||||
case 'time-date':
|
||||
const dateText = getLocalizedDateTime(
|
||||
locale,
|
||||
firstParsedDatetime,
|
||||
formatOptions?.date ?? { month: 'short', day: 'numeric', year: 'numeric' }
|
||||
);
|
||||
const timeText = getLocalizedTime(locale, firstParsedDatetime, computedHourCycle, formatOptions?.time);
|
||||
const dateText = getMonthDayAndYear(locale, firstParsedDatetime);
|
||||
const timeText = getLocalizedTime(locale, firstParsedDatetime, computedHourCycle);
|
||||
if (preferWheel) {
|
||||
this.dateText = `${dateText} ${timeText}`;
|
||||
} else {
|
||||
@@ -250,28 +246,20 @@ export class DatetimeButton implements ComponentInterface {
|
||||
}
|
||||
this.dateText = headerText;
|
||||
} else {
|
||||
this.dateText = getLocalizedDateTime(
|
||||
locale,
|
||||
firstParsedDatetime,
|
||||
formatOptions?.date ?? { month: 'short', day: 'numeric', year: 'numeric' }
|
||||
);
|
||||
this.dateText = getMonthDayAndYear(locale, firstParsedDatetime);
|
||||
}
|
||||
break;
|
||||
case 'time':
|
||||
this.timeText = getLocalizedTime(locale, firstParsedDatetime, computedHourCycle, formatOptions?.time);
|
||||
this.timeText = getLocalizedTime(locale, firstParsedDatetime, computedHourCycle);
|
||||
break;
|
||||
case 'month-year':
|
||||
this.dateText = getLocalizedDateTime(
|
||||
locale,
|
||||
firstParsedDatetime,
|
||||
formatOptions?.date ?? { month: 'long', year: 'numeric' }
|
||||
);
|
||||
this.dateText = getMonthAndYear(locale, firstParsedDatetime);
|
||||
break;
|
||||
case 'month':
|
||||
this.dateText = getLocalizedDateTime(locale, firstParsedDatetime, formatOptions?.time ?? { month: 'long' });
|
||||
this.dateText = getLocalizedDateTime(locale, firstParsedDatetime, { month: 'long' });
|
||||
break;
|
||||
case 'year':
|
||||
this.dateText = getLocalizedDateTime(locale, firstParsedDatetime, formatOptions?.time ?? { year: 'numeric' });
|
||||
this.dateText = getLocalizedDateTime(locale, firstParsedDatetime, { year: 'numeric' });
|
||||
break;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -244,87 +244,4 @@ configs({ modes: ['md'], directions: ['ltr'] }).forEach(({ title, config }) => {
|
||||
await expect(page.locator('#time-button')).not.toBeVisible();
|
||||
});
|
||||
});
|
||||
|
||||
test.describe(title('datetime-button: formatOptions'), () => {
|
||||
test('should include date and time for presentation date-time', async ({ page }) => {
|
||||
await page.setContent(
|
||||
`
|
||||
<ion-datetime-button datetime="datetime"></ion-datetime-button>
|
||||
<ion-datetime id="datetime" presentation="date-time" value="2023-11-02T01:22:00" locale="en-US"></ion-datetime>
|
||||
<script>
|
||||
const datetime = document.querySelector('ion-datetime');
|
||||
datetime.formatOptions = {
|
||||
date: {
|
||||
weekday: "short",
|
||||
month: "long",
|
||||
day: "2-digit"
|
||||
},
|
||||
time: {
|
||||
hour: "2-digit",
|
||||
minute: "2-digit"
|
||||
}
|
||||
}
|
||||
</script>
|
||||
`,
|
||||
config
|
||||
);
|
||||
|
||||
await page.locator('.datetime-ready').waitFor();
|
||||
|
||||
await expect(page.locator('#date-button')).toContainText('Thu, November 02');
|
||||
await expect(page.locator('#time-button')).toContainText('01:22 AM');
|
||||
});
|
||||
|
||||
test('should include date for presentation date', async ({ page }) => {
|
||||
await page.setContent(
|
||||
`
|
||||
<ion-datetime-button datetime="datetime"></ion-datetime-button>
|
||||
<ion-datetime id="datetime" presentation="date" value="2023-11-02" locale="en-US"></ion-datetime>
|
||||
<script>
|
||||
const datetime = document.querySelector('ion-datetime');
|
||||
datetime.formatOptions = {
|
||||
date: {
|
||||
weekday: "short",
|
||||
month: "long",
|
||||
day: "2-digit"
|
||||
}
|
||||
}
|
||||
</script>
|
||||
`,
|
||||
config
|
||||
);
|
||||
|
||||
await page.locator('.datetime-ready').waitFor();
|
||||
|
||||
await expect(page.locator('#date-button')).toContainText('Thu, November 02');
|
||||
});
|
||||
|
||||
test('should include date and time in same button for preferWheel', async ({ page }) => {
|
||||
await page.setContent(
|
||||
`
|
||||
<ion-datetime-button datetime="datetime"></ion-datetime-button>
|
||||
<ion-datetime id="datetime" presentation="date-time" value="2023-11-02T01:22:00" locale="en-US" prefer-wheel="true"></ion-datetime>
|
||||
<script>
|
||||
const datetime = document.querySelector('ion-datetime');
|
||||
datetime.formatOptions = {
|
||||
date: {
|
||||
weekday: "short",
|
||||
month: "long",
|
||||
day: "2-digit"
|
||||
},
|
||||
time: {
|
||||
hour: "2-digit",
|
||||
minute: "2-digit"
|
||||
}
|
||||
}
|
||||
</script>
|
||||
`,
|
||||
config
|
||||
);
|
||||
|
||||
await page.locator('.datetime-ready').waitFor();
|
||||
|
||||
await expect(page.locator('ion-datetime-button')).toContainText('Thu, November 02 01:22 AM');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -215,41 +215,8 @@
|
||||
></ion-datetime>
|
||||
</ion-popover>
|
||||
</div>
|
||||
|
||||
<div class="grid-item">
|
||||
<h2>formatOptions</h2>
|
||||
|
||||
<ion-item>
|
||||
<ion-label>Start Date</ion-label>
|
||||
<ion-datetime-button datetime="format-options" slot="end"></ion-datetime-button>
|
||||
</ion-item>
|
||||
|
||||
<ion-popover arrow="false">
|
||||
<ion-datetime
|
||||
id="format-options"
|
||||
presentation="date-time"
|
||||
value="2023-11-02T01:22:00"
|
||||
locale="en-US"
|
||||
></ion-datetime>
|
||||
</ion-popover>
|
||||
</div>
|
||||
</div>
|
||||
</ion-content>
|
||||
</ion-app>
|
||||
</body>
|
||||
|
||||
<script>
|
||||
const formatOptionsDatetime = document.querySelector('#format-options');
|
||||
formatOptionsDatetime.formatOptions = {
|
||||
date: {
|
||||
weekday: 'short',
|
||||
month: 'long',
|
||||
day: '2-digit',
|
||||
},
|
||||
time: {
|
||||
hour: '2-digit',
|
||||
minute: '2-digit',
|
||||
},
|
||||
};
|
||||
</script>
|
||||
</html>
|
||||
|
||||
@@ -36,16 +36,3 @@ export type DatetimeHighlight = { date: string } & DatetimeHighlightStyle;
|
||||
export type DatetimeHighlightCallback = (dateIsoString: string) => DatetimeHighlightStyle | undefined;
|
||||
|
||||
export type DatetimeHourCycle = 'h11' | 'h12' | 'h23' | 'h24';
|
||||
|
||||
/**
|
||||
* FormatOptions must include date and/or time; it cannot be an empty object
|
||||
*/
|
||||
export type FormatOptions =
|
||||
| {
|
||||
date: Intl.DateTimeFormatOptions;
|
||||
time?: Intl.DateTimeFormatOptions;
|
||||
}
|
||||
| {
|
||||
date?: Intl.DateTimeFormatOptions;
|
||||
time: Intl.DateTimeFormatOptions;
|
||||
};
|
||||
|
||||
@@ -20,7 +20,6 @@ import type {
|
||||
DatetimeHighlightStyle,
|
||||
DatetimeHighlightCallback,
|
||||
DatetimeHourCycle,
|
||||
FormatOptions,
|
||||
} from './datetime-interface';
|
||||
import { isSameDay, warnIfValueOutOfBounds, isBefore, isAfter } from './utils/comparison';
|
||||
import {
|
||||
@@ -34,7 +33,7 @@ import {
|
||||
getTimeColumnsData,
|
||||
getCombinedDateColumnData,
|
||||
} from './utils/data';
|
||||
import { formatValue, getLocalizedDateTime, getLocalizedTime, getMonthAndYear } from './utils/format';
|
||||
import { formatValue, getLocalizedTime, getMonthAndDay, getMonthAndYear } from './utils/format';
|
||||
import { isLocaleDayPeriodRTL, isMonthFirstLocale, getNumDaysInMonth, getHourCycle } from './utils/helpers';
|
||||
import {
|
||||
calculateHourFromAMPM,
|
||||
@@ -69,7 +68,6 @@ import {
|
||||
isNextMonthDisabled,
|
||||
isPrevMonthDisabled,
|
||||
} from './utils/state';
|
||||
import { checkForPresentationFormatMismatch, warnIfTimeZoneProvided } from './utils/validate';
|
||||
|
||||
/**
|
||||
* @virtualProp {"ios" | "md"} mode - The mode determines which platform styles to use.
|
||||
@@ -108,7 +106,6 @@ export class Datetime implements ComponentInterface {
|
||||
private calendarBodyRef?: HTMLElement;
|
||||
private monthYearToggleItemRef?: HTMLIonItemElement;
|
||||
private popoverRef?: HTMLIonPopoverElement;
|
||||
private intersectionTrackerRef?: HTMLElement;
|
||||
private clearFocusVisible?: () => void;
|
||||
private parsedMinuteValues?: number[];
|
||||
private parsedHourValues?: number[];
|
||||
@@ -174,20 +171,6 @@ export class Datetime implements ComponentInterface {
|
||||
*/
|
||||
@Prop() disabled = false;
|
||||
|
||||
/**
|
||||
* Formatting options for dates and times.
|
||||
* Should include a 'date' and/or 'time' object, each of which is of type [Intl.DateTimeFormatOptions](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/DateTimeFormat/DateTimeFormat#options).
|
||||
*
|
||||
*/
|
||||
@Prop() formatOptions?: FormatOptions;
|
||||
|
||||
@Watch('formatOptions')
|
||||
protected formatOptionsChanged() {
|
||||
const { el, formatOptions, presentation } = this;
|
||||
checkForPresentationFormatMismatch(el, presentation, formatOptions);
|
||||
warnIfTimeZoneProvided(el, formatOptions);
|
||||
}
|
||||
|
||||
/**
|
||||
* If `true`, the datetime appears normal but the selected date cannot be changed.
|
||||
*/
|
||||
@@ -252,12 +235,6 @@ export class Datetime implements ComponentInterface {
|
||||
*/
|
||||
@Prop() presentation: DatetimePresentation = 'date-time';
|
||||
|
||||
@Watch('presentation')
|
||||
protected presentationChanged() {
|
||||
const { el, formatOptions, presentation } = this;
|
||||
checkForPresentationFormatMismatch(el, presentation, formatOptions);
|
||||
}
|
||||
|
||||
private get isGridStyle() {
|
||||
const { presentation, preferWheel } = this;
|
||||
const hasDatePresentation = presentation === 'date' || presentation === 'date-time' || presentation === 'time-date';
|
||||
@@ -1080,8 +1057,6 @@ export class Datetime implements ComponentInterface {
|
||||
}
|
||||
|
||||
componentDidLoad() {
|
||||
const { el, intersectionTrackerRef } = this;
|
||||
|
||||
/**
|
||||
* If a scrollable element is hidden using `display: none`,
|
||||
* it will not have a scroll height meaning we cannot scroll elements
|
||||
@@ -1109,7 +1084,7 @@ export class Datetime implements ComponentInterface {
|
||||
this.el.classList.add('datetime-ready');
|
||||
});
|
||||
};
|
||||
const visibleIO = new IntersectionObserver(visibleCallback, { threshold: 0.01, root: el });
|
||||
const visibleIO = new IntersectionObserver(visibleCallback, { threshold: 0.01 });
|
||||
|
||||
/**
|
||||
* Use raf to avoid a race condition between the component loading and
|
||||
@@ -1117,7 +1092,7 @@ export class Datetime implements ComponentInterface {
|
||||
* could cause the datetime to start at a visibility of 0, erroneously
|
||||
* triggering the `hiddenIO` observer below.
|
||||
*/
|
||||
raf(() => visibleIO?.observe(intersectionTrackerRef!));
|
||||
raf(() => visibleIO?.observe(this.el));
|
||||
|
||||
/**
|
||||
* We need to clean up listeners when the datetime is hidden
|
||||
@@ -1147,8 +1122,8 @@ export class Datetime implements ComponentInterface {
|
||||
this.el.classList.remove('datetime-ready');
|
||||
});
|
||||
};
|
||||
const hiddenIO = new IntersectionObserver(hiddenCallback, { threshold: 0, root: el });
|
||||
raf(() => hiddenIO?.observe(intersectionTrackerRef!));
|
||||
const hiddenIO = new IntersectionObserver(hiddenCallback, { threshold: 0 });
|
||||
raf(() => hiddenIO?.observe(this.el));
|
||||
|
||||
/**
|
||||
* Datetime uses Ionic components that emit
|
||||
@@ -1382,7 +1357,7 @@ export class Datetime implements ComponentInterface {
|
||||
};
|
||||
|
||||
componentWillLoad() {
|
||||
const { el, formatOptions, highlightedDates, multiple, presentation, preferWheel } = this;
|
||||
const { el, highlightedDates, multiple, presentation, preferWheel } = this;
|
||||
|
||||
if (multiple) {
|
||||
if (presentation !== 'date') {
|
||||
@@ -1407,11 +1382,6 @@ export class Datetime implements ComponentInterface {
|
||||
}
|
||||
}
|
||||
|
||||
if (formatOptions) {
|
||||
checkForPresentationFormatMismatch(el, presentation, formatOptions);
|
||||
warnIfTimeZoneProvided(el, formatOptions);
|
||||
}
|
||||
|
||||
const hourValues = (this.parsedHourValues = convertToArrayOfNumbers(this.hourValues));
|
||||
const minuteValues = (this.parsedMinuteValues = convertToArrayOfNumbers(this.minuteValues));
|
||||
const monthValues = (this.parsedMonthValues = convertToArrayOfNumbers(this.monthValues));
|
||||
@@ -2384,7 +2354,7 @@ export class Datetime implements ComponentInterface {
|
||||
}
|
||||
|
||||
private renderTimeOverlay() {
|
||||
const { disabled, hourCycle, isTimePopoverOpen, locale, formatOptions } = this;
|
||||
const { disabled, hourCycle, isTimePopoverOpen, locale } = this;
|
||||
const computedHourCycle = getHourCycle(locale, hourCycle);
|
||||
const activePart = this.getActivePartsWithFallback();
|
||||
|
||||
@@ -2419,7 +2389,7 @@ export class Datetime implements ComponentInterface {
|
||||
}
|
||||
}}
|
||||
>
|
||||
{getLocalizedTime(locale, activePart, computedHourCycle, formatOptions?.time)}
|
||||
{getLocalizedTime(locale, activePart, computedHourCycle)}
|
||||
</button>,
|
||||
<ion-popover
|
||||
alignment="center"
|
||||
@@ -2454,7 +2424,7 @@ export class Datetime implements ComponentInterface {
|
||||
}
|
||||
|
||||
private getHeaderSelectedDateText() {
|
||||
const { activeParts, formatOptions, multiple, titleSelectedDatesFormatter } = this;
|
||||
const { activeParts, multiple, titleSelectedDatesFormatter } = this;
|
||||
const isArray = Array.isArray(activeParts);
|
||||
|
||||
let headerText: string;
|
||||
@@ -2469,11 +2439,7 @@ export class Datetime implements ComponentInterface {
|
||||
}
|
||||
} else {
|
||||
// for exactly 1 day selected (multiple set or not), show a formatted version of that
|
||||
headerText = getLocalizedDateTime(
|
||||
this.locale,
|
||||
this.getActivePartsWithFallback(),
|
||||
formatOptions?.date ?? { weekday: 'short', month: 'short', day: 'numeric' }
|
||||
);
|
||||
headerText = getMonthAndDay(this.locale, this.getActivePartsWithFallback());
|
||||
}
|
||||
|
||||
return headerText;
|
||||
@@ -2616,20 +2582,6 @@ export class Datetime implements ComponentInterface {
|
||||
}),
|
||||
}}
|
||||
>
|
||||
{/*
|
||||
WebKit has a quirk where IntersectionObserver callbacks are delayed until after
|
||||
an accelerated animation finishes if the "root" specified in the config is the
|
||||
browser viewport (the default behavior if "root" is not specified). This means
|
||||
that when presenting a datetime in a modal on iOS the calendar body appears
|
||||
blank until the modal animation finishes.
|
||||
|
||||
We can work around this by observing .intersection-tracker and using the host
|
||||
(ion-datetime) as the "root". This allows the IO callback to fire the moment
|
||||
the datetime is visible. The .intersection-tracker element should not have
|
||||
dimensions or additional styles, and it should not be positioned absolutely
|
||||
otherwise the IO callback may fire at unexpected times.
|
||||
*/}
|
||||
<div class="intersection-tracker" ref={(el) => (this.intersectionTrackerRef = el)}></div>
|
||||
{this.renderDatetime(mode)}
|
||||
</Host>
|
||||
);
|
||||
|
||||
@@ -323,12 +323,7 @@ configs({ modes: ['md'], directions: ['ltr'] }).forEach(({ title, config }) => {
|
||||
*/
|
||||
configs({ modes: ['ios'], directions: ['ltr'] }).forEach(({ title, config }) => {
|
||||
test.describe(title('datetime: visibility'), () => {
|
||||
// TODO FW-6015 re-enable on webkit when bug is fixed
|
||||
test('should reset month/year interface when hiding datetime', async ({ page, skip }) => {
|
||||
skip.browser(
|
||||
'webkit',
|
||||
'This is buggy in a headless Linux environment: https://bugs.webkit.org/show_bug.cgi?id=270358'
|
||||
);
|
||||
test('should reset month/year interface when hiding datetime', async ({ page }) => {
|
||||
await page.setContent(
|
||||
`
|
||||
<ion-datetime></ion-datetime>
|
||||
@@ -570,107 +565,3 @@ configs({ directions: ['ltr'] }).forEach(({ title, screenshot, config }) => {
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
/**
|
||||
* This behavior does not differ across
|
||||
* directions.
|
||||
*/
|
||||
configs({ directions: ['ltr'] }).forEach(({ title, config }) => {
|
||||
test.describe(title('datetime: formatOptions'), () => {
|
||||
test('should format header and time button', async ({ page }) => {
|
||||
await page.setContent(
|
||||
`
|
||||
<ion-datetime value="2022-02-01T16:30:00">
|
||||
<span slot="title">Select Date</span>
|
||||
</ion-datetime>
|
||||
<script>
|
||||
const datetime = document.querySelector('ion-datetime');
|
||||
datetime.formatOptions = {
|
||||
time: { hour: '2-digit', minute: '2-digit' },
|
||||
date: { day: '2-digit', month: 'long', era: 'short' },
|
||||
}
|
||||
</script>
|
||||
`,
|
||||
config
|
||||
);
|
||||
|
||||
await page.locator('.datetime-ready').waitFor();
|
||||
|
||||
const headerDate = page.locator('ion-datetime .datetime-selected-date');
|
||||
await expect(headerDate).toHaveText('February 01 AD');
|
||||
|
||||
const timeBody = page.locator('ion-datetime .time-body');
|
||||
await expect(timeBody).toHaveText('04:30 PM');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
/**
|
||||
* This behavior does not differ across
|
||||
* modes/directions.
|
||||
*/
|
||||
configs({ modes: ['md'], directions: ['ltr'] }).forEach(({ title, config }) => {
|
||||
test.describe(title('datetime: formatOptions misconfiguration errors'), () => {
|
||||
test('should log a warning if time zone is provided', async ({ page }) => {
|
||||
const logs: string[] = [];
|
||||
|
||||
page.on('console', (msg) => {
|
||||
if (msg.type() === 'warning') {
|
||||
logs.push(msg.text());
|
||||
}
|
||||
});
|
||||
|
||||
await page.setContent(
|
||||
`
|
||||
<ion-datetime value="2022-02-01T16:30:00" presentation="date">
|
||||
<span slot="title">Select Date</span>
|
||||
</ion-datetime>
|
||||
<script>
|
||||
const datetime = document.querySelector('ion-datetime');
|
||||
datetime.formatOptions = {
|
||||
date: { timeZone: 'UTC' },
|
||||
}
|
||||
</script>
|
||||
`,
|
||||
config
|
||||
);
|
||||
|
||||
await page.locator('.datetime-ready').waitFor();
|
||||
|
||||
expect(logs.length).toBe(1);
|
||||
expect(logs[0]).toContain(
|
||||
'[Ionic Warning]: Datetime: "timeZone" and "timeZoneName" are not supported in "formatOptions".'
|
||||
);
|
||||
});
|
||||
|
||||
test('should log a warning if the required formatOptions are not provided for a presentation', async ({ page }) => {
|
||||
const logs: string[] = [];
|
||||
|
||||
page.on('console', (msg) => {
|
||||
if (msg.type() === 'warning') {
|
||||
logs.push(msg.text());
|
||||
}
|
||||
});
|
||||
|
||||
await page.setContent(
|
||||
`
|
||||
<ion-datetime value="2022-02-01T16:30:00">
|
||||
<span slot="title">Select Date</span>
|
||||
</ion-datetime>
|
||||
<script>
|
||||
const datetime = document.querySelector('ion-datetime');
|
||||
datetime.formatOptions = {}
|
||||
</script>
|
||||
`,
|
||||
config
|
||||
);
|
||||
|
||||
await page.locator('.datetime-ready').waitFor();
|
||||
|
||||
expect(logs.length).toBe(1);
|
||||
expect(logs[0]).toContain(
|
||||
"[Ionic Warning]: Datetime: The 'date-time' presentation requires either a date or time object (or both) in formatOptions."
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -308,13 +308,6 @@
|
||||
</ion-datetime>
|
||||
</ion-modal>
|
||||
</div>
|
||||
|
||||
<div class="grid-item">
|
||||
<h2>formatOptions</h2>
|
||||
<ion-datetime value="2020-03-14T14:23:00.000Z" id="format-options-datetime">
|
||||
<span slot="title">Select Date</span>
|
||||
</ion-datetime>
|
||||
</div>
|
||||
</div>
|
||||
</ion-content>
|
||||
<script>
|
||||
@@ -410,12 +403,6 @@
|
||||
app.appendChild(modalElement);
|
||||
return modalElement;
|
||||
};
|
||||
|
||||
const formatOptions = document.querySelector('#format-options-datetime');
|
||||
formatOptions.formatOptions = {
|
||||
time: { hour: '2-digit', minute: '2-digit' },
|
||||
date: { day: '2-digit', month: 'long', era: 'short' },
|
||||
};
|
||||
</script>
|
||||
</ion-app>
|
||||
</body>
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
import type { DatetimeParts } from '../datetime-interface';
|
||||
import {
|
||||
generateDayAriaLabel,
|
||||
getMonthAndDay,
|
||||
getFormattedHour,
|
||||
addTimePadding,
|
||||
getMonthAndYear,
|
||||
getLocalizedDayPeriod,
|
||||
getLocalizedTime,
|
||||
stripTimeZone,
|
||||
} from '../utils/format';
|
||||
|
||||
describe('generateDayAriaLabel()', () => {
|
||||
@@ -37,6 +37,24 @@ describe('generateDayAriaLabel()', () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe('getMonthAndDay()', () => {
|
||||
it('should return Tue, May 11', () => {
|
||||
expect(getMonthAndDay('en-US', { month: 5, day: 11, year: 2021 })).toEqual('Tue, May 11');
|
||||
});
|
||||
|
||||
it('should return mar, 11 may', () => {
|
||||
expect(getMonthAndDay('es-ES', { month: 5, day: 11, year: 2021 })).toEqual('mar, 11 may');
|
||||
});
|
||||
|
||||
it('should return Sat, Apr 1', () => {
|
||||
expect(getMonthAndDay('en-US', { month: 4, day: 1, year: 2006 })).toEqual('Sat, Apr 1');
|
||||
});
|
||||
|
||||
it('should return sáb, 1 abr', () => {
|
||||
expect(getMonthAndDay('es-ES', { month: 4, day: 1, year: 2006 })).toEqual('sáb, 1 abr');
|
||||
});
|
||||
});
|
||||
|
||||
describe('getFormattedHour()', () => {
|
||||
it('should only add padding if using 24 hour time', () => {
|
||||
expect(getFormattedHour(1, 'h11')).toEqual('1');
|
||||
@@ -126,7 +144,6 @@ describe('getLocalizedTime', () => {
|
||||
|
||||
expect(getLocalizedTime('en-GB', datetimeParts, 'h12')).toEqual('12:00 am');
|
||||
});
|
||||
|
||||
it('should parse time-only values correctly', () => {
|
||||
const datetimeParts: Partial<DatetimeParts> = {
|
||||
hour: 22,
|
||||
@@ -136,79 +153,4 @@ describe('getLocalizedTime', () => {
|
||||
expect(getLocalizedTime('en-US', datetimeParts as DatetimeParts, 'h12')).toEqual('10:40 PM');
|
||||
expect(getLocalizedTime('en-US', datetimeParts as DatetimeParts, 'h23')).toEqual('22:40');
|
||||
});
|
||||
|
||||
it('should use formatOptions', () => {
|
||||
const datetimeParts: DatetimeParts = {
|
||||
day: 1,
|
||||
month: 1,
|
||||
year: 2022,
|
||||
hour: 9,
|
||||
minute: 40,
|
||||
};
|
||||
|
||||
const formatOptions: Intl.DateTimeFormatOptions = {
|
||||
hour: '2-digit',
|
||||
minute: '2-digit',
|
||||
dayPeriod: 'short',
|
||||
day: '2-digit',
|
||||
};
|
||||
|
||||
// Even though this method is intended to be used for time, the date may be displayed as well when passing formatOptions
|
||||
expect(getLocalizedTime('en-US', datetimeParts, 'h12', formatOptions)).toEqual('01, 09:40 in the morning');
|
||||
});
|
||||
|
||||
it('should override provided time zone with UTC', () => {
|
||||
const datetimeParts: DatetimeParts = {
|
||||
day: 1,
|
||||
month: 1,
|
||||
year: 2022,
|
||||
hour: 9,
|
||||
minute: 40,
|
||||
};
|
||||
|
||||
const formatOptions: Intl.DateTimeFormatOptions = {
|
||||
timeZone: 'Australia/Sydney',
|
||||
timeZoneName: 'long',
|
||||
hour: 'numeric',
|
||||
minute: 'numeric',
|
||||
};
|
||||
|
||||
expect(getLocalizedTime('en-US', datetimeParts, 'h12', formatOptions)).toEqual('9:40 AM');
|
||||
});
|
||||
|
||||
it('should not include time zone name', () => {
|
||||
const datetimeParts: DatetimeParts = {
|
||||
day: 1,
|
||||
month: 1,
|
||||
year: 2022,
|
||||
hour: 9,
|
||||
minute: 40,
|
||||
};
|
||||
|
||||
const formatOptions: Intl.DateTimeFormatOptions = {
|
||||
timeZone: 'America/Los_Angeles',
|
||||
timeZoneName: 'long',
|
||||
hour: 'numeric',
|
||||
minute: 'numeric',
|
||||
};
|
||||
|
||||
expect(getLocalizedTime('en-US', datetimeParts, 'h12', formatOptions)).toEqual('9:40 AM');
|
||||
});
|
||||
});
|
||||
|
||||
describe('stripTimeZone', () => {
|
||||
it('should remove the time zone name from the options and set the time zone to UTC', () => {
|
||||
const formatOptions: Intl.DateTimeFormatOptions = {
|
||||
timeZone: 'America/Los_Angeles',
|
||||
timeZoneName: 'long',
|
||||
hour: 'numeric',
|
||||
minute: 'numeric',
|
||||
};
|
||||
|
||||
expect(stripTimeZone(formatOptions)).toEqual({
|
||||
timeZone: 'UTC',
|
||||
hour: 'numeric',
|
||||
minute: 'numeric',
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
|
Before Width: | Height: | Size: 28 KiB After Width: | Height: | Size: 28 KiB |
|
Before Width: | Height: | Size: 28 KiB After Width: | Height: | Size: 28 KiB |
@@ -11,33 +11,7 @@ const getFormattedDayPeriod = (dayPeriod?: string) => {
|
||||
return dayPeriod.toUpperCase();
|
||||
};
|
||||
|
||||
/**
|
||||
* Including time zone options may lead to the rendered text showing a
|
||||
* different time from what was selected in the Datetime, which could cause
|
||||
* confusion.
|
||||
*/
|
||||
export const stripTimeZone = (formatOptions: Intl.DateTimeFormatOptions): Intl.DateTimeFormatOptions => {
|
||||
return {
|
||||
...formatOptions,
|
||||
/**
|
||||
* Setting the time zone to UTC ensures that the value shown is always the
|
||||
* same as what was selected and safeguards against older Safari bugs with
|
||||
* Intl.DateTimeFormat.
|
||||
*/
|
||||
timeZone: 'UTC',
|
||||
/**
|
||||
* We do not want to display the time zone name
|
||||
*/
|
||||
timeZoneName: undefined,
|
||||
};
|
||||
};
|
||||
|
||||
export const getLocalizedTime = (
|
||||
locale: string,
|
||||
refParts: DatetimeParts,
|
||||
hourCycle: DatetimeHourCycle,
|
||||
formatOptions: Intl.DateTimeFormatOptions = { hour: 'numeric', minute: 'numeric' }
|
||||
): string => {
|
||||
export const getLocalizedTime = (locale: string, refParts: DatetimeParts, hourCycle: DatetimeHourCycle): string => {
|
||||
const timeParts: Pick<DatetimeParts, 'hour' | 'minute'> = {
|
||||
hour: refParts.hour,
|
||||
minute: refParts.minute,
|
||||
@@ -48,7 +22,15 @@ export const getLocalizedTime = (
|
||||
}
|
||||
|
||||
return new Intl.DateTimeFormat(locale, {
|
||||
...stripTimeZone(formatOptions),
|
||||
hour: 'numeric',
|
||||
minute: 'numeric',
|
||||
/**
|
||||
* Setting the timeZone to UTC prevents
|
||||
* new Intl.DatetimeFormat from subtracting
|
||||
* the user's current timezone offset
|
||||
* when formatting the time.
|
||||
*/
|
||||
timeZone: 'UTC',
|
||||
/**
|
||||
* We use hourCycle here instead of hour12 due to:
|
||||
* https://bugs.chromium.org/p/chromium/issues/detail?id=1347316&q=hour12&can=2
|
||||
@@ -164,6 +146,17 @@ export const generateDayAriaLabel = (locale: string, today: boolean, refParts: D
|
||||
return today ? `Today, ${labelString}` : labelString;
|
||||
};
|
||||
|
||||
/**
|
||||
* Gets the day of the week, month, and day
|
||||
* Used for the header in MD mode.
|
||||
*/
|
||||
export const getMonthAndDay = (locale: string, refParts: DatetimeParts) => {
|
||||
const date = getNormalizedDate(refParts);
|
||||
return new Intl.DateTimeFormat(locale, { weekday: 'short', month: 'short', day: 'numeric', timeZone: 'UTC' }).format(
|
||||
date
|
||||
);
|
||||
};
|
||||
|
||||
/**
|
||||
* Given a locale and a date object,
|
||||
* return a formatted string that includes
|
||||
@@ -175,6 +168,16 @@ export const getMonthAndYear = (locale: string, refParts: DatetimeParts) => {
|
||||
return new Intl.DateTimeFormat(locale, { month: 'long', year: 'numeric', timeZone: 'UTC' }).format(date);
|
||||
};
|
||||
|
||||
/**
|
||||
* Given a locale and a date object,
|
||||
* return a formatted string that includes
|
||||
* the short month, numeric day, and full year.
|
||||
* Example: Apr 22, 2021
|
||||
*/
|
||||
export const getMonthDayAndYear = (locale: string, refParts: DatetimeParts) => {
|
||||
return getLocalizedDateTime(locale, refParts, { month: 'short', day: 'numeric', year: 'numeric' });
|
||||
};
|
||||
|
||||
/**
|
||||
* Given a locale and a date object,
|
||||
* return a formatted string that includes
|
||||
@@ -232,7 +235,7 @@ export const getLocalizedDateTime = (
|
||||
options: Intl.DateTimeFormatOptions
|
||||
): string => {
|
||||
const date = getNormalizedDate(refParts);
|
||||
return getDateTimeFormat(locale, stripTimeZone(options)).format(date);
|
||||
return getDateTimeFormat(locale, options).format(date);
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,54 +0,0 @@
|
||||
import { printIonWarning } from '@utils/logging';
|
||||
|
||||
import type { DatetimePresentation, FormatOptions } from '../datetime-interface';
|
||||
|
||||
/**
|
||||
* If a time zone is provided in the format options, the rendered text could
|
||||
* differ from what was selected in the Datetime, which could cause
|
||||
* confusion.
|
||||
*/
|
||||
export const warnIfTimeZoneProvided = (el: HTMLElement, formatOptions?: FormatOptions) => {
|
||||
if (
|
||||
formatOptions?.date?.timeZone ||
|
||||
formatOptions?.date?.timeZoneName ||
|
||||
formatOptions?.time?.timeZone ||
|
||||
formatOptions?.time?.timeZoneName
|
||||
) {
|
||||
printIonWarning('Datetime: "timeZone" and "timeZoneName" are not supported in "formatOptions".', el);
|
||||
}
|
||||
};
|
||||
|
||||
export const checkForPresentationFormatMismatch = (
|
||||
el: HTMLElement,
|
||||
presentation: DatetimePresentation,
|
||||
formatOptions?: FormatOptions
|
||||
) => {
|
||||
// formatOptions is not required
|
||||
if (!formatOptions) return;
|
||||
|
||||
// If formatOptions is provided, the date and/or time objects are required, depending on the presentation
|
||||
switch (presentation) {
|
||||
case 'date':
|
||||
case 'month-year':
|
||||
case 'month':
|
||||
case 'year':
|
||||
if (formatOptions.date === undefined) {
|
||||
printIonWarning(`Datetime: The '${presentation}' presentation requires a date object in formatOptions.`, el);
|
||||
}
|
||||
break;
|
||||
case 'time':
|
||||
if (formatOptions.time === undefined) {
|
||||
printIonWarning(`Datetime: The 'time' presentation requires a time object in formatOptions.`, el);
|
||||
}
|
||||
break;
|
||||
case 'date-time':
|
||||
case 'time-date':
|
||||
if (formatOptions.date === undefined && formatOptions.time === undefined) {
|
||||
printIonWarning(
|
||||
`Datetime: The '${presentation}' presentation requires either a date or time object (or both) in formatOptions.`,
|
||||
el
|
||||
);
|
||||
}
|
||||
break;
|
||||
}
|
||||
};
|
||||
|
Before Width: | Height: | Size: 86 KiB After Width: | Height: | Size: 86 KiB |
|
Before Width: | Height: | Size: 84 KiB After Width: | Height: | Size: 84 KiB |
@@ -132,11 +132,8 @@
|
||||
* We use opacity: 0 to avoid a layout shift.
|
||||
* We target both the attribute and the class in the event that the attribute
|
||||
* is not reflected on the host in some frameworks.
|
||||
*
|
||||
* Both headers should be scoped to iOS mode otherwise an MD app that uses an
|
||||
* iOS header may cause other MD headers to be unexpectedly hidden.
|
||||
*/
|
||||
ion-header.header-ios:not(.header-collapse-main):has(~ ion-content ion-header.header-ios[collapse="condense"],
|
||||
~ ion-content ion-header.header-ios.header-collapse-condense) {
|
||||
ion-header:not(.header-collapse-main):has(~ ion-content ion-header[collapse="condense"],
|
||||
~ ion-content ion-header.header-collapse-condense) {
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
@@ -85,91 +85,3 @@ configs({ modes: ['ios'], directions: ['ltr'] }).forEach(({ title, screenshot, c
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
/**
|
||||
* This test only impacts MD applications
|
||||
*/
|
||||
configs({ modes: ['md'], directions: ['ltr'] }).forEach(({ title, screenshot, config }) => {
|
||||
test.describe(title('header: translucent'), () => {
|
||||
test('should not hide MD headers when using a descendant iOS header in an MD app', async ({ page }) => {
|
||||
test.info().annotations.push({
|
||||
type: 'issue',
|
||||
description: 'https://github.com/ionic-team/ionic-framework/issues/28867',
|
||||
});
|
||||
await page.setContent(
|
||||
`
|
||||
<ion-header id="main-header">
|
||||
<ion-toolbar>
|
||||
<ion-title>Header</ion-title>
|
||||
</ion-toolbar>
|
||||
</ion-header>
|
||||
<ion-content>
|
||||
<ion-header collapse="condense">
|
||||
<ion-toolbar>
|
||||
<ion-title size="large">Header</ion-title>
|
||||
</ion-toolbar>
|
||||
</ion-header>
|
||||
|
||||
<ion-header mode="ios">
|
||||
<ion-toolbar>
|
||||
<ion-title>Welcome</ion-title>
|
||||
</ion-toolbar>
|
||||
</ion-header>
|
||||
</ion-content>
|
||||
`,
|
||||
config
|
||||
);
|
||||
|
||||
const header = page.locator('ion-header#main-header');
|
||||
|
||||
/**
|
||||
* The existence of the iOS header in an MD app should not cause the main MD header
|
||||
* to be hidden. We do not have toHaveVisible because the behavior that hides
|
||||
* the header under correct circumstances does it using opacity: 0.
|
||||
* Playwright considers an element with opacity: 0 to still be visible
|
||||
* because it has a non-zero bounding box.
|
||||
*/
|
||||
await expect(header).toHaveScreenshot(screenshot('header-md-visibility-ios-descendant'));
|
||||
});
|
||||
test('should not hide MD headers when using a root iOS header in an MD app', async ({ page }) => {
|
||||
test.info().annotations.push({
|
||||
type: 'issue',
|
||||
description: 'https://github.com/ionic-team/ionic-framework/issues/28867',
|
||||
});
|
||||
await page.setContent(
|
||||
`
|
||||
<ion-header id="main-header" mode="ios">
|
||||
<ion-toolbar>
|
||||
<ion-title>Header</ion-title>
|
||||
</ion-toolbar>
|
||||
</ion-header>
|
||||
<ion-content>
|
||||
<ion-header collapse="condense">
|
||||
<ion-toolbar>
|
||||
<ion-title size="large">Header</ion-title>
|
||||
</ion-toolbar>
|
||||
</ion-header>
|
||||
|
||||
<ion-header>
|
||||
<ion-toolbar>
|
||||
<ion-title>Welcome</ion-title>
|
||||
</ion-toolbar>
|
||||
</ion-header>
|
||||
</ion-content>
|
||||
`,
|
||||
config
|
||||
);
|
||||
|
||||
const header = page.locator('ion-header#main-header');
|
||||
|
||||
/**
|
||||
* The existence of the iOS header in an MD app should not cause the main MD header
|
||||
* to be hidden. We do not have toHaveVisible because the behavior that hides
|
||||
* the header under correct circumstances does it using opacity: 0.
|
||||
* Playwright considers an element with opacity: 0 to still be visible
|
||||
* because it has a non-zero bounding box.
|
||||
*/
|
||||
await expect(header).toHaveScreenshot(screenshot('header-md-visibility-ios-main'));
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
|
Before Width: | Height: | Size: 1.4 KiB |
|
Before Width: | Height: | Size: 2.0 KiB |
|
Before Width: | Height: | Size: 1.3 KiB |
|
Before Width: | Height: | Size: 1.3 KiB |
|
Before Width: | Height: | Size: 1.5 KiB |
|
Before Width: | Height: | Size: 1.1 KiB |
|
Before Width: | Height: | Size: 18 KiB After Width: | Height: | Size: 17 KiB |
@@ -1,5 +1,5 @@
|
||||
import type { ComponentInterface } from '@stencil/core';
|
||||
import { Component, Element, Host, Listen, Prop, State, Watch, forceUpdate, h } from '@stencil/core';
|
||||
import { Build, Component, Element, Host, Listen, Prop, State, Watch, forceUpdate, h } from '@stencil/core';
|
||||
import type { AnchorInterface, ButtonInterface } from '@utils/element-interface';
|
||||
import type { Attributes } from '@utils/helpers';
|
||||
import { inheritAttributes, raf } from '@utils/helpers';
|
||||
@@ -358,6 +358,15 @@ export class Item implements ComponentInterface, AnchorInterface, ButtonInterfac
|
||||
}
|
||||
|
||||
private getFirstInteractive() {
|
||||
if (Build.isTesting) {
|
||||
/**
|
||||
* Pseudo selectors can't be tested in unit tests.
|
||||
* It will cause an error when running the tests.
|
||||
*
|
||||
* TODO: FW-5205 - Remove the build conditional when this is fixed in Stencil
|
||||
*/
|
||||
return undefined;
|
||||
}
|
||||
const controls = this.el.querySelectorAll<HTMLElement>(
|
||||
'ion-toggle:not([disabled]), ion-checkbox:not([disabled]), ion-radio:not([disabled]), ion-select:not([disabled])'
|
||||
);
|
||||
|
||||
@@ -12,6 +12,165 @@
|
||||
<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>
|
||||
/*
|
||||
* Dark Colors
|
||||
* -------------------------------------------
|
||||
*/
|
||||
|
||||
body.dark {
|
||||
--ion-color-primary: #428cff;
|
||||
--ion-color-primary-rgb: 66, 140, 255;
|
||||
--ion-color-primary-contrast: #ffffff;
|
||||
--ion-color-primary-contrast-rgb: 255, 255, 255;
|
||||
--ion-color-primary-shade: #3a7be0;
|
||||
--ion-color-primary-tint: #5598ff;
|
||||
|
||||
--ion-color-secondary: #50c8ff;
|
||||
--ion-color-secondary-rgb: 80, 200, 255;
|
||||
--ion-color-secondary-contrast: #ffffff;
|
||||
--ion-color-secondary-contrast-rgb: 255, 255, 255;
|
||||
--ion-color-secondary-shade: #46b0e0;
|
||||
--ion-color-secondary-tint: #62ceff;
|
||||
|
||||
--ion-color-tertiary: #6a64ff;
|
||||
--ion-color-tertiary-rgb: 106, 100, 255;
|
||||
--ion-color-tertiary-contrast: #ffffff;
|
||||
--ion-color-tertiary-contrast-rgb: 255, 255, 255;
|
||||
--ion-color-tertiary-shade: #5d58e0;
|
||||
--ion-color-tertiary-tint: #7974ff;
|
||||
|
||||
--ion-color-success: #2fdf75;
|
||||
--ion-color-success-rgb: 47, 223, 117;
|
||||
--ion-color-success-contrast: #000000;
|
||||
--ion-color-success-contrast-rgb: 0, 0, 0;
|
||||
--ion-color-success-shade: #29c467;
|
||||
--ion-color-success-tint: #44e283;
|
||||
|
||||
--ion-color-warning: #ffd534;
|
||||
--ion-color-warning-rgb: 255, 213, 52;
|
||||
--ion-color-warning-contrast: #000000;
|
||||
--ion-color-warning-contrast-rgb: 0, 0, 0;
|
||||
--ion-color-warning-shade: #e0bb2e;
|
||||
--ion-color-warning-tint: #ffd948;
|
||||
|
||||
--ion-color-danger: #ff4961;
|
||||
--ion-color-danger-rgb: 255, 73, 97;
|
||||
--ion-color-danger-contrast: #ffffff;
|
||||
--ion-color-danger-contrast-rgb: 255, 255, 255;
|
||||
--ion-color-danger-shade: #e04055;
|
||||
--ion-color-danger-tint: #ff5b71;
|
||||
|
||||
--ion-color-dark: #f4f5f8;
|
||||
--ion-color-dark-rgb: 244, 245, 248;
|
||||
--ion-color-dark-contrast: #000000;
|
||||
--ion-color-dark-contrast-rgb: 0, 0, 0;
|
||||
--ion-color-dark-shade: #d7d8da;
|
||||
--ion-color-dark-tint: #f5f6f9;
|
||||
|
||||
--ion-color-medium: #989aa2;
|
||||
--ion-color-medium-rgb: 152, 154, 162;
|
||||
--ion-color-medium-contrast: #000000;
|
||||
--ion-color-medium-contrast-rgb: 0, 0, 0;
|
||||
--ion-color-medium-shade: #86888f;
|
||||
--ion-color-medium-tint: #a2a4ab;
|
||||
|
||||
--ion-color-light: #222428;
|
||||
--ion-color-light-rgb: 34, 36, 40;
|
||||
--ion-color-light-contrast: #ffffff;
|
||||
--ion-color-light-contrast-rgb: 255, 255, 255;
|
||||
--ion-color-light-shade: #1e2023;
|
||||
--ion-color-light-tint: #383a3e;
|
||||
}
|
||||
|
||||
/*
|
||||
* iOS Dark Theme
|
||||
* -------------------------------------------
|
||||
*/
|
||||
|
||||
.ios body.dark {
|
||||
--ion-background-color: #000000;
|
||||
--ion-background-color-rgb: 0, 0, 0;
|
||||
|
||||
--ion-text-color: #ffffff;
|
||||
--ion-text-color-rgb: 255, 255, 255;
|
||||
|
||||
--ion-color-step-50: #0d0d0d;
|
||||
--ion-color-step-100: #1a1a1a;
|
||||
--ion-color-step-150: #262626;
|
||||
--ion-color-step-200: #333333;
|
||||
--ion-color-step-250: #404040;
|
||||
--ion-color-step-300: #4d4d4d;
|
||||
--ion-color-step-350: #595959;
|
||||
--ion-color-step-400: #666666;
|
||||
--ion-color-step-450: #737373;
|
||||
--ion-color-step-500: #808080;
|
||||
--ion-color-step-550: #8c8c8c;
|
||||
--ion-color-step-600: #999999;
|
||||
--ion-color-step-650: #a6a6a6;
|
||||
--ion-color-step-700: #b3b3b3;
|
||||
--ion-color-step-750: #bfbfbf;
|
||||
--ion-color-step-800: #cccccc;
|
||||
--ion-color-step-850: #d9d9d9;
|
||||
--ion-color-step-900: #e6e6e6;
|
||||
--ion-color-step-950: #f2f2f2;
|
||||
|
||||
--ion-item-background: #000000;
|
||||
|
||||
--ion-card-background: #1c1c1d;
|
||||
}
|
||||
|
||||
.ios body.dark ion-modal {
|
||||
--ion-background-color: var(--ion-color-step-100);
|
||||
--ion-toolbar-background: var(--ion-color-step-150);
|
||||
--ion-toolbar-border-color: var(--ion-color-step-250);
|
||||
--ion-item-background: var(--ion-color-step-150);
|
||||
}
|
||||
|
||||
/*
|
||||
* Material Design Dark Theme
|
||||
* -------------------------------------------
|
||||
*/
|
||||
|
||||
.md body.dark {
|
||||
--ion-background-color: #121212;
|
||||
--ion-background-color-rgb: 18, 18, 18;
|
||||
|
||||
--ion-text-color: #ffffff;
|
||||
--ion-text-color-rgb: 255, 255, 255;
|
||||
|
||||
--ion-border-color: #222222;
|
||||
|
||||
--ion-color-step-50: #1e1e1e;
|
||||
--ion-color-step-100: #2a2a2a;
|
||||
--ion-color-step-150: #363636;
|
||||
--ion-color-step-200: #414141;
|
||||
--ion-color-step-250: #4d4d4d;
|
||||
--ion-color-step-300: #595959;
|
||||
--ion-color-step-350: #656565;
|
||||
--ion-color-step-400: #717171;
|
||||
--ion-color-step-450: #7d7d7d;
|
||||
--ion-color-step-500: #898989;
|
||||
--ion-color-step-550: #949494;
|
||||
--ion-color-step-600: #a0a0a0;
|
||||
--ion-color-step-650: #acacac;
|
||||
--ion-color-step-700: #b8b8b8;
|
||||
--ion-color-step-750: #c4c4c4;
|
||||
--ion-color-step-800: #d0d0d0;
|
||||
--ion-color-step-850: #dbdbdb;
|
||||
--ion-color-step-900: #e7e7e7;
|
||||
--ion-color-step-950: #f3f3f3;
|
||||
|
||||
--ion-item-background: #1e1e1e;
|
||||
|
||||
--ion-toolbar-background: #1f1f1f;
|
||||
|
||||
--ion-tab-bar-background: #1f1f1f;
|
||||
|
||||
--ion-card-background: #1e1e1e;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
@@ -188,6 +347,12 @@
|
||||
</style>
|
||||
|
||||
<script>
|
||||
// TODO FW-4005
|
||||
const params = new URL(window.location).searchParams;
|
||||
const dark = params.get('dark');
|
||||
if (dark !== null) {
|
||||
document.body.classList.add('dark');
|
||||
}
|
||||
const attach = document.getElementById('attachClick');
|
||||
|
||||
attach.addEventListener('click', (ev) => {
|
||||
|
||||
@@ -19,34 +19,14 @@ configs().forEach(({ title, screenshot, config }) => {
|
||||
});
|
||||
});
|
||||
|
||||
configs({ directions: ['ltr'], themes: ['dark'] }).forEach(({ title, screenshot, config }) => {
|
||||
configs({ directions: ['ltr'] }).forEach(({ title, screenshot, config }) => {
|
||||
test.describe(title('item: buttons dark'), () => {
|
||||
test('should not have visual regressions in dark', async ({ page }) => {
|
||||
test.info().annotations.push({
|
||||
type: 'issue',
|
||||
description: 'https://github.com/ionic-team/ionic-framework/issues/27130',
|
||||
});
|
||||
await page.goto(`/src/components/item/test/buttons?dark=true`, config);
|
||||
|
||||
await page.setContent(
|
||||
`
|
||||
<ion-list>
|
||||
<ion-item button="true">
|
||||
<ion-label>Button Item</ion-label>
|
||||
</ion-item>
|
||||
<ion-item button="true" class="ion-activated">
|
||||
<ion-label>Activated Button Item</ion-label>
|
||||
</ion-item>
|
||||
<ion-item button="true" class="ion-focused">
|
||||
<ion-label>Focused Button Item</ion-label>
|
||||
</ion-item>
|
||||
</ion-list>
|
||||
`,
|
||||
config
|
||||
);
|
||||
await page.setIonViewport();
|
||||
|
||||
const list = page.locator('ion-list');
|
||||
|
||||
await expect(list).toHaveScreenshot(screenshot(`item-buttons-dark-diff`));
|
||||
await expect(page).toHaveScreenshot(screenshot(`item-buttons-dark-diff`));
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
|
After Width: | Height: | Size: 71 KiB |
|
After Width: | Height: | Size: 82 KiB |
|
After Width: | Height: | Size: 62 KiB |
|
Before Width: | Height: | Size: 7.7 KiB |
|
Before Width: | Height: | Size: 8.0 KiB |
|
Before Width: | Height: | Size: 6.8 KiB |