Compare commits

...

46 Commits

Author SHA1 Message Date
Brandy Smith
360fce73d4 chore: grab theme changes from next 2025-08-13 10:46:59 -04:00
Maria Hutt
8c21980a70 feat(theme): more changes 2025-08-12 15:50:23 -04:00
Maria Hutt
3c6bb9fb00 feat(core): component level theming 2025-08-12 15:50:11 -04:00
Maria Hutt
a130a4a63a feat(core): separate mode and theme 2025-08-12 15:48:22 -04:00
renovate[bot]
e5ed8a10ed chore(deps): update actions/checkout action to v5 (#30624)
This PR contains the following updates:

| Package | Type | Update | Change |
|---|---|---|---|
| [actions/checkout](https://redirect.github.com/actions/checkout) |
action | major | `v4` -> `v5` |

---

### Release Notes

<details>
<summary>actions/checkout (actions/checkout)</summary>

### [`v5`](https://redirect.github.com/actions/checkout/compare/v4...v5)

[Compare
Source](https://redirect.github.com/actions/checkout/compare/v4...v5)

</details>

---

### Configuration

📅 **Schedule**: Branch creation - "every weekday before 11am" (UTC),
Automerge - At any time (no schedule defined).

🚦 **Automerge**: Disabled by config. Please merge this manually once you
are satisfied.

♻ **Rebasing**: Never, or you tick the rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about this update
again.

---

- [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check
this box

---

This PR was generated by [Mend Renovate](https://mend.io/renovate/).
View the [repository job
log](https://developer.mend.io/github/ionic-team/ionic-framework).

<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0MS42MC40IiwidXBkYXRlZEluVmVyIjoiNDEuNjAuNCIsInRhcmdldEJyYW5jaCI6Im1haW4iLCJsYWJlbHMiOltdfQ==-->

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-08-12 15:03:46 +00:00
Brandy Smith
8b0769ce75 chore(github): update archive to include proxies (#30623)
Co-authored-by: Brandy Smith <6577830+brandyscarney@users.noreply.github.com>
2025-08-11 16:50:12 +00:00
Brandy Smith
2229c24bf5 test(vue): improve test app (#30610)
Co-authored-by: Brandy Smith <6577830+brandyscarney@users.noreply.github.com>
2025-08-08 17:37:39 +00:00
Brandy Smith
a6b19f40b2 chore(deps): downgrade @stencil/angular-output-target and @stencil/vue-output-target (#30614)
Co-authored-by: Brandy Smith <6577830+brandyscarney@users.noreply.github.com>
2025-08-07 14:53:47 +00:00
Brandy Smith
d91edcffdf merge release-8.7.2 (#30607)
v8.7.2
2025-08-06 13:28:26 -04:00
ionitron
4c1d0127b6 chore(): update package lock files 2025-08-06 17:05:40 +00:00
ionitron
7075808ba8 v8.7.2 2025-08-06 17:04:58 +00:00
renovate[bot]
67a1800094 chore(deps): update dependency @stencil/angular-output-target to v1 (#30506)
This PR contains the following updates:

| Package | Change | Age | Adoption | Passing | Confidence |
|---|---|---|---|---|---|
| [@stencil/angular-output-target](https://stenciljs.com/)
([source](https://redirect.github.com/stenciljs/output-targets)) |
[`^0.10.0` ->
`^1.0.0`](https://renovatebot.com/diffs/npm/@stencil%2fangular-output-target/0.10.2/1.0.0)
|
[![age](https://developer.mend.io/api/mc/badges/age/npm/@stencil%2fangular-output-target/1.0.0?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/@stencil%2fangular-output-target/1.0.0?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/@stencil%2fangular-output-target/0.10.2/1.0.0?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/@stencil%2fangular-output-target/0.10.2/1.0.0?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|

---

### Release Notes

<details>
<summary>stenciljs/output-targets
(@&#8203;stencil/angular-output-target)</summary>

###
[`v1.0.0`](https://redirect.github.com/stenciljs/output-targets/blob/HEAD/CHANGELOG.md#stencilssr010-stencilreact-output-target100-2025-04-03)

[Compare
Source](a3588e9051...@stencil/angular-output-target@1.0.0)

##### 🚀 Enhancement

-
[`2873b0e`](2873b0e03c)
feat(react): support Vite based SSR
([#&#8203;624](https://redirect.github.com/stenciljs/output-targets/issues/624))
([@&#8203;christian-bromann](https://redirect.github.com/christian-bromann))
-
[`5a1a276`](5a1a276143)
feat(ssr): support object hydration
([#&#8203;633](https://redirect.github.com/stenciljs/output-targets/issues/633))
([@&#8203;christian-bromann](https://redirect.github.com/christian-bromann))

</details>

---

### Configuration

📅 **Schedule**: Branch creation - "every weekday before 11am" (UTC),
Automerge - At any time (no schedule defined).

🚦 **Automerge**: Disabled by config. Please merge this manually once you
are satisfied.

♻ **Rebasing**: Never, or you tick the rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about this update
again.

---

- [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check
this box

---

This PR was generated by [Mend Renovate](https://mend.io/renovate/).
View the [repository job
log](https://developer.mend.io/github/ionic-team/ionic-framework).

<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0MC42Mi4xIiwidXBkYXRlZEluVmVyIjoiNDAuNjIuMSIsInRhcmdldEJyYW5jaCI6Im1haW4iLCJsYWJlbHMiOltdfQ==-->

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-08-06 15:53:08 +00:00
renovate[bot]
895ef4798e chore(deps): update playwright (#30596)
This PR contains the following updates:

| Package | Change | Age | Confidence | Type | Update |
|---|---|---|---|---|---|
| [@playwright/test](https://playwright.dev)
([source](https://redirect.github.com/microsoft/playwright)) |
[`^1.54.1` ->
`^1.54.2`](https://renovatebot.com/diffs/npm/@playwright%2ftest/1.54.1/1.54.2)
|
[![age](https://developer.mend.io/api/mc/badges/age/npm/@playwright%2ftest/1.54.2?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/@playwright%2ftest/1.54.1/1.54.2?slim=true)](https://docs.renovatebot.com/merge-confidence/)
| devDependencies | patch |
| mcr.microsoft.com/playwright | `v1.54.1` -> `v1.54.2` |
[![age](https://developer.mend.io/api/mc/badges/age/docker/mcr.microsoft.com%2fplaywright/v1.54.2?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![confidence](https://developer.mend.io/api/mc/badges/confidence/docker/mcr.microsoft.com%2fplaywright/v1.54.1/v1.54.2?slim=true)](https://docs.renovatebot.com/merge-confidence/)
| final | patch |

---

### Release Notes

<details>
<summary>microsoft/playwright (@&#8203;playwright/test)</summary>

###
[`v1.54.2`](https://redirect.github.com/microsoft/playwright/releases/tag/v1.54.2)

[Compare
Source](https://redirect.github.com/microsoft/playwright/compare/v1.54.1...v1.54.2)

##### Highlights


[https://github.com/microsoft/playwright/issues/36714](https://redirect.github.com/microsoft/playwright/issues/36714)
- \[Regression]: Codegen is not able to launch in Administrator Terminal
on Windows (ProtocolError: Protocol
error)[https://github.com/microsoft/playwright/issues/36828](https://redirect.github.com/microsoft/playwright/issues/36828)8
- \[Regression]: Playwright Codegen keeps spamming with selected
optio[https://github.com/microsoft/playwright/issues/36810](https://redirect.github.com/microsoft/playwright/issues/36810)10
- \[Regression]: Starting Codegen with target language doesn't work
anymore

#### Browser Versions

- Chromium 139.0.7258.5
- Mozilla Firefox 140.0.2
- WebKit 26.0

This version was also tested against the following stable channels:

- Google Chrome 140
- Microsoft Edge 140

</details>

---

### Configuration

📅 **Schedule**: Branch creation - "every weekday before 11am" (UTC),
Automerge - At any time (no schedule defined).

🚦 **Automerge**: Disabled by config. Please merge this manually once you
are satisfied.

♻ **Rebasing**: Never, or you tick the rebase/retry checkbox.

👻 **Immortal**: This PR will be recreated if closed unmerged. Get
[config
help](https://redirect.github.com/renovatebot/renovate/discussions) if
that's undesired.

---

- [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check
this box

---

This PR was generated by [Mend Renovate](https://mend.io/renovate/).
View the [repository job
log](https://developer.mend.io/github/ionic-team/ionic-framework).

<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0MS41MS4xIiwidXBkYXRlZEluVmVyIjoiNDEuNTEuMSIsInRhcmdldEJyYW5jaCI6Im1haW4iLCJsYWJlbHMiOltdfQ==-->

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-08-06 14:24:45 +00:00
renovate[bot]
f1e6a4bb71 chore(deps): update actions/download-artifact action to v5 (#30605)
This PR contains the following updates:

| Package | Type | Update | Change |
|---|---|---|---|
|
[actions/download-artifact](https://redirect.github.com/actions/download-artifact)
| action | major | `v4` -> `v5` |

---

### Release Notes

<details>
<summary>actions/download-artifact (actions/download-artifact)</summary>

###
[`v5`](https://redirect.github.com/actions/download-artifact/compare/v4...v5)

[Compare
Source](https://redirect.github.com/actions/download-artifact/compare/v4...v5)

</details>

---

### Configuration

📅 **Schedule**: Branch creation - "every weekday before 11am" (UTC),
Automerge - At any time (no schedule defined).

🚦 **Automerge**: Disabled by config. Please merge this manually once you
are satisfied.

♻ **Rebasing**: Never, or you tick the rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about this update
again.

---

- [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check
this box

---

This PR was generated by [Mend Renovate](https://mend.io/renovate/).
View the [repository job
log](https://developer.mend.io/github/ionic-team/ionic-framework).

<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0MS41MS4xIiwidXBkYXRlZEluVmVyIjoiNDEuNTEuMSIsInRhcmdldEJyYW5jaCI6Im1haW4iLCJsYWJlbHMiOltdfQ==-->

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-08-06 14:11:23 +00:00
renovate[bot]
a671b74756 chore(deps): update dependency @stencil/vue-output-target to v0.11.8 (#30585)
This PR contains the following updates:

| Package | Change | Age | Confidence |
|---|---|---|---|
| [@stencil/vue-output-target](https://stenciljs.com/)
([source](https://redirect.github.com/stenciljs/output-targets)) |
[`0.10.8` ->
`0.11.8`](https://renovatebot.com/diffs/npm/@stencil%2fvue-output-target/0.10.8/0.11.8)
|
[![age](https://developer.mend.io/api/mc/badges/age/npm/@stencil%2fvue-output-target/0.11.8?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/@stencil%2fvue-output-target/0.10.8/0.11.8?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|

---

### Release Notes

<details>
<summary>stenciljs/output-targets
(@&#8203;stencil/vue-output-target)</summary>

###
[`v0.11.8`](https://redirect.github.com/stenciljs/output-targets/compare/@stencil/vue-output-target@0.10.8...32f98e2301193518a63f5d25c7e3f9e7384697e3)

[Compare
Source](https://redirect.github.com/stenciljs/output-targets/compare/@stencil/vue-output-target@0.10.8...32f98e2301193518a63f5d25c7e3f9e7384697e3)

</details>

---

### Configuration

📅 **Schedule**: Branch creation - "every weekday before 11am" (UTC),
Automerge - At any time (no schedule defined).

🚦 **Automerge**: Disabled by config. Please merge this manually once you
are satisfied.

♻ **Rebasing**: Never, or you tick the rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about this update
again.

---

- [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check
this box

---

This PR was generated by [Mend Renovate](https://mend.io/renovate/).
View the [repository job
log](https://developer.mend.io/github/ionic-team/ionic-framework).

<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0MS40My41IiwidXBkYXRlZEluVmVyIjoiNDEuNDYuMyIsInRhcmdldEJyYW5jaCI6Im1haW4iLCJsYWJlbHMiOltdfQ==-->

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-08-06 13:41:03 +00:00
renovate[bot]
b9013c9457 chore(deps): update capacitor to v7.0.2 (#30604)
This PR contains the following updates:

| Package | Change | Age | Confidence |
|---|---|---|---|
|
[@capacitor/haptics](https://redirect.github.com/ionic-team/capacitor-plugins)
| [`7.0.1` ->
`7.0.2`](https://renovatebot.com/diffs/npm/@capacitor%2fhaptics/7.0.1/7.0.2)
|
[![age](https://developer.mend.io/api/mc/badges/age/npm/@capacitor%2fhaptics/7.0.2?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/@capacitor%2fhaptics/7.0.1/7.0.2?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
|
[@capacitor/keyboard](https://redirect.github.com/ionic-team/capacitor-plugins)
| [`7.0.1` ->
`7.0.2`](https://renovatebot.com/diffs/npm/@capacitor%2fkeyboard/7.0.1/7.0.2)
|
[![age](https://developer.mend.io/api/mc/badges/age/npm/@capacitor%2fkeyboard/7.0.2?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/@capacitor%2fkeyboard/7.0.1/7.0.2?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
|
[@capacitor/status-bar](https://redirect.github.com/ionic-team/capacitor-plugins)
| [`7.0.1` ->
`7.0.2`](https://renovatebot.com/diffs/npm/@capacitor%2fstatus-bar/7.0.1/7.0.2)
|
[![age](https://developer.mend.io/api/mc/badges/age/npm/@capacitor%2fstatus-bar/7.0.2?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/@capacitor%2fstatus-bar/7.0.1/7.0.2?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|

---

### Release Notes

<details>
<summary>ionic-team/capacitor-plugins
(@&#8203;capacitor/haptics)</summary>

###
[`v7.0.2`](https://redirect.github.com/ionic-team/capacitor-plugins/releases/tag/%40capacitor/app%407.0.2)

[Compare
Source](https://redirect.github.com/ionic-team/capacitor-plugins/compare/@capacitor/haptics@7.0.1...@capacitor/haptics@7.0.2)

**Note:** Version bump only for package
[@&#8203;capacitor/app](https://redirect.github.com/capacitor/app)

</details>

---

### Configuration

📅 **Schedule**: Branch creation - "every weekday before 11am" (UTC),
Automerge - At any time (no schedule defined).

🚦 **Automerge**: Disabled by config. Please merge this manually once you
are satisfied.

♻ **Rebasing**: Never, or you tick the rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about these
updates again.

---

- [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check
this box

---

This PR was generated by [Mend Renovate](https://mend.io/renovate/).
View the [repository job
log](https://developer.mend.io/github/ionic-team/ionic-framework).

<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0MS41MS4xIiwidXBkYXRlZEluVmVyIjoiNDEuNTEuMSIsInRhcmdldEJyYW5jaCI6Im1haW4iLCJsYWJlbHMiOltdfQ==-->

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-08-06 13:36:23 +00:00
Shane
dc764e45e9 test(react): general navigation improvement (#30602)
Issue number: resolves internal

---------

<!-- Please do not submit updates to dependencies unless it fixes an
issue. -->

<!-- Please try to limit your pull request to one type (bugfix, feature,
etc). Submit multiple pull requests if needed. -->

## What is the current behavior?

Manual navigation in the react tests is very finnicky

## What is the new behavior?
<!-- Please describe the behavior or changes that are being added by
this PR. -->

Improved react test navigation so it more consistently moves from page
to page if you're manually reviewing react tests. This was done mostly
by adding missing `ion-page` components, but also by adding an exact
match to the main component. They're still pretty shaky and not great,
but better than before.

## Does this introduce a breaking change?

- [ ] Yes
- [X] No

<!--
  If this introduces a breaking change:
1. Describe the impact and migration path for existing applications
below.
  2. Update the BREAKING.md file with the breaking change.
3. Add "BREAKING CHANGE: [...]" to the commit description when merging.
See
https://github.com/ionic-team/ionic-framework/blob/main/docs/CONTRIBUTING.md#footer
for more information.
-->


## Other information

<!-- Any other information that is important to this PR such as
screenshots of how the component looks before and after the change. -->

---------

Co-authored-by: Brandy Smith <brandyscarney@users.noreply.github.com>
Co-authored-by: Brandy Smith <6577830+brandyscarney@users.noreply.github.com>
2025-08-05 17:11:52 +00:00
Brandy Smith
1cd81b9230 fix(reorder-group): add children fallback for framework compatibility (#30593)
Issue number: resolves #30592

---------

## What is the current behavior?
Reorder group is failing for Angular, React & Vue due to the change from
`children` to `__children`.

## What is the new behavior?
- Fallback to `children` if `__children` is undefined.
- Adds an e2e test for Angular (depends on
https://github.com/ionic-team/ionic-framework/pull/30594)
- Tasks have been created to migrate and add e2e tests for the other
frameworks

## Does this introduce a breaking change?

- [ ] Yes
- [x] No

## Other information

Dev build: `8.7.2-dev.11754087334.1815cf22`

---------

Co-authored-by: Brandy Smith <6577830+brandyscarney@users.noreply.github.com>
2025-08-05 14:27:18 +00:00
Brandy Smith
05026c5a48 test(angular): migrate to playwright (#30594)
- Migrates Angular test app tests from Cypress to Playwright
- Resolves test TODOs with Angular 18
- Resolves nav TODO by adding in standalone components
- Updates browserslist to remove warnings

---------

Co-authored-by: Brandy Smith <6577830+brandyscarney@users.noreply.github.com>
2025-08-05 13:58:46 +00:00
Shane
a2e803a553 fix(tabs): add fallback to select tab if router integration fails (#30599)
Issue number: resolves #30552

---------

<!-- Please do not submit updates to dependencies unless it fixes an
issue. -->

<!-- Please try to limit your pull request to one type (bugfix, feature,
etc). Submit multiple pull requests if needed. -->

## What is the current behavior?
<!-- Please describe the current behavior that you are modifying. -->

Something caused a timing shift in v8.6.0 that messed up the timing
required for react router to set the active tab ID. Currently, when the
router goes to set the tab ID, it's possibly too early and the tab may
not exist yet, causing it to go unset.

## What is the new behavior?
<!-- Please describe the behavior or changes that are being added by
this PR. -->

This PR is a workaround that allows tabs to check when they're rendered
if a tab should be selected as a fallback for the router not setting
them. I don't think the tabs, in the long run, should be responsible for
this, but I think this is a good intermediate step until the upcoming
react router upgrade, when we can look into a better solution for react
router that may require less timing precision.

This PR also adds regression tests for React to make sure this doesn't
happen again without getting noticed.

## Does this introduce a breaking change?

- [ ] Yes
- [X] No

<!--
  If this introduces a breaking change:
1. Describe the impact and migration path for existing applications
below.
  2. Update the BREAKING.md file with the breaking change.
3. Add "BREAKING CHANGE: [...]" to the commit description when merging.
See
https://github.com/ionic-team/ionic-framework/blob/main/docs/CONTRIBUTING.md#footer
for more information.
-->


## Other information

<!-- Any other information that is important to this PR such as
screenshots of how the component looks before and after the change. -->

**Current dev build:**
```
8.7.2-dev.11754338216.1a548096
```
2025-08-04 22:08:04 +00:00
Brandy Smith
56265e35d1 test(core): fix flaky datetime and input-otp tests (#30598)
This fixes the flaky/failing tests here:

`should not have visual regressions with a custom styled calendar`
<img width="1658" height="916" alt="CleanShot 2025-08-04 at 13 46 12@2x"
src="https://github.com/user-attachments/assets/b5d54ee8-b315-4db0-b09b-65d9cd2fa7ca"
/>

`should switch the calendar header when moving to a month with a
different number of days`
<img width="2104" height="1752" alt="CleanShot 2025-08-04 at 13 45
33@2x"
src="https://github.com/user-attachments/assets/8a0cdb0b-6e9d-4b5c-a2df-f9174431492b"
/>

You can run them locally using:

- `npm run test.e2e.docker src/components/datetime/test/datetime.e2e.ts
-- --repeat-each=10`
- `npm run test.e2e.docker
src/components/datetime/test/custom/datetime.e2e.ts -- --repeat-each=10`

---------

Co-authored-by: Brandy Smith <6577830+brandyscarney@users.noreply.github.com>
2025-08-04 21:23:45 +00:00
renovate[bot]
95a7d710e7 chore(deps): update dependency chalk to v5.5.0 (#30597)
This PR contains the following updates:

| Package | Change | Age | Confidence |
|---|---|---|---|
| [chalk](https://redirect.github.com/chalk/chalk) | [`5.4.1` ->
`5.5.0`](https://renovatebot.com/diffs/npm/chalk/5.4.1/5.5.0) |
[![age](https://developer.mend.io/api/mc/badges/age/npm/chalk/5.5.0?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/chalk/5.4.1/5.5.0?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|

---

### Release Notes

<details>
<summary>chalk/chalk (chalk)</summary>

###
[`v5.5.0`](https://redirect.github.com/chalk/chalk/compare/v5.4.1...67db246ae0a2bbcc57c190d641c5d767e5275160)

[Compare
Source](https://redirect.github.com/chalk/chalk/compare/v5.4.1...v5.5.0)

</details>

---

### Configuration

📅 **Schedule**: Branch creation - "every weekday before 11am" (UTC),
Automerge - At any time (no schedule defined).

🚦 **Automerge**: Disabled by config. Please merge this manually once you
are satisfied.

♻ **Rebasing**: Never, or you tick the rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about this update
again.

---

- [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check
this box

---

This PR was generated by [Mend Renovate](https://mend.io/renovate/).
View the [repository job
log](https://developer.mend.io/github/ionic-team/ionic-framework).

<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0MS41MS4xIiwidXBkYXRlZEluVmVyIjoiNDEuNTEuMSIsInRhcmdldEJyYW5jaCI6Im1haW4iLCJsYWJlbHMiOltdfQ==-->

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-08-04 15:59:56 +00:00
Brandy Smith
a00a389df7 merge release-8.7.1 (#30588)
v8.7.1
2025-07-31 12:24:41 -04:00
Brandy Smith
a62d382171 docs(changelog): include stencil update 2025-07-31 12:00:21 -04:00
ionitron
8d39ea0c6e chore(): update package lock files 2025-07-31 15:56:19 +00:00
ionitron
e4c042834c v8.7.1 2025-07-31 15:55:42 +00:00
Brandy Smith
6203b88b9f chore(deps): update @stencil/core to v4.36.2 (#30587)
Issue number: resolves #30565

---------

## What is the current behavior?
Stencil is on v4.33.1

## What is the new behavior?
- Updates Stencil to v4.36.2
- Updates `children` references to `__children` in `reorder-group`

## Does this introduce a breaking change?

- [ ] Yes
- [x] No

## Other information

I searched through the repository for other components that may be
affected but did not find any.

Dev build: `8.7.1-dev.11753971948.1b297d94`
Reorder Example using dev build:
[StackBlitz](https://stackblitz.com/edit/5nrzhbja)
Router Example using dev build:
[StackBlitz](https://stackblitz.com/edit/rvpcflzx)

---------

Co-authored-by: Brandy Smith <6577830+brandyscarney@users.noreply.github.com>
2025-07-31 15:35:43 +00:00
Brandy Smith
fdb77960ad merge release-8.7.0 (#30583)
v8.7.0
2025-07-30 17:23:36 -04:00
ionitron
227d637998 chore(): update package lock files 2025-07-30 21:05:52 +00:00
ionitron
cbb4ad5683 v8.7.0 2025-07-30 21:05:10 +00:00
Brandy Smith
75f6c05fb9 feat(css): add new css utility classes for display and flex utils (#30567)
Issue number: resolves #22469

---------

- Adds new responsive display classes with the following values: `none`, `inline`, `inline-block`, `block`, `flex`, `inline-flex`, `grid`, `inline-grid`, `table`, `table-cell`, `table-row`
- Adds new responsive flex util classes for the following properties: `align-content`, `align-items`, `align-self`, `justify-content`, `flex-direction`, `flex-wrap`, `flex`, `flex-grow` , `flex-shrink`, `order`
- Adds e2e tests to verify the correct classes are in the CSS files

---------

Co-authored-by: Brandy Smith <6577830+brandyscarney@users.noreply.github.com>
2025-07-30 16:45:45 -04:00
Brandy Smith
d5627c7368 feat(datetime): add border property to highlightedDates (#30534)
Issue number: resolves #29833

---------

- Adds the `border` property for customizing the border of highlighted dates
- Adds the `border` to the e2e test for highlightedDates
- Updates screenshots

---------

Co-authored-by: Brandy Smith <6577830+brandyscarney@users.noreply.github.com>
2025-07-30 16:45:38 -04:00
Christian Bromann
74cd71af24 feat(deps): update ionicons to v8 (#30390)
Issue number: resolves #30445

---------

Updates all packages to use the latest version of Ionicons v8

---------

Co-authored-by: Brandy Smith <6577830+brandyscarney@users.noreply.github.com>
2025-07-30 16:45:20 -04:00
Shane
30d1910d6e feat(modal): add IonModalToken for injecting modal elements in Angular components (#30474)
Issue number: resolves #internal

---------

<!-- Please do not submit updates to dependencies unless it fixes an
issue. -->

<!-- Please try to limit your pull request to one type (bugfix, feature,
etc). Submit multiple pull requests if needed. -->

## What is the current behavior?
<!-- Please describe the current behavior that you are modifying. -->

Currently, we provide no injection access to angular modals, which makes
it difficult to connect to their events normally.

## What is the new behavior?
<!-- Please describe the behavior or changes that are being added by
this PR. -->

This is an attempt to allow easier programmatic access to the internals
of injected modals.

## Does this introduce a breaking change?

- [ ] Yes
- [X] No

<!--
  If this introduces a breaking change:
1. Describe the impact and migration path for existing applications
below.
  2. Update the BREAKING.md file with the breaking change.
3. Add "BREAKING CHANGE: [...]" to the commit description when merging.
See
https://github.com/ionic-team/ionic-framework/blob/main/docs/CONTRIBUTING.md#footer
for more information.
-->


## Other information

<!-- Any other information that is important to this PR such as
screenshots of how the component looks before and after the change. -->

Dev build: `8.6.2-dev.11749830167.1460aa73`
2025-07-30 16:43:02 -04:00
Brandy Smith
b154f4ed09 feat(reorder-group): add ionReorderStart, ionReorderMove, ionReorderEnd events (#30471)
Issue number: resolves #23148 resolves #27614

---------

The `ion-reorder-group` only emits an `ionItemReorder` event when the reorder gesture ends AND the item position has changed. There is no way to listen for when the gesture starts, is actively moving, or ends without the item changing position.

- Adds an `ionReorderStart` event that is fired without any details on the start of the gesture.
- Adds an `ionReorderMove` event that is fired continuously during gesture move and includes the `from` and `to` detail.
- Adds an `ionReorderEnd` event that is fired at the end of the gesture and always includes the `from` and `to` detail, even if they are the same.
- Deprecates the `ionItemReorder` event, recommending to use the `ionReorderEnd` instead.

- [ ] Yes
- [x] No

While this does not introduce a breaking change, it does deprecate the `ionItemReorder` event in favor of the `ionReorderEnd` event. This event behaves a bit differently since it is always emitted on end. If the `from` and `to` are the same, it will still emit them, so it's possible to check if they are the same to determine if `ionReorderEnd` fired without moving item positions.

----

Co-authored-by: sfinktah <sfinktah@github.spamtrak.org>
Co-authored-by: Brandy Smith <6577830+brandyscarney@users.noreply.github.com>
2025-07-30 16:42:53 -04:00
Brandy Smith
d25b8a34f2 merge release-8.6.7 (#30580)
v8.6.7
2025-07-30 16:40:34 -04:00
Brandy Smith
244f9a1dd6 docs(changelog): add in deps updates 2025-07-30 16:22:23 -04:00
ionitron
ffcf5d0268 chore(): update package lock files 2025-07-30 20:15:16 +00:00
ionitron
759147fab6 v8.6.7 2025-07-30 20:14:30 +00:00
Brandy Smith
dc713167f9 chore(deps): downgrade Stencil to v4.33.1 (#30579)
A major regression related to Reorder was found in Stencil v4.36. Downgrade Stencil until this can be resolved.

Co-authored-by: Brandy Smith <6577830+brandyscarney@users.noreply.github.com>
2025-07-30 16:07:32 -04:00
Brandy Smith
0f7dd51767 merge release-8.6.6 (#30575)
v8.6.6
2025-07-30 14:40:27 -04:00
Brandy Smith
31c5416a51 docs(changelog): include stencil version bump 2025-07-30 14:18:12 -04:00
ionitron
baed34722b chore(): update package lock files 2025-07-30 18:12:14 +00:00
ionitron
708d5845b9 v8.6.6 2025-07-30 18:11:38 +00:00
renovate[bot]
5780a95a9c chore(deps): update dependency @stencil/core to v4.36.2 (#30574)
This PR contains the following updates:

| Package | Change | Age | Confidence |
|---|---|---|---|
| [@stencil/core](https://stenciljs.com/)
([source](https://redirect.github.com/stenciljs/core)) | [`4.36.1` ->
`4.36.2`](https://renovatebot.com/diffs/npm/@stencil%2fcore/4.36.1/4.36.2)
|
[![age](https://developer.mend.io/api/mc/badges/age/npm/@stencil%2fcore/4.36.2?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/@stencil%2fcore/4.36.1/4.36.2?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|

---

### Release Notes

<details>
<summary>stenciljs/core (@&#8203;stencil/core)</summary>

###
[`v4.36.2`](https://redirect.github.com/stenciljs/core/blob/HEAD/CHANGELOG.md#-4362-2025-07-28)

[Compare
Source](https://redirect.github.com/stenciljs/core/compare/v4.36.1...v4.36.2)

##### Bug Fixes

- **bundle:** remove post order of node-resolve
([#&#8203;6353](https://redirect.github.com/stenciljs/core/issues/6353))
([19b56d1](19b56d1977)),
closes
[#&#8203;6335](https://redirect.github.com/stenciljs/core/issues/6335)

</details>

---

### Configuration

📅 **Schedule**: Branch creation - "every weekday before 11am" (UTC),
Automerge - At any time (no schedule defined).

🚦 **Automerge**: Disabled by config. Please merge this manually once you
are satisfied.

♻ **Rebasing**: Never, or you tick the rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about this update
again.

---

- [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check
this box

---

This PR was generated by [Mend Renovate](https://mend.io/renovate/).
View the [repository job
log](https://developer.mend.io/github/ionic-team/ionic-framework).

<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0MS40My41IiwidXBkYXRlZEluVmVyIjoiNDEuNDMuNSIsInRhcmdldEJyYW5jaCI6Im1haW4iLCJsYWJlbHMiOltdfQ==-->

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-07-30 13:43:31 +00:00
renovate[bot]
dd68369338 chore(deps): update dependency @stencil/core to v4.36.1 (#30524)
This PR contains the following updates:

| Package | Change | Age | Confidence |
|---|---|---|---|
| [@stencil/core](https://stenciljs.com/)
([source](https://redirect.github.com/stenciljs/core)) | [`4.33.1` ->
`4.36.0`](https://renovatebot.com/diffs/npm/@stencil%2fcore/4.33.1/4.36.0)
|
[![age](https://developer.mend.io/api/mc/badges/age/npm/@stencil%2fcore/4.36.0?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/@stencil%2fcore/4.33.1/4.36.0?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|

---

### Release Notes

<details>
<summary>stenciljs/core (@&#8203;stencil/core)</summary>

###
[`v4.36.0`](https://redirect.github.com/stenciljs/core/blob/HEAD/CHANGELOG.md#-4360-2025-07-15)

[Compare
Source](https://redirect.github.com/stenciljs/core/compare/v4.36.0...58bc2b5403312dd227b0c5d6f1de167559f2b015)

##### Bug Fixes

* contructable stylesheets with older immutable spec (chrome <99)
([#6332](https://github.com/stenciljs/core/issues/6332))
([2f363dd](2f363dd130)),
closes [#6326](https://github.com/stenciljs/core/issues/6326)
* **runtime:** check shadow root nodes before appending them
([#6342](https://github.com/stenciljs/core/issues/6342))
([c63f25d](c63f25d0b4))
* **runtime:** do not remove first comment - can break frameworks
([#6343](https://github.com/stenciljs/core/issues/6343))
([188e7db](188e7dbfd7))
* **runtime:** double check hostRef value
([#6341](https://github.com/stenciljs/core/issues/6341))
([051522f](051522f598))
* **runtime:** fix blur handling of non-scoped elements
([#6314](https://github.com/stenciljs/core/issues/6314))
([bfbd683](bfbd683efd))
* **runtime:** fix prettier
([d84f9e7](d84f9e7e5f))
* **ssr:** `scoped: true` components forwarded slots
([#6340](https://github.com/stenciljs/core/issues/6340))
([fd4b892](fd4b892a73)),
closes [#6337](https://github.com/stenciljs/core/issues/6337), closes
[#6339](https://github.com/stenciljs/core/issues/6339)


##### Features

* **moc-doc:** serialize `delegatesFocus` shadow DOM property
([#6333](https://github.com/stenciljs/core/issues/6333))
([56fe6e3](56fe6e35a3)),
closes [#6265](https://github.com/stenciljs/core/issues/6265)
* **runtime:** skip initial task queue to improve first time rendering
([#6331](https://github.com/stenciljs/core/issues/6331))
([6106c70](6106c70aa3)),
closes [#6317](https://github.com/stenciljs/core/issues/6317)


###
[`v4.35.3`](https://redirect.github.com/stenciljs/core/blob/HEAD/CHANGELOG.md#-4353-2025-07-02)

[Compare
Source](https://redirect.github.com/stenciljs/core/compare/v4.35.2...58bc2b5403312dd227b0c5d6f1de167559f2b015)

##### Bug Fixes

- **declarations:** add ToggleEvent type
([ac92210](ac9221076c))

###
[`v4.35.2`](https://redirect.github.com/stenciljs/core/blob/HEAD/CHANGELOG.md#-4352-2025-07-02)

[Compare
Source](https://redirect.github.com/stenciljs/core/compare/v4.35.1...v4.35.2)

##### Bug Fixes

- **ci:** hardening security of GH actions
([#&#8203;6305](https://redirect.github.com/stenciljs/core/issues/6305))
([3f80413](3f80413171))
- **compiler:** fix attachInternals should be usable without formAssoc…
([#&#8203;6286](https://redirect.github.com/stenciljs/core/issues/6286))
([7132259](7132259c40)),
closes
[#&#8203;6285](https://redirect.github.com/stenciljs/core/issues/6285)
- **declarations:** update toggle event handler types
([#&#8203;6323](https://redirect.github.com/stenciljs/core/issues/6323))
([5925974](5925974d85)),
closes
[#&#8203;6322](https://redirect.github.com/stenciljs/core/issues/6322)
- **mock-doc:** prevent infinite recursion in blur event handlers
([#&#8203;6310](https://redirect.github.com/stenciljs/core/issues/6310))
([092cacd](092cacda99)),
closes
[#&#8203;6307](https://redirect.github.com/stenciljs/core/issues/6307)
- **security:** update email for outreach
([9da2c90](9da2c907af))
- **ssr:** fixes for `scoped: true` components during SSR
([#&#8203;6311](https://redirect.github.com/stenciljs/core/issues/6311))
([b07dda6](b07dda6c94)),
closes
[#&#8203;6313](https://redirect.github.com/stenciljs/core/issues/6313)
- **ssr:** slow property hydration, incorrect rendering
([#&#8203;6325](https://redirect.github.com/stenciljs/core/issues/6325))
([f018c73](f018c7349c)),
closes
[#&#8203;6324](https://redirect.github.com/stenciljs/core/issues/6324)
- **utils:** single global stylesheet instance for performance
([#&#8203;6320](https://redirect.github.com/stenciljs/core/issues/6320))
([fe5d130](fe5d130127))
- **testing:** support browser executable path detection via environm…
([#&#8203;6308](https://redirect.github.com/stenciljs/core/issues/6308))
([b7e2b50](b7e2b50120)),
closes
[#&#8203;6213](https://redirect.github.com/stenciljs/core/issues/6213)

###
[`v4.35.1`](https://redirect.github.com/stenciljs/core/blob/HEAD/CHANGELOG.md#-4351-2025-06-17)

[Compare
Source](https://redirect.github.com/stenciljs/core/compare/v4.35.0...v4.35.1)

##### Bug Fixes

- **mock-doc:** ensure event bubbling follows shadow DOM boundaries
([#&#8203;6301](https://redirect.github.com/stenciljs/core/issues/6301))
([1304ffc](1304ffcbfe)),
closes
[#&#8203;5676](https://redirect.github.com/stenciljs/core/issues/5676)
- **ssr:** expand `::part` css selectors for ssr `scoped` components
([#&#8203;6298](https://redirect.github.com/stenciljs/core/issues/6298))
([da24af6](da24af6f5c)),
closes
[#&#8203;6297](https://redirect.github.com/stenciljs/core/issues/6297)
- **ssr:** named slot dom order with `serializeShadowRoot: 'scoped'`
components
([#&#8203;6300](https://redirect.github.com/stenciljs/core/issues/6300))
([96c0f13](96c0f13b06)),
closes
[#&#8203;6299](https://redirect.github.com/stenciljs/core/issues/6299)

###
[`v4.35.0`](https://redirect.github.com/stenciljs/core/blob/HEAD/CHANGELOG.md#-4350-2025-06-13)

[Compare
Source](https://redirect.github.com/stenciljs/core/compare/v4.34.0...v4.35.0)

##### Bug Fixes

- **ssr:** retain slotted node order in serializeShadowRoot: `scoped`
([#&#8203;6294](https://redirect.github.com/stenciljs/core/issues/6294))
([c1e032d](c1e032d562)),
closes
[#&#8203;6293](https://redirect.github.com/stenciljs/core/issues/6293)

##### Features

- **global-styles:** add new `addGlobalStyleToComponents` extras config
option to "opt-out" of new globalStyle behaviour
([#&#8203;6292](https://redirect.github.com/stenciljs/core/issues/6292))
([cd9778a](cd9778a2ac))

###
[`v4.34.0`](https://redirect.github.com/stenciljs/core/blob/HEAD/CHANGELOG.md#-4340-2025-06-11)

[Compare
Source](https://redirect.github.com/stenciljs/core/compare/v4.33.1...v4.34.0)

##### Bug Fixes

- **compiler:** Prevent `extTransformsPlugin` from outputting collection
dependency css
([#&#8203;3306](https://redirect.github.com/stenciljs/core/issues/3306))
([28e2a06](28e2a062f6)),
closes
[#&#8203;3305](https://redirect.github.com/stenciljs/core/issues/3305)
- **declarations:** update PluginTransformResults after Rollup update
([#&#8203;6232](https://redirect.github.com/stenciljs/core/issues/6232))
([6ff8075](6ff8075a85)),
closes
[#&#8203;6231](https://redirect.github.com/stenciljs/core/issues/6231)
- **mock-doc:** move slot event listener support from runtime to MockDoc
([#&#8203;6287](https://redirect.github.com/stenciljs/core/issues/6287))
([f2dd25d](f2dd25d7e0))
- resolve TypeScript interface conflicts between component methods and
HTMLElement
([#&#8203;6282](https://redirect.github.com/stenciljs/core/issues/6282))
([614d305](614d305b1d)),
closes
[#&#8203;4467](https://redirect.github.com/stenciljs/core/issues/4467)
- **runtime:** add addEventListener support for slot elements in scope
components
([#&#8203;6281](https://redirect.github.com/stenciljs/core/issues/6281))
([32f66bd](32f66bd1cf)),
closes
[#&#8203;6269](https://redirect.github.com/stenciljs/core/issues/6269)
- **runtime:** correct boolean attribute handling for form-associated
components
([#&#8203;6280](https://redirect.github.com/stenciljs/core/issues/6280))
([7fe6372](7fe6372c2a)),
closes
[#&#8203;5461](https://redirect.github.com/stenciljs/core/issues/5461)
- **ssr:** mixed ssr methods styles
([#&#8203;6289](https://redirect.github.com/stenciljs/core/issues/6289))
([e253ceb](e253cebf54)),
closes
[#&#8203;6288](https://redirect.github.com/stenciljs/core/issues/6288)
- update `CHANGELOG.md` location
([#&#8203;6283](https://redirect.github.com/stenciljs/core/issues/6283))
([36fca61](36fca61886))

##### Features

- **compiler:** improve file watching architecture and add external d…
([#&#8203;6279](https://redirect.github.com/stenciljs/core/issues/6279))
([0844538](0844538a04)),
closes
[#&#8203;3151](https://redirect.github.com/stenciljs/core/issues/3151)

#### 🥃
[4.33.1](https://redirect.github.com/stenciljs/core/compare/v4.33.0...v4.33.1)
(2025-06-03)

##### Bug Fixes

- **runtime:** conditionally apply global styles using
`supportsConstructableStylesheets` flag
([f4f815f](f4f815f462))

</details>

---

### Configuration

📅 **Schedule**: Branch creation - "every weekday before 11am" (UTC),
Automerge - At any time (no schedule defined).

🚦 **Automerge**: Disabled by config. Please merge this manually once you
are satisfied.

♻ **Rebasing**: Never, or you tick the rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about this update
again.

---

- [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check
this box

---

This PR was generated by [Mend Renovate](https://mend.io/renovate/).
View the [repository job
log](https://developer.mend.io/github/ionic-team/ionic-framework).

<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0MC42Mi4xIiwidXBkYXRlZEluVmVyIjoiNDEuMTcuMiIsInRhcmdldEJyYW5jaCI6Im1haW4iLCJsYWJlbHMiOltdfQ==-->

---------

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: Christian Bromann <git@bromann.dev>
Co-authored-by: Brandy Smith <6577830+brandyscarney@users.noreply.github.com>
2025-07-29 18:13:53 +00:00
280 changed files with 12799 additions and 29731 deletions

View File

@@ -8,7 +8,7 @@ inputs:
runs:
using: 'composite'
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v5
- uses: actions/setup-node@v4
with:
node-version: 22.x

View File

@@ -8,7 +8,7 @@ inputs:
runs:
using: 'composite'
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v5
- uses: actions/setup-node@v4
with:
node-version: 22.x
@@ -31,4 +31,6 @@ runs:
with:
name: ionic-core
output: core/CoreBuild.zip
paths: core/dist core/components core/css core/hydrate core/loader core/src/components.d.ts core/api.txt
# Include generated proxy files from Stencil output targets so
# framework builds can detect when they need to be updated
paths: core/dist core/components core/css core/hydrate core/loader core/src/components.d.ts core/api.txt packages/angular/src/directives/proxies.ts packages/angular/src/directives/proxies-list.ts packages/angular/standalone/src/directives/proxies.ts packages/vue/src/proxies.ts packages/react/src/components/proxies.ts packages/react/src/components/inner-proxies.ts packages/react/src/components/routing-proxies.ts

View File

@@ -10,7 +10,7 @@ inputs:
runs:
using: 'composite'
steps:
- uses: actions/download-artifact@v4
- uses: actions/download-artifact@v5
with:
name: ${{ inputs.name }}
path: ${{ inputs.path }}

View File

@@ -32,6 +32,10 @@ runs:
run: npm install
shell: bash
working-directory: ./packages/angular/test/build/${{ inputs.app }}
- name: Install Playwright Browsers
run: npx playwright install
shell: bash
working-directory: ./packages/angular/test/build/${{ inputs.app }}
- name: Sync Built Changes
run: npm run sync
shell: bash

View File

@@ -10,7 +10,7 @@ runs:
- uses: actions/setup-node@v4
with:
node-version: 22.x
- uses: actions/download-artifact@v4
- uses: actions/download-artifact@v5
with:
path: ./artifacts
- name: Extract Archives

View File

@@ -22,7 +22,7 @@ jobs:
build-core:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v5
- 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@v5
- 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@v5
- 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@v5
- 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@v5
- 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@v5
- uses: ./.github/workflows/actions/build-vue
build-vue-router:
needs: [build-vue]
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v5
- 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@v5
- 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@v5
- uses: ./.github/workflows/actions/build-angular
build-angular-server:
needs: [build-core]
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v5
- 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@v5
- 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@v5
- uses: ./.github/workflows/actions/build-react
build-react-router:
needs: [build-react]
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v5
- 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@v5
- 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@v5
- uses: ./.github/workflows/actions/test-react-e2e
with:
app: ${{ matrix.apps }}

View File

@@ -14,7 +14,7 @@ jobs:
permissions:
security-events: write
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v5
- uses: github/codeql-action/init@v3
with:
languages: javascript

View File

@@ -9,7 +9,7 @@ jobs:
outputs:
dev-hash: ${{ steps.create-dev-hash.outputs.DEV_HASH }}
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v5
# 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

View File

@@ -12,7 +12,7 @@ jobs:
outputs:
nightly-hash: ${{ steps.create-nightly-hash.outputs.NIGHTLY_HASH }}
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v5
# 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

View File

@@ -22,7 +22,7 @@ jobs:
release-core:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v5
- 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@v5
- 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@v5
- 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@v5
- 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@v5
- 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@v5
- name: Restore @ionic/core built cache
uses: ./.github/workflows/actions/download-archive
with:
@@ -168,7 +168,7 @@ jobs:
needs: [release-react]
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v5
- name: Restore @ionic/core built cache
uses: ./.github/workflows/actions/download-archive
with:
@@ -194,7 +194,7 @@ jobs:
needs: [release-vue]
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v5
- name: Restore @ionic/core built cache
uses: ./.github/workflows/actions/download-archive
with:

View File

@@ -48,7 +48,7 @@ jobs:
needs: [release-ionic]
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v5
with:
token: ${{ secrets.IONITRON_TOKEN }}
fetch-depth: 0
@@ -76,7 +76,7 @@ jobs:
needs: [finalize-release]
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v5
# Pull the latest version of the reference
# branch instead of the revision that triggered
# the workflow otherwise we won't get the commit

View File

@@ -26,7 +26,7 @@ jobs:
build-core-with-stencil-nightly:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v5
- 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@v5
- 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@v5
- 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@v5
- 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@v5
- 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@v5
- uses: ./.github/workflows/actions/build-vue
build-vue-router:
needs: [build-vue]
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v5
- 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@v5
- 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@v5
- 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@v5
- 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@v5
- 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@v5
- uses: ./.github/workflows/actions/build-react
build-react-router:
needs: [build-react]
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v5
- 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@v5
- 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@v5
- uses: ./.github/workflows/actions/test-react-e2e
with:
app: ${{ matrix.apps }}

View File

@@ -26,7 +26,7 @@ jobs:
build-core:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v5
- uses: ./.github/workflows/actions/build-core
test-core-screenshot:
@@ -47,7 +47,7 @@ jobs:
needs: [build-core]
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v5
- uses: ./.github/workflows/actions/test-core-screenshot
with:
shard: ${{ matrix.shard }}
@@ -59,7 +59,7 @@ jobs:
runs-on: ubuntu-latest
needs: [test-core-screenshot]
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v5
# Normally, we could just push with the
# default GITHUB_TOKEN, but that will
# not cause the build workflow

View File

@@ -3,6 +3,65 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [8.7.2](https://github.com/ionic-team/ionic-framework/compare/v8.7.1...v8.7.2) (2025-08-06)
### Bug Fixes
* **reorder-group:** add children fallback for framework compatibility ([#30593](https://github.com/ionic-team/ionic-framework/issues/30593)) ([1cd81b9](https://github.com/ionic-team/ionic-framework/commit/1cd81b92301378d55bce63a01dfcf95a91c92652)), closes [#30592](https://github.com/ionic-team/ionic-framework/issues/30592)
* **tabs:** add fallback to select tab if router integration fails ([#30599](https://github.com/ionic-team/ionic-framework/issues/30599)) ([a2e803a](https://github.com/ionic-team/ionic-framework/commit/a2e803a553dc58fc0e1599e515a56180a7ab263a)), closes [#30552](https://github.com/ionic-team/ionic-framework/issues/30552)
## [8.7.1](https://github.com/ionic-team/ionic-framework/compare/v8.7.0...v8.7.1) (2025-07-31)
### Dependencies
* **stencil:** upgrade `@stencil/core` to version 4.36.2
# [8.7.0](https://github.com/ionic-team/ionic-framework/compare/v8.6.7...v8.7.0) (2025-07-30)
### Features
* **css:** add new css utility classes for display and flex utils ([#30567](https://github.com/ionic-team/ionic-framework/issues/30567)) ([75f6c05](https://github.com/ionic-team/ionic-framework/commit/75f6c05fb96313ef890cc80a229a3a3ed3d57460)), closes [#22469](https://github.com/ionic-team/ionic-framework/issues/22469)
* **datetime:** add border property to highlightedDates ([#30534](https://github.com/ionic-team/ionic-framework/issues/30534)) ([d5627c7](https://github.com/ionic-team/ionic-framework/commit/d5627c73681faf658ea3b869f3fb04d708391eb9)), closes [#29833](https://github.com/ionic-team/ionic-framework/issues/29833)
* **deps:** update ionicons to v8 ([#30390](https://github.com/ionic-team/ionic-framework/issues/30390)) ([74cd71a](https://github.com/ionic-team/ionic-framework/commit/74cd71af243183aa738d11b280e155bdfd652126)), closes [#30445](https://github.com/ionic-team/ionic-framework/issues/30445)
* **modal:** add IonModalToken for injecting modal elements in Angular components ([#30474](https://github.com/ionic-team/ionic-framework/issues/30474)) ([30d1910](https://github.com/ionic-team/ionic-framework/commit/30d1910d6ea5428b414d0e127e7681f59426c538))
* **reorder-group:** add ionReorderStart, ionReorderMove, ionReorderEnd events ([#30471](https://github.com/ionic-team/ionic-framework/issues/30471)) ([b154f4e](https://github.com/ionic-team/ionic-framework/commit/b154f4ed095890f57ccab539fd9217976a5466e5)), closes [#23148](https://github.com/ionic-team/ionic-framework/issues/23148) [#27614](https://github.com/ionic-team/ionic-framework/issues/27614)
## [8.6.7](https://github.com/ionic-team/ionic-framework/compare/v8.6.6...v8.6.7) (2025-07-30)
### Dependencies
* **stencil:** downgrade `@stencil/core` to version 4.33.1
_Stencil has been downgraded due to an uncaught regression in Reorder._
## [8.6.6](https://github.com/ionic-team/ionic-framework/compare/v8.6.5...v8.6.6) (2025-07-30)
### Dependencies
* **stencil:** upgrade `@stencil/core` to version 4.36.2
## [8.6.5](https://github.com/ionic-team/ionic-framework/compare/v8.6.4...v8.6.5) (2025-07-16)

View File

@@ -3,6 +3,64 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [8.7.2](https://github.com/ionic-team/ionic-framework/compare/v8.7.1...v8.7.2) (2025-08-06)
### Bug Fixes
* **reorder-group:** add children fallback for framework compatibility ([#30593](https://github.com/ionic-team/ionic-framework/issues/30593)) ([1cd81b9](https://github.com/ionic-team/ionic-framework/commit/1cd81b92301378d55bce63a01dfcf95a91c92652)), closes [#30592](https://github.com/ionic-team/ionic-framework/issues/30592)
* **tabs:** add fallback to select tab if router integration fails ([#30599](https://github.com/ionic-team/ionic-framework/issues/30599)) ([a2e803a](https://github.com/ionic-team/ionic-framework/commit/a2e803a553dc58fc0e1599e515a56180a7ab263a)), closes [#30552](https://github.com/ionic-team/ionic-framework/issues/30552)
## [8.7.1](https://github.com/ionic-team/ionic-framework/compare/v8.7.0...v8.7.1) (2025-07-31)
### Dependencies
* **stencil:** upgrade `@stencil/core` to version 4.36.2
# [8.7.0](https://github.com/ionic-team/ionic-framework/compare/v8.6.7...v8.7.0) (2025-07-30)
### Features
* **css:** add new css utility classes for display and flex utils ([#30567](https://github.com/ionic-team/ionic-framework/issues/30567)) ([75f6c05](https://github.com/ionic-team/ionic-framework/commit/75f6c05fb96313ef890cc80a229a3a3ed3d57460)), closes [#22469](https://github.com/ionic-team/ionic-framework/issues/22469)
* **datetime:** add border property to highlightedDates ([#30534](https://github.com/ionic-team/ionic-framework/issues/30534)) ([d5627c7](https://github.com/ionic-team/ionic-framework/commit/d5627c73681faf658ea3b869f3fb04d708391eb9)), closes [#29833](https://github.com/ionic-team/ionic-framework/issues/29833)
* **deps:** update ionicons to v8 ([#30390](https://github.com/ionic-team/ionic-framework/issues/30390)) ([74cd71a](https://github.com/ionic-team/ionic-framework/commit/74cd71af243183aa738d11b280e155bdfd652126)), closes [#30445](https://github.com/ionic-team/ionic-framework/issues/30445)
* **reorder-group:** add ionReorderStart, ionReorderMove, ionReorderEnd events ([#30471](https://github.com/ionic-team/ionic-framework/issues/30471)) ([b154f4e](https://github.com/ionic-team/ionic-framework/commit/b154f4ed095890f57ccab539fd9217976a5466e5)), closes [#23148](https://github.com/ionic-team/ionic-framework/issues/23148) [#27614](https://github.com/ionic-team/ionic-framework/issues/27614)
## [8.6.7](https://github.com/ionic-team/ionic-framework/compare/v8.6.6...v8.6.7) (2025-07-30)
### Dependencies
* **stencil:** downgrade `@stencil/core` to version 4.33.1
_Stencil has been downgraded due to an uncaught regression in Reorder._
## [8.6.6](https://github.com/ionic-team/ionic-framework/compare/v8.6.5...v8.6.6) (2025-07-30)
### Dependencies
* **stencil:** upgrade `@stencil/core` to version 4.36.2
## [8.6.5](https://github.com/ionic-team/ionic-framework/compare/v8.6.4...v8.6.5) (2025-07-16)

View File

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

View File

@@ -1205,6 +1205,37 @@ ion-modal,part,backdrop
ion-modal,part,content
ion-modal,part,handle
ion-my-chip,shadow
ion-my-chip,prop,color,"danger" | "dark" | "light" | "medium" | "primary" | "secondary" | "success" | "tertiary" | "warning" | string & Record<never, never> | undefined,undefined,false,true
ion-my-chip,prop,disabled,boolean,false,false,false
ion-my-chip,prop,hue,"bold" | "subtle" | undefined,'subtle',false,false
ion-my-chip,prop,mode,"ios" | "md",undefined,false,false
ion-my-chip,prop,outline,boolean,false,false,false
ion-my-chip,prop,shape,"rectangular" | "round" | "soft" | undefined,'soft',false,false
ion-my-chip,prop,size,"large" | "small" | undefined,'small',false,false
ion-my-chip,prop,theme,"ios" | "md" | "ionic",undefined,false,false
ion-my-chip,css-prop,--ion-chip-border-width
ion-my-chip,css-prop,--ion-chip-focus-ring-color
ion-my-chip,css-prop,--ion-chip-focus-ring-width
ion-my-chip,css-prop,--ion-chip-font-weight
ion-my-chip,css-prop,--ion-chip-gap
ion-my-chip,css-prop,--ion-chip-hue-bold-bg
ion-my-chip,css-prop,--ion-chip-hue-bold-border-color
ion-my-chip,css-prop,--ion-chip-hue-bold-color
ion-my-chip,css-prop,--ion-chip-hue-subtle-bg
ion-my-chip,css-prop,--ion-chip-hue-subtle-border-color
ion-my-chip,css-prop,--ion-chip-hue-subtle-color
ion-my-chip,css-prop,--ion-chip-line-height
ion-my-chip,css-prop,--ion-chip-padding-horizontal
ion-my-chip,css-prop,--ion-chip-padding-vertical
ion-my-chip,css-prop,--ion-chip-shape-rectangular-border-radius
ion-my-chip,css-prop,--ion-chip-shape-round-border-radius
ion-my-chip,css-prop,--ion-chip-shape-soft-border-radius
ion-my-chip,css-prop,--ion-chip-size-large-font-size
ion-my-chip,css-prop,--ion-chip-size-large-min-height
ion-my-chip,css-prop,--ion-chip-size-small-font-size
ion-my-chip,css-prop,--ion-chip-size-small-min-height
ion-nav,shadow
ion-nav,prop,animated,boolean,true,false,false
ion-nav,prop,animation,((baseEl: any, opts?: any) => Animation) | undefined,undefined,false,false
@@ -1231,6 +1262,7 @@ ion-nav,event,ionNavWillChange,void,false
ion-nav-link,none
ion-nav-link,prop,component,Function | HTMLElement | ViewController | null | string | undefined,undefined,false,false
ion-nav-link,prop,componentProps,undefined | { [key: string]: any; },undefined,false,false
ion-nav-link,prop,mode,"ios" | "md",undefined,false,false
ion-nav-link,prop,routerAnimation,((baseEl: any, opts?: any) => Animation) | undefined,undefined,false,false
ion-nav-link,prop,routerDirection,"back" | "forward" | "root",'forward',false,false
@@ -1508,6 +1540,9 @@ ion-reorder-group,none
ion-reorder-group,prop,disabled,boolean,true,false,false
ion-reorder-group,method,complete,complete(listOrReorder?: boolean | any[]) => Promise<any>
ion-reorder-group,event,ionItemReorder,ItemReorderEventDetail,true
ion-reorder-group,event,ionReorderEnd,ReorderEndEventDetail,true
ion-reorder-group,event,ionReorderMove,ReorderMoveEventDetail,true
ion-reorder-group,event,ionReorderStart,void,true
ion-ripple-effect,shadow
ion-ripple-effect,prop,type,"bounded" | "unbounded",'bounded',false,false

131
core/package-lock.json generated
View File

@@ -1,16 +1,16 @@
{
"name": "@ionic/core",
"version": "8.6.5",
"version": "8.7.2",
"lockfileVersion": 2,
"requires": true,
"packages": {
"": {
"name": "@ionic/core",
"version": "8.6.5",
"version": "8.7.2",
"license": "MIT",
"dependencies": {
"@stencil/core": "4.33.1",
"ionicons": "^7.2.2",
"@stencil/core": "4.36.2",
"ionicons": "^8.0.13",
"tslib": "^2.1.0"
},
"devDependencies": {
@@ -22,7 +22,7 @@
"@clack/prompts": "^0.11.0",
"@ionic/eslint-config": "^0.3.0",
"@ionic/prettier-config": "^2.0.0",
"@playwright/test": "^1.54.1",
"@playwright/test": "^1.54.2",
"@rollup/plugin-node-resolve": "^8.4.0",
"@rollup/plugin-virtual": "^2.0.3",
"@stencil/angular-output-target": "^0.10.0",
@@ -672,27 +672,27 @@
}
},
"node_modules/@capacitor/haptics": {
"version": "7.0.1",
"resolved": "https://registry.npmjs.org/@capacitor/haptics/-/haptics-7.0.1.tgz",
"integrity": "sha512-ewZmspE5krgDUj5ZvUDcfNZvgerAIr+3bDSk6DLzyvBZ/dYmr/tMLu5H6WtYaaKYZJ32aZAudGpIal5epDyBYA==",
"version": "7.0.2",
"resolved": "https://registry.npmjs.org/@capacitor/haptics/-/haptics-7.0.2.tgz",
"integrity": "sha512-vqfeEM6s2zMgLjpITCTUIy7P/hadq/Gr5E/RClFgMJPB41Y5FsqOKD+j85/uwh8N2cf/aWaPeXUmjnTzJbEB2g==",
"dev": true,
"peerDependencies": {
"@capacitor/core": ">=7.0.0"
}
},
"node_modules/@capacitor/keyboard": {
"version": "7.0.1",
"resolved": "https://registry.npmjs.org/@capacitor/keyboard/-/keyboard-7.0.1.tgz",
"integrity": "sha512-Gi064vOARMac+x9/DmEFeywN9oAETMf3OYsMuYm9gA8SvdsDJ3QJqMoFnSEIORYXe21Jzt2SIEdLlpT65P/b2g==",
"version": "7.0.2",
"resolved": "https://registry.npmjs.org/@capacitor/keyboard/-/keyboard-7.0.2.tgz",
"integrity": "sha512-9We5BY1mu+QWOReDukr+6HxA4Bh0mKBU0txFtwXJdjBohttMYWJzB+dQf4oHrX8odiU2Cm/BfDdAU2wV06Cyig==",
"dev": true,
"peerDependencies": {
"@capacitor/core": ">=7.0.0"
}
},
"node_modules/@capacitor/status-bar": {
"version": "7.0.1",
"resolved": "https://registry.npmjs.org/@capacitor/status-bar/-/status-bar-7.0.1.tgz",
"integrity": "sha512-iDv3mXYo9CdxYRVwt3/pRyuk25p7Sn4GfaS/zMZyVIqTzsvKLCIIH3GdKK+ta+nsNcAVpCw/t5jFEBt1D18ctA==",
"version": "7.0.2",
"resolved": "https://registry.npmjs.org/@capacitor/status-bar/-/status-bar-7.0.2.tgz",
"integrity": "sha512-fYYkkdzCbQV+MjZVnaQTFl5I4bddnFW8ZrPVxDjNoGVPTUG7H58Ij1+NcuNxHLXjJvZOoZeYJ3w3I16Wb2zssw==",
"dev": true,
"peerDependencies": {
"@capacitor/core": ">=7.0.0"
@@ -1715,12 +1715,12 @@
}
},
"node_modules/@playwright/test": {
"version": "1.54.1",
"resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.54.1.tgz",
"integrity": "sha512-FS8hQ12acieG2dYSksmLOF7BNxnVf2afRJdCuM1eMSxj6QTSE6G4InGF7oApGgDb65MX7AwMVlIkpru0yZA4Xw==",
"version": "1.54.2",
"resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.54.2.tgz",
"integrity": "sha512-A+znathYxPf+72riFd1r1ovOLqsIIB0jKIoPjyK2kqEIe30/6jF6BC7QNluHuwUmsD2tv1XZVugN8GqfTMOxsA==",
"dev": true,
"dependencies": {
"playwright": "1.54.1"
"playwright": "1.54.2"
},
"bin": {
"playwright": "cli.js"
@@ -1914,9 +1914,9 @@
}
},
"node_modules/@stencil/core": {
"version": "4.33.1",
"resolved": "https://registry.npmjs.org/@stencil/core/-/core-4.33.1.tgz",
"integrity": "sha512-12k9xhAJBkpg598it+NRmaYIdEe6TSnsL/v6/KRXDcUyTK11VYwZQej2eHnMWtqot+znJ+GNTqb5YbiXi+5Low==",
"version": "4.36.2",
"resolved": "https://registry.npmjs.org/@stencil/core/-/core-4.36.2.tgz",
"integrity": "sha512-PRFSpxNzX9Oi0Wfh02asztN9Sgev/MacfZwmd+VVyE6ZxW+a/kEpAYZhzGAmE+/aKVOGYuug7R9SulanYGxiDQ==",
"license": "MIT",
"bin": {
"stencil": "bin/stencil"
@@ -3474,9 +3474,9 @@
]
},
"node_modules/chalk": {
"version": "5.4.1",
"resolved": "https://registry.npmjs.org/chalk/-/chalk-5.4.1.tgz",
"integrity": "sha512-zgVZuo2WcZgfUEmsn6eO3kINexW8RAE4maiQ8QNs8CtpPCSyMiYsULR3HQYkm3w8FIA3SberyMJMSldGsW+U3w==",
"version": "5.5.0",
"resolved": "https://registry.npmjs.org/chalk/-/chalk-5.5.0.tgz",
"integrity": "sha512-1tm8DTaJhPBG3bIkVeZt1iZM9GfSX2lzOeDVZH9R9ffRHpmHvxZ/QhgQH/aDTkswQVt+YHdXAdS/In/30OjCbg==",
"dev": true,
"engines": {
"node": "^12.17.0 || ^14.13 || >=16.0.0"
@@ -5711,11 +5711,12 @@
}
},
"node_modules/ionicons": {
"version": "7.2.2",
"resolved": "https://registry.npmjs.org/ionicons/-/ionicons-7.2.2.tgz",
"integrity": "sha512-I3iYIfc9Q9FRifWyFSwTAvbEABWlWY32i0sAVDDPGYnaIZVugkLCZFbEcrphW6ixVPg8tt1oLwalo/JJwbEqnA==",
"version": "8.0.13",
"resolved": "https://registry.npmjs.org/ionicons/-/ionicons-8.0.13.tgz",
"integrity": "sha512-2QQVyG2P4wszne79jemMjWYLp0DBbDhr4/yFroPCxvPP1wtMxgdIV3l5n+XZ5E9mgoXU79w7yTWpm2XzJsISxQ==",
"license": "MIT",
"dependencies": {
"@stencil/core": "^4.0.3"
"@stencil/core": "^4.35.3"
}
},
"node_modules/is-alphabetical": {
@@ -8592,12 +8593,12 @@
}
},
"node_modules/playwright": {
"version": "1.54.1",
"resolved": "https://registry.npmjs.org/playwright/-/playwright-1.54.1.tgz",
"integrity": "sha512-peWpSwIBmSLi6aW2auvrUtf2DqY16YYcCMO8rTVx486jKmDTJg7UAhyrraP98GB8BoPURZP8+nxO7TSd4cPr5g==",
"version": "1.54.2",
"resolved": "https://registry.npmjs.org/playwright/-/playwright-1.54.2.tgz",
"integrity": "sha512-Hu/BMoA1NAdRUuulyvQC0pEqZ4vQbGfn8f7wPXcnqQmM+zct9UliKxsIkLNmz/ku7LElUNqmaiv1TG/aL5ACsw==",
"dev": true,
"dependencies": {
"playwright-core": "1.54.1"
"playwright-core": "1.54.2"
},
"bin": {
"playwright": "cli.js"
@@ -8610,9 +8611,9 @@
}
},
"node_modules/playwright-core": {
"version": "1.54.1",
"resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.54.1.tgz",
"integrity": "sha512-Nbjs2zjj0htNhzgiy5wu+3w09YetDx5pkrpI/kZotDlDUaYk0HVA5xrBVPdow4SAUIlhgKcJeJg4GRKW6xHusA==",
"version": "1.54.2",
"resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.54.2.tgz",
"integrity": "sha512-n5r4HFbMmWsB4twG7tJLDN9gmBUeSPcsBZiWSE4DnYz9mJMAFqr2ID7+eGC9kpEnxExJ1epttwR59LEWCk8mtA==",
"dev": true,
"bin": {
"playwright-core": "cli.js"
@@ -11110,23 +11111,23 @@
}
},
"@capacitor/haptics": {
"version": "7.0.1",
"resolved": "https://registry.npmjs.org/@capacitor/haptics/-/haptics-7.0.1.tgz",
"integrity": "sha512-ewZmspE5krgDUj5ZvUDcfNZvgerAIr+3bDSk6DLzyvBZ/dYmr/tMLu5H6WtYaaKYZJ32aZAudGpIal5epDyBYA==",
"version": "7.0.2",
"resolved": "https://registry.npmjs.org/@capacitor/haptics/-/haptics-7.0.2.tgz",
"integrity": "sha512-vqfeEM6s2zMgLjpITCTUIy7P/hadq/Gr5E/RClFgMJPB41Y5FsqOKD+j85/uwh8N2cf/aWaPeXUmjnTzJbEB2g==",
"dev": true,
"requires": {}
},
"@capacitor/keyboard": {
"version": "7.0.1",
"resolved": "https://registry.npmjs.org/@capacitor/keyboard/-/keyboard-7.0.1.tgz",
"integrity": "sha512-Gi064vOARMac+x9/DmEFeywN9oAETMf3OYsMuYm9gA8SvdsDJ3QJqMoFnSEIORYXe21Jzt2SIEdLlpT65P/b2g==",
"version": "7.0.2",
"resolved": "https://registry.npmjs.org/@capacitor/keyboard/-/keyboard-7.0.2.tgz",
"integrity": "sha512-9We5BY1mu+QWOReDukr+6HxA4Bh0mKBU0txFtwXJdjBohttMYWJzB+dQf4oHrX8odiU2Cm/BfDdAU2wV06Cyig==",
"dev": true,
"requires": {}
},
"@capacitor/status-bar": {
"version": "7.0.1",
"resolved": "https://registry.npmjs.org/@capacitor/status-bar/-/status-bar-7.0.1.tgz",
"integrity": "sha512-iDv3mXYo9CdxYRVwt3/pRyuk25p7Sn4GfaS/zMZyVIqTzsvKLCIIH3GdKK+ta+nsNcAVpCw/t5jFEBt1D18ctA==",
"version": "7.0.2",
"resolved": "https://registry.npmjs.org/@capacitor/status-bar/-/status-bar-7.0.2.tgz",
"integrity": "sha512-fYYkkdzCbQV+MjZVnaQTFl5I4bddnFW8ZrPVxDjNoGVPTUG7H58Ij1+NcuNxHLXjJvZOoZeYJ3w3I16Wb2zssw==",
"dev": true,
"requires": {}
},
@@ -11862,12 +11863,12 @@
}
},
"@playwright/test": {
"version": "1.54.1",
"resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.54.1.tgz",
"integrity": "sha512-FS8hQ12acieG2dYSksmLOF7BNxnVf2afRJdCuM1eMSxj6QTSE6G4InGF7oApGgDb65MX7AwMVlIkpru0yZA4Xw==",
"version": "1.54.2",
"resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.54.2.tgz",
"integrity": "sha512-A+znathYxPf+72riFd1r1ovOLqsIIB0jKIoPjyK2kqEIe30/6jF6BC7QNluHuwUmsD2tv1XZVugN8GqfTMOxsA==",
"dev": true,
"requires": {
"playwright": "1.54.1"
"playwright": "1.54.2"
}
},
"@rollup/plugin-node-resolve": {
@@ -11983,9 +11984,9 @@
"requires": {}
},
"@stencil/core": {
"version": "4.33.1",
"resolved": "https://registry.npmjs.org/@stencil/core/-/core-4.33.1.tgz",
"integrity": "sha512-12k9xhAJBkpg598it+NRmaYIdEe6TSnsL/v6/KRXDcUyTK11VYwZQej2eHnMWtqot+znJ+GNTqb5YbiXi+5Low==",
"version": "4.36.2",
"resolved": "https://registry.npmjs.org/@stencil/core/-/core-4.36.2.tgz",
"integrity": "sha512-PRFSpxNzX9Oi0Wfh02asztN9Sgev/MacfZwmd+VVyE6ZxW+a/kEpAYZhzGAmE+/aKVOGYuug7R9SulanYGxiDQ==",
"requires": {
"@rollup/rollup-darwin-arm64": "4.34.9",
"@rollup/rollup-darwin-x64": "4.34.9",
@@ -13075,9 +13076,9 @@
"dev": true
},
"chalk": {
"version": "5.4.1",
"resolved": "https://registry.npmjs.org/chalk/-/chalk-5.4.1.tgz",
"integrity": "sha512-zgVZuo2WcZgfUEmsn6eO3kINexW8RAE4maiQ8QNs8CtpPCSyMiYsULR3HQYkm3w8FIA3SberyMJMSldGsW+U3w==",
"version": "5.5.0",
"resolved": "https://registry.npmjs.org/chalk/-/chalk-5.5.0.tgz",
"integrity": "sha512-1tm8DTaJhPBG3bIkVeZt1iZM9GfSX2lzOeDVZH9R9ffRHpmHvxZ/QhgQH/aDTkswQVt+YHdXAdS/In/30OjCbg==",
"dev": true
},
"chalk-template": {
@@ -14744,11 +14745,11 @@
}
},
"ionicons": {
"version": "7.2.2",
"resolved": "https://registry.npmjs.org/ionicons/-/ionicons-7.2.2.tgz",
"integrity": "sha512-I3iYIfc9Q9FRifWyFSwTAvbEABWlWY32i0sAVDDPGYnaIZVugkLCZFbEcrphW6ixVPg8tt1oLwalo/JJwbEqnA==",
"version": "8.0.13",
"resolved": "https://registry.npmjs.org/ionicons/-/ionicons-8.0.13.tgz",
"integrity": "sha512-2QQVyG2P4wszne79jemMjWYLp0DBbDhr4/yFroPCxvPP1wtMxgdIV3l5n+XZ5E9mgoXU79w7yTWpm2XzJsISxQ==",
"requires": {
"@stencil/core": "^4.0.3"
"@stencil/core": "^4.35.3"
}
},
"is-alphabetical": {
@@ -16811,19 +16812,19 @@
}
},
"playwright": {
"version": "1.54.1",
"resolved": "https://registry.npmjs.org/playwright/-/playwright-1.54.1.tgz",
"integrity": "sha512-peWpSwIBmSLi6aW2auvrUtf2DqY16YYcCMO8rTVx486jKmDTJg7UAhyrraP98GB8BoPURZP8+nxO7TSd4cPr5g==",
"version": "1.54.2",
"resolved": "https://registry.npmjs.org/playwright/-/playwright-1.54.2.tgz",
"integrity": "sha512-Hu/BMoA1NAdRUuulyvQC0pEqZ4vQbGfn8f7wPXcnqQmM+zct9UliKxsIkLNmz/ku7LElUNqmaiv1TG/aL5ACsw==",
"dev": true,
"requires": {
"fsevents": "2.3.2",
"playwright-core": "1.54.1"
"playwright-core": "1.54.2"
}
},
"playwright-core": {
"version": "1.54.1",
"resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.54.1.tgz",
"integrity": "sha512-Nbjs2zjj0htNhzgiy5wu+3w09YetDx5pkrpI/kZotDlDUaYk0HVA5xrBVPdow4SAUIlhgKcJeJg4GRKW6xHusA==",
"version": "1.54.2",
"resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.54.2.tgz",
"integrity": "sha512-n5r4HFbMmWsB4twG7tJLDN9gmBUeSPcsBZiWSE4DnYz9mJMAFqr2ID7+eGC9kpEnxExJ1epttwR59LEWCk8mtA==",
"dev": true
},
"postcss": {

View File

@@ -1,6 +1,6 @@
{
"name": "@ionic/core",
"version": "8.6.5",
"version": "8.7.2",
"description": "Base components for Ionic",
"keywords": [
"ionic",
@@ -31,8 +31,8 @@
"loader/"
],
"dependencies": {
"@stencil/core": "4.33.1",
"ionicons": "^7.2.2",
"@stencil/core": "4.36.2",
"ionicons": "^8.0.13",
"tslib": "^2.1.0"
},
"devDependencies": {
@@ -44,7 +44,7 @@
"@clack/prompts": "^0.11.0",
"@ionic/eslint-config": "^0.3.0",
"@ionic/prettier-config": "^2.0.0",
"@playwright/test": "^1.54.1",
"@playwright/test": "^1.54.2",
"@rollup/plugin-node-resolve": "^8.4.0",
"@rollup/plugin-virtual": "^2.0.3",
"@stencil/angular-output-target": "^0.10.0",

View File

@@ -30,7 +30,7 @@ import { PopoverSize, PositionAlign, PositionReference, PositionSide, TriggerAct
import { RadioGroupChangeEventDetail, RadioGroupCompareFn } from "./components/radio-group/radio-group-interface";
import { PinFormatter, RangeChangeEventDetail, RangeKnobMoveEndEventDetail, RangeKnobMoveStartEventDetail, RangeValue } from "./components/range/range-interface";
import { RefresherEventDetail } from "./components/refresher/refresher-interface";
import { ItemReorderEventDetail } from "./components/reorder-group/reorder-group-interface";
import { ItemReorderEventDetail, ReorderEndEventDetail, ReorderMoveEventDetail } from "./components/reorder-group/reorder-group-interface";
import { NavigationHookCallback } from "./components/route/route-interface";
import { SearchbarChangeEventDetail, SearchbarInputEventDetail } from "./components/searchbar/searchbar-interface";
import { SegmentChangeEventDetail, SegmentValue } from "./components/segment/segment-interface";
@@ -68,7 +68,7 @@ export { PopoverSize, PositionAlign, PositionReference, PositionSide, TriggerAct
export { RadioGroupChangeEventDetail, RadioGroupCompareFn } from "./components/radio-group/radio-group-interface";
export { PinFormatter, RangeChangeEventDetail, RangeKnobMoveEndEventDetail, RangeKnobMoveStartEventDetail, RangeValue } from "./components/range/range-interface";
export { RefresherEventDetail } from "./components/refresher/refresher-interface";
export { ItemReorderEventDetail } from "./components/reorder-group/reorder-group-interface";
export { ItemReorderEventDetail, ReorderEndEventDetail, ReorderMoveEventDetail } from "./components/reorder-group/reorder-group-interface";
export { NavigationHookCallback } from "./components/route/route-interface";
export { SearchbarChangeEventDetail, SearchbarInputEventDetail } from "./components/searchbar/searchbar-interface";
export { SegmentChangeEventDetail, SegmentValue } from "./components/segment/segment-interface";
@@ -2072,6 +2072,45 @@ export namespace Components {
*/
"trigger": string | undefined;
}
interface IonMyChip {
/**
* The color to use from your application's color palette. Default options are: `"primary"`, `"secondary"`, `"tertiary"`, `"success"`, `"warning"`, `"danger"`, `"light"`, `"medium"`, and `"dark"`. For more information on colors, see [theming](/docs/theming/basics).
*/
"color"?: Color;
/**
* If `true`, the user cannot interact with the chip.
* @default false
*/
"disabled": boolean;
/**
* Set to `"bold"` for a chip with vibrant, bold colors or to `"subtle"` for a chip with muted, subtle colors. Only applies to the `ionic` theme.
* @default 'subtle'
*/
"hue"?: 'bold' | 'subtle';
/**
* The mode determines the platform behaviors of the component.
*/
"mode"?: "ios" | "md";
/**
* Display an outline style button.
* @default false
*/
"outline": boolean;
/**
* Set to `"soft"` for a chip with slightly rounded corners, `"round"` for a chip with fully rounded corners, or `"rectangular"` for a chip without rounded corners. Defaults to `"round"` for the `"ionic"` theme and `"soft"` for all other themes.
* @default 'soft'
*/
"shape"?: 'soft' | 'round' | 'rectangular';
/**
* Set to `"small"` for a chip with less height and padding. Defaults to `"large"` for the ionic theme, and undefined for all other themes.
* @default 'small'
*/
"size"?: 'small' | 'large';
/**
* The theme determines the visual appearance of the component.
*/
"theme"?: "ios" | "md" | "ionic";
}
interface IonNav {
/**
* If `true`, the nav should animate the transition of components.
@@ -2208,6 +2247,10 @@ export namespace Components {
* Data you want to pass to the component as props. Only used if the `"routerDirection"` is `"forward"` or `"root"`.
*/
"componentProps"?: ComponentProps;
/**
* The mode determines the platform behaviors of the component.
*/
"mode"?: "ios" | "md";
/**
* The transition animation when navigating to another page.
*/
@@ -2783,7 +2826,7 @@ export namespace Components {
}
interface IonReorderGroup {
/**
* Completes the reorder operation. Must be called by the `ionItemReorder` event. If a list of items is passed, the list will be reordered and returned in the proper order. If no parameters are passed or if `true` is passed in, the reorder will complete and the item will remain in the position it was dragged to. If `false` is passed, the reorder will complete and the item will bounce back to its original position.
* Completes the reorder operation. Must be called by the `ionReorderEnd` event. If a list of items is passed, the list will be reordered and returned in the proper order. If no parameters are passed or if `true` is passed in, the reorder will complete and the item will remain in the position it was dragged to. If `false` is passed, the reorder will complete and the item will bounce back to its original position.
* @param listOrReorder A list of items to be sorted and returned in the new order or a boolean of whether or not the reorder should reposition the item.
*/
"complete": (listOrReorder?: boolean | any[]) => Promise<any>;
@@ -4535,6 +4578,12 @@ declare global {
prototype: HTMLIonModalElement;
new (): HTMLIonModalElement;
};
interface HTMLIonMyChipElement extends Components.IonMyChip, HTMLStencilElement {
}
var HTMLIonMyChipElement: {
prototype: HTMLIonMyChipElement;
new (): HTMLIonMyChipElement;
};
interface HTMLIonNavElementEventMap {
"ionNavWillLoad": void;
"ionNavWillChange": void;
@@ -4769,6 +4818,9 @@ declare global {
};
interface HTMLIonReorderGroupElementEventMap {
"ionItemReorder": ItemReorderEventDetail;
"ionReorderStart": void;
"ionReorderMove": ReorderMoveEventDetail;
"ionReorderEnd": ReorderEndEventDetail;
}
interface HTMLIonReorderGroupElement extends Components.IonReorderGroup, HTMLStencilElement {
addEventListener<K extends keyof HTMLIonReorderGroupElementEventMap>(type: K, listener: (this: HTMLIonReorderGroupElement, ev: IonReorderGroupCustomEvent<HTMLIonReorderGroupElementEventMap[K]>) => any, options?: boolean | AddEventListenerOptions): void;
@@ -5233,6 +5285,7 @@ declare global {
"ion-menu-button": HTMLIonMenuButtonElement;
"ion-menu-toggle": HTMLIonMenuToggleElement;
"ion-modal": HTMLIonModalElement;
"ion-my-chip": HTMLIonMyChipElement;
"ion-nav": HTMLIonNavElement;
"ion-nav-link": HTMLIonNavLinkElement;
"ion-note": HTMLIonNoteElement;
@@ -7372,6 +7425,45 @@ declare namespace LocalJSX {
*/
"trigger"?: string | undefined;
}
interface IonMyChip {
/**
* The color to use from your application's color palette. Default options are: `"primary"`, `"secondary"`, `"tertiary"`, `"success"`, `"warning"`, `"danger"`, `"light"`, `"medium"`, and `"dark"`. For more information on colors, see [theming](/docs/theming/basics).
*/
"color"?: Color;
/**
* If `true`, the user cannot interact with the chip.
* @default false
*/
"disabled"?: boolean;
/**
* Set to `"bold"` for a chip with vibrant, bold colors or to `"subtle"` for a chip with muted, subtle colors. Only applies to the `ionic` theme.
* @default 'subtle'
*/
"hue"?: 'bold' | 'subtle';
/**
* The mode determines the platform behaviors of the component.
*/
"mode"?: "ios" | "md";
/**
* Display an outline style button.
* @default false
*/
"outline"?: boolean;
/**
* Set to `"soft"` for a chip with slightly rounded corners, `"round"` for a chip with fully rounded corners, or `"rectangular"` for a chip without rounded corners. Defaults to `"round"` for the `"ionic"` theme and `"soft"` for all other themes.
* @default 'soft'
*/
"shape"?: 'soft' | 'round' | 'rectangular';
/**
* Set to `"small"` for a chip with less height and padding. Defaults to `"large"` for the ionic theme, and undefined for all other themes.
* @default 'small'
*/
"size"?: 'small' | 'large';
/**
* The theme determines the visual appearance of the component.
*/
"theme"?: "ios" | "md" | "ionic";
}
interface IonNav {
/**
* If `true`, the nav should animate the transition of components.
@@ -7417,6 +7509,10 @@ declare namespace LocalJSX {
* Data you want to pass to the component as props. Only used if the `"routerDirection"` is `"forward"` or `"root"`.
*/
"componentProps"?: ComponentProps;
/**
* The mode determines the platform behaviors of the component.
*/
"mode"?: "ios" | "md";
/**
* The transition animation when navigating to another page.
*/
@@ -8053,9 +8149,22 @@ declare namespace LocalJSX {
*/
"disabled"?: boolean;
/**
* Event that needs to be listened to in order to complete the reorder action. Once the event has been emitted, the `complete()` method then needs to be called in order to finalize the reorder action.
* Event that needs to be listened to in order to complete the reorder action.
* @deprecated Use `ionReorderEnd` instead. If you are accessing `event.detail.from` or `event.detail.to` and relying on them being different you should now add checks as they are always emitted in `ionReorderEnd`, even when they are the same.
*/
"onIonItemReorder"?: (event: IonReorderGroupCustomEvent<ItemReorderEventDetail>) => void;
/**
* Event that is emitted when the reorder gesture ends. The from and to properties are always available, regardless of if the reorder gesture moved the item. If the item did not change from its start position, the from and to properties will be the same. Once the event has been emitted, the `complete()` method then needs to be called in order to finalize the reorder action.
*/
"onIonReorderEnd"?: (event: IonReorderGroupCustomEvent<ReorderEndEventDetail>) => void;
/**
* Event that is emitted as the reorder gesture moves.
*/
"onIonReorderMove"?: (event: IonReorderGroupCustomEvent<ReorderMoveEventDetail>) => void;
/**
* Event that is emitted when the reorder gesture starts.
*/
"onIonReorderStart"?: (event: IonReorderGroupCustomEvent<void>) => void;
}
interface IonRippleEffect {
/**
@@ -9150,6 +9259,7 @@ declare namespace LocalJSX {
"ion-menu-button": IonMenuButton;
"ion-menu-toggle": IonMenuToggle;
"ion-modal": IonModal;
"ion-my-chip": IonMyChip;
"ion-nav": IonNav;
"ion-nav-link": IonNavLink;
"ion-note": IonNote;
@@ -9253,6 +9363,7 @@ declare module "@stencil/core" {
"ion-menu-button": LocalJSX.IonMenuButton & JSXBase.HTMLAttributes<HTMLIonMenuButtonElement>;
"ion-menu-toggle": LocalJSX.IonMenuToggle & JSXBase.HTMLAttributes<HTMLIonMenuToggleElement>;
"ion-modal": LocalJSX.IonModal & JSXBase.HTMLAttributes<HTMLIonModalElement>;
"ion-my-chip": LocalJSX.IonMyChip & JSXBase.HTMLAttributes<HTMLIonMyChipElement>;
"ion-nav": LocalJSX.IonNav & JSXBase.HTMLAttributes<HTMLIonNavElement>;
"ion-nav-link": LocalJSX.IonNavLink & JSXBase.HTMLAttributes<HTMLIonNavLinkElement>;
"ion-note": LocalJSX.IonNote & JSXBase.HTMLAttributes<HTMLIonNoteElement>;

View File

@@ -125,7 +125,7 @@
<ion-toolbar color="dark">
<ion-buttons slot="start">
<ion-back-button class="ion-hide"></ion-back-button>
<ion-back-button class="ion-display-none"></ion-back-button>
</ion-buttons>
<ion-title>Hidden</ion-title>
</ion-toolbar>

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

After

Width:  |  Height:  |  Size: 12 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 13 KiB

After

Width:  |  Height:  |  Size: 14 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 15 KiB

After

Width:  |  Height:  |  Size: 15 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 10 KiB

After

Width:  |  Height:  |  Size: 10 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

After

Width:  |  Height:  |  Size: 12 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 13 KiB

After

Width:  |  Height:  |  Size: 13 KiB

View File

@@ -22,15 +22,15 @@ export type DatetimePresentation = 'date-time' | 'time-date' | 'date' | 'time' |
export type TitleSelectedDatesFormatter = (selectedDates: string[]) => string;
export type DatetimeHighlightStyle =
| {
textColor: string;
backgroundColor?: string;
}
| {
textColor?: string;
backgroundColor: string;
};
/**
* DatetimeHighlightStyle must include textColor, backgroundColor, or border.
* It cannot be an empty object.
*/
export type DatetimeHighlightStyle = {
textColor?: string;
backgroundColor?: string;
border?: string;
} & ({ textColor: string } | { backgroundColor: string } | { border: string });
export type DatetimeHighlight = { date: string } & DatetimeHighlightStyle;

View File

@@ -2335,6 +2335,7 @@ export class Datetime implements ComponentInterface {
`${dateStyle ? dateStyle.backgroundColor : ''}`,
'important'
);
el.style.setProperty('border', `${dateStyle ? dateStyle.border : ''}`, 'important');
}
}}
tabindex="-1"

View File

@@ -5,6 +5,8 @@ configs({ directions: ['ltr'] }).forEach(({ title, screenshot, config }) => {
test.describe(title('datetime: custom'), () => {
test.beforeEach(async ({ page }) => {
await page.goto(`/src/components/datetime/test/custom`, config);
await page.locator('.datetime-ready').last().waitFor();
});
test('should allow styling wheel style datetimes', async ({ page }) => {
@@ -30,6 +32,13 @@ configs({ directions: ['ltr'] }).forEach(({ title, screenshot, config }) => {
test('should allow styling calendar days in grid style datetimes', async ({ page }) => {
const datetime = page.locator('#custom-calendar-days');
// Wait for calendar days to be rendered
await page.waitForFunction(() => {
const datetime = document.querySelector('#custom-calendar-days');
const calendarDays = datetime?.shadowRoot?.querySelectorAll('.calendar-day');
return calendarDays && calendarDays.length > 0;
});
await expect(datetime).toHaveScreenshot(screenshot(`datetime-custom-calendar-days`));
});
});

View File

@@ -164,7 +164,7 @@
const customDatetime = document.querySelector('#custom-calendar-days');
// Mock the current day to always have the same screenshots
const mockToday = '2023-06-10T16:22';
const mockToday = '2023-06-10T16:22:00.000Z';
Date = class extends Date {
constructor(...args) {
if (args.length === 0) {

View File

@@ -22,11 +22,23 @@ configs({ modes: ['md'], directions: ['ltr'] }).forEach(({ title, config }) => {
await expect(monthYearToggle).toContainText('January 2022');
// Click to open the picker
await monthYearToggle.click();
await page.waitForChanges();
// February
await monthColumnItems.nth(1).click();
// Wait for the picker to be open
await page.locator('.month-year-picker-open').waitFor();
// Wait a bit for the picker to fully load
await page.waitForTimeout(200);
const ionChange = await page.spyOnEvent('ionChange');
// Click on February
await monthColumnItems.filter({ hasText: 'February' }).click();
// Wait for changes
await ionChange.next();
await page.waitForChanges();
await expect(monthYearToggle).toContainText('February 2022');
@@ -38,13 +50,23 @@ configs({ modes: ['md'], directions: ['ltr'] }).forEach(({ title, config }) => {
const datetime = page.locator('ion-datetime');
const ionChange = await page.spyOnEvent('ionChange');
// Click to open the picker
await monthYearToggle.click();
await page.waitForChanges();
// February
await monthColumnItems.nth(1).click();
// Wait for the picker to be open
await page.locator('.month-year-picker-open').waitFor();
// Wait a bit for the picker to fully load
await page.waitForTimeout(200);
// Click on February
await monthColumnItems.filter({ hasText: 'February' }).click();
// Wait for changes
await ionChange.next();
await page.waitForChanges();
await expect(ionChange).toHaveReceivedEventTimes(1);
await expect(datetime).toHaveJSProperty('value', '2022-02-28');
});

View File

@@ -21,16 +21,19 @@ configs({ directions: ['ltr'] }).forEach(({ title, screenshot, config }) => {
date: '2023-01-01', // ensure selected date style overrides highlight
textColor: '#800080',
backgroundColor: '#ffc0cb',
border: '2px solid purple',
},
{
date: '2023-01-02',
textColor: '#b22222',
backgroundColor: '#fa8072',
border: '2px solid purple',
},
{
date: '2023-01-03',
textColor: '#0000ff',
backgroundColor: '#add8e6',
border: '2px solid purple',
},
];
});
@@ -52,6 +55,7 @@ configs({ directions: ['ltr'] }).forEach(({ title, screenshot, config }) => {
return {
textColor: '#b22222',
backgroundColor: '#fa8072',
border: '2px solid purple',
};
}
@@ -59,6 +63,7 @@ configs({ directions: ['ltr'] }).forEach(({ title, screenshot, config }) => {
return {
textColor: '#800080',
backgroundColor: '#ffc0cb',
border: '2px solid purple',
};
}
@@ -66,6 +71,7 @@ configs({ directions: ['ltr'] }).forEach(({ title, screenshot, config }) => {
return {
textColor: '#0000ff',
backgroundColor: '#add8e6',
border: '2px solid purple',
};
}
@@ -77,7 +83,7 @@ configs({ directions: ['ltr'] }).forEach(({ title, screenshot, config }) => {
await expect(datetime).toHaveScreenshot(screenshot(`datetime-highlightedDates-callback`));
});
test('should render highlights correctly when only using one color or the other', async ({ page }) => {
test('should render highlights correctly when only using only one color property', async ({ page }) => {
const datetime = page.locator('ion-datetime');
await datetime.evaluate((el: HTMLIonDatetimeElement) => {
@@ -90,6 +96,10 @@ configs({ directions: ['ltr'] }).forEach(({ title, screenshot, config }) => {
date: '2023-01-03',
textColor: '#0000ff',
},
{
date: '2023-01-04',
border: '2px solid purple',
},
];
});

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 21 KiB

After

Width:  |  Height:  |  Size: 22 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 27 KiB

After

Width:  |  Height:  |  Size: 29 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 27 KiB

After

Width:  |  Height:  |  Size: 28 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 15 KiB

After

Width:  |  Height:  |  Size: 16 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 20 KiB

After

Width:  |  Height:  |  Size: 22 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 19 KiB

After

Width:  |  Height:  |  Size: 20 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 28 KiB

After

Width:  |  Height:  |  Size: 32 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 34 KiB

After

Width:  |  Height:  |  Size: 40 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 33 KiB

After

Width:  |  Height:  |  Size: 40 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 22 KiB

After

Width:  |  Height:  |  Size: 27 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 26 KiB

After

Width:  |  Height:  |  Size: 34 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 27 KiB

After

Width:  |  Height:  |  Size: 36 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 21 KiB

After

Width:  |  Height:  |  Size: 22 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 27 KiB

After

Width:  |  Height:  |  Size: 29 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 26 KiB

After

Width:  |  Height:  |  Size: 27 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 15 KiB

After

Width:  |  Height:  |  Size: 16 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 19 KiB

After

Width:  |  Height:  |  Size: 21 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 18 KiB

After

Width:  |  Height:  |  Size: 20 KiB

View File

@@ -78,6 +78,10 @@
textColor: 'blue',
backgroundColor: 'lightblue',
},
{
date: '2023-01-07',
border: '2px dotted red',
},
];
document.querySelector('#withCallback').highlightedDates = (isoString) => {
@@ -103,6 +107,7 @@
date: new Date().toISOString().split('T')[0],
textColor: 'purple',
backgroundColor: 'pink',
border: '2px solid purple',
},
];
</script>

View File

@@ -207,6 +207,7 @@ export const getHighlightStyles = (
return {
textColor: matchingHighlight.textColor,
backgroundColor: matchingHighlight.backgroundColor,
border: matchingHighlight.border,
} as DatetimeHighlightStyle;
}
} else {

View File

@@ -2,7 +2,7 @@
<html lang="en" dir="ltr">
<head>
<meta charset="UTF-8" />
<title>Infinite Scroll - Basic</title>
<title>Infinite Scroll - Top</title>
<meta
name="viewport"
content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no"
@@ -18,7 +18,7 @@
<ion-app>
<ion-header>
<ion-toolbar>
<ion-title>Infinite Scroll - Basic</ion-title>
<ion-title>Infinite Scroll - Top</ion-title>
</ion-toolbar>
</ion-header>
@@ -28,9 +28,9 @@
</ion-infinite-scroll-content>
</ion-infinite-scroll>
<button onclick="toggleInfiniteScroll()" class="expand">Toggle InfiniteScroll</button>
<div id="list"></div>
<ion-list id="list"></ion-list>
<button onclick="toggleInfiniteScroll()" class="expand">Toggle InfiniteScroll</button>
</ion-content>
</ion-app>
@@ -46,17 +46,26 @@
console.log('Loading data...');
await wait(500);
infiniteScroll.complete();
appendItems();
appendItems(true);
// Custom event consumed in the e2e tests
window.dispatchEvent(new CustomEvent('ionInfiniteComplete'));
console.log('Done');
});
function appendItems() {
function appendItems(newItems = false) {
const randomColor =
'#' +
Math.floor(Math.random() * 16777215)
.toString(16)
.padStart(6, '0');
for (var i = 0; i < 30; i++) {
const el = document.createElement('ion-item');
el.textContent = `${1 + i}`;
el.textContent = `Item ${1 + i}`;
if (newItems) {
el.style.borderLeft = `4px solid ${randomColor}`;
}
list.prepend(el);
}
}

View File

@@ -95,6 +95,8 @@ configs({ modes: ['ios'], directions: ['ltr'] }).forEach(({ title, config }) =>
el.separators = [2, 3];
});
await page.waitForChanges();
await expect(await hasSeparatorAfter(page, 0)).toBe(false);
await expect(await hasSeparatorAfter(page, 1)).toBe(true);
await expect(await hasSeparatorAfter(page, 2)).toBe(true);

View File

@@ -84,7 +84,7 @@
}
function initGroup(group) {
var groupEl = document.getElementById(group.id);
groupEl.addEventListener('ionItemReorder', function (ev) {
groupEl.addEventListener('ionReorderEnd', function (ev) {
ev.detail.complete();
});
var groupItems = [];

View File

@@ -18,7 +18,13 @@ configs({ modes: ['ios'], directions: ['ltr'] }).forEach(({ title, config }) =>
const heading = page.locator('ion-menu h1');
await expect(heading).toHaveText('Open Menu');
const results = await new AxeBuilder({ page }).analyze();
/**
* Disable the 'scrollable-region-focusable' rule because this test
* is missing the required `ion-app` wrapper component. The `ion-app`
* wrapper provides the necessary focus management that allows the
* menu content to be focusable.
*/
const results = await new AxeBuilder({ page }).disableRules('scrollable-region-focusable').analyze();
expect(results.violations).toEqual([]);
});
});

View File

@@ -0,0 +1,187 @@
@import "../../themes/ionic.functions.color";
@import "../../themes/ionic.mixins";
:host {
/**
* @prop --ion-chip-focus-ring-color: Color of the focus ring
* @prop --ion-chip-focus-ring-width: Width of the focus ring
* @prop --ion-chip-padding-horizontal: Padding top and bottom of the chip
* @prop --ion-chip-padding-vertical: Padding start and end of the chip
* @prop --ion-chip-font-weight: Font weight of the chip
* @prop --ion-chip-line-height: Line height of the chip
* @prop --ion-chip-gap: Gap between the chip and the text
* @prop --ion-chip-border-width: Border width of the chip
*
* @prop --ion-chip-shape-soft-border-radius: Border radius of the chip for the soft shape
* @prop --ion-chip-shape-round-border-radius: Border radius of the chip for the round shape
* @prop --ion-chip-shape-rectangular-border-radius: Border radius of the chip for the rectangular shape
*
* @prop --ion-chip-size-small-min-height: Minimum height of the chip for the small size
* @prop --ion-chip-size-large-min-height: Minimum height of the chip for the large size
* @prop --ion-chip-size-small-font-size: Font size of the chip for the small size
* @prop --ion-chip-size-large-font-size: Font size of the chip for the large size
*
* @prop --ion-chip-hue-subtle-bg: Background of the chip for the subtle hue
* @prop --ion-chip-hue-subtle-color: Color of the chip for the subtle hue
* @prop --ion-chip-hue-subtle-border-color: Border color of the chip for the subtle hue
* @prop --ion-chip-hue-bold-bg: Background of the chip for the bold hue
* @prop --ion-chip-hue-bold-color: Color of the chip for the bold hue
* @prop --ion-chip-hue-bold-border-color: Border color of the chip for the bold hue
*/
--ion-chip-focus-ring-color: var(--ion-color-blue-50);
--ion-chip-focus-ring-width: var(--ion-spacing-xs);
--ion-chip-padding-horizontal: var(--ion-spacing-xs);
--ion-chip-padding-vertical: var(--ion-spacing-sm);
--ion-chip-font-weight: var(--ion-font-weights-normal);
--ion-chip-line-height: var(--ion-line-heights-md);
--ion-chip-gap: var(--ion-spacing-xs);
--ion-chip-border-width: var(--ion-spacing-xxs);
--ion-chip-shape-soft-border-radius: var(--ion-radii-lg);
--ion-chip-shape-round-border-radius: var(--ion-radii-xxl);
--ion-chip-shape-rectangular-border-radius: var(--ion-radii-none);
--ion-chip-size-small-min-height: var(--ion-scaling-600);
--ion-chip-size-large-min-height: var(--ion-scaling-900);
--ion-chip-size-small-font-size: var(--ion-font-sizes-sm-rem);
--ion-chip-size-large-font-size: var(--ion-font-sizes-lg-rem);
--ion-chip-hue-subtle-bg: var(--ion-color-gray-100);
--ion-chip-hue-subtle-color: var(--ion-color-gray-800);
--ion-chip-hue-subtle-border-color: var(--ion-color-gray-300);
--ion-chip-hue-bold-bg: var(--ion-color-gray-700);
--ion-chip-hue-bold-color: var(--ion-color-white);
--ion-chip-hue-bold-border-color: var(--ion-color-gray-800);
@include font-smoothing();
@include padding(var(--ion-chip-padding-horizontal), var(--ion-chip-padding-vertical));
@include border-radius(var(--ion-chip-border-radius));
display: inline-flex;
position: relative;
align-items: center;
justify-content: center;
background: var(--ion-chip-background);
color: var(--ion-chip-color);
cursor: pointer;
font-weight: var(--ion-chip-font-weight);
line-height: var(--ion-chip-line-height);
gap: var(--ion-chip-gap);
overflow: hidden;
box-sizing: border-box;
vertical-align: middle;
}
:host(.chip-disabled) {
cursor: default;
pointer-events: none;
}
// Outline Chip
// ---------------------------------------------
:host(.chip-outline) {
border-width: var(--ion-chip-border-width);
border-style: solid; // Do we need to use a variable here? ionic uses tokens but all themes use solid so it's not really necessary
}
// Chip Shapes
// ---------------------------------------------
:host(.chip-soft) {
--ion-chip-border-radius: var(--ion-chip-shape-soft-border-radius);
}
:host(.chip-round) {
--ion-chip-border-radius: var(--ion-chip-shape-round-border-radius);
}
:host(.chip-rectangular) {
--ion-chip-border-radius: var(--ion-chip-shape-rectangular-border-radius);
}
// Size
// ---------------------------------------------
:host(.chip-small) {
min-height: var(--ion-chip-size-small-min-height);
font-size: var(--ion-chip-size-small-font-size);
}
:host(.chip-large) {
min-height: var(--ion-chip-size-large-min-height);
font-size: var(--ion-chip-size-large-font-size);
}
// Subtle Chip
// ---------------------------------------------
:host(.chip-subtle) {
--ion-chip-background: var(--ion-chip-hue-subtle-bg);
--ion-chip-color: var(--ion-chip-hue-subtle-color);
}
:host(.chip-outline.chip-subtle) {
border-color: var(--ion-chip-hue-subtle-border-color);
}
// Bold Chip
// ---------------------------------------------
:host(.chip-bold) {
--ion-chip-background: var(--ion-chip-hue-bold-bg);
--ion-chip-color: var(--ion-chip-hue-bold-color);
}
:host(.chip-outline.chip-bold) {
border-color: var(--ion-chip-hue-bold-border-color);
}
// Chip Colors
// ---------------------------------------------
// Subtle
:host(.chip-subtle.ion-color) {
background: current-color(
base,
$subtle: true
); // these don't work because we need to update the function to use the new color system
color: current-color(
contrast,
$subtle: true
); // these don't work because we need to update the function to use the new color system
}
:host(.chip-subtle.chip-outline.ion-color) {
border-color: current-color(
shade,
$subtle: true
); // these don't work because we need to update the function to use the new color system
}
// Bold
:host(.chip-bold.ion-color) {
background: current-color(
base
); // these don't work because we need to update the function to use the new color system
color: current-color(
contrast
); // these don't work because we need to update the function to use the new color system
}
:host(.chip-bold.chip-outline.ion-color) {
border-color: current-color(
shade
); // these don't work because we need to update the function to use the new color system
}

View File

@@ -0,0 +1,113 @@
import type { ComponentInterface } from '@stencil/core';
import { Component, Host, Prop, h, Element } from '@stencil/core';
import { createColorClasses } from '@utils/theme';
import { getIonMode, getIonCustomTheme } from '../../global/ionic-global';
import type { Color } from '../../interface';
import { generateCSSVars } from '../../themes/base/generate-css-vars';
/**
* @virtualProp {"ios" | "md"} mode - The mode determines the platform behaviors of the component.
* @virtualProp {"ios" | "md" | "ionic"} theme - The theme determines the visual appearance of the component.
*/
@Component({
tag: 'ion-my-chip',
styleUrl: 'my-chip.base.scss',
shadow: true,
})
export class MyChip implements ComponentInterface {
private isThemed = false;
@Element() el!: HTMLElement;
/**
* The color to use from your application's color palette.
* Default options are: `"primary"`, `"secondary"`, `"tertiary"`, `"success"`, `"warning"`, `"danger"`, `"light"`, `"medium"`, and `"dark"`.
* For more information on colors, see [theming](/docs/theming/basics).
*/
@Prop({ reflect: true }) color?: Color;
/**
* Display an outline style button.
*/
@Prop() outline = false;
/**
* If `true`, the user cannot interact with the chip.
*/
@Prop() disabled = false;
/**
* Set to `"bold"` for a chip with vibrant, bold colors or to `"subtle"` for
* a chip with muted, subtle colors.
*
* Only applies to the `ionic` theme.
*/
// THOUGHT: Comparing to ChakraUI, they use variants (aka fills) for this
// maybe we should consider using variants: solid, outline, subtle
// they use solid for bold solid background, no outline, has states
// subtle for light background, no outline, has states
// outline for outline style, no background, has states
// surface for light background, with outline, has states
// ghost for no background, no outline, has states
// plain for no background, no outline, no states
@Prop() hue?: 'bold' | 'subtle' = 'subtle';
/**
* Set to `"soft"` for a chip with slightly rounded corners, `"round"` for a chip with fully
* rounded corners, or `"rectangular"` for a chip without rounded corners.
* Defaults to `"round"` for the `"ionic"` theme and `"soft"` for all other themes.
*/
@Prop() shape?: 'soft' | 'round' | 'rectangular' = 'soft';
/**
* Set to `"small"` for a chip with less height and padding.
*
* Defaults to `"large"` for the ionic theme, and undefined for all other themes.
*/
@Prop() size?: 'small' | 'large' = 'small';
componentWillLoad() {
const myCustomTheme = getIonCustomTheme();
const componentTheme = myCustomTheme.components['IonChip'];
// check if componentTheme is not an empty object or undefined
if (componentTheme !== undefined || Object.keys(componentTheme).length > 0) {
this.isThemed = true;
// apply a style tag to this component
const style = document.createElement('style');
style.innerHTML = [generateCSSVars(componentTheme, '--ion-chip-', ':host(.chip-themed)')].join('\n\n');
// Attach to Shadow Root if available, otherwise Light DOM
const root = this.el.shadowRoot ?? this.el;
root.appendChild(style);
}
}
render() {
const { hue, shape, size } = this;
const mode = getIonMode(this);
return (
<Host
aria-disabled={this.disabled ? 'true' : null}
class={createColorClasses(this.color, {
// Needed to properly add the custom styles else
// the styles would be ignored due to styling order
'chip-themed': this.isThemed,
[`chip-${shape}`]: shape !== undefined,
'chip-outline': this.outline,
'chip-disabled': this.disabled,
'ion-activatable': true,
'ion-focusable': !this.disabled,
[`chip-${size}`]: size !== undefined,
[`chip-${hue}`]: hue !== undefined,
})}
>
<slot></slot>
{mode === 'md' && <ion-ripple-effect></ion-ripple-effect>}
</Host>
);
}
}

View File

@@ -0,0 +1,95 @@
<!DOCTYPE html>
<html lang="en" dir="ltr">
<head>
<meta charset="UTF-8" />
<title>MyChip - Basic</title>
<meta
name="viewport"
content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no"
/>
<link href="../../../../../css/ionic.bundle.css" rel="stylesheet" />
<link href="../../../../../scripts/testing/styles.css" rel="stylesheet" />
<script src="../../../../../scripts/testing/scripts.js"></script>
<script nomodule src="../../../../../dist/ionic/ionic.js"></script>
<script type="module" src="../../../../../dist/ionic/ionic.esm.js"></script>
</head>
<body>
<ion-app>
<ion-header>
<ion-toolbar>
<ion-title>MyChip - Basic</ion-title>
</ion-toolbar>
</ion-header>
<ion-content class="ion-padding" id="content" style="text-align: center">
<h2>My Chip</h2>
<p>
This is a POC, not all the features are working as expected. For example, the color property still needs to be
worked on.
</p>
<p>You can verify that the variables are being generated correctly by inspecting the root element.</p>
<ion-my-chip>default</ion-my-chip>
<ion-my-chip outline>outline</ion-my-chip>
<ion-my-chip size="large">large</ion-my-chip>
<ion-my-chip hue="bold">bold</ion-my-chip>
<ion-my-chip hue="bold" outline>bold with outline</ion-my-chip>
<ion-my-chip color="primary">primary, subtle hue</ion-my-chip>
<ion-my-chip color="primary" hue="bold">primary, bold hue</ion-my-chip>
<ion-my-chip color="secondary">secondary, subtle hue</ion-my-chip>
<ion-my-chip color="secondary" hue="bold">secondary, bold hue</ion-my-chip>
</ion-content>
</ion-app>
<script>
window.Ionic = {
config: {
customTheme: {
palette: {
light: {
color: {
primary: {
bold: {
base: 'pink',
constrast: 'black',
},
},
secondary: {
bold: {
base: '#510aa8',
},
},
// gray: {
// 800: 'pink',
// }
},
},
},
components: {
IonChip: {
hue: {
subtle: {
bg: 'red',
color: 'white',
borderColor: 'black'
},
bold: {
bg: 'blue',
color: 'white',
borderColor: 'black'
}
}
},
},
},
},
};
</script>
</body>
</html>

View File

@@ -7,6 +7,9 @@ import type { RouterDirection } from '../router/utils/interface';
import { navLink } from './nav-link-utils';
/**
* @virtualProp {"ios" | "md"} mode - The mode determines the platform behaviors of the component.
*/
@Component({
tag: 'ion-nav-link',
})

View File

@@ -107,6 +107,7 @@ const renderProgress = (value: number, buffer: number) => {
* When finalBuffer === 1, we use display: none
* instead of removing the element to avoid flickering.
*/
// TODO(FW-6697): change `ion-hide` class to `ion-display-none` or another class
<div
class={{ 'buffer-circles-container': true, 'ion-hide': finalBuffer === 1 }}
style={{ transform: `translateX(${finalBuffer * 100}%)` }}

View File

@@ -1,10 +1,33 @@
// TODO(FW-6590): Remove this once the deprecated event is removed
export interface ItemReorderEventDetail {
from: number;
to: number;
complete: (data?: boolean | any[]) => any;
}
// TODO(FW-6590): Remove this once the deprecated event is removed
export interface ItemReorderCustomEvent extends CustomEvent {
detail: ItemReorderEventDetail;
target: HTMLIonReorderGroupElement;
}
export interface ReorderMoveEventDetail {
from: number;
to: number;
}
export interface ReorderEndEventDetail {
from: number;
to: number;
complete: (data?: boolean | any[]) => any;
}
export interface ReorderMoveCustomEvent extends CustomEvent {
detail: ReorderMoveEventDetail;
target: HTMLIonReorderGroupElement;
}
export interface ReorderEndCustomEvent extends CustomEvent {
detail: ReorderEndEventDetail;
target: HTMLIonReorderGroupElement;
}

View File

@@ -6,8 +6,9 @@ import { hapticSelectionChanged, hapticSelectionEnd, hapticSelectionStart } from
import { getIonMode } from '../../global/ionic-global';
import type { Gesture, GestureDetail } from '../../interface';
import type { HTMLStencilElement } from '../../utils/element-interface';
import type { ItemReorderEventDetail } from './reorder-group-interface';
import type { ItemReorderEventDetail, ReorderMoveEventDetail, ReorderEndEventDetail } from './reorder-group-interface';
// TODO(FW-2832): types
@@ -38,7 +39,7 @@ export class ReorderGroup implements ComponentInterface {
@State() state = ReorderGroupState.Idle;
@Element() el!: HTMLElement;
@Element() el!: HTMLStencilElement;
/**
* If `true`, the reorder will be hidden.
@@ -51,12 +52,35 @@ export class ReorderGroup implements ComponentInterface {
}
}
// TODO(FW-6590): Remove this in a major release.
/**
* Event that needs to be listened to in order to complete the reorder action.
* @deprecated Use `ionReorderEnd` instead. If you are accessing
* `event.detail.from` or `event.detail.to` and relying on them
* being different you should now add checks as they are always emitted
* in `ionReorderEnd`, even when they are the same.
*/
@Event() ionItemReorder!: EventEmitter<ItemReorderEventDetail>;
/**
* Event that is emitted when the reorder gesture starts.
*/
@Event() ionReorderStart!: EventEmitter<void>;
/**
* Event that is emitted as the reorder gesture moves.
*/
@Event() ionReorderMove!: EventEmitter<ReorderMoveEventDetail>;
/**
* Event that is emitted when the reorder gesture ends.
* The from and to properties are always available, regardless of
* if the reorder gesture moved the item. If the item did not change
* from its start position, the from and to properties will be the same.
* Once the event has been emitted, the `complete()` method then needs
* to be called in order to finalize the reorder action.
*/
@Event() ionItemReorder!: EventEmitter<ItemReorderEventDetail>;
@Event() ionReorderEnd!: EventEmitter<ReorderEndEventDetail>;
async connectedCallback() {
const contentEl = findClosestIonContent(this.el);
@@ -88,7 +112,8 @@ export class ReorderGroup implements ComponentInterface {
}
/**
* Completes the reorder operation. Must be called by the `ionItemReorder` event.
* Completes the reorder operation. Must be called by the `ionReorderEnd` event.
*
* If a list of items is passed, the list will be reordered and returned in the
* proper order.
*
@@ -128,7 +153,7 @@ export class ReorderGroup implements ComponentInterface {
const heights = this.cachedHeights;
heights.length = 0;
const el = this.el;
const children: any = el.children;
const children: any = el.__children || el.children;
if (!children || children.length === 0) {
return;
}
@@ -163,6 +188,8 @@ export class ReorderGroup implements ComponentInterface {
item.classList.add(ITEM_REORDER_SELECTED);
hapticSelectionStart();
this.ionReorderStart.emit();
}
private onMove(ev: GestureDetail) {
@@ -179,6 +206,7 @@ export class ReorderGroup implements ComponentInterface {
const currentY = Math.max(top, Math.min(ev.currentY, bottom));
const deltaY = scroll + currentY - ev.startY;
const normalizedY = currentY - top;
const fromIndex = this.lastToIndex;
const toIndex = this.itemIndexForTop(normalizedY);
if (toIndex !== this.lastToIndex) {
const fromIndex = indexForItem(selectedItem);
@@ -190,6 +218,11 @@ export class ReorderGroup implements ComponentInterface {
// Update selected item position
selectedItem.style.transform = `translateY(${deltaY}px)`;
this.ionReorderMove.emit({
from: fromIndex,
to: toIndex,
});
}
private onEnd() {
@@ -206,6 +239,7 @@ export class ReorderGroup implements ComponentInterface {
if (toIndex === fromIndex) {
this.completeReorder();
} else {
// TODO(FW-6590): Remove this once the deprecated event is removed
this.ionItemReorder.emit({
from: fromIndex,
to: toIndex,
@@ -214,12 +248,18 @@ export class ReorderGroup implements ComponentInterface {
}
hapticSelectionEnd();
this.ionReorderEnd.emit({
from: fromIndex,
to: toIndex,
complete: this.completeReorder.bind(this),
});
}
private completeReorder(listOrReorder?: boolean | any[]): any {
const selectedItemEl = this.selectedItemEl;
if (selectedItemEl && this.state === ReorderGroupState.Complete) {
const children = this.el.children as any;
const children: any = this.el.__children || this.el.children;
const len = children.length;
const toIndex = this.lastToIndex;
const fromIndex = indexForItem(selectedItemEl);
@@ -269,7 +309,7 @@ export class ReorderGroup implements ComponentInterface {
/********* DOM WRITE ********* */
private reorderMove(fromIndex: number, toIndex: number) {
const itemHeight = this.selectedItemHeight;
const children = this.el.children;
const children: any = this.el.__children || this.el.children;
for (let i = 0; i < children.length; i++) {
const style = (children[i] as any).style;
let value = '';

View File

@@ -122,8 +122,25 @@
const reorderGroup = document.getElementById('reorder');
reorderGroup.disabled = !reorderGroup.disabled;
// TODO(FW-6590): Remove this once the deprecated event is removed
reorderGroup.addEventListener('ionItemReorder', ({ detail }) => {
console.log('Dragged from index', detail.from, 'to', detail.to);
console.log('ionItemReorder: Dragged from index', detail.from, 'to', detail.to);
});
reorderGroup.addEventListener('ionReorderStart', () => {
console.log('ionReorderStart');
});
reorderGroup.addEventListener('ionReorderMove', ({ detail }) => {
console.log('ionReorderMove: Dragged from index', detail.from, 'to', detail.to);
});
reorderGroup.addEventListener('ionReorderEnd', ({ detail }) => {
if (detail.from !== detail.to) {
console.log('ionReorderEnd: Dragged from index', detail.from, 'to', detail.to);
} else {
console.log('ionReorderEnd: No position change occurred');
}
detail.complete();
});

View File

@@ -14,7 +14,7 @@
<script type="module" src="../../../../../dist/ionic/ionic.esm.js"></script>
</head>
<body onLoad="render()">
<body>
<ion-app>
<ion-header>
<ion-toolbar>
@@ -24,7 +24,7 @@
<ion-content id="content">
<ion-list>
<ion-reorder-group id="reorderGroup" disabled="false">
<ion-reorder-group disabled="false">
<!-- items will be inserted here -->
</ion-reorder-group>
</ion-list>
@@ -36,27 +36,44 @@
for (var i = 0; i < 30; i++) {
items.push(i + 1);
}
const reorderGroup = document.getElementById('reorderGroup');
function render() {
let html = '';
for (let item of items) {
html += `
<ion-item>
<ion-label>${item}</ion-label>
<ion-reorder slot="end"></ion-reorder>
</ion-item>`;
}
reorderGroup.innerHTML = html;
}
reorderGroup.addEventListener('ionItemReorder', ({ detail }) => {
console.log('Dragged from index', detail.from, 'to', detail.to);
const reorderGroup = document.querySelector('ion-reorder-group');
reorderItems(items);
reorderGroup.addEventListener('ionReorderEnd', ({ detail }) => {
// Before complete is called with the items they will remain in the
// order before the drag
console.log('Before complete', items);
// Finish the reorder and position the item in the DOM based on
// where the gesture ended. Update the items variable to the
// new order of items
items = detail.complete(items);
// Reorder the items in the DOM
reorderItems(items);
// After complete is called the items will be in the new order
console.log('After complete', items);
});
function reorderItems(items) {
reorderGroup.replaceChildren();
let reordered = '';
for (let i = 0; i < items.length; i++) {
reordered += `
<ion-item>
<ion-label>
Item ${items[i]}
</ion-label>
<ion-reorder slot="end"></ion-reorder>
</ion-item>
`;
}
reorderGroup.innerHTML = reordered;
}
</script>
</body>
</html>

View File

@@ -37,9 +37,9 @@
</ion-reorder-group>
<script>
const group = document.querySelector('ion-reorder-group');
group.addEventListener('ionItemReorder', (ev) => {
group.addEventListener('ionReorderEnd', (ev) => {
ev.detail.complete();
window.dispatchEvent(new CustomEvent('ionItemReorderComplete'));
window.dispatchEvent(new CustomEvent('ionReorderComplete'));
});
</script>
</body>

View File

@@ -11,24 +11,24 @@ configs({ modes: ['md'], directions: ['ltr'] }).forEach(({ title, config }) => {
});
test('should drag and drop when ion-reorder wraps ion-item', async ({ page }) => {
const items = page.locator('ion-item');
const ionItemReorderComplete = await page.spyOnEvent('ionItemReorderComplete');
const ionReorderComplete = await page.spyOnEvent('ionReorderComplete');
await expect(items).toContainText(['Item 1', 'Item 2', 'Item 3', 'Item 4']);
await dragElementBy(items.nth(1), page, 0, 300);
await ionItemReorderComplete.next();
await ionReorderComplete.next();
await expect(items).toContainText(['Item 1', 'Item 3', 'Item 4', 'Item 2']);
});
test('should drag and drop when ion-item wraps ion-reorder', async ({ page }) => {
const reorderHandle = page.locator('ion-reorder');
const items = page.locator('ion-item');
const ionItemReorderComplete = await page.spyOnEvent('ionItemReorderComplete');
const ionReorderComplete = await page.spyOnEvent('ionReorderComplete');
await expect(items).toContainText(['Item 1', 'Item 2', 'Item 3', 'Item 4']);
await dragElementBy(reorderHandle.nth(0), page, 0, 300);
await ionItemReorderComplete.next();
await ionReorderComplete.next();
await expect(items).toContainText(['Item 2', 'Item 3', 'Item 4', 'Item 1']);
});

View File

@@ -68,9 +68,9 @@
customElements.define('app-reorder', AppReorder);
const group = document.querySelector('ion-reorder-group');
group.addEventListener('ionItemReorder', (ev) => {
group.addEventListener('ionReorderEnd', (ev) => {
ev.detail.complete();
window.dispatchEvent(new CustomEvent('ionItemReorderComplete'));
window.dispatchEvent(new CustomEvent('ionReorderComplete'));
});
</script>
</ion-app>

View File

@@ -11,24 +11,24 @@ configs({ modes: ['md'], directions: ['ltr'] }).forEach(({ title, config }) => {
});
test('should drag and drop when ion-reorder wraps ion-item', async ({ page }) => {
const items = page.locator('app-reorder');
const ionItemReorderComplete = await page.spyOnEvent('ionItemReorderComplete');
const ionReorderComplete = await page.spyOnEvent('ionReorderComplete');
await expect(items).toContainText(['Item 1', 'Item 2', 'Item 3', 'Item 4']);
await dragElementBy(items.nth(1), page, 0, 300);
await ionItemReorderComplete.next();
await ionReorderComplete.next();
await expect(items).toContainText(['Item 1', 'Item 3', 'Item 4', 'Item 2']);
});
test('should drag and drop when ion-item wraps ion-reorder', async ({ page }) => {
const reorderHandle = page.locator('app-reorder ion-reorder');
const items = page.locator('app-reorder');
const ionItemReorderComplete = await page.spyOnEvent('ionItemReorderComplete');
const ionReorderComplete = await page.spyOnEvent('ionReorderComplete');
await expect(items).toContainText(['Item 1', 'Item 2', 'Item 3', 'Item 4']);
await dragElementBy(reorderHandle.nth(0), page, 0, 300);
await ionItemReorderComplete.next();
await ionReorderComplete.next();
await expect(items).toContainText(['Item 2', 'Item 3', 'Item 4', 'Item 1']);
});

View File

@@ -0,0 +1,289 @@
import { expect } from '@playwright/test';
import { configs, dragElementBy, test } from '@utils/test/playwright';
/**
* This behavior does not vary across modes/directions.
*/
configs({ modes: ['ios'], directions: ['ltr'] }).forEach(({ title, config }) => {
test.describe(title('reorder-group: events:'), () => {
test.describe('ionReorderStart', () => {
test('should emit when the reorder operation starts', async ({ page }) => {
await page.setContent(
`
<ion-reorder-group disabled="false">
<ion-item>
<ion-label>Item 1</ion-label>
<ion-reorder slot="end"></ion-reorder>
</ion-item>
<ion-item>
<ion-label>Item 2</ion-label>
<ion-reorder slot="end"></ion-reorder>
</ion-item>
<ion-item>
<ion-label>Item 3</ion-label>
<ion-reorder slot="end"></ion-reorder>
</ion-item>
</ion-reorder-group>
`,
config
);
const reorderGroup = page.locator('ion-reorder-group');
const ionReorderStart = await page.spyOnEvent('ionReorderStart');
await expect(ionReorderStart).toHaveReceivedEventTimes(0);
// Start the drag to verify it emits the event without having to
// actually move the item. Do not release the drag here.
await dragElementBy(reorderGroup.locator('ion-reorder').first(), page, 0, 0, undefined, undefined, false);
await page.waitForChanges();
await expect(ionReorderStart).toHaveReceivedEventTimes(1);
// Drag the reorder item further to verify it does
// not emit the event again
await dragElementBy(reorderGroup.locator('ion-reorder').first(), page, 0, 300);
await page.waitForChanges();
await expect(ionReorderStart).toHaveReceivedEventTimes(1);
});
});
test.describe('ionReorderMove', () => {
test('should emit when the reorder operation does not move the item position', async ({ page }) => {
await page.setContent(
`
<ion-reorder-group disabled="false">
<ion-item>
<ion-label>Item 1</ion-label>
<ion-reorder slot="end"></ion-reorder>
</ion-item>
<ion-item>
<ion-label>Item 2</ion-label>
<ion-reorder slot="end"></ion-reorder>
</ion-item>
<ion-item>
<ion-label>Item 3</ion-label>
<ion-reorder slot="end"></ion-reorder>
</ion-item>
</ion-reorder-group>
`,
config
);
const reorderGroup = page.locator('ion-reorder-group');
const ionReorderMove = await page.spyOnEvent('ionReorderMove');
await dragElementBy(reorderGroup.locator('ion-reorder').first(), page, 0, 0);
await page.waitForChanges();
expect(ionReorderMove.events.length).toBeGreaterThan(0);
// Grab the last event to verify that it is emitting
// the correct from and to positions
const lastEvent = ionReorderMove.events[ionReorderMove.events.length - 1];
expect(lastEvent?.detail.from).toBe(0);
expect(lastEvent?.detail.to).toBe(0);
});
test('should emit when the reorder operation moves the item by multiple positions', async ({ page }) => {
await page.setContent(
`
<ion-reorder-group disabled="false">
<ion-item>
<ion-label>Item 1</ion-label>
<ion-reorder slot="end"></ion-reorder>
</ion-item>
<ion-item>
<ion-label>Item 2</ion-label>
<ion-reorder slot="end"></ion-reorder>
</ion-item>
<ion-item>
<ion-label>Item 3</ion-label>
<ion-reorder slot="end"></ion-reorder>
</ion-item>
</ion-reorder-group>
`,
config
);
const reorderGroup = page.locator('ion-reorder-group');
const ionReorderMove = await page.spyOnEvent('ionReorderMove');
// Drag the reorder item by a lot to verify it emits the event
await dragElementBy(reorderGroup.locator('ion-reorder').first(), page, 0, 300);
await page.waitForChanges();
expect(ionReorderMove.events.length).toBeGreaterThan(0);
// Grab the last event where the from and to are different to
// verify that it is not using the gesture start position as the from
const lastDifferentEvent = ionReorderMove.events
.reverse()
.find((event) => event.detail.from !== event.detail.to);
expect(lastDifferentEvent?.detail.from).toBe(1);
expect(lastDifferentEvent?.detail.to).toBe(2);
});
});
test.describe('ionReorderEnd', () => {
test('should emit without details when the reorder operation ends without moving the item position', async ({
page,
}) => {
await page.setContent(
`
<ion-reorder-group disabled="false">
<ion-item>
<ion-label>Item 1</ion-label>
<ion-reorder slot="end"></ion-reorder>
</ion-item>
<ion-item>
<ion-label>Item 2</ion-label>
<ion-reorder slot="end"></ion-reorder>
</ion-item>
<ion-item>
<ion-label>Item 3</ion-label>
<ion-reorder slot="end"></ion-reorder>
</ion-item>
</ion-reorder-group>
`,
config
);
const reorderGroup = page.locator('ion-reorder-group');
const ionReorderEnd = await page.spyOnEvent('ionReorderEnd');
// Drag the reorder item a little bit but not enough to
// make it switch to a different position
await dragElementBy(reorderGroup.locator('ion-reorder').first(), page, 0, 20);
await page.waitForChanges();
await expect(ionReorderEnd).toHaveReceivedEventTimes(1);
await expect(ionReorderEnd).toHaveReceivedEventDetail({ from: 0, to: 0, complete: undefined });
});
test('should emit with details when the reorder operation ends and the item has moved', async ({ page }) => {
await page.setContent(
`
<ion-reorder-group disabled="false">
<ion-item>
<ion-label>Item 1</ion-label>
<ion-reorder slot="end"></ion-reorder>
</ion-item>
<ion-item>
<ion-label>Item 2</ion-label>
<ion-reorder slot="end"></ion-reorder>
</ion-item>
<ion-item>
<ion-label>Item 3</ion-label>
<ion-reorder slot="end"></ion-reorder>
</ion-item>
</ion-reorder-group>
`,
config
);
const reorderGroup = page.locator('ion-reorder-group');
const ionReorderEnd = await page.spyOnEvent('ionReorderEnd');
// Start the drag to verify it does not emit the event at the start
// of the drag or during the drag. Do not release the drag here.
await dragElementBy(reorderGroup.locator('ion-reorder').first(), page, 0, 100, undefined, undefined, false);
await page.waitForChanges();
await expect(ionReorderEnd).toHaveReceivedEventTimes(0);
// Drag the reorder item further and release the drag to verify it emits the event
await dragElementBy(reorderGroup.locator('ion-reorder').first(), page, 0, 300);
await page.waitForChanges();
await expect(ionReorderEnd).toHaveReceivedEventTimes(1);
await expect(ionReorderEnd).toHaveReceivedEventDetail({ from: 0, to: 2, complete: undefined });
});
});
// TODO(FW-6590): Remove this once the deprecated event is removed
test.describe('ionItemReorder', () => {
test('should not emit when the reorder operation ends without moving the item position', async ({ page }) => {
await page.setContent(
`
<ion-reorder-group disabled="false">
<ion-item>
<ion-label>Item 1</ion-label>
<ion-reorder slot="end"></ion-reorder>
</ion-item>
<ion-item>
<ion-label>Item 2</ion-label>
<ion-reorder slot="end"></ion-reorder>
</ion-item>
<ion-item>
<ion-label>Item 3</ion-label>
<ion-reorder slot="end"></ion-reorder>
</ion-item>
</ion-reorder-group>
`,
config
);
const reorderGroup = page.locator('ion-reorder-group');
const ionItemReorder = await page.spyOnEvent('ionItemReorder');
// Drag the reorder item a little bit but not enough to
// make it switch to a different position
await dragElementBy(reorderGroup.locator('ion-reorder').first(), page, 0, 20);
await page.waitForChanges();
await expect(ionItemReorder).toHaveReceivedEventTimes(0);
});
test('should emit when the reorder operation ends and the item has moved', async ({ page }) => {
await page.setContent(
`
<ion-reorder-group disabled="false">
<ion-item>
<ion-label>Item 1</ion-label>
<ion-reorder slot="end"></ion-reorder>
</ion-item>
<ion-item>
<ion-label>Item 2</ion-label>
<ion-reorder slot="end"></ion-reorder>
</ion-item>
<ion-item>
<ion-label>Item 3</ion-label>
<ion-reorder slot="end"></ion-reorder>
</ion-item>
</ion-reorder-group>
`,
config
);
const reorderGroup = page.locator('ion-reorder-group');
const ionItemReorder = await page.spyOnEvent('ionItemReorder');
// Start the drag to verify it does not emit the event at the start
// of the drag or during the drag. Do not release the drag here.
await dragElementBy(reorderGroup.locator('ion-reorder').first(), page, 0, 100, undefined, undefined, false);
await page.waitForChanges();
await expect(ionItemReorder).toHaveReceivedEventTimes(0);
// Drag the reorder item further and release the drag to verify it emits the event
await dragElementBy(reorderGroup.locator('ion-reorder').first(), page, 0, 300);
await page.waitForChanges();
await expect(ionItemReorder).toHaveReceivedEventTimes(1);
await expect(ionItemReorder).toHaveReceivedEventDetail({ from: 0, to: 2, complete: undefined });
});
});
});
});

View File

@@ -57,9 +57,9 @@
<script>
const group = document.querySelector('ion-reorder-group');
group.addEventListener('ionItemReorder', (ev) => {
group.addEventListener('ionReorderEnd', (ev) => {
ev.detail.complete();
window.dispatchEvent(new CustomEvent('ionItemReorderComplete'));
window.dispatchEvent(new CustomEvent('ionReorderComplete'));
});
</script>
</body>

View File

@@ -11,24 +11,24 @@ configs({ modes: ['md'], directions: ['ltr'] }).forEach(({ title, config }) => {
});
test('should drag and drop when ion-reorder wraps ion-item', async ({ page }) => {
const items = page.locator('ion-item');
const ionItemReorderComplete = await page.spyOnEvent('ionItemReorderComplete');
const ionReorderComplete = await page.spyOnEvent('ionReorderComplete');
await expect(items).toContainText(['Item 1', 'Item 2', 'Item 3', 'Item 4']);
await dragElementBy(items.nth(1), page, 0, 300);
await ionItemReorderComplete.next();
await ionReorderComplete.next();
await expect(items).toContainText(['Item 1', 'Item 3', 'Item 4', 'Item 2']);
});
test('should drag and drop when ion-item wraps ion-reorder', async ({ page }) => {
const reorderHandle = page.locator('ion-reorder');
const items = page.locator('ion-item');
const ionItemReorderComplete = await page.spyOnEvent('ionItemReorderComplete');
const ionReorderComplete = await page.spyOnEvent('ionReorderComplete');
await expect(items).toContainText(['Item 1', 'Item 2', 'Item 3', 'Item 4']);
await dragElementBy(reorderHandle.nth(0), page, 0, 300);
await ionItemReorderComplete.next();
await ionReorderComplete.next();
await expect(items).toContainText(['Item 2', 'Item 3', 'Item 4', 'Item 1']);
});

View File

@@ -1,10 +1,6 @@
import type { AnimationBuilder, ComponentProps } from '../../../interface';
import type { AnimationBuilder, ComponentProps, HTMLStencilElement } from '../../../interface';
import type { NavigationHookCallback } from '../../route/route-interface';
export interface HTMLStencilElement extends HTMLElement {
componentOnReady(): Promise<this>;
}
export interface NavOutlet {
setRouteId(
id: string,

View File

@@ -68,7 +68,27 @@ export class Tabs implements NavOutlet {
componentWillRender() {
const tabBar = this.el.querySelector('ion-tab-bar');
if (tabBar) {
const tab = this.selectedTab ? this.selectedTab.tab : undefined;
let tab = this.selectedTab ? this.selectedTab.tab : undefined;
// Fallback: if no selectedTab is set but we're using router mode,
// determine the active tab from the current URL. This works around
// timing issues in React Router integration where setRouteId may not
// be called in time for the initial render.
// TODO(FW-6724): Remove this with React Router upgrade
if (!tab && this.useRouter && typeof window !== 'undefined') {
const currentPath = window.location.pathname;
const tabButtons = this.el.querySelectorAll('ion-tab-button');
// Look for a tab button that matches the current path pattern
for (const tabButton of tabButtons) {
const tabId = tabButton.getAttribute('tab');
if (tabId && currentPath.includes(tabId)) {
tab = tabId;
break;
}
}
}
tabBar.selectedTab = tab;
}
}

View File

@@ -2,9 +2,14 @@
@import "../themes/ionic.mixins";
// Display
// --------------------------------------------------
// Modifies display of a particular element based on the given classes
// ------------------------------------------------------------------
// Provides utility classes to control the CSS display property
// of elements. Includes responsive variants for toggling between
// block, inline, flex, grid, and other display values at different
// breakpoints.
// TODO(FW-6697): remove ion-hide-* classes in favor of the new
// ion-display-* classes
.ion-hide {
display: none !important;
}
@@ -29,3 +34,29 @@
}
}
}
$display-values: (
none,
inline,
inline-block,
block,
flex,
inline-flex,
grid,
inline-grid,
table,
table-cell,
table-row
);
@each $display in $display-values {
@each $breakpoint in map-keys($screen-breakpoints) {
$infix: breakpoint-infix($breakpoint, $screen-breakpoints);
@include media-breakpoint-up($breakpoint, $screen-breakpoints) {
.ion-display#{$infix}-#{$display} {
display: #{$display} !important;
}
}
}
}

View File

@@ -1,99 +1,211 @@
@import "../themes/ionic.globals";
@import "../themes/ionic.mixins";
// Flex Utilities
// --------------------------------------------------
// Creates flex classes to align flex containers
// and items
// ------------------------------------------------------------------
// Provides utility classes to control flexbox layout, alignment,
// and sizing of elements. Includes responsive variants for managing
// flex direction, alignment, justification, wrapping, growth,
// shrinking, and ordering at different breakpoints.
// Align Self
// --------------------------------------------------
// Align Content
// ------------------------------------------------------------------
.ion-align-self-start {
align-self: flex-start !important;
$align-content-values: (
start: flex-start,
end: flex-end,
center: center,
between: space-between,
around: space-around,
stretch: stretch
);
@each $breakpoint in map-keys($screen-breakpoints) {
$infix: breakpoint-infix($breakpoint, $screen-breakpoints);
@include media-breakpoint-up($breakpoint, $screen-breakpoints) {
@each $key, $value in $align-content-values {
.ion-align-content#{$infix}-#{$key} {
align-content: #{$value} !important;
}
}
}
}
.ion-align-self-end {
align-self: flex-end !important;
}
.ion-align-self-center {
align-self: center !important;
}
.ion-align-self-stretch {
align-self: stretch !important;
}
.ion-align-self-baseline {
align-self: baseline !important;
}
.ion-align-self-auto {
align-self: auto !important;
}
// Flex Wrap
// --------------------------------------------------
.ion-wrap {
flex-wrap: wrap !important;
}
.ion-nowrap {
flex-wrap: nowrap !important;
}
.ion-wrap-reverse {
flex-wrap: wrap-reverse !important;
}
// Justify Content
// --------------------------------------------------
.ion-justify-content-start {
justify-content: flex-start !important;
}
.ion-justify-content-center {
justify-content: center !important;
}
.ion-justify-content-end {
justify-content: flex-end !important;
}
.ion-justify-content-around {
justify-content: space-around !important;
}
.ion-justify-content-between {
justify-content: space-between !important;
}
.ion-justify-content-evenly {
justify-content: space-evenly !important;
}
// Align Items
// --------------------------------------------------
// ------------------------------------------------------------------
.ion-align-items-start {
align-items: flex-start !important;
$align-items-values: (
start,
end,
center,
stretch,
baseline
);
@each $breakpoint in map-keys($screen-breakpoints) {
$infix: breakpoint-infix($breakpoint, $screen-breakpoints);
@include media-breakpoint-up($breakpoint, $screen-breakpoints) {
@each $value in $align-items-values {
.ion-align-items#{$infix}-#{$value} {
align-items: #{$value} !important;
}
}
}
}
.ion-align-items-center {
align-items: center !important;
// Align Self
// ------------------------------------------------------------------
$align-self-values: (
start,
end,
center,
stretch,
baseline,
auto
);
@each $breakpoint in map-keys($screen-breakpoints) {
$infix: breakpoint-infix($breakpoint, $screen-breakpoints);
@include media-breakpoint-up($breakpoint, $screen-breakpoints) {
@each $value in $align-self-values {
.ion-align-self#{$infix}-#{$value} {
align-self: #{$value} !important;
}
}
}
}
.ion-align-items-end {
align-items: flex-end !important;
// Justify Content
// ------------------------------------------------------------------
$justify-content-values: (
start: flex-start,
end: flex-end,
center: center,
between: space-between,
around: space-around,
evenly: space-evenly
);
@each $breakpoint in map-keys($screen-breakpoints) {
$infix: breakpoint-infix($breakpoint, $screen-breakpoints);
@include media-breakpoint-up($breakpoint, $screen-breakpoints) {
@each $key, $value in $justify-content-values {
.ion-justify-content#{$infix}-#{$key} {
justify-content: #{$value} !important;
}
}
}
}
.ion-align-items-stretch {
align-items: stretch !important;
// Flex Direction
// ------------------------------------------------------------------
$flex-direction-values: (
row,
row-reverse,
column,
column-reverse
);
@each $breakpoint in map-keys($screen-breakpoints) {
$infix: breakpoint-infix($breakpoint, $screen-breakpoints);
@include media-breakpoint-up($breakpoint, $screen-breakpoints) {
@each $value in $flex-direction-values {
.ion-flex#{$infix}-#{$value} {
flex-direction: #{$value} !important;
}
}
}
}
.ion-align-items-baseline {
align-items: baseline !important;
// Flex Wrap
// ------------------------------------------------------------------
$flex-wrap-values: (
wrap,
nowrap,
wrap-reverse
);
@each $value in $flex-wrap-values {
// TODO(FW-6697): remove ion-wrap, ion-nowrap, ion-wrap-reverse
// in favor of the new ion-flex-wrap, ion-flex-nowrap, and
// ion-flex-wrap-reverse classes
.ion-#{$value} {
flex-wrap: #{$value} !important;
}
}
@each $breakpoint in map-keys($screen-breakpoints) {
$infix: breakpoint-infix($breakpoint, $screen-breakpoints);
@include media-breakpoint-up($breakpoint, $screen-breakpoints) {
@each $value in $flex-wrap-values {
.ion-flex#{$infix}-#{$value} {
flex-wrap: #{$value} !important;
}
}
}
}
// Flex Fill
// ------------------------------------------------------------------
$flex-fill-values: (
1,
auto,
initial,
none
);
@each $breakpoint in map-keys($screen-breakpoints) {
$infix: breakpoint-infix($breakpoint, $screen-breakpoints);
@include media-breakpoint-up($breakpoint, $screen-breakpoints) {
@each $value in $flex-fill-values {
.ion-flex#{$infix}-#{$value} {
flex: #{$value} !important;
}
}
}
}
// Flex Grow and Shrink
// ------------------------------------------------------------------
@each $breakpoint in map-keys($screen-breakpoints) {
$infix: breakpoint-infix($breakpoint, $screen-breakpoints);
@include media-breakpoint-up($breakpoint, $screen-breakpoints) {
.ion-flex#{$infix}-grow-0 {
flex-grow: 0 !important;
}
.ion-flex#{$infix}-grow-1 {
flex-grow: 1 !important;
}
.ion-flex#{$infix}-shrink-0 {
flex-shrink: 0 !important;
}
.ion-flex#{$infix}-shrink-1 {
flex-shrink: 1 !important;
}
}
}
// Flex Order
// ------------------------------------------------------------------
@each $breakpoint in map-keys($screen-breakpoints) {
$infix: breakpoint-infix($breakpoint, $screen-breakpoints);
@include media-breakpoint-up($breakpoint, $screen-breakpoints) {
.ion-order#{$infix}-first { order: -1 !important; }
@for $i from 0 through 12 {
.ion-order#{$infix}-#{$i} { order: #{$i} !important; }
}
.ion-order#{$infix}-last { order: 13 !important; }
}
}

View File

@@ -11,61 +11,70 @@ $light: #222428;
$medium: #989aa2;
$dark: #f4f5f8;
$colors: (
$colors: (
primary: (
base: $primary,
contrast: #000,
shade: get-color-shade($primary),
tint: get-color-tint($primary)
base: $primary,
contrast: #000,
shade: get-color-shade($primary),
tint: get-color-tint($primary),
foreground: $primary,
),
secondary: (
base: $secondary,
contrast: #000,
shade: get-color-shade($secondary),
tint: get-color-tint($secondary)
base: $secondary,
contrast: #000,
shade: get-color-shade($secondary),
tint: get-color-tint($secondary),
foreground: $secondary,
),
tertiary: (
base: $tertiary,
contrast: #000,
shade: get-color-shade($tertiary),
tint: get-color-tint($tertiary)
base: $tertiary,
contrast: #000,
shade: get-color-shade($tertiary),
tint: get-color-tint($tertiary),
foreground: $tertiary,
),
success: (
base: $success,
contrast: #000,
shade: get-color-shade($success),
tint: get-color-tint($success)
base: $success,
contrast: #000,
shade: get-color-shade($success),
tint: get-color-tint($success),
foreground: $success,
),
warning: (
base: $warning,
contrast: #000,
shade: get-color-shade($warning),
tint: get-color-tint($warning)
base: $warning,
contrast: #000,
shade: get-color-shade($warning),
tint: get-color-tint($warning),
foreground: $warning,
),
danger: (
base: $danger,
contrast: #000,
shade: get-color-shade($danger),
tint: get-color-tint($danger)
base: $danger,
contrast: #000,
shade: get-color-shade($danger),
tint: get-color-tint($danger),
foreground: $danger,
),
light: (
base: $light,
contrast: #fff,
shade: get-color-shade($light),
tint: get-color-tint($light)
base: $light,
contrast: #fff,
shade: get-color-shade($light),
tint: get-color-tint($light),
foreground: $light,
),
medium: (
base: $medium,
contrast: #000,
shade: get-color-shade($medium),
tint: get-color-tint($medium)
base: $medium,
contrast: #000,
shade: get-color-shade($medium),
tint: get-color-tint($medium),
foreground: $medium,
),
dark: (
base: $dark,
contrast: #000,
shade: get-color-shade($dark),
tint: get-color-tint($dark)
)
base: $dark,
contrast: #000,
shade: get-color-shade($dark),
tint: get-color-tint($dark),
foreground: $dark,
),
);
@mixin dark-base-palette() {

View File

@@ -1,71 +1,80 @@
@use "sass:map";
@import "../../themes/ionic.functions.color";
$primary: #7cabff;
$secondary: #62bdff;
$tertiary: #b6b9f9;
$success: #4ada71;
$warning: #ffce31;
$danger: #fc9aa2;
$light: #222428;
$medium: #a8aab3;
$dark: #f4f5f8;
$primary: #7cabff;
$secondary: #62bdff;
$tertiary: #b6b9f9;
$success: #4ada71;
$warning: #ffce31;
$danger: #fc9aa2;
$light: #222428;
$medium: #a8aab3;
$dark: #f4f5f8;
$colors: (
$colors: (
primary: (
base: $primary,
contrast: #000,
shade: get-color-shade($primary),
tint: get-color-tint($primary)
base: $primary,
contrast: #000,
shade: get-color-shade($primary),
tint: get-color-tint($primary),
foreground: $primary,
),
secondary: (
base: $secondary,
contrast: #000,
shade: get-color-shade($secondary),
tint: get-color-tint($secondary)
base: $secondary,
contrast: #000,
shade: get-color-shade($secondary),
tint: get-color-tint($secondary),
foreground: $secondary,
),
tertiary: (
base: $tertiary,
contrast: #000,
shade: get-color-shade($tertiary),
tint: get-color-tint($tertiary)
base: $tertiary,
contrast: #000,
shade: get-color-shade($tertiary),
tint: get-color-tint($tertiary),
foreground: $tertiary,
),
success: (
base: $success,
contrast: #000,
shade: get-color-shade($success),
tint: get-color-tint($success)
base: $success,
contrast: #000,
shade: get-color-shade($success),
tint: get-color-tint($success),
foreground: $success,
),
warning: (
base: $warning,
contrast: #000,
shade: get-color-shade($warning),
tint: get-color-tint($warning)
base: $warning,
contrast: #000,
shade: get-color-shade($warning),
tint: get-color-tint($warning),
foreground: $warning,
),
danger: (
base: $danger,
contrast: #000,
shade: get-color-shade($danger),
tint: get-color-tint($danger)
base: $danger,
contrast: #000,
shade: get-color-shade($danger),
tint: get-color-tint($danger),
foreground: $danger,
),
light: (
base: $light,
contrast: #fff,
shade: get-color-shade($light),
tint: get-color-tint($light)
base: $light,
contrast: #fff,
shade: get-color-shade($light),
tint: get-color-tint($light),
foreground: $light,
),
medium: (
base: $medium,
contrast: #000,
shade: get-color-shade($medium),
tint: get-color-tint($medium)
base: $medium,
contrast: #000,
shade: get-color-shade($medium),
tint: get-color-tint($medium),
foreground: $medium,
),
dark: (
base: $dark,
contrast: #000,
shade: get-color-shade($dark),
tint: get-color-tint($dark)
)
base: $dark,
contrast: #000,
shade: get-color-shade($dark),
tint: get-color-tint($dark),
foreground: $dark,
),
);
/// Text step colors are generated based on
@@ -105,13 +114,12 @@ $lightest-text-color: $text-color;
--ion-color-#{$color-name}-shade: #{map.get($value, shade)};
--ion-color-#{$color-name}-tint: #{map.get($value, tint)};
}
}
}
@mixin high-contrast-dark-ios-palette() {
$background-color: #000000;
& {
--ion-background-color: #{$background-color};
--ion-background-color-rgb: #{color-to-rgb-list($background-color)};
@@ -175,7 +183,7 @@ $lightest-text-color: $text-color;
@mixin high-contrast-dark-md-palette() {
$background-color: #121212;
& {
--ion-background-color: #{$background-color};
--ion-background-color-rgb: #{color-to-rgb-list($background-color)};

View File

@@ -1,71 +1,80 @@
@use "sass:map";
@import "../../themes/ionic.functions.color";
$primary: #003fae;
$secondary: #01487b;
$tertiary: #3400e6;
$success: #004314;
$warning: #5f4100;
$danger: #9c000c;
$light: #f4f5f8;
$medium: #444446;
$dark: #222428;
$primary: #003fae;
$secondary: #01487b;
$tertiary: #3400e6;
$success: #004314;
$warning: #5f4100;
$danger: #9c000c;
$light: #f4f5f8;
$medium: #444446;
$dark: #222428;
$colors: (
$colors: (
primary: (
base: $primary,
contrast: #fff,
shade: get-color-shade($primary),
tint: get-color-tint($primary)
base: $primary,
contrast: #fff,
shade: get-color-shade($primary),
tint: get-color-tint($primary),
foreground: $primary,
),
secondary: (
base: $secondary,
contrast: #fff,
shade: get-color-shade($secondary),
tint: get-color-tint($secondary)
base: $secondary,
contrast: #fff,
shade: get-color-shade($secondary),
tint: get-color-tint($secondary),
foreground: $secondary,
),
tertiary: (
base: $tertiary,
contrast: #fff,
shade: get-color-shade($tertiary),
tint: get-color-tint($tertiary)
base: $tertiary,
contrast: #fff,
shade: get-color-shade($tertiary),
tint: get-color-tint($tertiary),
foreground: $tertiary,
),
success: (
base: $success,
contrast: #fff,
shade: get-color-shade($success),
tint: get-color-tint($success)
base: $success,
contrast: #fff,
shade: get-color-shade($success),
tint: get-color-tint($success),
foreground: $success,
),
warning: (
base: $warning,
contrast: #fff,
shade: get-color-shade($warning),
tint: get-color-tint($warning)
base: $warning,
contrast: #fff,
shade: get-color-shade($warning),
tint: get-color-tint($warning),
foreground: $warning,
),
danger: (
base: $danger,
contrast: #fff,
shade: get-color-shade($danger),
tint: get-color-tint($danger)
base: $danger,
contrast: #fff,
shade: get-color-shade($danger),
tint: get-color-tint($danger),
foreground: $danger,
),
light: (
base: $light,
contrast: #000,
shade: get-color-shade($light),
tint: get-color-tint($light)
base: $light,
contrast: #000,
shade: get-color-shade($light),
tint: get-color-tint($light),
foreground: $light,
),
medium: (
base: $medium,
contrast: #fff,
shade: get-color-shade($medium),
tint: get-color-tint($medium)
base: $medium,
contrast: #fff,
shade: get-color-shade($medium),
tint: get-color-tint($medium),
foreground: $medium,
),
dark: (
base: $dark,
contrast: #fff,
shade: get-color-shade($dark),
tint: get-color-tint($dark)
)
base: $dark,
contrast: #fff,
shade: get-color-shade($dark),
tint: get-color-tint($dark),
foreground: $dark,
),
);
/// Text step colors are generated based on

View File

@@ -0,0 +1,48 @@
import { test, expect } from '@playwright/test';
import fs from 'fs';
import path from 'path';
test.describe('display css utility classes', () => {
let css: string;
test.beforeAll(() => {
css = fs.readFileSync(path.resolve(__dirname, '../../../css/display.css'), 'utf8');
});
const INFIXES = ['', '-sm', '-md', '-lg', '-xl'];
// TODO(FW-6697): remove `ion-hide classes` test
test('ion-hide classes', () => {
expect(css).toContain('.ion-hide');
const values = ['up', 'down'];
for (const value of values) {
for (const infix of INFIXES) {
expect(css).toContain(`.ion-hide${infix}-${value}`);
}
}
});
test('ion-display classes', () => {
const values = [
'none',
'inline',
'inline-block',
'block',
'flex',
'inline-flex',
'grid',
'inline-grid',
'table',
'table-cell',
'table-row',
];
for (const value of values) {
for (const infix of INFIXES) {
expect(css).toContain(`.ion-display${infix}-${value}`);
}
}
});
});

View File

@@ -0,0 +1,100 @@
import { test, expect } from '@playwright/test';
import fs from 'fs';
import path from 'path';
test.describe('flex-utils css utility classes', () => {
let css: string;
test.beforeAll(() => {
css = fs.readFileSync(path.resolve(__dirname, '../../../css/flex-utils.css'), 'utf8');
});
const INFIXES = ['', '-sm', '-md', '-lg', '-xl'];
test('align-content classes', () => {
const values = ['start', 'end', 'center', 'between', 'around', 'stretch'];
for (const value of values) {
for (const infix of INFIXES) {
expect(css).toContain(`.ion-align-content${infix}-${value}`);
}
}
});
test('align-items classes', () => {
const values = ['start', 'center', 'end', 'stretch', 'baseline'];
for (const value of values) {
for (const infix of INFIXES) {
expect(css).toContain(`.ion-align-items${infix}-${value}`);
}
}
});
test('align-self classes', () => {
const values = ['start', 'end', 'center', 'stretch', 'baseline', 'auto'];
for (const value of values) {
for (const infix of INFIXES) {
expect(css).toContain(`.ion-align-self${infix}-${value}`);
}
}
});
test('justify-content classes', () => {
const values = ['start', 'center', 'end', 'around', 'between', 'evenly'];
for (const value of values) {
for (const infix of INFIXES) {
expect(css).toContain(`.ion-justify-content${infix}-${value}`);
}
}
});
test('flex-direction classes', () => {
const values = ['row', 'row-reverse', 'column', 'column-reverse'];
for (const value of values) {
for (const infix of INFIXES) {
expect(css).toContain(`.ion-flex${infix}-${value}`);
}
}
});
test('flex-wrap classes', () => {
const values = ['wrap', 'nowrap', 'wrap-reverse'];
// TODO(FW-6697): remove all `ion-wrap-*` expects
for (const value of values) {
expect(css).toContain(`.ion-${value}`);
}
for (const value of values) {
for (const infix of INFIXES) {
expect(css).toContain(`.ion-flex${infix}-${value}`);
}
}
});
test('flex-fill classes', () => {
const values = ['1', 'auto', 'initial', 'none'];
for (const value of values) {
for (const infix of INFIXES) {
expect(css).toContain(`.ion-flex${infix}-${value}`);
}
}
});
test('flex-grow and flex-shrink classes', () => {
const values = ['grow', 'shrink'];
for (const value of values) {
for (const infix of INFIXES) {
expect(css).toContain(`.ion-flex${infix}-${value}-0`);
expect(css).toContain(`.ion-flex${infix}-${value}-1`);
}
}
});
test('flex-order classes', () => {
for (const infix of INFIXES) {
expect(css).toContain(`.ion-order${infix}-first`);
expect(css).toContain(`.ion-order${infix}-last`);
for (let i = 0; i <= 12; i++) {
expect(css).toContain(`.ion-order${infix}-${i}`);
}
}
});
});

View File

@@ -41,7 +41,10 @@ html {
/**
* Includes fallback if Dynamic Type is not enabled.
*/
font: var(--ion-dynamic-font, 16px var(--ion-font-family));
// ion-font-sizes-root needs a fallback since the new theming isn't fully
// implemented in the framework yet.
font: var(--ion-dynamic-font, var(--ion-font-sizes-root, 16px) var(--ion-font-family));
// font: var(--ion-dynamic-font, var(--ion-font-sizes-root) var(--ion-font-family));
}
}

View File

@@ -1,7 +1,10 @@
import { getMode, setMode } from '@stencil/core';
import { printIonWarning } from '@utils/logging';
import type { IonicConfig, Mode } from '../interface';
import { defaultTheme as baseTheme } from '../themes/base/base.tokens';
import type { Theme as BaseTheme } from '../themes/base/base.tokens';
import { deepMerge, generateCSSVars } from '../themes/base/generate-css-vars';
import { printIonWarning } from '../utils/logging';
import { isPlatform, setupPlatforms } from '../utils/platform';
import { config, configFromSession, configFromURL, saveConfig } from './config';
@@ -10,8 +13,183 @@ import { config, configFromSession, configFromURL, saveConfig } from './config';
let defaultMode: Mode;
export const getIonMode = (ref?: any): Mode => {
return (ref && getMode(ref)) || defaultMode;
type Theme = 'ios' | 'md' | 'ionic';
const getElement = (ref: any): HTMLElement => {
if (ref && typeof ref === 'object' && ref.tagName) {
return ref;
}
return document.documentElement;
};
/**
* Prints a warning message to the developer to inform them of
* an invalid configuration of mode and theme.
* @param mode The invalid mode configuration.
* @param theme The invalid theme configuration.
*/
const printInvalidModeWarning = (mode: Mode, theme: Theme, ref?: any) => {
printIonWarning(
`Invalid mode and theme combination provided: mode: ${mode}, theme: ${theme}. Fallback mode ${getDefaultModeForTheme(
theme
)} will be used.`,
ref
);
};
const applyTheme = (userTheme: BaseTheme, prefix?: string) => {
const mergedTheme = deepMerge(baseTheme, userTheme);
const { palette, components, ...restTokens } = mergedTheme;
const { enabled, ...restDarkTokens } = palette.dark;
config.set('customTheme', mergedTheme);
const style = document.createElement('style');
style.innerHTML = [generateCSSVars(restTokens, prefix), generateCSSVars(palette.light, prefix)].join('\n\n');
if (enabled === 'system') {
style.innerHTML += `@media (prefers-color-scheme: dark) {\n${generateCSSVars(restDarkTokens, prefix)}\n}`;
}
document.head.appendChild(style);
};
/**
* Validates if a mode is accepted for a theme configuration.
* @param mode The mode to validate.
* @param theme The theme the mode is being used with.
* @returns `true` if the mode is valid for the theme, `false` if invalid.
*/
export const isModeValidForTheme = (mode: Mode, theme: Theme) => {
if (mode === 'md') {
return theme === 'md' || theme === 'ionic';
} else if (mode === 'ios') {
return theme === 'ios' || theme === 'ionic';
}
return false;
};
/**
* Returns the default mode for a specified theme.
* @param theme The theme to return a default mode for.
* @returns The default mode, either `ios` or `md`.
*/
const getDefaultModeForTheme = (theme: Theme): Mode => {
if (theme === 'ios') {
return 'ios';
}
return 'md';
};
/**
* Returns the default theme for a specified mode.
* @param mode The mode to return a default theme for.
* @returns The default theme.
*/
const getDefaultThemeForMode = (mode: Mode): Theme => {
if (mode === 'ios') {
return 'ios';
}
return 'md';
};
// const isModeSupported = (elmMode: string) => ['ios', 'md'].includes(elmMode);
// const isThemeSupported = (theme: string) => ['ios', 'md', 'ionic'].includes(theme);
// const isIonicElement = (elm: HTMLElement) => elm.tagName?.startsWith('ION-');
/**
* Returns the mode value of the element reference or the closest
* parent with a valid mode.
* @param ref The element reference to look up the mode for.
* @param theme Optionally can provide the theme to avoid an additional look-up.
* @returns The mode value for the element reference.
*/
export const getIonMode = (ref?: any, theme = getIonTheme(ref)): Mode => {
if (ref?.mode && isModeValidForTheme(ref?.mode, theme)) {
/**
* If the reference already has a mode configuration,
* use it instead of performing a look-up.
*/
return ref.mode;
} else {
const el = getElement(ref);
const mode = (el.closest('[mode]')?.getAttribute('mode') as Mode) || defaultMode;
if (isModeValidForTheme(mode, theme)) {
/**
* The mode configuration is supported for the configured theme.
*/
return mode;
} else {
printInvalidModeWarning(mode, theme, ref);
}
}
return getDefaultModeForTheme(theme);
};
/**
* Returns the theme value of the element reference or the closest
* parent with a valid theme.
*
* @param ref The element reference to look up the theme for.
* @returns The theme value for the element reference, defaults to
* the default theme if it cannot be determined.
*/
export const getIonTheme = (ref?: any): Theme => {
const theme: Theme = ref && getMode<Theme>(ref);
if (theme) {
return theme;
}
const el = getElement(ref);
const mode = ref?.mode ?? (el.closest('[mode]')?.getAttribute('mode') as Mode);
if (mode) {
return getDefaultThemeForMode(mode);
}
// Return a default theme string, not the baseTheme object
return 'md'; // or 'ionic' as your default
};
export const getIonCustomTheme = (): any => {
const customTheme = config.get('customTheme');
if (customTheme) {
return customTheme;
}
return baseTheme;
};
export const rIC = (callback: () => void) => {
if ('requestIdleCallback' in window) {
(window as any).requestIdleCallback(callback);
} else {
setTimeout(callback, 32);
}
};
export const needInputShims = () => {
/**
* iOS always needs input shims
*/
const needsShimsIOS = isPlatform(window, 'ios') && isPlatform(window, 'mobile');
if (needsShimsIOS) {
return true;
}
/**
* Android only needs input shims when running
* in the browser and only if the browser is using the
* new Chrome 108+ resize behavior: https://developer.chrome.com/blog/viewport-resize-behavior/
*/
const isAndroidMobileWeb = isPlatform(window, 'android') && isPlatform(window, 'mobileweb');
if (isAndroidMobileWeb) {
return true;
}
return false;
};
export const initialize = (userConfig: IonicConfig = {}) => {
@@ -53,6 +231,17 @@ export const initialize = (userConfig: IonicConfig = {}) => {
doc.documentElement.setAttribute('mode', defaultMode);
doc.documentElement.classList.add(defaultMode);
// Remove this line as 'theme' is not a valid IonicConfig key
// config.set('theme', defaultTheme);
// doc.documentElement.setAttribute('theme', defaultTheme);
// doc.documentElement.classList.add(defaultTheme);
const customTheme: BaseTheme | undefined = configObj.customTheme;
if (customTheme) {
applyTheme(customTheme);
}
if (config.getBoolean('_testing')) {
config.set('animated', false);
}

View File

@@ -23,9 +23,13 @@ export { PickerOptions, PickerColumnOption } from './components/picker-legacy/pi
export { PopoverOptions } from './components/popover/popover-interface';
export { RadioGroupCustomEvent } from './components/radio-group/radio-group-interface';
export { RangeCustomEvent, PinFormatter } from './components/range/range-interface';
export { HTMLStencilElement, RouterCustomEvent } from './components/router/utils/interface';
export { RouterCustomEvent } from './components/router/utils/interface';
export { RefresherCustomEvent } from './components/refresher/refresher-interface';
export { ItemReorderCustomEvent } from './components/reorder-group/reorder-group-interface';
export {
ItemReorderCustomEvent,
ReorderEndCustomEvent,
ReorderMoveCustomEvent,
} from './components/reorder-group/reorder-group-interface';
export { SearchbarCustomEvent } from './components/searchbar/searchbar-interface';
export { SegmentCustomEvent } from './components/segment/segment-interface';
export { SelectCustomEvent, SelectCompareFn } from './components/select/select-interface';
@@ -45,6 +49,7 @@ export {
AnimationKeyFrames,
AnimationLifecycle,
} from './utils/animation/animation-interface';
export { HTMLStencilElement } from './utils/element-interface';
export { TransitionOptions } from './utils/transition';
export { HTMLIonOverlayElement, OverlayController, OverlayInterface } from './utils/overlays-interface';
export { Config, config } from './global/config';

View File

@@ -0,0 +1,86 @@
import { defaultDarkTheme } from './dark.tokens';
import { defaultLightTheme } from './light.tokens';
export const defaultTheme = {
palette: {
light: defaultLightTheme,
dark: defaultDarkTheme,
},
// so far spacing is being used for
// padding, margin, gap, border-width, height, width
spacing: {
none: '0',
xxs: '2px',
xs: '4px',
sm: '8px',
md: '16px',
lg: '24px',
xl: '32px',
xxl: '40px',
},
// scaling is used for width and height
scaling: {
0: '0',
100: '4px',
150: '6px',
200: '8px',
250: '10px',
300: '12px',
350: '14px',
400: '16px',
450: '18px',
500: '20px',
550: '22px',
600: '24px',
650: '26px',
700: '28px',
750: '30px',
800: '32px',
850: '34px',
900: '36px',
},
radii: {
none: '0',
xs: '1px',
sm: '2px',
md: '4px',
lg: '8px',
xl: '16px',
xxl: '32px',
},
dynamicFont: '-apple-system-body',
fontFamily: 'Roboto, "Helvetica Neue", sans-serif',
fontWeights: {
thin: '100',
extraLight: '200',
light: '300',
normal: '400',
medium: '500',
semiBold: '600',
bold: '700',
extraBold: '800',
black: '900',
},
fontSizes: {
root: '16px',
xxs: '10px',
xs: '12px',
sm: '14px',
md: '16px',
lg: '18px',
xl: '20px',
xxl: '24px',
},
lineHeights: {
xxs: '1',
xs: '1.2',
sm: '1.4',
md: '1.6',
lg: '1.8',
xl: '2',
xxl: '2.4',
},
components: {},
};
export type Theme = typeof defaultTheme;

View File

@@ -0,0 +1,58 @@
export const defaultDarkTheme = {
enabled: 'never', // 'always' | 'system' | 'class' | 'never'
color: {
primary: {
bold: {
base: '#0054e9',
constrast: '#ffffff',
shade: '#0041c4', // darker version
tint: '#0065ff', // lighter version
},
subtle: {
base: '#0054e9',
constrast: '#ffffff',
shade: '#0041c4', // darker version
tint: '#0065ff', // lighter version
},
},
secondary: {
bold: {
base: '#0163aa',
constrast: '#ffffff',
shade: '#015a9e',
tint: '#0176c4',
},
subtle: {
base: '#0163aa',
constrast: '#ffffff',
shade: '#015a9e',
tint: '#0176c4',
},
},
red: {
50: '#ffebee',
100: '#ffcdd2',
200: '#ef9a9a',
},
blue: {
50: '#e3f2fd',
100: '#bbdefb',
200: '#90caf9',
},
gray: {
50: '#f5f5f5',
100: '#eeeeee',
200: '#e0e0e0',
300: '#bdbdbd',
400: '#9e9e9e',
500: '#757575',
600: '#616161',
700: '#424242',
800: '#212121',
},
white: 'green',
black: '#000000',
},
};
export type Theme = typeof defaultDarkTheme;

View File

@@ -0,0 +1,45 @@
// import type { Theme } from './base.tokens';
export function generateCSSVars(theme: any, themePrefix = '--ion-', selector = ':root'): string {
const flatten = (obj: any, prefix = themePrefix): string =>
Object.entries(obj)
.flatMap(([key, val]) => {
// if key is camelCase, convert to kebab-case
if (key.match(/([a-z])([A-Z])/g)) {
key = key.replace(/([a-z])([A-Z])/g, '$1-$2').toLowerCase();
}
// If it's a font-sizes key, create rem version
// This is necessary to support the dynamic font size feature
if (key === 'font-sizes' && typeof val === 'object' && val !== null) {
const fontSizeBase = parseFloat(theme.fontSizes.root);
return Object.entries(val).map(([sizeKey, sizeValue]) => {
const remValue = `${parseFloat(sizeValue) / fontSizeBase}rem`;
// Need a check to determine if the value is already in rem
return [
`${prefix}${key}-${sizeKey}: ${sizeValue};`, // original px value
`${prefix}${key}-${sizeKey}-rem: ${remValue};` // rem value
].join('\n');
}).join('\n');
}
return typeof val === 'object' && val !== null
? flatten(val, `${prefix}${key}-`)
: [`${prefix}${key}: ${val};`];
})
.join('\n');
return `${selector} {\n${flatten(theme)}\n}`;
}
// Simple deep merge function
export function deepMerge(target: any, source: any): any {
for (const key in source) {
if (source[key] && typeof source[key] === 'object' && !Array.isArray(source[key])) {
target[key] = deepMerge(target[key] ?? {}, source[key]);
} else {
target[key] = source[key];
}
}
return target;
}

View File

@@ -0,0 +1,57 @@
export const defaultLightTheme = {
color: {
primary: {
bold: {
base: '#0054e9',
constrast: '#ffffff',
shade: '#0041c4', // darker version
tint: '#0065ff', // lighter version
},
subtle: {
base: '#0054e9',
constrast: '#ffffff',
shade: '#0041c4', // darker version
tint: '#0065ff', // lighter version
},
},
secondary: {
bold: {
base: '#0163aa',
constrast: '#ffffff',
shade: '#015a9e',
tint: '#0176c4',
},
subtle: {
base: '#0163aa',
constrast: '#ffffff',
shade: '#015a9e',
tint: '#0176c4',
},
},
red: {
50: '#ffebee',
100: '#ffcdd2',
200: '#ef9a9a',
},
blue: {
50: '#e3f2fd',
100: '#bbdefb',
200: '#90caf9',
},
gray: {
50: '#f5f5f5',
100: '#eeeeee',
200: '#e0e0e0',
300: '#bdbdbd',
400: '#9e9e9e',
500: '#757575',
600: '#616161',
700: '#424242',
800: '#212121',
},
white: '#ffffff',
black: '#000000',
},
};
export type Theme = typeof defaultLightTheme;

View File

@@ -1,14 +1,18 @@
@use "sass:map";
// Gets the active color's css variable from a variation. Alpha is optional.
// --------------------------------------------------------------------------------------------
// Example usage:
// current-color(base) => var(--ion-color-base)
// current-color(contrast, 0.1) => rgba(var(--ion-color-contrast-rgb), 0.1)
// --------------------------------------------------------------------------------------------
@function current-color($variation, $alpha: null) {
@function current-color($variation, $alpha: null, $subtle: false) {
$variable: if($subtle, "--ion-color-subtle-#{$variation}", "--ion-color-#{$variation}");
@if $alpha == null {
@return var(--ion-color-#{$variation});
@return var(#{$variable});
} @else {
@return rgba(var(--ion-color-#{$variation}-rgb), #{$alpha});
@return rgba(var(#{$variable}-rgb), #{$alpha});
}
}
@@ -19,19 +23,36 @@
// ion-color(secondary, contrast) => var(--ion-color-secondary-contrast)
// ion-color(primary, base, 0.5) => rgba(var(--ion-color-primary-rgb, 56, 128, 255), 0.5)
// --------------------------------------------------------------------------------------------
@function ion-color($name, $variation, $alpha: null, $rgb: null) {
$values: map-get($colors, $name);
$value: map-get($values, $variation);
$variable: --ion-color-#{$name}-#{$variation};
@function ion-color($name, $variation, $alpha: null, $rgb: null, $subtle: false) {
$values: map.get($colors, $name);
$values: map.get($values, if($subtle, subtle, bold));
$value: map.get($values, $variation);
// TODO(FW-6417): this can be removed when foreground is required
// Fallback to "base" variant when "foreground" variant is undefined
@if ($variation == foreground and $value == null) {
$variation: base;
$value: map.get($values, $variation);
}
// If the color requested is subtle we return `--ion-color-{color}-subtle-contrast`,
// otherwise we return `--ion-color-{color}-contrast`.
$variable: if($subtle, "--ion-color-#{$name}-subtle-#{$variation}", "--ion-color-#{$name}-#{$variation}");
// If the variation being used is "base", we do not include the variant.
// If the color requested is subtle we return `--ion-color-{color}-subtle`,
// otherwise we return `--ion-color-{color}`.
@if ($variation == base) {
$variable: --ion-color-#{$name};
$variable: if($subtle, "--ion-color-#{$name}-subtle", "--ion-color-#{$name}");
}
@if ($alpha) {
$value: color-to-rgb-list($value);
@return rgba(var(#{$variable}-rgb, $value), $alpha);
}
@if ($rgb) {
$value: color-to-rgb-list($value);
$variable: #{$variable}-rgb;
@@ -43,17 +64,181 @@
// Mixes a color with black to create its shade.
// --------------------------------------------------------------------------------------------
@function get-color-shade($color) {
@if (type-of($color) != color) {
@return $color;
}
@return mix(#000, $color, 12%);
}
// Mixes a color with white to create its tint.
// --------------------------------------------------------------------------------------------
@function get-color-tint($color) {
@if (type-of($color) != color) {
@return $color;
}
@return mix(#fff, $color, 10%);
}
// Converts a color to a comma separated rgb.
// --------------------------------------------------------------------------------------------
@function color-to-rgb-list($color) {
@return #{red($color)},#{green($color)},#{blue($color)};
@if (type-of($color) != color) {
@return $color;
}
@return #{red($color)}, #{green($color)}, #{blue($color)};
}
// Generates color variants for the specified color based on the
// colors map for whichever hue is passed (bold, subtle).
// --------------------------------------------------------------------------------------------
// Example usage (bold):
// .ion-color-primary {
// @include generate-color-variants("primary");
// }
//
// Example output (bold):
// .ion-color-primary {
// --ion-color-base: var(--ion-color-primary-base, #105cef) !important;
// --ion-color-base-rgb: var(--ion-color-primary-base-rgb, 16, 92, 239) !important;
// --ion-color-contrast: var(--ion-color-primary-contrast, #fff) !important;
// --ion-color-contrast-rgb: var(--ion-color-primary-contrast-rgb, 255, 255, 255) !important;
// --ion-color-shade: var(--ion-color-primary-shade, #0f54da) !important;
// --ion-color-tint: var(--ion-color-primary-tint, #94a5f4) !important;
// }
// --------------------------------------------------------------------------------------------
// Example usage (subtle):
// .ion-color-primary {
// @include generate-color-variants("primary", "subtle")
// }
//
// Example output (subtle):
// .ion-color-primary {
// --ion-color-subtle-base: var(--ion-color-primary-subtle-base, #f2f4fd) !important;
// --ion-color-subtle-base-rgb: var(--ion-color-primary-subtle-base-rgb, 242, 244, 253) !important;
// --ion-color-subtle-contrast: var(--ion-color-primary-subtle-contrast, #105cef) !important;
// --ion-color-subtle-contrast-rgb: var(--ion-color-primary-subtle-contrast-rgb, 16, 92, 239) !important;
// --ion-color-subtle-shade: var(--ion-color-primary-subtle-shade, #d0d7fa) !important;
// --ion-color-subtle-tint: var(--ion-color-primary-subtle-tint, #e9ecfc) !important;
// }
// --------------------------------------------------------------------------------------------
@mixin generate-color-variants($color-name, $hue: "bold") {
@if not($colors) {
@error 'No theme colors set. Please make sure to call set-theme-colors($colorsMap) before using ion-color()';
}
// Grab the different hue color maps for the
// specified color and then grab the map of color variants
$hue-colors: map.get($colors, $color-name);
$color-variants: map.get($hue-colors, $hue);
$prefix: if($hue == "subtle", "-subtle", "");
// TODO(FW-6417) this @if can be removed if we add subtle colors for ios and md
// Only proceed if the color variants exist
@if $color-variants {
// Grab the individual color variants
$base: map.get($color-variants, base);
$base-rgb: map.get($color-variants, base-rgb);
$contrast: map.get($color-variants, contrast);
$contrast-rgb: map.get($color-variants, contrast-rgb);
$shade: map.get($color-variants, shade);
$tint: map.get($color-variants, tint);
$foreground: map.get($color-variants, foreground);
// Generate CSS variables dynamically
--ion-color#{$prefix}-base: var(--ion-color-#{$color-name}#{$prefix}, #{$base}) !important;
--ion-color#{$prefix}-base-rgb: var(--ion-color-#{$color-name}#{$prefix}-rgb, #{$base-rgb}) !important;
--ion-color#{$prefix}-contrast: var(--ion-color-#{$color-name}#{$prefix}-contrast, #{$contrast}) !important;
--ion-color#{$prefix}-contrast-rgb: var(
--ion-color-#{$color-name}#{$prefix}-contrast-rgb,
#{$contrast-rgb}
) !important;
--ion-color#{$prefix}-shade: var(--ion-color-#{$color-name}#{$prefix}-shade, #{$shade}) !important;
--ion-color#{$prefix}-tint: var(--ion-color-#{$color-name}#{$prefix}-tint, #{$tint}) !important;
// TODO(FW-6417): remove the fallback variable when the foreground variable is
// required by all palettes for all themes:
// --ion-color#{$prefix}-foreground: var(--ion-color-#{$color-name}#{$prefix}-foreground, #{$foreground}) !important;
--ion-color#{$prefix}-foreground: var(
--ion-color-#{$color-name}#{$prefix}-foreground,
var(--ion-color-#{$color-name}#{$prefix}, #{$foreground})
) !important;
}
}
// Generates both bold and subtle color variables
// for the specified color in the colors map.
// --------------------------------------------------------------------------------------------
@mixin generate-color($color-name) {
@include generate-color-variants($color-name);
@include generate-color-variants($color-name, "subtle");
}
// Generates color variables for all colors in the colors map for both hues (bold, subtle).
// --------------------------------------------------------------------------------------------
// Example usage:
// :root {
// generate-color-variables()
// }
//
// Example output:
// :root {
// --ion-color-primary: #105cef;
// --ion-color-primary-rgb: 16, 92, 239;
// --ion-color-primary-contrast: #ffffff;
// --ion-color-primary-contrast-rgb: 255, 255, 255;
// --ion-color-primary-shade: #0f54da;
// --ion-color-primary-tint: #94a5f4;
// --ion-color-primary-foreground: #105cef;
// --ion-color-primary-subtle: #f2f4fd;
// --ion-color-primary-subtle-rgb: 242, 244, 253;
// --ion-color-primary-subtle-contrast: #105cef;
// --ion-color-primary-subtle-contrast-rgb: 16, 92, 239;
// --ion-color-primary-subtle-shade: #d0d7fa;
// --ion-color-primary-subtle-tint: #e9ecfc;
// --ion-color-primary-foreground: #105cef;
// ...
// --ion-color-dark: #292929;
// --ion-color-dark-rgb: 41, 41, 41;
// --ion-color-dark-contrast: #ffffff;
// --ion-color-dark-contrast-rgb: 255, 255, 255;
// --ion-color-dark-shade: #242424;
// --ion-color-dark-tint: #4e4e4e;
// --ion-color-dark-foreground: #242424;
// --ion-color-dark-subtle: #f5f5f5;
// --ion-color-dark-subtle-rgb: 245, 245, 245;
// --ion-color-dark-subtle-contrast: #292929;
// --ion-color-dark-subtle-contrast-rgb: 41, 41, 41;
// --ion-color-dark-subtle-shade: #e0e0e0;
// --ion-color-dark-subtle-tint: #efefef;
// --ion-color-dark-subtle-foreground: #242424;
// }
// --------------------------------------------------------------------------------------------
@mixin generate-color-variables() {
@if not($colors) {
@error 'No theme colors set. Please make sure to call set-theme-colors($colorsMap) before using ion-color().';
}
@each $color-name, $value in $colors {
@each $hue in (bold, subtle) {
$colors: map.get($value, $hue);
@if $colors != null {
$prefix: if($hue == subtle, "-subtle", "");
--ion-color-#{$color-name}#{$prefix}: #{map.get($colors, base)};
--ion-color-#{$color-name}#{$prefix}-rgb: #{map.get($colors, base-rgb)};
--ion-color-#{$color-name}#{$prefix}-contrast: #{map.get($colors, contrast)};
--ion-color-#{$color-name}#{$prefix}-contrast-rgb: #{map.get($colors, contrast-rgb)};
--ion-color-#{$color-name}#{$prefix}-shade: #{map.get($colors, shade)};
--ion-color-#{$color-name}#{$prefix}-tint: #{map.get($colors, tint)};
// TODO(FW-6417): this "if" can be removed when foreground is defined for ios/md
// themes. It should not be added until we want foreground to be required for
// ios and md because this will be a breaking change, requiring users to add
// `--ion-color-{color}-foreground` in order to override the default colors
@if (map.get($colors, foreground)) {
--ion-color-#{$color-name}#{$prefix}-foreground: #{map.get($colors, foreground)};
}
}
}
}
}

View File

@@ -7,92 +7,130 @@
// Default Ionic Colors
// -------------------------------------------------------------------------------------------
// Color map should provide
// - base: main color to be used.
// - contrast: Color that will provide readable text against the base color
// - shade: 12% darker version of the base color (mix with black)
// - tint: 10% lighter version of the base color (mix with white)
// - base: The main color used for backgrounds
// - base-rgb: The base color in RGB format
// - contrast: A color that ensures readable text on the base color
// - contrast-rgb: The contrast color in RGB format
// - shade: 12% darker version of the base color (mix with black), used for pressed/active states
// - tint: 10% lighter version of the base color (mix with white), used for focused/hover states
$primary: #0054e9;
$secondary: #0163aa;
$tertiary: #6030ff;
$success: #2dd55b;
$warning: #ffc409;
$danger: #c5000f;
$light: #f4f5f8;
$medium: #636469;
$dark: #222428;
$primary: #0054e9;
$secondary: #0163aa;
$tertiary: #6030ff;
$success: #2dd55b;
$warning: #ffc409;
$danger: #c5000f;
$light: #f4f5f8;
$medium: #636469;
$dark: #222428;
$colors: (
$colors: (
primary: (
base: $primary,
contrast: #fff,
shade: get-color-shade($primary),
tint: get-color-tint($primary)
bold: (
base: $primary,
base-rgb: color-to-rgb-list($primary),
contrast: #fff,
contrast-rgb: color-to-rgb-list(#fff),
shade: get-color-shade($primary),
tint: get-color-tint($primary),
),
),
secondary: (
base: $secondary,
contrast: #fff,
shade: get-color-shade($secondary),
tint: get-color-tint($secondary)
bold: (
base: $secondary,
base-rgb: color-to-rgb-list($secondary),
contrast: #fff,
contrast-rgb: color-to-rgb-list(#fff),
shade: get-color-shade($secondary),
tint: get-color-tint($secondary),
),
),
tertiary: (
base: $tertiary,
contrast: #fff,
shade: get-color-shade($tertiary),
tint: get-color-tint($tertiary)
bold: (
base: $tertiary,
base-rgb: color-to-rgb-list($tertiary),
contrast: #fff,
contrast-rgb: color-to-rgb-list(#fff),
shade: get-color-shade($tertiary),
tint: get-color-tint($tertiary),
),
),
success: (
base: $success,
contrast: #000,
shade: get-color-shade($success),
tint: get-color-tint($success)
bold: (
base: $success,
base-rgb: color-to-rgb-list($success),
contrast: #000,
contrast-rgb: color-to-rgb-list(#000),
shade: get-color-shade($success),
tint: get-color-tint($success),
),
),
warning: (
base: $warning,
contrast: #000,
shade: get-color-shade($warning),
tint: get-color-tint($warning)
bold: (
base: $warning,
base-rgb: color-to-rgb-list($warning),
contrast: #000,
contrast-rgb: color-to-rgb-list(#000),
shade: get-color-shade($warning),
tint: get-color-tint($warning),
),
),
danger: (
base: $danger,
contrast: #fff,
shade: get-color-shade($danger),
tint: get-color-tint($danger)
bold: (
base: $danger,
base-rgb: color-to-rgb-list($danger),
contrast: #fff,
contrast-rgb: color-to-rgb-list(#fff),
shade: get-color-shade($danger),
tint: get-color-tint($danger),
),
),
light: (
base: $light,
contrast: #000,
shade: get-color-shade($light),
tint: get-color-tint($light)
bold: (
base: $light,
base-rgb: color-to-rgb-list($light),
contrast: #000,
contrast-rgb: color-to-rgb-list(#000),
shade: get-color-shade($light),
tint: get-color-tint($light),
),
),
medium: (
base: $medium,
contrast: #fff,
shade: get-color-shade($medium),
tint: get-color-tint($medium)
bold: (
base: $medium,
base-rgb: color-to-rgb-list($medium),
contrast: #fff,
contrast-rgb: color-to-rgb-list(#fff),
shade: get-color-shade($medium),
tint: get-color-tint($medium),
),
),
dark: (
base: $dark,
contrast: #fff,
shade: get-color-shade($dark),
tint: get-color-tint($dark)
)
bold: (
base: $dark,
base-rgb: color-to-rgb-list($dark),
contrast: #fff,
contrast-rgb: color-to-rgb-list(#fff),
shade: get-color-shade($dark),
tint: get-color-tint($dark),
),
),
);
// Default Foreground and Background Colors
// -------------------------------------------------------------------------------------------
// Used internally to calculate the default steps
$background-color-value: #fff;
$background-color-rgb-value: 255, 255, 255;
$background-color-value: #fff;
$background-color-rgb-value: 255, 255, 255;
$text-color-value: #000;
$text-color-rgb-value: 0, 0, 0;
$text-color-value: #000;
$text-color-rgb-value: 0, 0, 0;
$background-color: var(--ion-background-color, $background-color-value);
$background-color-rgb: var(--ion-background-color-rgb, $background-color-rgb-value);
$text-color: var(--ion-text-color, $text-color-value);
$text-color-rgb: var(--ion-text-color-rgb, $text-color-rgb-value);
$background-color: var(--ion-background-color, $background-color-value);
$background-color-rgb: var(--ion-background-color-rgb, $background-color-rgb-value);
$text-color: var(--ion-text-color, $text-color-value);
$text-color-rgb: var(--ion-text-color-rgb, $text-color-rgb-value);
// Default Foreground and Background Step Colors
// -------------------------------------------------------------------------------------------
@@ -101,45 +139,159 @@ $text-color-rgb: var(--ion-text-color-rgb, $text-color-rgb-va
// For example, $text-color-step-XXX will be $text-color stepping towards $background-color,
// but a $background-color-step-XXX will be $background-color stepping towards $text-color.
$background-color-step-50: var(--ion-color-step-50, var(--ion-background-color-step-50, mix($text-color-value, $background-color-value, 5%)));
$background-color-step-100: var(--ion-color-step-100, var(--ion-background-color-step-100, mix($text-color-value, $background-color-value, 10%)));
$background-color-step-150: var(--ion-color-step-150, var(--ion-background-color-step-150, mix($text-color-value, $background-color-value, 15%)));
$background-color-step-200: var(--ion-color-step-200, var(--ion-background-color-step-200, mix($text-color-value, $background-color-value, 20%)));
$background-color-step-250: var(--ion-color-step-250, var(--ion-background-color-step-250, mix($text-color-value, $background-color-value, 25%)));
$background-color-step-300: var(--ion-color-step-300, var(--ion-background-color-step-300, mix($text-color-value, $background-color-value, 30%)));
$background-color-step-350: var(--ion-color-step-350, var(--ion-background-color-step-350, mix($text-color-value, $background-color-value, 35%)));
$background-color-step-400: var(--ion-color-step-400, var(--ion-background-color-step-400, mix($text-color-value, $background-color-value, 40%)));
$background-color-step-450: var(--ion-color-step-450, var(--ion-background-color-step-450, mix($text-color-value, $background-color-value, 45%)));
$background-color-step-500: var(--ion-color-step-500, var(--ion-background-color-step-500, mix($text-color-value, $background-color-value, 50%)));
$background-color-step-550: var(--ion-color-step-550, var(--ion-background-color-step-550, mix($text-color-value, $background-color-value, 55%)));
$background-color-step-600: var(--ion-color-step-600, var(--ion-background-color-step-600, mix($text-color-value, $background-color-value, 60%)));
$background-color-step-650: var(--ion-color-step-650, var(--ion-background-color-step-650, mix($text-color-value, $background-color-value, 65%)));
$background-color-step-700: var(--ion-color-step-700, var(--ion-background-color-step-700, mix($text-color-value, $background-color-value, 70%)));
$background-color-step-750: var(--ion-color-step-750, var(--ion-background-color-step-750, mix($text-color-value, $background-color-value, 75%)));
$background-color-step-800: var(--ion-color-step-800, var(--ion-background-color-step-800, mix($text-color-value, $background-color-value, 80%)));
$background-color-step-850: var(--ion-color-step-850, var(--ion-background-color-step-850, mix($text-color-value, $background-color-value, 85%)));
$background-color-step-900: var(--ion-color-step-900, var(--ion-background-color-step-900, mix($text-color-value, $background-color-value, 90%)));
$background-color-step-950: var(--ion-color-step-950, var(--ion-background-color-step-950, mix($text-color-value, $background-color-value, 95%)));
$text-color-step-50: var(--ion-color-step-950, var(--ion-text-color-step-50, mix($background-color-value, $text-color-value, 5%)));
$text-color-step-100: var(--ion-color-step-900, var(--ion-text-color-step-100, mix($background-color-value, $text-color-value, 10%)));
$text-color-step-150: var(--ion-color-step-850, var(--ion-text-color-step-150, mix($background-color-value, $text-color-value, 15%)));
$text-color-step-200: var(--ion-color-step-800, var(--ion-text-color-step-200, mix($background-color-value, $text-color-value, 20%)));
$text-color-step-250: var(--ion-color-step-750, var(--ion-text-color-step-250, mix($background-color-value, $text-color-value, 25%)));
$text-color-step-300: var(--ion-color-step-700, var(--ion-text-color-step-300, mix($background-color-value, $text-color-value, 30%)));
$text-color-step-350: var(--ion-color-step-650, var(--ion-text-color-step-350, mix($background-color-value, $text-color-value, 35%)));
$text-color-step-400: var(--ion-color-step-600, var(--ion-text-color-step-400, mix($background-color-value, $text-color-value, 40%)));
$text-color-step-450: var(--ion-color-step-550, var(--ion-text-color-step-450, mix($background-color-value, $text-color-value, 45%)));
$text-color-step-500: var(--ion-color-step-500, var(--ion-text-color-step-500, mix($background-color-value, $text-color-value, 50%)));
$text-color-step-550: var(--ion-color-step-450, var(--ion-text-color-step-550, mix($background-color-value, $text-color-value, 55%)));
$text-color-step-600: var(--ion-color-step-400, var(--ion-text-color-step-600, mix($background-color-value, $text-color-value, 60%)));
$text-color-step-650: var(--ion-color-step-350, var(--ion-text-color-step-650, mix($background-color-value, $text-color-value, 65%)));
$text-color-step-700: var(--ion-color-step-300, var(--ion-text-color-step-700, mix($background-color-value, $text-color-value, 70%)));
$text-color-step-750: var(--ion-color-step-250, var(--ion-text-color-step-750, mix($background-color-value, $text-color-value, 75%)));
$text-color-step-800: var(--ion-color-step-200, var(--ion-text-color-step-800, mix($background-color-value, $text-color-value, 80%)));
$text-color-step-850: var(--ion-color-step-150, var(--ion-text-color-step-850, mix($background-color-value, $text-color-value, 85%)));
$text-color-step-900: var(--ion-color-step-100, var(--ion-text-color-step-900, mix($background-color-value, $text-color-value, 90%)));
$text-color-step-950: var(--ion-color-step-50, var(--ion-text-color-step-950, mix($background-color-value, $text-color-value, 95%)));
$background-color-step-50: var(
--ion-color-step-50,
var(--ion-background-color-step-50, mix($text-color-value, $background-color-value, 5%))
);
$background-color-step-100: var(
--ion-color-step-100,
var(--ion-background-color-step-100, mix($text-color-value, $background-color-value, 10%))
);
$background-color-step-150: var(
--ion-color-step-150,
var(--ion-background-color-step-150, mix($text-color-value, $background-color-value, 15%))
);
$background-color-step-200: var(
--ion-color-step-200,
var(--ion-background-color-step-200, mix($text-color-value, $background-color-value, 20%))
);
$background-color-step-250: var(
--ion-color-step-250,
var(--ion-background-color-step-250, mix($text-color-value, $background-color-value, 25%))
);
$background-color-step-300: var(
--ion-color-step-300,
var(--ion-background-color-step-300, mix($text-color-value, $background-color-value, 30%))
);
$background-color-step-350: var(
--ion-color-step-350,
var(--ion-background-color-step-350, mix($text-color-value, $background-color-value, 35%))
);
$background-color-step-400: var(
--ion-color-step-400,
var(--ion-background-color-step-400, mix($text-color-value, $background-color-value, 40%))
);
$background-color-step-450: var(
--ion-color-step-450,
var(--ion-background-color-step-450, mix($text-color-value, $background-color-value, 45%))
);
$background-color-step-500: var(
--ion-color-step-500,
var(--ion-background-color-step-500, mix($text-color-value, $background-color-value, 50%))
);
$background-color-step-550: var(
--ion-color-step-550,
var(--ion-background-color-step-550, mix($text-color-value, $background-color-value, 55%))
);
$background-color-step-600: var(
--ion-color-step-600,
var(--ion-background-color-step-600, mix($text-color-value, $background-color-value, 60%))
);
$background-color-step-650: var(
--ion-color-step-650,
var(--ion-background-color-step-650, mix($text-color-value, $background-color-value, 65%))
);
$background-color-step-700: var(
--ion-color-step-700,
var(--ion-background-color-step-700, mix($text-color-value, $background-color-value, 70%))
);
$background-color-step-750: var(
--ion-color-step-750,
var(--ion-background-color-step-750, mix($text-color-value, $background-color-value, 75%))
);
$background-color-step-800: var(
--ion-color-step-800,
var(--ion-background-color-step-800, mix($text-color-value, $background-color-value, 80%))
);
$background-color-step-850: var(
--ion-color-step-850,
var(--ion-background-color-step-850, mix($text-color-value, $background-color-value, 85%))
);
$background-color-step-900: var(
--ion-color-step-900,
var(--ion-background-color-step-900, mix($text-color-value, $background-color-value, 90%))
);
$background-color-step-950: var(
--ion-color-step-950,
var(--ion-background-color-step-950, mix($text-color-value, $background-color-value, 95%))
);
$text-color-step-50: var(
--ion-color-step-950,
var(--ion-text-color-step-50, mix($background-color-value, $text-color-value, 5%))
);
$text-color-step-100: var(
--ion-color-step-900,
var(--ion-text-color-step-100, mix($background-color-value, $text-color-value, 10%))
);
$text-color-step-150: var(
--ion-color-step-850,
var(--ion-text-color-step-150, mix($background-color-value, $text-color-value, 15%))
);
$text-color-step-200: var(
--ion-color-step-800,
var(--ion-text-color-step-200, mix($background-color-value, $text-color-value, 20%))
);
$text-color-step-250: var(
--ion-color-step-750,
var(--ion-text-color-step-250, mix($background-color-value, $text-color-value, 25%))
);
$text-color-step-300: var(
--ion-color-step-700,
var(--ion-text-color-step-300, mix($background-color-value, $text-color-value, 30%))
);
$text-color-step-350: var(
--ion-color-step-650,
var(--ion-text-color-step-350, mix($background-color-value, $text-color-value, 35%))
);
$text-color-step-400: var(
--ion-color-step-600,
var(--ion-text-color-step-400, mix($background-color-value, $text-color-value, 40%))
);
$text-color-step-450: var(
--ion-color-step-550,
var(--ion-text-color-step-450, mix($background-color-value, $text-color-value, 45%))
);
$text-color-step-500: var(
--ion-color-step-500,
var(--ion-text-color-step-500, mix($background-color-value, $text-color-value, 50%))
);
$text-color-step-550: var(
--ion-color-step-450,
var(--ion-text-color-step-550, mix($background-color-value, $text-color-value, 55%))
);
$text-color-step-600: var(
--ion-color-step-400,
var(--ion-text-color-step-600, mix($background-color-value, $text-color-value, 60%))
);
$text-color-step-650: var(
--ion-color-step-350,
var(--ion-text-color-step-650, mix($background-color-value, $text-color-value, 65%))
);
$text-color-step-700: var(
--ion-color-step-300,
var(--ion-text-color-step-700, mix($background-color-value, $text-color-value, 70%))
);
$text-color-step-750: var(
--ion-color-step-250,
var(--ion-text-color-step-750, mix($background-color-value, $text-color-value, 75%))
);
$text-color-step-800: var(
--ion-color-step-200,
var(--ion-text-color-step-800, mix($background-color-value, $text-color-value, 80%))
);
$text-color-step-850: var(
--ion-color-step-150,
var(--ion-text-color-step-850, mix($background-color-value, $text-color-value, 85%))
);
$text-color-step-900: var(
--ion-color-step-100,
var(--ion-text-color-step-900, mix($background-color-value, $text-color-value, 90%))
);
$text-color-step-950: var(
--ion-color-step-50,
var(--ion-text-color-step-950, mix($background-color-value, $text-color-value, 95%))
);
// Default General Colors
// --------------------------------------------------
$placeholder-text-color: var(--ion-placeholder-color, $text-color-step-600);
$placeholder-text-color: var(--ion-placeholder-color, $text-color-step-600);

View File

@@ -238,6 +238,8 @@ export interface IonicConfig {
scrollAssist?: boolean;
hideCaretOnScroll?: boolean;
customTheme?: any;
// INTERNAL configs
// TODO(FW-2832): types
persistConfig?: boolean;

View File

@@ -1,6 +1,19 @@
// The interfaces in this file are used to make sure our components
// have the correct properties defined that are needed to pass to
// the native HTML elements they render
// the native HTML elements they render. The HTMLStencilElement interface
// extends HTMLElement to provide Stencil-specific functionality like
// componentOnReady() and proper children handling.
export interface HTMLStencilElement extends HTMLElement {
componentOnReady(): Promise<this>;
/**
* Stencil patches `el.children` to behave like calling `el.children` on an
* element with shadow DOM even though the component is not a shadow DOM element.
* To allow components to work properly we need to access the original accessor
* for this property which is `__children`.
*/
__children?: HTMLCollection;
}
export interface AnchorInterface {
href: string | undefined;

View File

@@ -216,7 +216,7 @@ export const config: Config = {
},
{
type: 'dist',
esmLoaderPath: '../loader'
esmLoaderPath: '../loader',
},
{
type: 'dist-custom-elements',

View File

@@ -3,5 +3,5 @@
"core",
"packages/*"
],
"version": "8.6.5"
"version": "8.7.2"
}

View File

@@ -3,6 +3,46 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [8.7.2](https://github.com/ionic-team/ionic-framework/compare/v8.7.1...v8.7.2) (2025-08-06)
**Note:** Version bump only for package @ionic/angular-server
## [8.7.1](https://github.com/ionic-team/ionic-framework/compare/v8.7.0...v8.7.1) (2025-07-31)
**Note:** Version bump only for package @ionic/angular-server
# [8.7.0](https://github.com/ionic-team/ionic-framework/compare/v8.6.7...v8.7.0) (2025-07-30)
**Note:** Version bump only for package @ionic/angular-server
## [8.6.7](https://github.com/ionic-team/ionic-framework/compare/v8.6.6...v8.6.7) (2025-07-30)
**Note:** Version bump only for package @ionic/angular-server
## [8.6.6](https://github.com/ionic-team/ionic-framework/compare/v8.6.5...v8.6.6) (2025-07-30)
**Note:** Version bump only for package @ionic/angular-server
## [8.6.5](https://github.com/ionic-team/ionic-framework/compare/v8.6.4...v8.6.5) (2025-07-16)
**Note:** Version bump only for package @ionic/angular-server

View File

@@ -1,15 +1,15 @@
{
"name": "@ionic/angular-server",
"version": "8.6.5",
"version": "8.7.2",
"lockfileVersion": 2,
"requires": true,
"packages": {
"": {
"name": "@ionic/angular-server",
"version": "8.6.5",
"version": "8.7.2",
"license": "MIT",
"dependencies": {
"@ionic/core": "^8.6.5"
"@ionic/core": "^8.7.2"
},
"devDependencies": {
"@angular-eslint/eslint-plugin": "^16.0.0",
@@ -1031,13 +1031,13 @@
"dev": true
},
"node_modules/@ionic/core": {
"version": "8.6.5",
"resolved": "https://registry.npmjs.org/@ionic/core/-/core-8.6.5.tgz",
"integrity": "sha512-HN+6/Q67fEEpRA86QzXSrCahuHwaTPBsa910RuvY0pIYuoY4rpzGPU9ZOQ5q2wBsrln921rroEPU1xdpPKIH8Q==",
"version": "8.7.2",
"resolved": "https://registry.npmjs.org/@ionic/core/-/core-8.7.2.tgz",
"integrity": "sha512-u1xTJHltvcwiHkwGowQ/uywiUmvszNeR4mXT5JSp1RH6npe8e9doIY9KSzKRrzpWu1T+H0bUwGbhaYg/I/poRA==",
"license": "MIT",
"dependencies": {
"@stencil/core": "4.33.1",
"ionicons": "^7.2.2",
"@stencil/core": "4.36.2",
"ionicons": "^8.0.13",
"tslib": "^2.1.0"
}
},
@@ -1386,9 +1386,9 @@
]
},
"node_modules/@stencil/core": {
"version": "4.33.1",
"resolved": "https://registry.npmjs.org/@stencil/core/-/core-4.33.1.tgz",
"integrity": "sha512-12k9xhAJBkpg598it+NRmaYIdEe6TSnsL/v6/KRXDcUyTK11VYwZQej2eHnMWtqot+znJ+GNTqb5YbiXi+5Low==",
"version": "4.36.2",
"resolved": "https://registry.npmjs.org/@stencil/core/-/core-4.36.2.tgz",
"integrity": "sha512-PRFSpxNzX9Oi0Wfh02asztN9Sgev/MacfZwmd+VVyE6ZxW+a/kEpAYZhzGAmE+/aKVOGYuug7R9SulanYGxiDQ==",
"license": "MIT",
"bin": {
"stencil": "bin/stencil"
@@ -3818,11 +3818,12 @@
}
},
"node_modules/ionicons": {
"version": "7.4.0",
"resolved": "https://registry.npmjs.org/ionicons/-/ionicons-7.4.0.tgz",
"integrity": "sha512-ZK94MMqgzMCPPMhmk8Ouu6goyVHFIlw/ACP6oe3FrikcI0N7CX0xcwVaEbUc0G/v3W0shI93vo+9ve/KpvcNhQ==",
"version": "8.0.13",
"resolved": "https://registry.npmjs.org/ionicons/-/ionicons-8.0.13.tgz",
"integrity": "sha512-2QQVyG2P4wszne79jemMjWYLp0DBbDhr4/yFroPCxvPP1wtMxgdIV3l5n+XZ5E9mgoXU79w7yTWpm2XzJsISxQ==",
"license": "MIT",
"dependencies": {
"@stencil/core": "^4.0.3"
"@stencil/core": "^4.35.3"
}
},
"node_modules/is-array-buffer": {
@@ -7305,12 +7306,12 @@
"dev": true
},
"@ionic/core": {
"version": "8.6.5",
"resolved": "https://registry.npmjs.org/@ionic/core/-/core-8.6.5.tgz",
"integrity": "sha512-HN+6/Q67fEEpRA86QzXSrCahuHwaTPBsa910RuvY0pIYuoY4rpzGPU9ZOQ5q2wBsrln921rroEPU1xdpPKIH8Q==",
"version": "8.7.2",
"resolved": "https://registry.npmjs.org/@ionic/core/-/core-8.7.2.tgz",
"integrity": "sha512-u1xTJHltvcwiHkwGowQ/uywiUmvszNeR4mXT5JSp1RH6npe8e9doIY9KSzKRrzpWu1T+H0bUwGbhaYg/I/poRA==",
"requires": {
"@stencil/core": "4.33.1",
"ionicons": "^7.2.2",
"@stencil/core": "4.36.2",
"ionicons": "^8.0.13",
"tslib": "^2.1.0"
}
},
@@ -7528,9 +7529,9 @@
"optional": true
},
"@stencil/core": {
"version": "4.33.1",
"resolved": "https://registry.npmjs.org/@stencil/core/-/core-4.33.1.tgz",
"integrity": "sha512-12k9xhAJBkpg598it+NRmaYIdEe6TSnsL/v6/KRXDcUyTK11VYwZQej2eHnMWtqot+znJ+GNTqb5YbiXi+5Low==",
"version": "4.36.2",
"resolved": "https://registry.npmjs.org/@stencil/core/-/core-4.36.2.tgz",
"integrity": "sha512-PRFSpxNzX9Oi0Wfh02asztN9Sgev/MacfZwmd+VVyE6ZxW+a/kEpAYZhzGAmE+/aKVOGYuug7R9SulanYGxiDQ==",
"requires": {
"@rollup/rollup-darwin-arm64": "4.34.9",
"@rollup/rollup-darwin-x64": "4.34.9",
@@ -9239,11 +9240,11 @@
}
},
"ionicons": {
"version": "7.4.0",
"resolved": "https://registry.npmjs.org/ionicons/-/ionicons-7.4.0.tgz",
"integrity": "sha512-ZK94MMqgzMCPPMhmk8Ouu6goyVHFIlw/ACP6oe3FrikcI0N7CX0xcwVaEbUc0G/v3W0shI93vo+9ve/KpvcNhQ==",
"version": "8.0.13",
"resolved": "https://registry.npmjs.org/ionicons/-/ionicons-8.0.13.tgz",
"integrity": "sha512-2QQVyG2P4wszne79jemMjWYLp0DBbDhr4/yFroPCxvPP1wtMxgdIV3l5n+XZ5E9mgoXU79w7yTWpm2XzJsISxQ==",
"requires": {
"@stencil/core": "^4.0.3"
"@stencil/core": "^4.35.3"
}
},
"is-array-buffer": {

View File

@@ -1,6 +1,6 @@
{
"name": "@ionic/angular-server",
"version": "8.6.5",
"version": "8.7.2",
"description": "Angular SSR Module for Ionic",
"keywords": [
"ionic",
@@ -62,6 +62,6 @@
},
"prettier": "@ionic/prettier-config",
"dependencies": {
"@ionic/core": "^8.6.5"
"@ionic/core": "^8.7.2"
}
}

View File

@@ -3,6 +3,54 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [8.7.2](https://github.com/ionic-team/ionic-framework/compare/v8.7.1...v8.7.2) (2025-08-06)
### Bug Fixes
* **reorder-group:** add children fallback for framework compatibility ([#30593](https://github.com/ionic-team/ionic-framework/issues/30593)) ([1cd81b9](https://github.com/ionic-team/ionic-framework/commit/1cd81b92301378d55bce63a01dfcf95a91c92652)), closes [#30592](https://github.com/ionic-team/ionic-framework/issues/30592)
## [8.7.1](https://github.com/ionic-team/ionic-framework/compare/v8.7.0...v8.7.1) (2025-07-31)
**Note:** Version bump only for package @ionic/angular
# [8.7.0](https://github.com/ionic-team/ionic-framework/compare/v8.6.7...v8.7.0) (2025-07-30)
### Features
* **deps:** update ionicons to v8 ([#30390](https://github.com/ionic-team/ionic-framework/issues/30390)) ([74cd71a](https://github.com/ionic-team/ionic-framework/commit/74cd71af243183aa738d11b280e155bdfd652126)), closes [#30445](https://github.com/ionic-team/ionic-framework/issues/30445)
* **modal:** add IonModalToken for injecting modal elements in Angular components ([#30474](https://github.com/ionic-team/ionic-framework/issues/30474)) ([30d1910](https://github.com/ionic-team/ionic-framework/commit/30d1910d6ea5428b414d0e127e7681f59426c538))
* **reorder-group:** add ionReorderStart, ionReorderMove, ionReorderEnd events ([#30471](https://github.com/ionic-team/ionic-framework/issues/30471)) ([b154f4e](https://github.com/ionic-team/ionic-framework/commit/b154f4ed095890f57ccab539fd9217976a5466e5)), closes [#23148](https://github.com/ionic-team/ionic-framework/issues/23148) [#27614](https://github.com/ionic-team/ionic-framework/issues/27614)
## [8.6.7](https://github.com/ionic-team/ionic-framework/compare/v8.6.6...v8.6.7) (2025-07-30)
**Note:** Version bump only for package @ionic/angular
## [8.6.6](https://github.com/ionic-team/ionic-framework/compare/v8.6.5...v8.6.6) (2025-07-30)
**Note:** Version bump only for package @ionic/angular
## [8.6.5](https://github.com/ionic-team/ionic-framework/compare/v8.6.4...v8.6.5) (2025-07-16)
**Note:** Version bump only for package @ionic/angular

View File

@@ -1,34 +1,34 @@
export { MenuController } from './providers/menu-controller';
export { DomController } from './providers/dom-controller';
export { MenuController } from './providers/menu-controller';
export { NavController } from './providers/nav-controller';
export { Config, ConfigToken } from './providers/config';
export { Platform } from './providers/platform';
export { bindLifecycleEvents, AngularDelegate } from './providers/angular-delegate';
export { AngularDelegate, bindLifecycleEvents, IonModalToken } from './providers/angular-delegate';
export type { IonicWindow } from './types/interfaces';
export type { ViewWillEnter, ViewWillLeave, ViewDidEnter, ViewDidLeave } from './types/ionic-lifecycle-hooks';
export type { ViewDidEnter, ViewDidLeave, ViewWillEnter, ViewWillLeave } from './types/ionic-lifecycle-hooks';
export { NavParams } from './directives/navigation/nav-params';
export { IonPopover } from './overlays/popover';
export { IonModal } from './overlays/modal';
export { IonPopover } from './overlays/popover';
export { IonRouterOutlet, provideComponentInputBinding } from './directives/navigation/router-outlet';
export * from './directives/control-value-accessors';
export { IonBackButton } from './directives/navigation/back-button';
export { IonNav } from './directives/navigation/nav';
export {
RouterLinkDelegateDirective,
RouterLinkWithHrefDelegateDirective,
} from './directives/navigation/router-link-delegate';
export { IonNav } from './directives/navigation/nav';
export { IonTabs } from './directives/navigation/tabs';
export * from './directives/control-value-accessors';
export { ProxyCmp } from './utils/proxy';
export { IonicRouteStrategy } from './utils/routing';
export { OverlayBaseController } from './utils/overlay';
export { IonicRouteStrategy } from './utils/routing';
export { raf } from './utils/util';

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