Compare commits
116 Commits
item-clean
...
datetime-r
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
674bfeb0c8 | ||
|
|
6b13e1323f | ||
|
|
eb7ba2355a | ||
|
|
30552f1cef | ||
|
|
2d8c9f4942 | ||
|
|
bf1ae7b6fe | ||
|
|
84ea30db4e | ||
|
|
f7aa4a7e6b | ||
|
|
ffd1bf5139 | ||
|
|
73af759906 | ||
|
|
4f68044f84 | ||
|
|
c69adbf988 | ||
|
|
cde84983b2 | ||
|
|
3f3f196a24 | ||
|
|
ffce443585 | ||
|
|
4698d22413 | ||
|
|
bfaf528e61 | ||
|
|
9b59138011 | ||
|
|
4efdc88a29 | ||
|
|
7b90025d31 | ||
|
|
176bb43262 | ||
|
|
c9916ff4b5 | ||
|
|
9738228bc0 | ||
|
|
f0da2c1727 | ||
|
|
368fb2fc70 | ||
|
|
8259cd0cd9 | ||
|
|
638ad30b59 | ||
|
|
ea8e220861 | ||
|
|
8ee5790d1f | ||
|
|
2562392a62 | ||
|
|
d8599b3282 | ||
|
|
1388014b65 | ||
|
|
1073d22b56 | ||
|
|
cea0b493fc | ||
|
|
adf220b681 | ||
|
|
e64015a609 | ||
|
|
3d9871a77f | ||
|
|
e91fee4f2d | ||
|
|
b315b0cb29 | ||
|
|
7b6c330f17 | ||
|
|
b3cd49bf22 | ||
|
|
6c36cef241 | ||
|
|
4d6edee89c | ||
|
|
4b79bbef7d | ||
|
|
ac7631a324 | ||
|
|
b5cb828861 | ||
|
|
101ad5402f | ||
|
|
de35fa8b94 | ||
|
|
c766528a17 | ||
|
|
9b3cf9fbc2 | ||
|
|
ee5da7a747 | ||
|
|
c4bfc783e0 | ||
|
|
0137e732ce | ||
|
|
88ecb29e39 | ||
|
|
f726c35868 | ||
|
|
4a9d84ecbd | ||
|
|
f08759c2b8 | ||
|
|
2053bc77a6 | ||
|
|
02e05bd7cb | ||
|
|
fa387cb2a2 | ||
|
|
8ab116150c | ||
|
|
8c9182c52f | ||
|
|
c0a8e7a95d | ||
|
|
0c5a2967d8 | ||
|
|
6ebb3c4e38 | ||
|
|
cdcb6decbd | ||
|
|
652ea169b7 | ||
|
|
42c09a7ea1 | ||
|
|
c23be1befd | ||
|
|
a2923aaeb3 | ||
|
|
eeab96de55 | ||
|
|
6c500fd6b2 | ||
|
|
ca0923812a | ||
|
|
1be956bd18 | ||
|
|
6e477b743e | ||
|
|
44529f0a62 | ||
|
|
500854d929 | ||
|
|
8ad66c03d7 | ||
|
|
9efeb0ad31 | ||
|
|
b0a10dfa56 | ||
|
|
63a2d4fb44 | ||
|
|
892594de06 | ||
|
|
bb1402e71e | ||
|
|
90fcddea3d | ||
|
|
f6c3141a82 | ||
|
|
48abe43a85 | ||
|
|
a8302769dd | ||
|
|
3057ab5217 | ||
|
|
4a29c64675 | ||
|
|
cdcb2025c9 | ||
|
|
8c578da8cb | ||
|
|
8c56b0b94a | ||
|
|
d1253c08c1 | ||
|
|
7ca6b80b04 | ||
|
|
4cd8fb15af | ||
|
|
78653868fe | ||
|
|
d9f97d0f52 | ||
|
|
9619ee30d9 | ||
|
|
e8f63560eb | ||
|
|
58d217d0cf | ||
|
|
acc1042124 | ||
|
|
73d661a3a2 | ||
|
|
fc5d692a05 | ||
|
|
e50d32a388 | ||
|
|
761e1b47dd | ||
|
|
55464ddf84 | ||
|
|
e98620ee99 | ||
|
|
5577d3866f | ||
|
|
02f89bbc42 | ||
|
|
f75977699d | ||
|
|
fdfecd32c3 | ||
|
|
d67fdcc43a | ||
|
|
9ed692ce4f | ||
|
|
5a42841d52 | ||
|
|
19c1bc16cb | ||
|
|
459a023bac |
66
.github/CODEOWNERS
vendored
@@ -13,73 +13,7 @@
|
||||
|
||||
* @ionic-team/framework
|
||||
|
||||
# Frameworks
|
||||
|
||||
## Angular
|
||||
|
||||
/packages/angular/ @sean-perkins @thetaPC
|
||||
/packages/angular-server @sean-perkins @thetaPC
|
||||
/packages/angular/test @thetaPC
|
||||
|
||||
## React
|
||||
|
||||
/packages/react/ @amandaejohnston
|
||||
/packages/react-router @amandaejohnston
|
||||
/packages/react/test-app/
|
||||
/packages/react-router/test-app/
|
||||
|
||||
## Vue
|
||||
|
||||
/packages/vue/ @liamdebeasi @thetaPC
|
||||
/packages/vue-router/ @liamdebeasi @thetaPC
|
||||
/packages/vue/test/ @thetaPC
|
||||
/packages/vue-router/__tests__ @thetaPC
|
||||
|
||||
# Components
|
||||
|
||||
/core/src/components/accordion/ @liamdebeasi
|
||||
/core/src/components/accordion-group/ @liamdebeasi
|
||||
|
||||
/core/src/components/checkbox/ @amandaejohnston
|
||||
|
||||
/core/src/components/datetime/ @liamdebeasi @amandaejohnston @sean-perkins
|
||||
/core/src/components/datetime-button/ @liamdebeasi
|
||||
|
||||
/core/src/components/item/ @brandyscarney
|
||||
|
||||
/core/src/components/menu/ @amandaejohnston
|
||||
/core/src/components/menu-toggle/ @amandaejohnston
|
||||
|
||||
/core/src/components/nav/ @sean-perkins
|
||||
/core/src/components/nav-link/ @sean-perkins
|
||||
|
||||
/core/src/components/picker/ @liamdebeasi
|
||||
/core/src/components/picker-column/ @liamdebeasi
|
||||
|
||||
/core/src/components/radio/ @amandaejohnston
|
||||
/core/src/components/radio-group/ @amandaejohnston
|
||||
|
||||
/core/src/components/refresher/ @liamdebeasi
|
||||
/core/src/components/refresher-content/ @liamdebeasi
|
||||
|
||||
/core/src/components/searchbar/ @brandyscarney
|
||||
|
||||
/core/src/components/segment/ @brandyscarney
|
||||
/core/src/components/segment-button/ @brandyscarney
|
||||
|
||||
/core/src/components/skeleton-text/ @brandyscarney
|
||||
|
||||
# Utilities
|
||||
|
||||
/core/src/utils/animation/ @liamdebeasi
|
||||
/core/src/utils/content/ @sean-perkins
|
||||
/core/src/utils/gesture/ @liamdebeasi
|
||||
/core/src/utils/input-shims/ @liamdebeasi
|
||||
/core/src/utils/keyboard/ @liamdebeasi
|
||||
/core/src/utils/logging/ @amandaejohnston
|
||||
/core/src/utils/sanitization/ @liamdebeasi
|
||||
/core/src/utils/tap-click/ @liamdebeasi
|
||||
/core/src/utils/transition/ @liamdebeasi
|
||||
|
||||
/core/src/css/ @brandyscarney
|
||||
/core/src/themes/ @brandyscarney
|
||||
|
||||
2
.github/PULL_REQUEST_TEMPLATE.md
vendored
@@ -25,7 +25,7 @@ Issue number: resolves #
|
||||
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/.github/CONTRIBUTING.md#footer for more information.
|
||||
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.
|
||||
-->
|
||||
|
||||
|
||||
|
||||
@@ -32,11 +32,11 @@ runs:
|
||||
run: npm ci
|
||||
shell: bash
|
||||
- name: Install Dependencies
|
||||
run: npx lerna bootstrap --include-dependencies --scope ${{ inputs.scope }} --ignore-scripts -- --legacy-peer-deps
|
||||
run: npx lerna@5 bootstrap --include-dependencies --scope ${{ inputs.scope }} --ignore-scripts -- --legacy-peer-deps
|
||||
shell: bash
|
||||
working-directory: ${{ inputs.working-directory }}
|
||||
- name: Update Version
|
||||
run: npx lerna version ${{ inputs.version }} --yes --exact --no-changelog --no-push --no-git-tag-version --preid=${{ inputs.preid }}
|
||||
run: npx lerna@5 version ${{ inputs.version }} --yes --exact --no-changelog --no-push --no-git-tag-version --preid=${{ inputs.preid }}
|
||||
shell: bash
|
||||
working-directory: ${{ inputs.working-directory }}
|
||||
- name: Run Build
|
||||
|
||||
@@ -21,33 +21,13 @@ runs:
|
||||
name: ionic-core
|
||||
path: ./core
|
||||
filename: CoreBuild.zip
|
||||
- name: Install Playwright Dependencies
|
||||
run: npm install && npx playwright install && npx playwright install-deps
|
||||
- name: Install Dependencies
|
||||
run: npm install
|
||||
shell: bash
|
||||
working-directory: ./core
|
||||
- id: clean-component-name
|
||||
name: Clean Component Name
|
||||
# Remove `ion-` prefix from the `component` variable if it exists.
|
||||
run: |
|
||||
echo "component=$(echo ${{ inputs.component }} | sed 's/ion-//g')" >> $GITHUB_OUTPUT
|
||||
shell: bash
|
||||
- id: set-test-file
|
||||
name: Set Test File
|
||||
# Screenshots can be updated for all components or specified component(s).
|
||||
# If the `component` variable is set, then the test has the option to
|
||||
# - run all the file paths that are in a component folder.
|
||||
# -- For example: if the `component` value is "item", then the test will run all the file paths that are in the "src/components/item" folder.
|
||||
# -- For example: if the `component` value is "item chip", then the test will run all the file paths that are in the "src/components/item" and "src/components/chip" folders.
|
||||
run: |
|
||||
if [ -n "${{ steps.clean-component-name.outputs.component }}" ]; then
|
||||
echo "testFile=\$(echo '${{ steps.clean-component-name.outputs.component }}' | awk '{for(i=1;i<=NF;i++) \$i=\"src/components/\"\$i}1')" >> $GITHUB_OUTPUT
|
||||
else
|
||||
echo "testFile=$(echo '')" >> $GITHUB_OUTPUT
|
||||
fi
|
||||
shell: bash
|
||||
- name: Test
|
||||
if: inputs.update != 'true'
|
||||
run: npm run test.e2e ${{ steps.set-test-file.outputs.testFile }} -- --shard=${{ inputs.shard }}/${{ inputs.totalShards }}
|
||||
run: npm run test.e2e.docker.ci ${{ inputs.component }} -- --shard=${{ inputs.shard }}/${{ inputs.totalShards }}
|
||||
shell: bash
|
||||
working-directory: ./core
|
||||
- name: Test and Update
|
||||
@@ -69,7 +49,7 @@ runs:
|
||||
# which is why we not using the upload-archive
|
||||
# composite step here.
|
||||
run: |
|
||||
npm run test.e2e ${{ steps.set-test-file.outputs.testFile }} -- --shard=${{ inputs.shard }}/${{ inputs.totalShards }} --update-snapshots
|
||||
npm run test.e2e.docker.ci ${{ inputs.component }} -- --shard=${{ inputs.shard }}/${{ inputs.totalShards }} --update-snapshots
|
||||
git add src/\*.png --force
|
||||
mkdir updated-screenshots
|
||||
cd ../ && rsync -R --progress $(git diff --name-only --cached) core/updated-screenshots
|
||||
|
||||
@@ -25,12 +25,9 @@ runs:
|
||||
# Configure user as Ionitron
|
||||
# and push only the changed .png snapshots
|
||||
# to the remote branch.
|
||||
# Screenshots are in .gitignore
|
||||
# Non-Linux screenshots are in .gitignore
|
||||
# to prevent local screenshots from getting
|
||||
# pushed to Git. As a result, we need --force
|
||||
# here so that CI generated screenshots can
|
||||
# get added to git. Screenshot ground truths
|
||||
# should only be added via this CI process.
|
||||
# pushed to Git.
|
||||
run: |
|
||||
git config user.name ionitron
|
||||
git config user.email hi@ionicframework.com
|
||||
@@ -38,7 +35,7 @@ runs:
|
||||
# This adds an empty entry for new
|
||||
# screenshot files so we can track them with
|
||||
# git diff
|
||||
git add src/\*.png --force -N
|
||||
git add src/\*.png -N
|
||||
|
||||
if git diff --exit-code; then
|
||||
echo -e "\033[1;31m⚠️ Error: No new screenshots generated ⚠️\033[0m"
|
||||
@@ -48,7 +45,7 @@ runs:
|
||||
else
|
||||
# This actually adds the contents
|
||||
# of the screenshots (including new ones)
|
||||
git add src/\*.png --force
|
||||
git add src/\*.png
|
||||
git commit -m "chore(): add updated snapshots"
|
||||
git push
|
||||
fi
|
||||
|
||||
4
.github/workflows/assign-issues.yml
vendored
@@ -11,8 +11,8 @@ jobs:
|
||||
issues: write
|
||||
steps:
|
||||
- name: 'Auto-assign issue'
|
||||
uses: pozil/auto-assign-issue@edee9537367a8fbc625d27f9e10aa8bad47b8723 # v1.13.0
|
||||
uses: pozil/auto-assign-issue@65947009a243e6b3993edeef4e64df3ca85d760c # v1.14.0
|
||||
with:
|
||||
assignees: liamdebeasi, sean-perkins, brandyscarney, amandaejohnston, mapsandapps, thetaPC
|
||||
assignees: liamdebeasi, sean-perkins, brandyscarney, thetaPC
|
||||
numOfAssignee: 1
|
||||
allowSelfAssign: false
|
||||
|
||||
2
.github/workflows/build.yml
vendored
@@ -140,7 +140,7 @@ jobs:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
apps: [ng14, ng15, ng16, ng17]
|
||||
apps: [ng16, ng17]
|
||||
needs: [build-angular, build-angular-server]
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
|
||||
8
.github/workflows/release-ionic.yml
vendored
@@ -41,8 +41,8 @@ jobs:
|
||||
uses: ./.github/workflows/actions/upload-archive
|
||||
with:
|
||||
name: ionic-docs
|
||||
output: docs/DocsBuild.zip
|
||||
paths: docs/core.json docs/core.d.ts
|
||||
output: packages/docs/DocsBuild.zip
|
||||
paths: packages/docs/core.json packages/docs/core.d.ts
|
||||
|
||||
release-docs:
|
||||
needs: [release-core]
|
||||
@@ -53,7 +53,7 @@ jobs:
|
||||
uses: ./.github/workflows/actions/download-archive
|
||||
with:
|
||||
name: ionic-docs
|
||||
path: ./docs
|
||||
path: ./packages/docs
|
||||
filename: DocsBuild.zip
|
||||
- uses: ./.github/workflows/actions/publish-npm
|
||||
with:
|
||||
@@ -61,7 +61,7 @@ jobs:
|
||||
tag: ${{ inputs.tag }}
|
||||
version: ${{ inputs.version }}
|
||||
preid: ${{ inputs.preid }}
|
||||
working-directory: 'docs'
|
||||
working-directory: 'packages/docs'
|
||||
token: ${{ secrets.NPM_TOKEN }}
|
||||
|
||||
release-angular:
|
||||
|
||||
14
.github/workflows/update-screenshots.yml
vendored
@@ -3,6 +3,20 @@ name: 'Update Reference Screenshots'
|
||||
on:
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
# Screenshots can be updated for all components or specified component(s).
|
||||
# If the `component` variable is set, then the test has the option to
|
||||
# - run all the instances of the specified component(s) in the `src/components` folder
|
||||
# -- For example: if the `component` value is "item", then the following command will be: `npm run test.e2e item`
|
||||
# - run the specified file path
|
||||
# -- For example: if the `component` value is "src/components/item/test/basic", then the following command will be: `npm run test.e2e src/components/item/test/basic`
|
||||
# - run multiple specified components based on the space-separated value
|
||||
# -- For example: if the `component` value is "item basic", then the following command will be: `npm run test.e2e item basic`
|
||||
# -- For example: if the `component` value is "src/components/item/test/basic src/components/item/test/a11y", then the following command will be: `npm run test.e2e src/components/item/test/basic src/components/item/test/a11y`
|
||||
#
|
||||
# If the `component` variable is not set, then the test will run all the instances of the components in the `src/components` folder.
|
||||
# - For example: `npm run test.e2e`
|
||||
#
|
||||
# More common options can be found at the Playwright Command line page: https://playwright.dev/docs/test-cli
|
||||
component:
|
||||
description: 'What component(s) should be updated? (leave blank to update all or use a space-separated list for multiple components)'
|
||||
required: false
|
||||
|
||||
11
.gitignore
vendored
@@ -68,7 +68,16 @@ core/www/
|
||||
# playwright
|
||||
core/test-results/
|
||||
core/playwright-report/
|
||||
core/**/*-snapshots
|
||||
|
||||
# ground truths generated outside of docker should not be committed to the repo
|
||||
core/**/*-snapshots/*
|
||||
|
||||
# new ground truths should only be generated inside of docker which will result in -linux.png screenshots
|
||||
!core/**/*-snapshots/*-linux.png
|
||||
|
||||
# these files are going to be different per-developer environment so do not add them to the repo
|
||||
core/docker-display.txt
|
||||
core/docker-display-volume.txt
|
||||
|
||||
# angular
|
||||
packages/angular/css/
|
||||
|
||||
1
.vercelignore
Normal file
@@ -0,0 +1 @@
|
||||
core/src/components/**/*/*.png
|
||||
35
BREAKING.md
@@ -14,8 +14,9 @@ This is a comprehensive list of the breaking changes introduced in the major ver
|
||||
## Version 8.x
|
||||
|
||||
- [Browser and Platform Support](#version-8x-browser-platform-support)
|
||||
- [Dark Theme](#version-8x-dark-theme)
|
||||
- [Dark Mode](#version-8x-dark-mode)
|
||||
- [Global Styles](#version-8x-global-styles)
|
||||
- [Haptics](#version-8x-haptics)
|
||||
- [Components](#version-8x-components)
|
||||
- [Button](#version-8x-button)
|
||||
- [Checkbox](#version-8x-checkbox)
|
||||
@@ -29,6 +30,7 @@ This is a comprehensive list of the breaking changes introduced in the major ver
|
||||
- [Progress bar](#version-8x-progress-bar)
|
||||
- [Radio](#version-8x-radio)
|
||||
- [Range](#version-8x-range)
|
||||
- [Searchbar](#version-8x-searchbar)
|
||||
- [Select](#version-8x-select)
|
||||
- [Textarea](#version-8x-textarea)
|
||||
- [Toggle](#version-8x-toggle)
|
||||
@@ -60,9 +62,12 @@ This section details the desktop browser, JavaScript framework, and mobile platf
|
||||
| iOS | 15+ |
|
||||
| Android | 5.1+ with Chromium 89+ |
|
||||
|
||||
<h2 id="version-8x-dark-theme">Dark Theme</h2>
|
||||
Ionic Framework v8 removes backwards support for CSS Animations in favor of the [Web Animations API](https://developer.mozilla.org/en-US/docs/Web/API/Web_Animations_API). All minimum browser versions listed above support the Web Animations API.
|
||||
|
||||
In previous versions, it was recommended to define the dark theme in the following way:
|
||||
<h2 id="version-8x-dark-mode">Dark Mode</h2>
|
||||
|
||||
|
||||
In previous versions, it was recommended to define the dark palette in the following way:
|
||||
|
||||
```css
|
||||
@media (prefers-color-scheme: dark) {
|
||||
@@ -80,15 +85,15 @@ In previous versions, it was recommended to define the dark theme in the followi
|
||||
}
|
||||
```
|
||||
|
||||
In Ionic Framework version 8, the dark theme is being distributed via css files that can be imported. Below is an example of importing a dark theme file in Angular:
|
||||
In Ionic Framework version 8, the dark palette is being distributed via css files that can be imported. Below is an example of importing a dark palette file in Angular:
|
||||
|
||||
```css
|
||||
/* @import '@ionic/angular/css/themes/dark.always.css'; */
|
||||
/* @import "@ionic/angular/css/themes/dark.class.css"; */
|
||||
@import "@ionic/angular/css/themes/dark.system.css";
|
||||
/* @import '@ionic/angular/css/palettes/dark.always.css'; */
|
||||
/* @import "@ionic/angular/css/palettes/dark.class.css"; */
|
||||
@import "@ionic/angular/css/palettes/dark.system.css";
|
||||
```
|
||||
|
||||
By importing the `dark.system.css` file, the dark theme variables will be defined like the following:
|
||||
By importing the `dark.system.css` file, the dark palette variables will be defined like the following:
|
||||
|
||||
```css
|
||||
@media (prefers-color-scheme: dark) {
|
||||
@@ -106,11 +111,11 @@ By importing the `dark.system.css` file, the dark theme variables will be define
|
||||
}
|
||||
```
|
||||
|
||||
Notice that the dark theme is now applied to the `:root` selector instead of the `body` selector. The [`:root`](https://developer.mozilla.org/en-US/docs/Web/CSS/:root) selector represents the `<html>` element and is identical to the selector `html`, except that its specificity is higher.
|
||||
Notice that the dark palette is now applied to the `:root` selector instead of the `body` selector. The [`:root`](https://developer.mozilla.org/en-US/docs/Web/CSS/:root) selector represents the `<html>` element and is identical to the selector `html`, except that its specificity is higher.
|
||||
|
||||
While migrating to include the new dark theme files is unlikely to cause breaking changes, these new selectors can lead to unexpected overrides if custom CSS variables are being set on the `body` element. We recommend updating any instances where global application variables are set to target the `:root` selector instead.
|
||||
While migrating to include the new dark palette files is unlikely to cause breaking changes, these new selectors can lead to unexpected overrides if custom CSS variables are being set on the `body` element. We recommend updating any instances where global application variables are set to target the `:root` selector instead.
|
||||
|
||||
For more information on the new dark theme files, refer to the [Dark Mode documentation](https://ionicframework.com/docs/theming/dark-mode).
|
||||
For more information on the new dark palette files, refer to the [Dark Mode documentation](https://ionicframework.com/docs/theming/dark-mode).
|
||||
|
||||
<h2 id="version-8x-global-styles">Global Styles</h2>
|
||||
|
||||
@@ -138,6 +143,10 @@ Developers who want to disable dynamic font scaling can set `--ion-dynamic-font:
|
||||
|
||||
For more information on the dynamic font, refer to the [Dynamic Font Scaling documentation](https://ionicframework.com/docs/layout/dynamic-font-scaling).
|
||||
|
||||
<h2 id="version-8x-haptics">Haptics</h2>
|
||||
|
||||
- Support for the Cordova Haptics plugin has been removed. Components that integrate with haptics, such as `ion-picker` and `ion-toggle`, will continue to function but will no longer play haptics in Cordova environments. Developers should migrate to Capacitor to continue to have haptics in these components.
|
||||
|
||||
<h2 id="version-8x-components">Components</h2>
|
||||
|
||||
<h4 id="version-8x-button">Button</h4>
|
||||
@@ -256,6 +265,10 @@ For more information on styling toast buttons, refer to the [Toast Theming docum
|
||||
|
||||
- The `legacy` property and support for the legacy syntax, which involved placing an `ion-range` inside of an `ion-item` with an `ion-label`, have been removed. Ionic will also no longer attempt to automatically associate form controls with sibling `<label>` elements as these label elements are now used inside the form control. Developers should provide a label (either visible text or `aria-label`) directly to the form control. For more information on migrating from the legacy range syntax, refer to the [Range documentation](https://ionicframework.com/docs/api/range#migrating-from-legacy-range-syntax).
|
||||
|
||||
<h4 id="version-8x-searchbar">Searchbar</h4>
|
||||
|
||||
- The `autocapitalize` property now defaults to `'off'`.
|
||||
|
||||
<h4 id="version-8x-select">Select</h4>
|
||||
|
||||
- The `legacy` property and support for the legacy syntax, which involved placing an `ion-select` inside of an `ion-item` with an `ion-label`, have been removed. Ionic will also no longer attempt to automatically associate form controls with sibling `<label>` elements as these label elements are now used inside the form control. Developers should provide a label (either visible text or `aria-label`) directly to the form control. For more information on migrating from the legacy select syntax, refer to the [Select documentation](https://ionicframework.com/docs/api/select#migrating-from-legacy-select-syntax).
|
||||
|
||||
148
CHANGELOG.md
@@ -3,6 +3,154 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
# [8.0.0](https://github.com/ionic-team/ionic-framework/compare/v8.0.0-rc.2...v8.0.0) (2024-04-17)
|
||||
|
||||
**Note:** Version bump only for package ionic-framework
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [8.0.0-rc.2](https://github.com/ionic-team/ionic-framework/compare/v8.0.0-rc.1...v8.0.0-rc.2) (2024-04-17)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **dark-palette:** improve base colors ([#29239](https://github.com/ionic-team/ionic-framework/issues/29239)) ([4698d22](https://github.com/ionic-team/ionic-framework/commit/4698d22413966b59f9fa65b4e2533695cf00ed70)), closes [#29219](https://github.com/ionic-team/ionic-framework/issues/29219)
|
||||
* **form-controls:** adjust flex properties inside of an item ([#29328](https://github.com/ionic-team/ionic-framework/issues/29328)) ([9b59138](https://github.com/ionic-team/ionic-framework/commit/9b59138011fd1e71def209ec3a43fb7f91b58949)), closes [#29319](https://github.com/ionic-team/ionic-framework/issues/29319)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## [7.8.5](https://github.com/ionic-team/ionic-framework/compare/v7.8.4...v7.8.5) (2024-04-17)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **modal:** improve sheet modal scrolling and gesture behavior ([#29312](https://github.com/ionic-team/ionic-framework/issues/29312)) ([9738228](https://github.com/ionic-team/ionic-framework/commit/9738228bc05abe3e2012e57b0e6b85f0ec06f66b)), closes [#24583](https://github.com/ionic-team/ionic-framework/issues/24583)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [8.0.0-rc.1](https://github.com/ionic-team/ionic-framework/compare/v8.0.0-rc.0...v8.0.0-rc.1) (2024-04-10)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **button:** use clamp for font sizes on circle shape ([#29200](https://github.com/ionic-team/ionic-framework/issues/29200)) ([4d6edee](https://github.com/ionic-team/ionic-framework/commit/4d6edee89c7bb2cb669d67730d7ddf24c78b3cb1))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## [7.8.4](https://github.com/ionic-team/ionic-framework/compare/v7.8.3...v7.8.4) (2024-04-10)
|
||||
|
||||
|
||||
### Performance Improvements
|
||||
|
||||
* **styles:** compress distributed global stylesheets ([#29275](https://github.com/ionic-team/ionic-framework/issues/29275)) ([b3cd49b](https://github.com/ionic-team/ionic-framework/commit/b3cd49bf2219aacffc1ac34acbae7c76ef243765))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## [7.8.3](https://github.com/ionic-team/ionic-framework/compare/v7.8.2...v7.8.3) (2024-04-03)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **button:** activated outline button in toolbar no longer blends into background on MD dark mode ([#29216](https://github.com/ionic-team/ionic-framework/issues/29216)) ([ee5da7a](https://github.com/ionic-team/ionic-framework/commit/ee5da7a747c0a0b420c5e371a9fe9ec4938d179e))
|
||||
* **popover:** viewport can be scrolled if no content present ([#29215](https://github.com/ionic-team/ionic-framework/issues/29215)) ([f08759c](https://github.com/ionic-team/ionic-framework/commit/f08759c2b8256ff66f8d1901bd8e0be4617db262)), closes [#29211](https://github.com/ionic-team/ionic-framework/issues/29211)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [8.0.0-rc.0](https://github.com/ionic-team/ionic-framework/compare/v8.0.0-beta.4...v8.0.0-rc.0) (2024-03-27)
|
||||
|
||||
**Note:** Version bump only for package ionic-framework
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [8.0.0-beta.4](https://github.com/ionic-team/ionic-framework/compare/v8.0.0-beta.3...v8.0.0-beta.4) (2024-03-27)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **angular:** schematics account for new theme files ([#29185](https://github.com/ionic-team/ionic-framework/issues/29185)) ([b0a10df](https://github.com/ionic-team/ionic-framework/commit/b0a10dfa56a65ee3905cc2c3d48d2221a42f222f))
|
||||
|
||||
|
||||
### Code Refactoring
|
||||
|
||||
* **haptics:** remove cordova haptics support ([#29186](https://github.com/ionic-team/ionic-framework/issues/29186)) ([9efeb0a](https://github.com/ionic-team/ionic-framework/commit/9efeb0ad31aadee5f5ae542641d928ecf93fe82a))
|
||||
* **searchbar:** autocapitalize defaults to off ([#29107](https://github.com/ionic-team/ionic-framework/issues/29107)) ([6e477b7](https://github.com/ionic-team/ionic-framework/commit/6e477b743e41b2b37627c8208901704f599b762a))
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **button:** add circular shape as round ([#29161](https://github.com/ionic-team/ionic-framework/issues/29161)) ([44529f0](https://github.com/ionic-team/ionic-framework/commit/44529f0a62f1b1ce42750a20f19e829b2789febd))
|
||||
* **input:** add input-password-toggle component ([#29175](https://github.com/ionic-team/ionic-framework/issues/29175)) ([6c500fd](https://github.com/ionic-team/ionic-framework/commit/6c500fd6b2e2553c11fcddc9d86ac9a29f76e172))
|
||||
* remove css animations support for ionic animations ([#29123](https://github.com/ionic-team/ionic-framework/issues/29123)) ([892594d](https://github.com/ionic-team/ionic-framework/commit/892594de0665e8fc5c8a737d292812842ea03d64))
|
||||
|
||||
|
||||
### BREAKING CHANGES
|
||||
|
||||
* **searchbar:** The `autocapitalize` property on Searchbar now defaults to `'off'`.
|
||||
* **haptics:** Support for the Cordova Haptics plugin has been removed. Components that integrate with haptics, such as `ion-picker` and `ion-toggle`, will continue to function but will no longer play haptics in Cordova environments. Developers should migrate to Capacitor to continue to have haptics in these components.
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## [7.8.2](https://github.com/ionic-team/ionic-framework/compare/v7.8.1...v7.8.2) (2024-03-27)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **searchbar:** autocapitalize is initialized correctly ([#29197](https://github.com/ionic-team/ionic-framework/issues/29197)) ([8ad66c0](https://github.com/ionic-team/ionic-framework/commit/8ad66c03d777edcab19c97cba696b171acc2d2e8)), closes [#29193](https://github.com/ionic-team/ionic-framework/issues/29193)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [8.0.0-beta.3](https://github.com/ionic-team/ionic-framework/compare/v8.0.0-beta.2...v8.0.0-beta.3) (2024-03-20)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **input, textarea, select:** account for multiple start/end slot elements ([#29172](https://github.com/ionic-team/ionic-framework/issues/29172)) ([acc1042](https://github.com/ionic-team/ionic-framework/commit/acc104212468e2324b94c85ba6eebc2934fba812))
|
||||
* **range, select:** prefer labels passed by developer ([#29145](https://github.com/ionic-team/ionic-framework/issues/29145)) ([56014cf](https://github.com/ionic-team/ionic-framework/commit/56014cf64c387bd4492270905327c570f6814a6b))
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* rename dark/high-contrast themes to palettes ([#29149](https://github.com/ionic-team/ionic-framework/issues/29149)) ([761e1b4](https://github.com/ionic-team/ionic-framework/commit/761e1b47dd5d49ab44c81ddba5490b6d2106f123))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## [7.8.1](https://github.com/ionic-team/ionic-framework/compare/v7.8.0...v7.8.1) (2024-03-20)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **datetime:** wheel picker shows consistently in overlays ([#29147](https://github.com/ionic-team/ionic-framework/issues/29147)) ([19c1bc1](https://github.com/ionic-team/ionic-framework/commit/19c1bc16cbc6725463890382365203824b7fd353)), closes [#26234](https://github.com/ionic-team/ionic-framework/issues/26234)
|
||||
* **header:** iOS headers in MD app are not hidden ([#29164](https://github.com/ionic-team/ionic-framework/issues/29164)) ([fdfecd3](https://github.com/ionic-team/ionic-framework/commit/fdfecd32c33c41cf202d3b30c073bfb1b077e2d6)), closes [#28867](https://github.com/ionic-team/ionic-framework/issues/28867)
|
||||
* **react:** avoid definitely typed errors with @types/react@18 ([#29182](https://github.com/ionic-team/ionic-framework/issues/29182)) ([58d217d](https://github.com/ionic-team/ionic-framework/commit/58d217d0cf6b716da855c71c169fb1870d4067d3)), closes [#29178](https://github.com/ionic-team/ionic-framework/issues/29178)
|
||||
|
||||
|
||||
### Performance Improvements
|
||||
|
||||
* **datetime:** calendar body shows immediately in modal on ios ([#29163](https://github.com/ionic-team/ionic-framework/issues/29163)) ([f759776](https://github.com/ionic-team/ionic-framework/commit/f75977699dae5aeea3d97d4318377633e935afb9)), closes [#24542](https://github.com/ionic-team/ionic-framework/issues/24542)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [8.0.0-beta.2](https://github.com/ionic-team/ionic-framework/compare/v8.0.0-beta.1...v8.0.0-beta.2) (2024-03-13)
|
||||
|
||||
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
<a href="https://github.com/ionic-team/ionic-framework/blob/main/LICENSE">
|
||||
<img src="https://img.shields.io/badge/license-MIT-blue.svg" alt="Ionic Framework is released under the MIT license." />
|
||||
</a>
|
||||
<a href="https://github.com/ionic-team/ionic/blob/main/.github/CONTRIBUTING.md">
|
||||
<a href="https://github.com/ionic-team/ionic/blob/main/docs/CONTRIBUTING.md">
|
||||
<img src="https://img.shields.io/badge/PRs-welcome-brightgreen.svg" alt="PRs welcome!" />
|
||||
</a>
|
||||
<a href="https://twitter.com/Ionicframework">
|
||||
@@ -38,7 +38,7 @@
|
||||
Documentation
|
||||
</a>
|
||||
<span> · </span>
|
||||
<a href="https://github.com/ionic-team/ionic/blob/main/.github/CONTRIBUTING.md">Contribute</a>
|
||||
<a href="https://github.com/ionic-team/ionic/blob/main/docs/CONTRIBUTING.md">Contribute</a>
|
||||
<span> · </span>
|
||||
<a href="https://blog.ionicframework.com/">Blog</a>
|
||||
<br />
|
||||
@@ -88,7 +88,7 @@ The Ionic Conference App is a full featured Ionic app. It is the perfect startin
|
||||
### Contributing
|
||||
|
||||
Thanks for your interest in contributing! Read up on our guidelines for
|
||||
[contributing](https://github.com/ionic-team/ionic/blob/main/.github/CONTRIBUTING.md)
|
||||
[contributing](https://github.com/ionic-team/ionic/blob/main/docs/CONTRIBUTING.md)
|
||||
and then look through our issues with a [help wanted](https://github.com/ionic-team/ionic/issues?q=is%3Aopen+is%3Aissue+label%3A%22help+wanted%22)
|
||||
label.
|
||||
|
||||
|
||||
@@ -3,6 +3,149 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
# [8.0.0](https://github.com/ionic-team/ionic-framework/compare/v8.0.0-rc.2...v8.0.0) (2024-04-17)
|
||||
|
||||
**Note:** Version bump only for package @ionic/core
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [8.0.0-rc.2](https://github.com/ionic-team/ionic-framework/compare/v8.0.0-rc.1...v8.0.0-rc.2) (2024-04-17)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **dark-palette:** improve base colors ([#29239](https://github.com/ionic-team/ionic-framework/issues/29239)) ([4698d22](https://github.com/ionic-team/ionic-framework/commit/4698d22413966b59f9fa65b4e2533695cf00ed70)), closes [#29219](https://github.com/ionic-team/ionic-framework/issues/29219)
|
||||
* **form-controls:** adjust flex properties inside of an item ([#29328](https://github.com/ionic-team/ionic-framework/issues/29328)) ([9b59138](https://github.com/ionic-team/ionic-framework/commit/9b59138011fd1e71def209ec3a43fb7f91b58949)), closes [#29319](https://github.com/ionic-team/ionic-framework/issues/29319)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## [7.8.5](https://github.com/ionic-team/ionic-framework/compare/v7.8.4...v7.8.5) (2024-04-17)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **modal:** improve sheet modal scrolling and gesture behavior ([#29312](https://github.com/ionic-team/ionic-framework/issues/29312)) ([9738228](https://github.com/ionic-team/ionic-framework/commit/9738228bc05abe3e2012e57b0e6b85f0ec06f66b)), closes [#24583](https://github.com/ionic-team/ionic-framework/issues/24583)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [8.0.0-rc.1](https://github.com/ionic-team/ionic-framework/compare/v8.0.0-rc.0...v8.0.0-rc.1) (2024-04-10)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **button:** use clamp for font sizes on circle shape ([#29200](https://github.com/ionic-team/ionic-framework/issues/29200)) ([4d6edee](https://github.com/ionic-team/ionic-framework/commit/4d6edee89c7bb2cb669d67730d7ddf24c78b3cb1))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## [7.8.4](https://github.com/ionic-team/ionic-framework/compare/v7.8.3...v7.8.4) (2024-04-10)
|
||||
|
||||
|
||||
### Performance Improvements
|
||||
|
||||
* **styles:** compress distributed global stylesheets ([#29275](https://github.com/ionic-team/ionic-framework/issues/29275)) ([b3cd49b](https://github.com/ionic-team/ionic-framework/commit/b3cd49bf2219aacffc1ac34acbae7c76ef243765))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## [7.8.3](https://github.com/ionic-team/ionic-framework/compare/v7.8.2...v7.8.3) (2024-04-03)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **button:** activated outline button in toolbar no longer blends into background on MD dark mode ([#29216](https://github.com/ionic-team/ionic-framework/issues/29216)) ([ee5da7a](https://github.com/ionic-team/ionic-framework/commit/ee5da7a747c0a0b420c5e371a9fe9ec4938d179e))
|
||||
* **popover:** viewport can be scrolled if no content present ([#29215](https://github.com/ionic-team/ionic-framework/issues/29215)) ([f08759c](https://github.com/ionic-team/ionic-framework/commit/f08759c2b8256ff66f8d1901bd8e0be4617db262)), closes [#29211](https://github.com/ionic-team/ionic-framework/issues/29211)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [8.0.0-rc.0](https://github.com/ionic-team/ionic-framework/compare/v8.0.0-beta.4...v8.0.0-rc.0) (2024-03-27)
|
||||
|
||||
**Note:** Version bump only for package @ionic/core
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [8.0.0-beta.4](https://github.com/ionic-team/ionic-framework/compare/v8.0.0-beta.3...v8.0.0-beta.4) (2024-03-27)
|
||||
|
||||
|
||||
### Code Refactoring
|
||||
|
||||
* **haptics:** remove cordova haptics support ([#29186](https://github.com/ionic-team/ionic-framework/issues/29186)) ([9efeb0a](https://github.com/ionic-team/ionic-framework/commit/9efeb0ad31aadee5f5ae542641d928ecf93fe82a))
|
||||
* **searchbar:** autocapitalize defaults to off ([#29107](https://github.com/ionic-team/ionic-framework/issues/29107)) ([6e477b7](https://github.com/ionic-team/ionic-framework/commit/6e477b743e41b2b37627c8208901704f599b762a))
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **button:** add circular shape as round ([#29161](https://github.com/ionic-team/ionic-framework/issues/29161)) ([44529f0](https://github.com/ionic-team/ionic-framework/commit/44529f0a62f1b1ce42750a20f19e829b2789febd))
|
||||
* **input:** add input-password-toggle component ([#29175](https://github.com/ionic-team/ionic-framework/issues/29175)) ([6c500fd](https://github.com/ionic-team/ionic-framework/commit/6c500fd6b2e2553c11fcddc9d86ac9a29f76e172))
|
||||
* remove css animations support for ionic animations ([#29123](https://github.com/ionic-team/ionic-framework/issues/29123)) ([892594d](https://github.com/ionic-team/ionic-framework/commit/892594de0665e8fc5c8a737d292812842ea03d64))
|
||||
|
||||
|
||||
### BREAKING CHANGES
|
||||
|
||||
* **searchbar:** The `autocapitalize` property on Searchbar now defaults to `'off'`.
|
||||
* **haptics:** Support for the Cordova Haptics plugin has been removed. Components that integrate with haptics, such as `ion-picker` and `ion-toggle`, will continue to function but will no longer play haptics in Cordova environments. Developers should migrate to Capacitor to continue to have haptics in these components.
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## [7.8.2](https://github.com/ionic-team/ionic-framework/compare/v7.8.1...v7.8.2) (2024-03-27)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **searchbar:** autocapitalize is initialized correctly ([#29197](https://github.com/ionic-team/ionic-framework/issues/29197)) ([8ad66c0](https://github.com/ionic-team/ionic-framework/commit/8ad66c03d777edcab19c97cba696b171acc2d2e8)), closes [#29193](https://github.com/ionic-team/ionic-framework/issues/29193)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [8.0.0-beta.3](https://github.com/ionic-team/ionic-framework/compare/v7.8.1...v8.0.0-beta.3) (2024-03-20)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **input, textarea, select:** account for multiple start/end slot elements ([#29172](https://github.com/ionic-team/ionic-framework/issues/29172)) ([acc1042](https://github.com/ionic-team/ionic-framework/commit/acc104212468e2324b94c85ba6eebc2934fba812))
|
||||
* **range, select:** prefer labels passed by developer ([#29145](https://github.com/ionic-team/ionic-framework/issues/29145)) ([56014cf](https://github.com/ionic-team/ionic-framework/commit/56014cf64c387bd4492270905327c570f6814a6b))
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* rename dark/high-contrast themes to palettes ([#29149](https://github.com/ionic-team/ionic-framework/issues/29149)) ([761e1b4](https://github.com/ionic-team/ionic-framework/commit/761e1b47dd5d49ab44c81ddba5490b6d2106f123))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## [7.8.1](https://github.com/ionic-team/ionic-framework/compare/v7.8.0...v7.8.1) (2024-03-20)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **datetime:** wheel picker shows consistently in overlays ([#29147](https://github.com/ionic-team/ionic-framework/issues/29147)) ([19c1bc1](https://github.com/ionic-team/ionic-framework/commit/19c1bc16cbc6725463890382365203824b7fd353)), closes [#26234](https://github.com/ionic-team/ionic-framework/issues/26234)
|
||||
* **header:** iOS headers in MD app are not hidden ([#29164](https://github.com/ionic-team/ionic-framework/issues/29164)) ([fdfecd3](https://github.com/ionic-team/ionic-framework/commit/fdfecd32c33c41cf202d3b30c073bfb1b077e2d6)), closes [#28867](https://github.com/ionic-team/ionic-framework/issues/28867)
|
||||
|
||||
|
||||
### Performance Improvements
|
||||
|
||||
* **datetime:** calendar body shows immediately in modal on ios ([#29163](https://github.com/ionic-team/ionic-framework/issues/29163)) ([f759776](https://github.com/ionic-team/ionic-framework/commit/f75977699dae5aeea3d97d4318377633e935afb9)), closes [#24542](https://github.com/ionic-team/ionic-framework/issues/24542)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [8.0.0-beta.2](https://github.com/ionic-team/ionic-framework/compare/v8.0.0-beta.1...v8.0.0-beta.2) (2024-03-13)
|
||||
|
||||
|
||||
|
||||
5
core/Dockerfile
Normal file
@@ -0,0 +1,5 @@
|
||||
# Get Playwright
|
||||
FROM mcr.microsoft.com/playwright:v1.42.1
|
||||
|
||||
# Set the working directory
|
||||
WORKDIR /ionic
|
||||
12
core/api.txt
@@ -558,7 +558,7 @@ ion-input,prop,color,"danger" | "dark" | "light" | "medium" | "primary" | "secon
|
||||
ion-input,prop,counter,boolean,false,false,false
|
||||
ion-input,prop,counterFormatter,((inputLength: number, maxLength: number) => string) | undefined,undefined,false,false
|
||||
ion-input,prop,debounce,number | undefined,undefined,false,false
|
||||
ion-input,prop,disabled,boolean,false,false,false
|
||||
ion-input,prop,disabled,boolean,false,false,true
|
||||
ion-input,prop,enterkeyhint,"done" | "enter" | "go" | "next" | "previous" | "search" | "send" | undefined,undefined,false,false
|
||||
ion-input,prop,errorText,string | undefined,undefined,false,false
|
||||
ion-input,prop,fill,"outline" | "solid" | undefined,undefined,false,false
|
||||
@@ -575,7 +575,7 @@ ion-input,prop,multiple,boolean | undefined,undefined,false,false
|
||||
ion-input,prop,name,string,this.inputId,false,false
|
||||
ion-input,prop,pattern,string | undefined,undefined,false,false
|
||||
ion-input,prop,placeholder,string | undefined,undefined,false,false
|
||||
ion-input,prop,readonly,boolean,false,false,false
|
||||
ion-input,prop,readonly,boolean,false,false,true
|
||||
ion-input,prop,required,boolean,false,false,false
|
||||
ion-input,prop,shape,"round" | undefined,undefined,false,false
|
||||
ion-input,prop,spellcheck,boolean,false,false,false
|
||||
@@ -607,6 +607,12 @@ ion-input,css-prop,--placeholder-font-style
|
||||
ion-input,css-prop,--placeholder-font-weight
|
||||
ion-input,css-prop,--placeholder-opacity
|
||||
|
||||
ion-input-password-toggle,shadow
|
||||
ion-input-password-toggle,prop,color,"danger" | "dark" | "light" | "medium" | "primary" | "secondary" | "success" | "tertiary" | "warning" | string & Record<never, never> | undefined,undefined,false,true
|
||||
ion-input-password-toggle,prop,hideIcon,string | undefined,undefined,false,false
|
||||
ion-input-password-toggle,prop,mode,"ios" | "md",undefined,false,false
|
||||
ion-input-password-toggle,prop,showIcon,string | undefined,undefined,false,false
|
||||
|
||||
ion-item,shadow
|
||||
ion-item,prop,button,boolean,false,false,false
|
||||
ion-item,prop,color,"danger" | "dark" | "light" | "medium" | "primary" | "secondary" | "success" | "tertiary" | "warning" | string & Record<never, never> | undefined,undefined,false,true
|
||||
@@ -1166,7 +1172,7 @@ ion-row,shadow
|
||||
|
||||
ion-searchbar,scoped
|
||||
ion-searchbar,prop,animated,boolean,false,false,false
|
||||
ion-searchbar,prop,autocapitalize,string,undefined,true,false
|
||||
ion-searchbar,prop,autocapitalize,string,'off',false,false
|
||||
ion-searchbar,prop,autocomplete,"name" | "email" | "tel" | "url" | "on" | "off" | "honorific-prefix" | "given-name" | "additional-name" | "family-name" | "honorific-suffix" | "nickname" | "username" | "new-password" | "current-password" | "one-time-code" | "organization-title" | "organization" | "street-address" | "address-line1" | "address-line2" | "address-line3" | "address-level4" | "address-level3" | "address-level2" | "address-level1" | "country" | "country-name" | "postal-code" | "cc-name" | "cc-given-name" | "cc-additional-name" | "cc-family-name" | "cc-number" | "cc-exp" | "cc-exp-month" | "cc-exp-year" | "cc-csc" | "cc-type" | "transaction-currency" | "transaction-amount" | "language" | "bday" | "bday-day" | "bday-month" | "bday-year" | "sex" | "tel-country-code" | "tel-national" | "tel-area-code" | "tel-local" | "tel-extension" | "impp" | "photo",'off',false,false
|
||||
ion-searchbar,prop,autocorrect,"off" | "on",'off',false,false
|
||||
ion-searchbar,prop,cancelButtonIcon,string,config.get('backButtonIcon', arrowBackSharp) as string,false,false
|
||||
|
||||
799
core/package-lock.json
generated
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@ionic/core",
|
||||
"version": "8.0.0-beta.2",
|
||||
"version": "8.0.0",
|
||||
"description": "Base components for Ionic",
|
||||
"keywords": [
|
||||
"ionic",
|
||||
@@ -54,12 +54,13 @@
|
||||
"@types/node": "^14.6.0",
|
||||
"@typescript-eslint/eslint-plugin": "^6.7.2",
|
||||
"@typescript-eslint/parser": "^6.7.2",
|
||||
"chalk": "^5.3.0",
|
||||
"clean-css-cli": "^5.6.1",
|
||||
"domino": "^2.1.6",
|
||||
"eslint": "^7.32.0",
|
||||
"eslint-config-prettier": "^8.5.0",
|
||||
"eslint-plugin-custom-rules": "file:custom-rules",
|
||||
"execa": "^5.0.0",
|
||||
"execa": "^8.0.1",
|
||||
"fs-extra": "^9.0.1",
|
||||
"jest": "^29.7.0",
|
||||
"jest-cli": "^29.7.0",
|
||||
@@ -77,7 +78,7 @@
|
||||
"build.docs.json": "stencil build --docs-json dist/docs.json",
|
||||
"clean": "node scripts/clean.js",
|
||||
"css.minify": "cleancss -O2 -o ./css/ionic.bundle.css ./css/ionic.bundle.css",
|
||||
"css.sass": "sass --embed-sources src/css:./css",
|
||||
"css.sass": "sass --embed-sources --style compressed src/css:./css",
|
||||
"eslint": "eslint src",
|
||||
"lint": "npm run lint.ts && npm run lint.sass && npm run prettier -- --write --cache",
|
||||
"lint.fix": "npm run lint.ts.fix && npm run lint.sass.fix && npm run prettier -- --write --cache",
|
||||
@@ -94,7 +95,11 @@
|
||||
"test.e2e.update-snapshots": "npm run test.e2e -- --update-snapshots",
|
||||
"test.watch": "jest --watch --no-cache",
|
||||
"test.treeshake": "node scripts/treeshaking.js dist/index.js",
|
||||
"validate": "npm run lint && npm run test && npm run build && npm run test.treeshake"
|
||||
"validate": "npm run lint && npm run test && npm run build && npm run test.treeshake",
|
||||
"docker.build": "docker build -t ionic-playwright .",
|
||||
"test.e2e.docker": "npm run docker.build && node ./scripts/docker.mjs",
|
||||
"test.e2e.docker.update-snapshots": "npm run test.e2e.docker -- --update-snapshots",
|
||||
"test.e2e.docker.ci": "npm run docker.build && CI=true node ./scripts/docker.mjs"
|
||||
},
|
||||
"author": "Ionic Team",
|
||||
"license": "MIT",
|
||||
|
||||
56
core/scripts/docker.mjs
Normal file
@@ -0,0 +1,56 @@
|
||||
import { execa } from 'execa';
|
||||
import * as fs from 'fs';
|
||||
import { resolve } from 'path';
|
||||
import chalk from 'chalk';
|
||||
|
||||
const removeNewline = (string) => {
|
||||
return string.replace(/(\r\n|\n|\r)/gm, "");
|
||||
}
|
||||
|
||||
const readConfigFile = (file) => {
|
||||
if (fs.existsSync(file)) {
|
||||
return fs.readFileSync(file, { encoding: 'utf-8' });
|
||||
}
|
||||
|
||||
return '';
|
||||
}
|
||||
|
||||
// These files are optional, so we don't want to error if they don't exist
|
||||
const display = removeNewline(readConfigFile('docker-display.txt'));
|
||||
const displayVolume = removeNewline(readConfigFile('docker-display-volume.txt'));
|
||||
|
||||
// Using --mount requires an absolute path which is what this gives us.
|
||||
const pwd = resolve('./');
|
||||
|
||||
/**
|
||||
* -it will let the user gracefully kill the process using Ctrl+C (or equivalent)
|
||||
* -e DISPLAY and -v handle configuration for headed mode
|
||||
* --ipc=host is recommended when using Chromium to avoid out of memory crashes: https://playwright.dev/docs/ci#docker
|
||||
* --init is recommended to avoid zombie processes: https://playwright.dev/docs/ci#docker
|
||||
* --mount allow us to mount the local Ionic project inside of the Docker container so devs do not need to re-build the project in Docker.
|
||||
*/
|
||||
const args = ['run', '--rm', '--init', `-e DISPLAY=${display}`, `-v ${displayVolume}`, '--ipc=host', `--mount=type=bind,source=${pwd},target=/ionic`, 'ionic-playwright', 'npm run test.e2e --', ...process.argv.slice(2)];
|
||||
|
||||
// Set the CI env variable so Playwright uses the CI config
|
||||
if (process.env.CI) {
|
||||
args.splice(1, 0, '-e CI=true');
|
||||
/**
|
||||
* Otherwise, we should let the session be interactive locally. This will
|
||||
* not work on CI which is why we do not apply it there.
|
||||
*/
|
||||
} else {
|
||||
args.splice(1, 0, '-it');
|
||||
}
|
||||
|
||||
/**
|
||||
* While these config files are optional to run the tests, they are required to run
|
||||
* the tests in headed mode. Add a warning if dev tries to run headed tests without
|
||||
* the correct config files.
|
||||
*/
|
||||
const requestHeaded = process.argv.find(arg => arg.includes('headed'));
|
||||
const hasHeadedConfigFiles = display && displayVolume;
|
||||
if (requestHeaded && !hasHeadedConfigFiles) {
|
||||
console.warn(chalk.yellow.bold('\n⚠️ You are running tests in headed mode, but one or more of your headed config files was not found.\nPlease ensure that both docker-display.txt and docker-display-volume.txt have been created in the correct location.\n'));
|
||||
}
|
||||
|
||||
execa('docker', args, { shell: true, stdio: 'inherit' });
|
||||
@@ -1,44 +1,4 @@
|
||||
|
||||
## Build
|
||||
# Core Scripts
|
||||
|
||||
### 1. Clone ionic
|
||||
|
||||
git@github.com:ionic-team/ionic.git
|
||||
cd ionic
|
||||
|
||||
### 2. Run `npm install`
|
||||
|
||||
cd core
|
||||
npm install
|
||||
|
||||
|
||||
Notice that `@ionic/core` lives in `core`.
|
||||
|
||||
### 3. Run `npm start`
|
||||
|
||||
Make sure you are inside the `core` directory.
|
||||
|
||||
npm start
|
||||
|
||||
With the `dev` command, Ionic components will be built with [Stencil](https://stenciljs.com/), changes to source files are watched, a local http server will startup, and http://localhost:3333/ will open in a browser.
|
||||
|
||||
### 4. Preview
|
||||
|
||||
Navigate to http://localhost:3333/src/components/. Each component has small e2e apps found in the `test` directory, for example: http://localhost:3333/src/components/button/test/basic
|
||||
|
||||
As changes are made in an editor to source files, the e2e app will live-reload.
|
||||
|
||||
## How to contribute
|
||||
|
||||
1. `npm start` allows you to modify the components and have live reloading, just like another ionic app.
|
||||
|
||||
2. When everything looks good, run `npm run validate` to verify the tests linter and production build passes.
|
||||
|
||||
|
||||
# Deploy
|
||||
|
||||
1. `npm run prepare.deploy`
|
||||
2. Review/update changelog
|
||||
3. Commit updates using the package name and version number as the commit message.
|
||||
4. `npm run deploy`
|
||||
5. :tada:
|
||||
This file has been moved to [/docs/core/testing/preview-changes.md](/docs/core/testing/preview-changes.md).
|
||||
|
||||
63
core/src/components.d.ts
vendored
@@ -1287,6 +1287,25 @@ export namespace Components {
|
||||
*/
|
||||
"value"?: string | number | null;
|
||||
}
|
||||
interface IonInputPasswordToggle {
|
||||
/**
|
||||
* 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;
|
||||
/**
|
||||
* The icon that can be used to represent hiding a password. If not set, the "eyeOff" Ionicon will be used.
|
||||
*/
|
||||
"hideIcon"?: string;
|
||||
/**
|
||||
* The mode determines which platform styles to use.
|
||||
*/
|
||||
"mode"?: "ios" | "md";
|
||||
/**
|
||||
* The icon that can be used to represent showing a password. If not set, the "eye" Ionicon will be used.
|
||||
*/
|
||||
"showIcon"?: string;
|
||||
"type": TextFieldTypes;
|
||||
}
|
||||
interface IonItem {
|
||||
/**
|
||||
* If `true`, a button tag will be rendered and the item will be tappable.
|
||||
@@ -3179,7 +3198,7 @@ export namespace Components {
|
||||
}
|
||||
interface IonToggle {
|
||||
/**
|
||||
* How to control the alignment of the toggle and label on the cross axis. ``"start"`: The label and control will appear on the left of the cross axis in LTR, and on the right side in RTL. `"center"`: The label and control will appear at the center of the cross axis in both LTR and RTL.
|
||||
* How to control the alignment of the toggle and label on the cross axis. `"start"`: The label and control will appear on the left of the cross axis in LTR, and on the right side in RTL. `"center"`: The label and control will appear at the center of the cross axis in both LTR and RTL.
|
||||
*/
|
||||
"alignment": 'start' | 'center';
|
||||
/**
|
||||
@@ -3796,7 +3815,6 @@ declare global {
|
||||
"ionChange": InputChangeEventDetail;
|
||||
"ionBlur": FocusEvent;
|
||||
"ionFocus": FocusEvent;
|
||||
"ionStyle": StyleEventDetail;
|
||||
}
|
||||
interface HTMLIonInputElement extends Components.IonInput, HTMLStencilElement {
|
||||
addEventListener<K extends keyof HTMLIonInputElementEventMap>(type: K, listener: (this: HTMLIonInputElement, ev: IonInputCustomEvent<HTMLIonInputElementEventMap[K]>) => any, options?: boolean | AddEventListenerOptions): void;
|
||||
@@ -3812,6 +3830,12 @@ declare global {
|
||||
prototype: HTMLIonInputElement;
|
||||
new (): HTMLIonInputElement;
|
||||
};
|
||||
interface HTMLIonInputPasswordToggleElement extends Components.IonInputPasswordToggle, HTMLStencilElement {
|
||||
}
|
||||
var HTMLIonInputPasswordToggleElement: {
|
||||
prototype: HTMLIonInputPasswordToggleElement;
|
||||
new (): HTMLIonInputPasswordToggleElement;
|
||||
};
|
||||
interface HTMLIonItemElement extends Components.IonItem, HTMLStencilElement {
|
||||
}
|
||||
var HTMLIonItemElement: {
|
||||
@@ -4512,7 +4536,6 @@ declare global {
|
||||
interface HTMLIonTextareaElementEventMap {
|
||||
"ionChange": TextareaChangeEventDetail;
|
||||
"ionInput": TextareaInputEventDetail;
|
||||
"ionStyle": StyleEventDetail;
|
||||
"ionBlur": FocusEvent;
|
||||
"ionFocus": FocusEvent;
|
||||
}
|
||||
@@ -4637,6 +4660,7 @@ declare global {
|
||||
"ion-infinite-scroll": HTMLIonInfiniteScrollElement;
|
||||
"ion-infinite-scroll-content": HTMLIonInfiniteScrollContentElement;
|
||||
"ion-input": HTMLIonInputElement;
|
||||
"ion-input-password-toggle": HTMLIonInputPasswordToggleElement;
|
||||
"ion-item": HTMLIonItemElement;
|
||||
"ion-item-divider": HTMLIonItemDividerElement;
|
||||
"ion-item-group": HTMLIonItemGroupElement;
|
||||
@@ -5958,10 +5982,6 @@ declare namespace LocalJSX {
|
||||
* The `ionInput` event is fired each time the user modifies the input's value. Unlike the `ionChange` event, the `ionInput` event is fired for each alteration to the input's value. This typically happens for each keystroke as the user types. For elements that accept text input (`type=text`, `type=tel`, etc.), the interface is [`InputEvent`](https://developer.mozilla.org/en-US/docs/Web/API/InputEvent); for others, the interface is [`Event`](https://developer.mozilla.org/en-US/docs/Web/API/Event). If the input is cleared on edit, the type is `null`.
|
||||
*/
|
||||
"onIonInput"?: (event: IonInputCustomEvent<InputInputEventDetail>) => void;
|
||||
/**
|
||||
* Emitted when the styles change.
|
||||
*/
|
||||
"onIonStyle"?: (event: IonInputCustomEvent<StyleEventDetail>) => void;
|
||||
/**
|
||||
* A regular expression that the value is checked against. The pattern must match the entire value, not just some subset. Use the title attribute to describe the pattern to help the user. This attribute applies when the value of the type attribute is `"text"`, `"search"`, `"tel"`, `"url"`, `"email"`, `"date"`, or `"password"`, otherwise it is ignored. When the type attribute is `"date"`, `pattern` will only be used in browsers that do not support the `"date"` input type natively. See https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/date for more information.
|
||||
*/
|
||||
@@ -5999,6 +6019,25 @@ declare namespace LocalJSX {
|
||||
*/
|
||||
"value"?: string | number | null;
|
||||
}
|
||||
interface IonInputPasswordToggle {
|
||||
/**
|
||||
* 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;
|
||||
/**
|
||||
* The icon that can be used to represent hiding a password. If not set, the "eyeOff" Ionicon will be used.
|
||||
*/
|
||||
"hideIcon"?: string;
|
||||
/**
|
||||
* The mode determines which platform styles to use.
|
||||
*/
|
||||
"mode"?: "ios" | "md";
|
||||
/**
|
||||
* The icon that can be used to represent showing a password. If not set, the "eye" Ionicon will be used.
|
||||
*/
|
||||
"showIcon"?: string;
|
||||
"type"?: TextFieldTypes;
|
||||
}
|
||||
interface IonItem {
|
||||
/**
|
||||
* If `true`, a button tag will be rendered and the item will be tappable.
|
||||
@@ -7219,7 +7258,7 @@ declare namespace LocalJSX {
|
||||
/**
|
||||
* Indicates whether and how the text value should be automatically capitalized as it is entered/edited by the user. Available options: `"off"`, `"none"`, `"on"`, `"sentences"`, `"words"`, `"characters"`.
|
||||
*/
|
||||
"autocapitalize": string;
|
||||
"autocapitalize"?: string;
|
||||
/**
|
||||
* Set the input's autocomplete property.
|
||||
*/
|
||||
@@ -7781,10 +7820,6 @@ declare namespace LocalJSX {
|
||||
* The `ionInput` event is fired each time the user modifies the textarea's value. Unlike the `ionChange` event, the `ionInput` event is fired for each alteration to the textarea's value. This typically happens for each keystroke as the user types. When `clearOnEdit` is enabled, the `ionInput` event will be fired when the user clears the textarea by performing a keydown event.
|
||||
*/
|
||||
"onIonInput"?: (event: IonTextareaCustomEvent<TextareaInputEventDetail>) => void;
|
||||
/**
|
||||
* Emitted when the styles change.
|
||||
*/
|
||||
"onIonStyle"?: (event: IonTextareaCustomEvent<StyleEventDetail>) => void;
|
||||
/**
|
||||
* Instructional text that shows before the input has a value.
|
||||
*/
|
||||
@@ -7953,7 +7988,7 @@ declare namespace LocalJSX {
|
||||
}
|
||||
interface IonToggle {
|
||||
/**
|
||||
* How to control the alignment of the toggle and label on the cross axis. ``"start"`: The label and control will appear on the left of the cross axis in LTR, and on the right side in RTL. `"center"`: The label and control will appear at the center of the cross axis in both LTR and RTL.
|
||||
* How to control the alignment of the toggle and label on the cross axis. `"start"`: The label and control will appear on the left of the cross axis in LTR, and on the right side in RTL. `"center"`: The label and control will appear at the center of the cross axis in both LTR and RTL.
|
||||
*/
|
||||
"alignment"?: 'start' | 'center';
|
||||
/**
|
||||
@@ -8050,6 +8085,7 @@ declare namespace LocalJSX {
|
||||
"ion-infinite-scroll": IonInfiniteScroll;
|
||||
"ion-infinite-scroll-content": IonInfiniteScrollContent;
|
||||
"ion-input": IonInput;
|
||||
"ion-input-password-toggle": IonInputPasswordToggle;
|
||||
"ion-item": IonItem;
|
||||
"ion-item-divider": IonItemDivider;
|
||||
"ion-item-group": IonItemGroup;
|
||||
@@ -8148,6 +8184,7 @@ declare module "@stencil/core" {
|
||||
"ion-infinite-scroll": LocalJSX.IonInfiniteScroll & JSXBase.HTMLAttributes<HTMLIonInfiniteScrollElement>;
|
||||
"ion-infinite-scroll-content": LocalJSX.IonInfiniteScrollContent & JSXBase.HTMLAttributes<HTMLIonInfiniteScrollContentElement>;
|
||||
"ion-input": LocalJSX.IonInput & JSXBase.HTMLAttributes<HTMLIonInputElement>;
|
||||
"ion-input-password-toggle": LocalJSX.IonInputPasswordToggle & JSXBase.HTMLAttributes<HTMLIonInputPasswordToggleElement>;
|
||||
"ion-item": LocalJSX.IonItem & JSXBase.HTMLAttributes<HTMLIonItemElement>;
|
||||
"ion-item-divider": LocalJSX.IonItemDivider & JSXBase.HTMLAttributes<HTMLIonItemDividerElement>;
|
||||
"ion-item-group": LocalJSX.IonItemGroup & JSXBase.HTMLAttributes<HTMLIonItemGroupElement>;
|
||||
|
||||
@@ -306,6 +306,10 @@ configs({ directions: ['ltr'] }).forEach(({ title, screenshot, config }) => {
|
||||
await alert.evaluate((el: HTMLIonAlertElement) => el.present());
|
||||
await ionAlertDidPresent.next();
|
||||
|
||||
/**
|
||||
* The borders on the text fields may not be visible in the screenshot
|
||||
* when using Safari, this is due to a WebKit rendering quirk.
|
||||
*/
|
||||
await expect(page).toHaveScreenshot(screenshot(`alert-text-fields-scale`));
|
||||
});
|
||||
});
|
||||
|
||||
|
Before Width: | Height: | Size: 22 KiB After Width: | Height: | Size: 22 KiB |
|
Before Width: | Height: | Size: 23 KiB After Width: | Height: | Size: 23 KiB |
|
Before Width: | Height: | Size: 23 KiB After Width: | Height: | Size: 23 KiB |
|
Before Width: | Height: | Size: 26 KiB After Width: | Height: | Size: 27 KiB |
|
Before Width: | Height: | Size: 18 KiB After Width: | Height: | Size: 19 KiB |
|
Before Width: | Height: | Size: 26 KiB After Width: | Height: | Size: 27 KiB |
|
Before Width: | Height: | Size: 18 KiB After Width: | Height: | Size: 19 KiB |
|
Before Width: | Height: | Size: 34 KiB After Width: | Height: | Size: 35 KiB |
|
Before Width: | Height: | Size: 22 KiB After Width: | Height: | Size: 21 KiB |
|
Before Width: | Height: | Size: 34 KiB After Width: | Height: | Size: 35 KiB |
|
Before Width: | Height: | Size: 22 KiB After Width: | Height: | Size: 21 KiB |
@@ -114,11 +114,6 @@
|
||||
font-size: #{$button-ios-small-font-size};
|
||||
}
|
||||
|
||||
:host(.button-has-icon-only) {
|
||||
--padding-top: 0;
|
||||
--padding-bottom: 0;
|
||||
}
|
||||
|
||||
|
||||
// iOS Round Button
|
||||
// --------------------------------------------------
|
||||
@@ -131,7 +126,6 @@
|
||||
--padding-bottom: #{$button-ios-round-padding-bottom};
|
||||
}
|
||||
|
||||
|
||||
// iOS Strong Button
|
||||
// --------------------------------------------------
|
||||
|
||||
@@ -139,6 +133,85 @@
|
||||
font-weight: #{$button-ios-strong-font-weight};
|
||||
}
|
||||
|
||||
// iOS Icon Only Button
|
||||
// --------------------------------------------------
|
||||
|
||||
:host(.button-has-icon-only) {
|
||||
--padding-top: 0;
|
||||
--padding-bottom: var(--padding-top);
|
||||
--padding-end: var(--padding-top);
|
||||
--padding-start: var(--padding-end);
|
||||
// TODO(FW-6053): replace em value with the min-height variable.
|
||||
min-width: clamp(30px, 2.125em, 60px);
|
||||
|
||||
// TODO(FW-6053): replace em value with the min-height variable.
|
||||
min-height: clamp(30px, 2.125em, 60px);
|
||||
}
|
||||
|
||||
::slotted(ion-icon[slot="icon-only"]) {
|
||||
/**
|
||||
* The values were provided through a native iOS app.
|
||||
* min font size: 15px, default font size: 18px, max font size: 43px
|
||||
*
|
||||
* Since the `ion-button` uses `rem` for the font size, we can't
|
||||
* just pass the desired icon font size in `em` to the `
|
||||
* dynamic-font-clamp`. Instead, we need to adjust the base size
|
||||
* to account for the ion-button` font size.
|
||||
*
|
||||
* For example, if the default font size of `ion-button` is 16px
|
||||
* (derived from rem), then the base size can use the default font
|
||||
* size of the icon.
|
||||
*/
|
||||
font-size: dynamic-font-clamp(0.84, 18px, 2.39, 1em);
|
||||
}
|
||||
|
||||
:host(.button-small.button-has-icon-only) {
|
||||
// TODO(FW-6053): replace em value with the min-height variable.
|
||||
min-width: clamp(23px, 2.16em, 54px);
|
||||
// TODO(FW-6053): replace em value with the min-height variable.
|
||||
min-height: clamp(23px, 2.16em, 54px);
|
||||
}
|
||||
|
||||
:host(.button-small) ::slotted(ion-icon[slot="icon-only"]) {
|
||||
/**
|
||||
* The values were provided through a native iOS app.
|
||||
* min font size: 12px, default font size: 17px, max font size: 40px
|
||||
*
|
||||
* Since the `ion-button` uses `rem` for the font size, we can't
|
||||
* just pass the desired icon font size in `em` to the `
|
||||
* dynamic-font-clamp`. Instead, we need to adjust the base size
|
||||
* to account for the ion-button` font size.
|
||||
*
|
||||
* For example, if the default font size of `ion-button` is 13px
|
||||
* (derived from rem) and the default font size of the icon is
|
||||
* 17px, then the base size would need to be increased.
|
||||
*/
|
||||
font-size: dynamic-font-clamp(0.58, 20.93px, 1.92, 1em);
|
||||
}
|
||||
|
||||
:host(.button-large.button-has-icon-only) {
|
||||
// TODO(FW-6053): replace em value with the min-height variable.
|
||||
min-width: clamp(46px, 2.5em, 78px);
|
||||
// TODO(FW-6053): replace em value with the min-height variable.
|
||||
min-height: clamp(46px, 2.5em, 78px);
|
||||
}
|
||||
|
||||
:host(.button-large) ::slotted(ion-icon[slot="icon-only"]) {
|
||||
/**
|
||||
* The values were provided through a native iOS app.
|
||||
* min font size: 15px, default font size: 18px, max font size: 43px
|
||||
*
|
||||
* Since the `ion-button` uses `rem` for the font size, we can't
|
||||
* just pass the desired icon font size in `em` to the `
|
||||
* dynamic-font-clamp`. Instead, we need to adjust the base size
|
||||
* to account for the ion-button` font size.
|
||||
*
|
||||
* For example, if the default font size of `ion-button` is 20px
|
||||
* (derived from rem) and the default font size of the icon is
|
||||
* 18px, then the base size would need to be decreased.
|
||||
*/
|
||||
font-size: dynamic-font-clamp(1.05, 14.4px, 2.99, 1em);
|
||||
}
|
||||
|
||||
// iOS Button Focused
|
||||
// --------------------------------------------------
|
||||
@@ -212,3 +285,12 @@
|
||||
:host(.button-solid.ion-color.ion-activated) .button-native::after {
|
||||
background: #{current-color(shade)};
|
||||
}
|
||||
|
||||
|
||||
// Activated Button in Toolbar
|
||||
// --------------------------------------------------
|
||||
|
||||
:host(.button-outline.ion-activated.in-toolbar:not(.ion-color):not(.in-toolbar-color)) .button-native {
|
||||
background: var(--ion-toolbar-color, var(--color));
|
||||
color: #{var(--ion-toolbar-background, var(--background), ion-color(primary, contrast))};
|
||||
}
|
||||
|
||||
@@ -113,12 +113,6 @@
|
||||
font-size: #{$button-md-small-font-size};
|
||||
}
|
||||
|
||||
:host(.button-has-icon-only) {
|
||||
--padding-top: 0;
|
||||
--padding-bottom: 0;
|
||||
}
|
||||
|
||||
|
||||
// MD strong Button
|
||||
// --------------------------------------------------
|
||||
|
||||
@@ -126,10 +120,94 @@
|
||||
font-weight: #{$button-md-strong-font-weight};
|
||||
}
|
||||
|
||||
::slotted(ion-icon[slot="icon-only"]) {
|
||||
@include padding(0);
|
||||
// MD Icon Only Button
|
||||
//
|
||||
// MD does not specify a small size, these
|
||||
// styles are based on the iOS small size.
|
||||
//
|
||||
// MD does not specify a large size, these
|
||||
// styles are based on the iOS large size.
|
||||
// --------------------------------------------------
|
||||
|
||||
:host(.button-has-icon-only) {
|
||||
--padding-top: 0;
|
||||
--padding-bottom: var(--padding-top);
|
||||
--padding-end: var(--padding-top);
|
||||
--padding-start: var(--padding-end);
|
||||
// TODO(FW-6053): replace em value with the min-height variable.
|
||||
min-width: clamp(30px, 2.86em, 60px);
|
||||
|
||||
// TODO(FW-6053): replace em value with the min-height variable.
|
||||
min-height: clamp(30px, 2.86em, 60px);
|
||||
}
|
||||
|
||||
::slotted(ion-icon[slot="icon-only"]) {
|
||||
/**
|
||||
* The values were provided through MD design,
|
||||
* large and small are based on the iOS sizes.
|
||||
* min font size: 15px, default font size: 22.4px, max font size: 43px
|
||||
*
|
||||
* Since the `ion-button` uses `rem` for the font size, we can't
|
||||
* just pass the desired icon font size in `em` to the `
|
||||
* dynamic-font-clamp`. Instead, we need to adjust the base size
|
||||
* to account for the ion-button` font size.
|
||||
*
|
||||
* For example, if the default font size of `ion-button` is 14px
|
||||
* (derived from rem) and the default font size of the icon is
|
||||
* 22.4px, then the base size would need to be increased.
|
||||
*/
|
||||
font-size: dynamic-font-clamp(0.59, 25.6px, 1.68, 1em);
|
||||
}
|
||||
|
||||
:host(.button-small.button-has-icon-only) {
|
||||
// TODO(FW-6053): replace em value with the min-height variable.
|
||||
min-width: clamp(23px, 2.16em, 54px);
|
||||
// TODO(FW-6053): replace em value with the min-height variable.
|
||||
min-height: clamp(23px, 2.16em, 54px);
|
||||
}
|
||||
|
||||
:host(.button-small) ::slotted(ion-icon[slot="icon-only"]) {
|
||||
/**
|
||||
* The values were provided through MD design,
|
||||
* large and small are based on the iOS sizes.
|
||||
* min font size: 12px, default font size: 16px, max font size: 40px
|
||||
*
|
||||
* Since the `ion-button` uses `rem` for the font size, we can't
|
||||
* just pass the desired icon font size in `em` to the `
|
||||
* dynamic-font-clamp`. Instead, we need to adjust the base size
|
||||
* to account for the ion-button` font size.
|
||||
*
|
||||
* For example, if the default font size of `ion-button` is 13px
|
||||
* (derived from rem) and the default font size of the icon is
|
||||
* 16px, then the base size would need to be increased.
|
||||
*/
|
||||
font-size: dynamic-font-clamp(0.66, 19.7px, 2.05, 1em);
|
||||
}
|
||||
|
||||
:host(.button-large.button-has-icon-only) {
|
||||
// TODO(FW-6053): replace em value with the min-height variable.
|
||||
min-width: clamp(46px, 2.5em, 78px);
|
||||
// TODO(FW-6053): replace em value with the min-height variable.
|
||||
min-height: clamp(46px, 2.5em, 78px);
|
||||
}
|
||||
|
||||
:host(.button-large) ::slotted(ion-icon[slot="icon-only"]) {
|
||||
/**
|
||||
* The values were provided through MD design,
|
||||
* large and small are based on the iOS sizes.
|
||||
* min font size: 15px, default font size: 28px, max font size: 43px
|
||||
*
|
||||
* Since the `ion-button` uses `rem` for the font size, we can't
|
||||
* just pass the desired icon font size in `em` to the `
|
||||
* dynamic-font-clamp`. Instead, we need to adjust the base size
|
||||
* to account for the ion-button` font size.
|
||||
*
|
||||
* For example, if the default font size of `ion-button` is 20px
|
||||
* (derived from rem) and the default font size of the icon is
|
||||
* 28px, then the base size would need to be increased.
|
||||
*/
|
||||
font-size: dynamic-font-clamp(0.67, 22.4px, 1.92, 1em);
|
||||
}
|
||||
|
||||
// Material Design Button: Hover
|
||||
// --------------------------------------------------
|
||||
@@ -160,3 +238,12 @@
|
||||
background: #{current-color(base)};
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Activated Button in Toolbar
|
||||
// --------------------------------------------------
|
||||
|
||||
:host(.button-outline.ion-activated.in-toolbar:not(.ion-color):not(.in-toolbar-color)) .button-native {
|
||||
background: var(--ion-toolbar-background, var(--color));
|
||||
color: #{var(--ion-toolbar-color, var(--background), ion-color(primary, contrast))};
|
||||
}
|
||||
|
||||
@@ -235,11 +235,6 @@
|
||||
@include margin(0, -0.2em, 0, 0.3em);
|
||||
}
|
||||
|
||||
::slotted(ion-icon[slot="icon-only"]) {
|
||||
font-size: 1.8em;
|
||||
}
|
||||
|
||||
|
||||
// Button Ripple effect
|
||||
// --------------------------------------------------
|
||||
|
||||
@@ -330,11 +325,3 @@ ion-ripple-effect {
|
||||
background: #{var(--ion-toolbar-color, var(--background))};
|
||||
color: #{var(--ion-toolbar-background, var(--color))};
|
||||
}
|
||||
|
||||
// Activated Button in Toolbar
|
||||
// --------------------------------------------------
|
||||
|
||||
:host(.button-outline.ion-activated.in-toolbar:not(.ion-color):not(.in-toolbar-color)) .button-native {
|
||||
background: var(--ion-toolbar-color, var(--color));
|
||||
color: #{var(--ion-toolbar-background, var(--background), ion-color(primary, contrast))};
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import type { ComponentInterface, EventEmitter } from '@stencil/core';
|
||||
import { Component, Element, Event, Host, Prop, Watch, h } from '@stencil/core';
|
||||
import { Component, Element, Event, Host, Prop, Watch, State, h } from '@stencil/core';
|
||||
import type { AnchorInterface, ButtonInterface } from '@utils/element-interface';
|
||||
import type { Attributes } from '@utils/helpers';
|
||||
import { inheritAriaAttributes, hasShadowDom } from '@utils/helpers';
|
||||
@@ -38,6 +38,11 @@ export class Button implements ComponentInterface, AnchorInterface, ButtonInterf
|
||||
|
||||
@Element() el!: HTMLElement;
|
||||
|
||||
/**
|
||||
* If `true`, the button only has an icon.
|
||||
*/
|
||||
@State() isCircle: boolean = false;
|
||||
|
||||
/**
|
||||
* The color to use from your application's color palette.
|
||||
* Default options are: `"primary"`, `"secondary"`, `"tertiary"`, `"success"`, `"warning"`, `"danger"`, `"light"`, `"medium"`, and `"dark"`.
|
||||
@@ -295,6 +300,18 @@ export class Button implements ComponentInterface, AnchorInterface, ButtonInterf
|
||||
this.ionBlur.emit();
|
||||
};
|
||||
|
||||
private slotChanged = () => {
|
||||
/**
|
||||
* Ensures that the 'has-icon-only' class is properly added
|
||||
* or removed from `ion-button` when manipulating the
|
||||
* `icon-only` slot.
|
||||
*
|
||||
* Without this, the 'has-icon-only' class is only checked
|
||||
* or added when `ion-button` component first renders.
|
||||
*/
|
||||
this.isCircle = this.hasIconOnly;
|
||||
};
|
||||
|
||||
render() {
|
||||
const mode = getIonMode(this);
|
||||
const {
|
||||
@@ -374,7 +391,7 @@ export class Button implements ComponentInterface, AnchorInterface, ButtonInterf
|
||||
{...inheritedAttributes}
|
||||
>
|
||||
<span class="button-inner">
|
||||
<slot name="icon-only"></slot>
|
||||
<slot name="icon-only" onSlotchange={this.slotChanged}></slot>
|
||||
<slot name="start"></slot>
|
||||
<slot></slot>
|
||||
<slot name="end"></slot>
|
||||
|
||||
@@ -16,4 +16,4 @@ $button-round-padding-bottom: $button-round-padding-top !default;
|
||||
$button-round-padding-start: $button-round-padding-end !default;
|
||||
|
||||
/// @prop - Border radius of the round button
|
||||
$button-round-border-radius: 64px !default;
|
||||
$button-round-border-radius: 999px !default;
|
||||
|
||||
|
Before Width: | Height: | Size: 2.5 KiB After Width: | Height: | Size: 2.5 KiB |
|
Before Width: | Height: | Size: 2.3 KiB After Width: | Height: | Size: 2.3 KiB |
|
Before Width: | Height: | Size: 93 KiB After Width: | Height: | Size: 93 KiB |
|
Before Width: | Height: | Size: 93 KiB After Width: | Height: | Size: 93 KiB |
|
Before Width: | Height: | Size: 88 KiB After Width: | Height: | Size: 89 KiB |
|
Before Width: | Height: | Size: 88 KiB After Width: | Height: | Size: 89 KiB |
|
Before Width: | Height: | Size: 31 KiB After Width: | Height: | Size: 29 KiB |
|
Before Width: | Height: | Size: 43 KiB After Width: | Height: | Size: 42 KiB |
|
Before Width: | Height: | Size: 29 KiB After Width: | Height: | Size: 28 KiB |
|
Before Width: | Height: | Size: 31 KiB After Width: | Height: | Size: 29 KiB |
|
Before Width: | Height: | Size: 44 KiB After Width: | Height: | Size: 42 KiB |
|
Before Width: | Height: | Size: 29 KiB After Width: | Height: | Size: 27 KiB |
|
Before Width: | Height: | Size: 30 KiB After Width: | Height: | Size: 30 KiB |
|
Before Width: | Height: | Size: 46 KiB After Width: | Height: | Size: 43 KiB |
|
Before Width: | Height: | Size: 29 KiB After Width: | Height: | Size: 28 KiB |
|
Before Width: | Height: | Size: 31 KiB After Width: | Height: | Size: 30 KiB |
|
Before Width: | Height: | Size: 47 KiB After Width: | Height: | Size: 44 KiB |
|
Before Width: | Height: | Size: 29 KiB After Width: | Height: | Size: 28 KiB |
|
Before Width: | Height: | Size: 117 KiB After Width: | Height: | Size: 118 KiB |
|
Before Width: | Height: | Size: 116 KiB After Width: | Height: | Size: 117 KiB |
@@ -6,12 +6,64 @@ import { configs, test } from '@utils/test/playwright';
|
||||
*/
|
||||
configs({ directions: ['ltr'] }).forEach(({ title, screenshot, config }) => {
|
||||
test.describe(title('button: round'), () => {
|
||||
test('should not have visual regressions', async ({ page }) => {
|
||||
await page.goto(`/src/components/button/test/round`, config);
|
||||
test.describe('default', () => {
|
||||
test('should not have visual regressions', async ({ page }) => {
|
||||
await page.goto(`/src/components/button/test/round`, config);
|
||||
|
||||
await page.setIonViewport();
|
||||
await page.setIonViewport();
|
||||
|
||||
await expect(page).toHaveScreenshot(screenshot(`button-round`));
|
||||
const container = page.locator('#default');
|
||||
|
||||
await expect(container).toHaveScreenshot(screenshot(`button-round`));
|
||||
});
|
||||
});
|
||||
|
||||
test.describe('outline', () => {
|
||||
test('should not have visual regressions', async ({ page }) => {
|
||||
await page.goto(`/src/components/button/test/round`, config);
|
||||
|
||||
await page.setIonViewport();
|
||||
|
||||
const container = page.locator('#outline');
|
||||
|
||||
await expect(container).toHaveScreenshot(screenshot(`button-outline-round`));
|
||||
});
|
||||
});
|
||||
|
||||
test.describe('clear', () => {
|
||||
test('should not have visual regressions', async ({ page }) => {
|
||||
await page.goto(`/src/components/button/test/round`, config);
|
||||
|
||||
await page.setIonViewport();
|
||||
|
||||
const container = page.locator('#clear');
|
||||
|
||||
await expect(container).toHaveScreenshot(screenshot(`button-clear-round`));
|
||||
});
|
||||
});
|
||||
|
||||
test.describe('color', () => {
|
||||
test('should not have visual regressions', async ({ page }) => {
|
||||
await page.goto(`/src/components/button/test/round`, config);
|
||||
|
||||
await page.setIonViewport();
|
||||
|
||||
const container = page.locator('#color');
|
||||
|
||||
await expect(container).toHaveScreenshot(screenshot(`button-color-round`));
|
||||
});
|
||||
});
|
||||
|
||||
test.describe('expand', () => {
|
||||
test('should not have visual regressions', async ({ page }) => {
|
||||
await page.goto(`/src/components/button/test/round`, config);
|
||||
|
||||
await page.setIonViewport();
|
||||
|
||||
const container = page.locator('#expand');
|
||||
|
||||
await expect(container).toHaveScreenshot(screenshot(`button-expand-round`));
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
|
After Width: | Height: | Size: 7.9 KiB |
|
After Width: | Height: | Size: 9.3 KiB |
|
After Width: | Height: | Size: 7.2 KiB |
|
After Width: | Height: | Size: 8.6 KiB |
|
After Width: | Height: | Size: 9.6 KiB |
|
After Width: | Height: | Size: 8.1 KiB |
|
After Width: | Height: | Size: 44 KiB |
|
After Width: | Height: | Size: 50 KiB |
|
After Width: | Height: | Size: 43 KiB |
|
After Width: | Height: | Size: 40 KiB |
|
After Width: | Height: | Size: 52 KiB |
|
After Width: | Height: | Size: 40 KiB |
|
After Width: | Height: | Size: 10 KiB |
|
After Width: | Height: | Size: 12 KiB |
|
After Width: | Height: | Size: 9.6 KiB |
|
After Width: | Height: | Size: 9.1 KiB |
|
After Width: | Height: | Size: 12 KiB |
|
After Width: | Height: | Size: 8.8 KiB |
|
After Width: | Height: | Size: 10 KiB |
|
After Width: | Height: | Size: 11 KiB |
|
After Width: | Height: | Size: 10 KiB |
|
After Width: | Height: | Size: 13 KiB |
|
After Width: | Height: | Size: 12 KiB |
|
After Width: | Height: | Size: 12 KiB |
|
Before Width: | Height: | Size: 65 KiB After Width: | Height: | Size: 9.0 KiB |
|
Before Width: | Height: | Size: 80 KiB After Width: | Height: | Size: 9.5 KiB |
|
Before Width: | Height: | Size: 63 KiB After Width: | Height: | Size: 8.3 KiB |
|
Before Width: | Height: | Size: 62 KiB After Width: | Height: | Size: 13 KiB |
|
Before Width: | Height: | Size: 84 KiB After Width: | Height: | Size: 15 KiB |
|
Before Width: | Height: | Size: 60 KiB After Width: | Height: | Size: 12 KiB |
@@ -12,6 +12,14 @@
|
||||
<script src="../../../../../scripts/testing/scripts.js"></script>
|
||||
<script nomodule src="../../../../../dist/ionic/ionic.js"></script>
|
||||
<script type="module" src="../../../../../dist/ionic/ionic.esm.js"></script>
|
||||
|
||||
<style>
|
||||
.grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(3, 1fr);
|
||||
grid-gap: 10px;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
@@ -22,45 +30,131 @@
|
||||
</ion-toolbar>
|
||||
</ion-header>
|
||||
|
||||
<ion-content class="ion-padding ion-text-center" id="content" no-bounce>
|
||||
<ion-button shape="round">Default</ion-button>
|
||||
<ion-button shape="round" color="primary">Primary</ion-button>
|
||||
<ion-button shape="round" color="secondary">Secondary</ion-button>
|
||||
<ion-button shape="round" color="tertiary">Tertiary</ion-button>
|
||||
<ion-button shape="round" color="success">Success</ion-button>
|
||||
<ion-button shape="round" color="warning">Warning</ion-button>
|
||||
<ion-button shape="round" color="danger">Danger</ion-button>
|
||||
<ion-button shape="round" color="light">Light</ion-button>
|
||||
<ion-button shape="round" color="medium">Medium</ion-button>
|
||||
<ion-button shape="round" color="dark">Dark</ion-button>
|
||||
<ion-content class="ion-padding" no-bounce>
|
||||
<h1>Default</h1>
|
||||
<div id="default" class="grid">
|
||||
<div>
|
||||
<ion-button size="small" shape="round">Button</ion-button>
|
||||
</div>
|
||||
<div>
|
||||
<ion-button shape="round">Button</ion-button>
|
||||
</div>
|
||||
<div>
|
||||
<ion-button size="large" shape="round">Button</ion-button>
|
||||
</div>
|
||||
|
||||
<ion-button fill="outline" shape="round">Default</ion-button>
|
||||
<ion-button fill="outline" shape="round" color="primary">Primary</ion-button>
|
||||
<ion-button fill="outline" shape="round" color="secondary">Secondary</ion-button>
|
||||
<ion-button fill="outline" shape="round" color="tertiary">Tertiary</ion-button>
|
||||
<ion-button fill="outline" shape="round" color="success">Success</ion-button>
|
||||
<ion-button fill="outline" shape="round" color="warning">Warning</ion-button>
|
||||
<ion-button fill="outline" shape="round" color="danger">Danger</ion-button>
|
||||
<ion-button fill="outline" shape="round" color="light">Light</ion-button>
|
||||
<ion-button fill="outline" shape="round" color="medium">Medium</ion-button>
|
||||
<ion-button fill="outline" shape="round" color="dark">Dark</ion-button>
|
||||
<div>
|
||||
<ion-button size="small" shape="round">
|
||||
<ion-icon slot="icon-only" ios="logo-apple" md="settings-sharp"></ion-icon>
|
||||
</ion-button>
|
||||
</div>
|
||||
<div>
|
||||
<ion-button shape="round">
|
||||
<ion-icon slot="icon-only" ios="logo-apple" md="settings-sharp"></ion-icon>
|
||||
</ion-button>
|
||||
</div>
|
||||
<div>
|
||||
<ion-button size="large" shape="round">
|
||||
<ion-icon slot="icon-only" ios="logo-apple" md="settings-sharp"></ion-icon>
|
||||
</ion-button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<ion-button shape="round" fill="clear">Clear</ion-button>
|
||||
<ion-button shape="round" expand="block">Block</ion-button>
|
||||
<ion-button shape="round" expand="full" color="danger">Full</ion-button>
|
||||
<h1>Outline</h1>
|
||||
<div id="outline" class="grid">
|
||||
<div>
|
||||
<ion-button size="small" shape="round" fill="outline">Button</ion-button>
|
||||
</div>
|
||||
<div>
|
||||
<ion-button shape="round" fill="outline">Button</ion-button>
|
||||
</div>
|
||||
<div>
|
||||
<ion-button size="large" shape="round" fill="outline">Button</ion-button>
|
||||
</div>
|
||||
<div>
|
||||
<ion-button size="small" shape="round" fill="outline">
|
||||
<ion-icon slot="icon-only" ios="logo-apple" md="settings-sharp"></ion-icon>
|
||||
</ion-button>
|
||||
</div>
|
||||
<div>
|
||||
<ion-button shape="round" fill="outline">
|
||||
<ion-icon slot="icon-only" ios="logo-apple" md="settings-sharp"></ion-icon>
|
||||
</ion-button>
|
||||
</div>
|
||||
<div>
|
||||
<ion-button size="large" shape="round" fill="outline">
|
||||
<ion-icon slot="icon-only" ios="logo-apple" md="settings-sharp"></ion-icon>
|
||||
</ion-button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<ion-button shape="round" fill="outline" expand="block">Block - Outline</ion-button>
|
||||
<ion-button shape="round" fill="outline" expand="full" color="danger">Full - Outline</ion-button>
|
||||
<h1>Clear</h1>
|
||||
<!-- The buttons have the `ion-focused` class to highlight that they are round. Otherwise, they would be invisible. -->
|
||||
<div id="clear" class="grid">
|
||||
<div>
|
||||
<ion-button size="small" shape="round" fill="clear" class="ion-focused">Button</ion-button>
|
||||
</div>
|
||||
<div>
|
||||
<ion-button shape="round" fill="clear" class="ion-focused">Button</ion-button>
|
||||
</div>
|
||||
<div>
|
||||
<ion-button size="large" shape="round" fill="clear" class="ion-focused">Button</ion-button>
|
||||
</div>
|
||||
<div>
|
||||
<ion-button size="small" shape="round" fill="clear" class="ion-focused">
|
||||
<ion-icon slot="icon-only" ios="logo-apple" md="settings-sharp"></ion-icon>
|
||||
</ion-button>
|
||||
</div>
|
||||
<div>
|
||||
<ion-button shape="round" fill="clear" class="ion-focused">
|
||||
<ion-icon slot="icon-only" ios="logo-apple" md="settings-sharp"></ion-icon>
|
||||
</ion-button>
|
||||
</div>
|
||||
<div>
|
||||
<ion-button size="large" shape="round" fill="clear" class="ion-focused">
|
||||
<ion-icon slot="icon-only" ios="logo-apple" md="settings-sharp"></ion-icon>
|
||||
</ion-button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<ion-button shape="round" strong>Strong</ion-button>
|
||||
<h1>Color</h1>
|
||||
<div id="color">
|
||||
<ion-button shape="round">Default</ion-button>
|
||||
<ion-button shape="round" color="primary">Primary</ion-button>
|
||||
<ion-button shape="round" color="secondary">Secondary</ion-button>
|
||||
<ion-button shape="round" color="tertiary">Tertiary</ion-button>
|
||||
<ion-button shape="round" color="success">Success</ion-button>
|
||||
<ion-button shape="round" color="warning">Warning</ion-button>
|
||||
<ion-button shape="round" color="danger">Danger</ion-button>
|
||||
<ion-button shape="round" color="light">Light</ion-button>
|
||||
<ion-button shape="round" color="medium">Medium</ion-button>
|
||||
<ion-button shape="round" color="dark">Dark</ion-button>
|
||||
|
||||
<ion-button fill="outline" shape="round">Default</ion-button>
|
||||
<ion-button fill="outline" shape="round" color="primary">Primary</ion-button>
|
||||
<ion-button fill="outline" shape="round" color="secondary">Secondary</ion-button>
|
||||
<ion-button fill="outline" shape="round" color="tertiary">Tertiary</ion-button>
|
||||
<ion-button fill="outline" shape="round" color="success">Success</ion-button>
|
||||
<ion-button fill="outline" shape="round" color="warning">Warning</ion-button>
|
||||
<ion-button fill="outline" shape="round" color="danger">Danger</ion-button>
|
||||
<ion-button fill="outline" shape="round" color="light">Light</ion-button>
|
||||
<ion-button fill="outline" shape="round" color="medium">Medium</ion-button>
|
||||
<ion-button fill="outline" shape="round" color="dark">Dark</ion-button>
|
||||
</div>
|
||||
|
||||
<h1>Expand</h1>
|
||||
<div id="expand">
|
||||
<ion-button shape="round" expand="block">Block</ion-button>
|
||||
<ion-button shape="round" expand="full" color="danger">Full</ion-button>
|
||||
<ion-button shape="round" fill="outline" expand="block">Block - Outline</ion-button>
|
||||
<ion-button shape="round" fill="outline" expand="full" color="danger">Full - Outline</ion-button>
|
||||
</div>
|
||||
|
||||
<h1>Strong</h1>
|
||||
<div id="strong">
|
||||
<ion-button shape="round" strong>Strong</ion-button>
|
||||
</div>
|
||||
</ion-content>
|
||||
</ion-app>
|
||||
|
||||
<style>
|
||||
ion-button {
|
||||
display: block !important;
|
||||
margin: 8px auto !important;
|
||||
}
|
||||
</style>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -38,6 +38,8 @@
|
||||
}
|
||||
|
||||
:host(.in-item) {
|
||||
flex: 1 1 0;
|
||||
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
@@ -107,6 +107,7 @@ export class Datetime implements ComponentInterface {
|
||||
private inputId = `ion-dt-${datetimeIds++}`;
|
||||
private calendarBodyRef?: HTMLElement;
|
||||
private popoverRef?: HTMLIonPopoverElement;
|
||||
private intersectionTrackerRef?: HTMLElement;
|
||||
private clearFocusVisible?: () => void;
|
||||
private parsedMinuteValues?: number[];
|
||||
private parsedHourValues?: number[];
|
||||
@@ -846,6 +847,23 @@ export class Datetime implements ComponentInterface {
|
||||
this.maxParts = parseMaxParts(max, defaultParts);
|
||||
};
|
||||
|
||||
private centerCalendarGrid = (workingMonth: HTMLElement) => {
|
||||
const { el, calendarBodyRef } = this;
|
||||
|
||||
if (!calendarBodyRef) return;
|
||||
|
||||
const monthRight = workingMonth.offsetLeft + workingMonth.offsetWidth;
|
||||
const elRight = el.offsetLeft + el.offsetWidth;
|
||||
|
||||
if (monthRight > elRight) {
|
||||
calendarBodyRef.scrollLeft = workingMonth.clientWidth;
|
||||
console.log('LTR', workingMonth)
|
||||
} else {
|
||||
calendarBodyRef.scrollLeft = -workingMonth.clientWidth;
|
||||
console.log('RTL', workingMonth)
|
||||
}
|
||||
}
|
||||
|
||||
private initializeCalendarListener = () => {
|
||||
const calendarBodyRef = this.calendarBodyRef;
|
||||
if (!calendarBodyRef) {
|
||||
@@ -867,11 +885,11 @@ export class Datetime implements ComponentInterface {
|
||||
* the months in a row allows us to mostly sidestep
|
||||
* that issue.
|
||||
*/
|
||||
const months = calendarBodyRef.querySelectorAll('.calendar-month');
|
||||
const months = calendarBodyRef.querySelectorAll<HTMLElement>('.calendar-month');
|
||||
|
||||
const startMonth = months[0] as HTMLElement;
|
||||
const workingMonth = months[1] as HTMLElement;
|
||||
const endMonth = months[2] as HTMLElement;
|
||||
const startMonth = months[0];
|
||||
const workingMonth = months[1];
|
||||
const endMonth = months[2];
|
||||
const mode = getIonMode(this);
|
||||
const needsiOSRubberBandFix = mode === 'ios' && typeof navigator !== 'undefined' && navigator.maxTouchPoints > 1;
|
||||
|
||||
@@ -882,7 +900,7 @@ export class Datetime implements ComponentInterface {
|
||||
* if element is not in viewport. Use scrollLeft instead.
|
||||
*/
|
||||
writeTask(() => {
|
||||
calendarBodyRef.scrollLeft = startMonth.clientWidth * (isRTL(this.el) ? -1 : 1);
|
||||
this.centerCalendarGrid(workingMonth);
|
||||
|
||||
const getChangedMonth = (parts: DatetimeParts): DatetimeParts | undefined => {
|
||||
const box = calendarBodyRef.getBoundingClientRect();
|
||||
@@ -952,6 +970,7 @@ export class Datetime implements ComponentInterface {
|
||||
* then we can return early.
|
||||
*/
|
||||
const newDate = getChangedMonth(this.workingParts);
|
||||
console.log(newDate,this.workingParts)
|
||||
if (!newDate) return;
|
||||
|
||||
const { month, day, year } = newDate;
|
||||
@@ -992,7 +1011,7 @@ export class Datetime implements ComponentInterface {
|
||||
year,
|
||||
});
|
||||
|
||||
calendarBodyRef.scrollLeft = workingMonth.clientWidth * (isRTL(this.el) ? -1 : 1);
|
||||
this.centerCalendarGrid(workingMonth);
|
||||
calendarBodyRef.style.removeProperty('overflow');
|
||||
|
||||
if (this.resolveForceDateScrolling) {
|
||||
@@ -1078,6 +1097,8 @@ export class Datetime implements ComponentInterface {
|
||||
}
|
||||
|
||||
componentDidLoad() {
|
||||
const { el, intersectionTrackerRef } = this;
|
||||
|
||||
/**
|
||||
* If a scrollable element is hidden using `display: none`,
|
||||
* it will not have a scroll height meaning we cannot scroll elements
|
||||
@@ -1105,7 +1126,7 @@ export class Datetime implements ComponentInterface {
|
||||
this.el.classList.add('datetime-ready');
|
||||
});
|
||||
};
|
||||
const visibleIO = new IntersectionObserver(visibleCallback, { threshold: 0.01 });
|
||||
const visibleIO = new IntersectionObserver(visibleCallback, { threshold: 0.01, root: el });
|
||||
|
||||
/**
|
||||
* Use raf to avoid a race condition between the component loading and
|
||||
@@ -1113,7 +1134,7 @@ export class Datetime implements ComponentInterface {
|
||||
* could cause the datetime to start at a visibility of 0, erroneously
|
||||
* triggering the `hiddenIO` observer below.
|
||||
*/
|
||||
raf(() => visibleIO?.observe(this.el));
|
||||
raf(() => visibleIO?.observe(intersectionTrackerRef!));
|
||||
|
||||
/**
|
||||
* We need to clean up listeners when the datetime is hidden
|
||||
@@ -1143,8 +1164,8 @@ export class Datetime implements ComponentInterface {
|
||||
this.el.classList.remove('datetime-ready');
|
||||
});
|
||||
};
|
||||
const hiddenIO = new IntersectionObserver(hiddenCallback, { threshold: 0 });
|
||||
raf(() => hiddenIO?.observe(this.el));
|
||||
const hiddenIO = new IntersectionObserver(hiddenCallback, { threshold: 0, root: el });
|
||||
raf(() => hiddenIO?.observe(intersectionTrackerRef!));
|
||||
|
||||
/**
|
||||
* Datetime uses Ionic components that emit
|
||||
@@ -1182,7 +1203,7 @@ export class Datetime implements ComponentInterface {
|
||||
*/
|
||||
const hasCalendarGrid = !preferWheel && ['date-time', 'time-date', 'date'].includes(presentation);
|
||||
if (minParts !== undefined && hasCalendarGrid && calendarBodyRef) {
|
||||
const workingMonth = calendarBodyRef.querySelector('.calendar-month:nth-of-type(1)');
|
||||
const workingMonth = calendarBodyRef.querySelector<HTMLElement>('.calendar-month:nth-of-type(1)');
|
||||
/**
|
||||
* We need to make sure the datetime is not in the process
|
||||
* of scrolling to a new datetime value if the value
|
||||
@@ -1197,7 +1218,7 @@ export class Datetime implements ComponentInterface {
|
||||
* and the resolveForceDateScrolling promise never resolves.
|
||||
*/
|
||||
if (workingMonth && forceRenderDate === undefined) {
|
||||
calendarBodyRef.scrollLeft = workingMonth.clientWidth * (isRTL(this.el) ? -1 : 1);
|
||||
this.centerCalendarGrid(workingMonth);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1461,16 +1482,24 @@ export class Datetime implements ComponentInterface {
|
||||
return;
|
||||
}
|
||||
|
||||
const nextMonth = calendarBodyRef.querySelector('.calendar-month:last-of-type');
|
||||
const nextMonth = calendarBodyRef.querySelector<HTMLElement>('.calendar-month:last-of-type');
|
||||
if (!nextMonth) {
|
||||
return;
|
||||
}
|
||||
|
||||
const left = (nextMonth as HTMLElement).offsetWidth * 2;
|
||||
const left = nextMonth.offsetWidth * 2;
|
||||
|
||||
if (!calendarBodyRef) return;
|
||||
|
||||
console.log('yay',left)
|
||||
|
||||
const monthRight = nextMonth.offsetLeft + nextMonth.offsetWidth;
|
||||
const elRight = this.el.offsetLeft + this.el.offsetWidth;
|
||||
const direction = monthRight > elRight ? 1 : -1;
|
||||
|
||||
calendarBodyRef.scrollTo({
|
||||
top: 0,
|
||||
left: left * (isRTL(this.el) ? -1 : 1),
|
||||
left: left * direction,
|
||||
behavior: 'smooth',
|
||||
});
|
||||
};
|
||||
@@ -2621,6 +2650,20 @@ export class Datetime implements ComponentInterface {
|
||||
}),
|
||||
}}
|
||||
>
|
||||
{/*
|
||||
WebKit has a quirk where IntersectionObserver callbacks are delayed until after
|
||||
an accelerated animation finishes if the "root" specified in the config is the
|
||||
browser viewport (the default behavior if "root" is not specified). This means
|
||||
that when presenting a datetime in a modal on iOS the calendar body appears
|
||||
blank until the modal animation finishes.
|
||||
|
||||
We can work around this by observing .intersection-tracker and using the host
|
||||
(ion-datetime) as the "root". This allows the IO callback to fire the moment
|
||||
the datetime is visible. The .intersection-tracker element should not have
|
||||
dimensions or additional styles, and it should not be positioned absolutely
|
||||
otherwise the IO callback may fire at unexpected times.
|
||||
*/}
|
||||
<div class="intersection-tracker" ref={(el) => (this.intersectionTrackerRef = el)}></div>
|
||||
{this.renderDatetime(mode)}
|
||||
</Host>
|
||||
);
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
<title>Datetime - Basic</title>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0" />
|
||||
<link href="../../../../../css/ionic.bundle.css" rel="stylesheet" />
|
||||
<link href="../../../../../css/palettes/dark.class.css" rel="stylesheet" />
|
||||
<link href="../../../../../scripts/testing/styles.css" rel="stylesheet" />
|
||||
<script src="../../../../../scripts/testing/scripts.js"></script>
|
||||
<script type="module" src="../../../../../dist/ionic/ionic.esm.js"></script>
|
||||
@@ -49,158 +50,6 @@
|
||||
ion-datetime {
|
||||
width: 350px;
|
||||
}
|
||||
|
||||
body.dark {
|
||||
--ion-color-primary: #428cff;
|
||||
--ion-color-primary-rgb: 66, 140, 255;
|
||||
--ion-color-primary-contrast: #ffffff;
|
||||
--ion-color-primary-contrast-rgb: 255, 255, 255;
|
||||
--ion-color-primary-shade: #3a7be0;
|
||||
--ion-color-primary-tint: #5598ff;
|
||||
|
||||
--ion-color-secondary: #50c8ff;
|
||||
--ion-color-secondary-rgb: 80, 200, 255;
|
||||
--ion-color-secondary-contrast: #ffffff;
|
||||
--ion-color-secondary-contrast-rgb: 255, 255, 255;
|
||||
--ion-color-secondary-shade: #46b0e0;
|
||||
--ion-color-secondary-tint: #62ceff;
|
||||
|
||||
--ion-color-tertiary: #6a64ff;
|
||||
--ion-color-tertiary-rgb: 106, 100, 255;
|
||||
--ion-color-tertiary-contrast: #ffffff;
|
||||
--ion-color-tertiary-contrast-rgb: 255, 255, 255;
|
||||
--ion-color-tertiary-shade: #5d58e0;
|
||||
--ion-color-tertiary-tint: #7974ff;
|
||||
|
||||
--ion-color-success: #2fdf75;
|
||||
--ion-color-success-rgb: 47, 223, 117;
|
||||
--ion-color-success-contrast: #000000;
|
||||
--ion-color-success-contrast-rgb: 0, 0, 0;
|
||||
--ion-color-success-shade: #29c467;
|
||||
--ion-color-success-tint: #44e283;
|
||||
|
||||
--ion-color-warning: #ffd534;
|
||||
--ion-color-warning-rgb: 255, 213, 52;
|
||||
--ion-color-warning-contrast: #000000;
|
||||
--ion-color-warning-contrast-rgb: 0, 0, 0;
|
||||
--ion-color-warning-shade: #e0bb2e;
|
||||
--ion-color-warning-tint: #ffd948;
|
||||
|
||||
--ion-color-danger: #ff4961;
|
||||
--ion-color-danger-rgb: 255, 73, 97;
|
||||
--ion-color-danger-contrast: #ffffff;
|
||||
--ion-color-danger-contrast-rgb: 255, 255, 255;
|
||||
--ion-color-danger-shade: #e04055;
|
||||
--ion-color-danger-tint: #ff5b71;
|
||||
|
||||
--ion-color-dark: #f4f5f8;
|
||||
--ion-color-dark-rgb: 244, 245, 248;
|
||||
--ion-color-dark-contrast: #000000;
|
||||
--ion-color-dark-contrast-rgb: 0, 0, 0;
|
||||
--ion-color-dark-shade: #d7d8da;
|
||||
--ion-color-dark-tint: #f5f6f9;
|
||||
|
||||
--ion-color-medium: #989aa2;
|
||||
--ion-color-medium-rgb: 152, 154, 162;
|
||||
--ion-color-medium-contrast: #000000;
|
||||
--ion-color-medium-contrast-rgb: 0, 0, 0;
|
||||
--ion-color-medium-shade: #86888f;
|
||||
--ion-color-medium-tint: #a2a4ab;
|
||||
|
||||
--ion-color-light: #222428;
|
||||
--ion-color-light-rgb: 34, 36, 40;
|
||||
--ion-color-light-contrast: #ffffff;
|
||||
--ion-color-light-contrast-rgb: 255, 255, 255;
|
||||
--ion-color-light-shade: #1e2023;
|
||||
--ion-color-light-tint: #383a3e;
|
||||
}
|
||||
|
||||
/*
|
||||
* iOS Dark Theme
|
||||
* -------------------------------------------
|
||||
*/
|
||||
|
||||
.ios body.dark {
|
||||
--ion-background-color: #000000;
|
||||
--ion-background-color-rgb: 0, 0, 0;
|
||||
|
||||
--ion-text-color: #ffffff;
|
||||
--ion-text-color-rgb: 255, 255, 255;
|
||||
|
||||
--ion-color-step-50: #0d0d0d;
|
||||
--ion-color-step-100: #1a1a1a;
|
||||
--ion-color-step-150: #262626;
|
||||
--ion-color-step-200: #333333;
|
||||
--ion-color-step-250: #404040;
|
||||
--ion-color-step-300: #4d4d4d;
|
||||
--ion-color-step-350: #595959;
|
||||
--ion-color-step-400: #666666;
|
||||
--ion-color-step-450: #737373;
|
||||
--ion-color-step-500: #808080;
|
||||
--ion-color-step-550: #8c8c8c;
|
||||
--ion-color-step-600: #999999;
|
||||
--ion-color-step-650: #a6a6a6;
|
||||
--ion-color-step-700: #b3b3b3;
|
||||
--ion-color-step-750: #bfbfbf;
|
||||
--ion-color-step-800: #cccccc;
|
||||
--ion-color-step-850: #d9d9d9;
|
||||
--ion-color-step-900: #e6e6e6;
|
||||
--ion-color-step-950: #f2f2f2;
|
||||
|
||||
--ion-item-background: #000000;
|
||||
|
||||
--ion-card-background: #1c1c1d;
|
||||
}
|
||||
|
||||
.ios body.dark ion-modal {
|
||||
--ion-background-color: var(--ion-color-step-100);
|
||||
--ion-toolbar-background: var(--ion-color-step-150);
|
||||
--ion-toolbar-border-color: var(--ion-color-step-250);
|
||||
--ion-item-background: var(--ion-color-step-150);
|
||||
}
|
||||
|
||||
/*
|
||||
* Material Design Dark Theme
|
||||
* -------------------------------------------
|
||||
*/
|
||||
|
||||
.md body.dark {
|
||||
--ion-background-color: #121212;
|
||||
--ion-background-color-rgb: 18, 18, 18;
|
||||
|
||||
--ion-text-color: #ffffff;
|
||||
--ion-text-color-rgb: 255, 255, 255;
|
||||
|
||||
--ion-border-color: #222222;
|
||||
|
||||
--ion-color-step-50: #1e1e1e;
|
||||
--ion-color-step-100: #2a2a2a;
|
||||
--ion-color-step-150: #363636;
|
||||
--ion-color-step-200: #414141;
|
||||
--ion-color-step-250: #4d4d4d;
|
||||
--ion-color-step-300: #595959;
|
||||
--ion-color-step-350: #656565;
|
||||
--ion-color-step-400: #717171;
|
||||
--ion-color-step-450: #7d7d7d;
|
||||
--ion-color-step-500: #898989;
|
||||
--ion-color-step-550: #949494;
|
||||
--ion-color-step-600: #a0a0a0;
|
||||
--ion-color-step-650: #acacac;
|
||||
--ion-color-step-700: #b8b8b8;
|
||||
--ion-color-step-750: #c4c4c4;
|
||||
--ion-color-step-800: #d0d0d0;
|
||||
--ion-color-step-850: #dbdbdb;
|
||||
--ion-color-step-900: #e7e7e7;
|
||||
--ion-color-step-950: #f3f3f3;
|
||||
|
||||
--ion-item-background: #1e1e1e;
|
||||
|
||||
--ion-toolbar-background: #1f1f1f;
|
||||
|
||||
--ion-tab-bar-background: #1f1f1f;
|
||||
|
||||
--ion-card-background: #1e1e1e;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
@@ -250,173 +99,12 @@
|
||||
</ion-toolbar>
|
||||
</ion-header>
|
||||
<ion-content class="ion-padding">
|
||||
<div class="grid">
|
||||
<div class="grid-item">
|
||||
<h2>Inline</h2>
|
||||
<ion-datetime value="2020-03-14T14:23:00.000Z" id="inline-datetime"></ion-datetime>
|
||||
</div>
|
||||
|
||||
<div class="grid-item">
|
||||
<h2>Inline - No Default Value</h2>
|
||||
<ion-datetime id="inline-datetime-no-value"></ion-datetime>
|
||||
</div>
|
||||
|
||||
<div class="grid-item">
|
||||
<h2>Popover</h2>
|
||||
<ion-button onclick="presentPopover(defaultPopover, event)">Present Popover</ion-button>
|
||||
<ion-popover class="datetime-popover" id="default-popover">
|
||||
<ion-datetime></ion-datetime>
|
||||
</ion-popover>
|
||||
</div>
|
||||
|
||||
<div class="grid-item">
|
||||
<h2>Modal</h2>
|
||||
<ion-button onclick="presentModal()">Present Modal</ion-button>
|
||||
</div>
|
||||
|
||||
<div class="grid-item">
|
||||
<h2>Inline - Custom</h2>
|
||||
<ion-datetime show-default-buttons="true" color="danger" id="custom-datetime" show-clear-button="true">
|
||||
<span slot="title">Select Date</span>
|
||||
</ion-datetime>
|
||||
</div>
|
||||
|
||||
<div class="grid-item">
|
||||
<h2>Popover - Custom</h2>
|
||||
<ion-button id="open-popover">Present Popover</ion-button>
|
||||
<ion-popover class="datetime-popover" trigger="open-popover" id="custom-popover">
|
||||
<ion-datetime>
|
||||
<span slot="title">My Custom Title</span>
|
||||
<ion-buttons slot="buttons">
|
||||
<ion-button color="danger">Destroy</ion-button>
|
||||
<ion-button color="primary">Confirm</ion-button>
|
||||
</ion-buttons>
|
||||
</ion-datetime>
|
||||
</ion-popover>
|
||||
</div>
|
||||
|
||||
<div class="grid-item">
|
||||
<h2>Modal - Custom</h2>
|
||||
<ion-button id="open-modal">Present Modal</ion-button>
|
||||
<ion-modal trigger="open-modal" id="modal">
|
||||
<ion-datetime>
|
||||
<span slot="title">My Custom Title</span>
|
||||
<ion-buttons slot="buttons">
|
||||
<ion-button color="danger">Destroy</ion-button>
|
||||
<ion-button color="primary">Confirm</ion-button>
|
||||
</ion-buttons>
|
||||
</ion-datetime>
|
||||
</ion-modal>
|
||||
</div>
|
||||
|
||||
<div class="grid-item">
|
||||
<h2>formatOptions</h2>
|
||||
<ion-datetime value="2020-03-14T14:23:00.000Z" id="format-options-datetime">
|
||||
<span slot="title">Select Date</span>
|
||||
</ion-datetime>
|
||||
</div>
|
||||
<ion-datetime></ion-datetime>
|
||||
<ion-datetime dir="rtl"></ion-datetime>
|
||||
<div dir="rtl">
|
||||
<ion-datetime></ion-datetime>
|
||||
</div>
|
||||
</ion-content>
|
||||
<script>
|
||||
const datetimes = document.querySelectorAll('ion-datetime');
|
||||
const color = document.querySelector('#color');
|
||||
const locale = document.querySelector('#locale');
|
||||
const datetime = document.querySelector('ion-datetime');
|
||||
const buttons = document.querySelectorAll('ion-button');
|
||||
const titleToggle = document.querySelector('#titleToggle');
|
||||
const buttonsToggle = document.querySelector('#buttonsToggle');
|
||||
|
||||
locale.addEventListener('ionBlur', (ev) => {
|
||||
const value = ev.target.value;
|
||||
datetimes.forEach((datetime) => {
|
||||
datetime.locale = !!value ? value : 'default';
|
||||
});
|
||||
});
|
||||
|
||||
const darkModeCheckbox = document.querySelector('ion-checkbox');
|
||||
darkModeCheckbox.addEventListener('ionChange', (ev) => {
|
||||
if (ev.detail.checked) {
|
||||
document.body.classList.add('dark');
|
||||
} else {
|
||||
document.body.classList.remove('dark');
|
||||
}
|
||||
});
|
||||
color.addEventListener('ionChange', (ev) => {
|
||||
datetime.color = ev.target.value;
|
||||
buttons.forEach((button) => {
|
||||
button.color = ev.target.value;
|
||||
});
|
||||
});
|
||||
|
||||
titleToggle.addEventListener('ionChange', (ev) => {
|
||||
datetimes.forEach((datetime) => {
|
||||
datetime.showDefaultTitle = ev.detail.checked;
|
||||
});
|
||||
});
|
||||
buttonsToggle.addEventListener('ionChange', (ev) => {
|
||||
datetimes.forEach((datetime) => {
|
||||
datetime.showDefaultButtons = ev.detail.checked;
|
||||
});
|
||||
});
|
||||
|
||||
datetimes.forEach((datetime) => {
|
||||
datetime.addEventListener('ionFocus', () => {
|
||||
console.log('Listen ionFocus: fired');
|
||||
});
|
||||
|
||||
datetime.addEventListener('ionBlur', () => {
|
||||
console.log('Listen ionBlur: fired');
|
||||
});
|
||||
});
|
||||
|
||||
const defaultPopover = document.querySelector('ion-popover#default-popover');
|
||||
const customPopover = document.querySelector('ion-popover#custom-popover');
|
||||
const presentPopover = (popover, ev) => {
|
||||
popover.event = ev;
|
||||
popover.showBackdrop = false;
|
||||
popover.isOpen = true;
|
||||
|
||||
const dismiss = () => {
|
||||
popover.isOpen = false;
|
||||
popover.event = undefined;
|
||||
|
||||
popover.removeEventListener('didDismiss', dismiss);
|
||||
};
|
||||
|
||||
popover.addEventListener('didDismiss', dismiss);
|
||||
};
|
||||
|
||||
const presentModal = async () => {
|
||||
const modal = await createModal();
|
||||
|
||||
await modal.present();
|
||||
};
|
||||
|
||||
const createModal = () => {
|
||||
// create component to open
|
||||
const element = document.createElement('div');
|
||||
element.innerHTML = `
|
||||
<ion-datetime show-default-buttons="true" color="danger">
|
||||
<span slot="title">Select Date</span>
|
||||
</ion-datetime>
|
||||
`;
|
||||
|
||||
// present the modal
|
||||
const modalElement = Object.assign(document.createElement('ion-modal'), {
|
||||
component: element,
|
||||
});
|
||||
|
||||
const app = document.querySelector('ion-app');
|
||||
app.appendChild(modalElement);
|
||||
return modalElement;
|
||||
};
|
||||
|
||||
const formatOptions = document.querySelector('#format-options-datetime');
|
||||
formatOptions.formatOptions = {
|
||||
time: { hour: '2-digit', minute: '2-digit' },
|
||||
date: { day: '2-digit', month: 'long', era: 'short' },
|
||||
};
|
||||
</script>
|
||||
</ion-app>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -4,19 +4,28 @@ import { configs, test } from '@utils/test/playwright';
|
||||
/**
|
||||
* This behavior does not vary across directions
|
||||
*/
|
||||
configs({ directions: ['ltr'] }).forEach(({ title, screenshot, config }) => {
|
||||
configs({ directions: ['ltr'], palettes: ['light', 'dark'] }).forEach(({ title, screenshot, config }) => {
|
||||
test.describe(title('datetime: color'), () => {
|
||||
test('should not have visual regressions', async ({ page }) => {
|
||||
await page.goto('/src/components/datetime/test/color', config);
|
||||
await page.setContent(
|
||||
`
|
||||
<div id="container" style="width: 250px;">
|
||||
<ion-datetime
|
||||
color="danger"
|
||||
value="2022-05-03"
|
||||
show-default-title="true"
|
||||
show-default-buttons="true"
|
||||
></ion-datetime>
|
||||
</div>
|
||||
`,
|
||||
config
|
||||
);
|
||||
|
||||
const datetime = page.locator('#color-datetime');
|
||||
const container = page.locator('#container');
|
||||
|
||||
await expect(datetime).toHaveScreenshot(screenshot(`datetime-color`));
|
||||
await page.locator('.datetime-ready').waitFor();
|
||||
|
||||
await page.evaluate(() => document.body.classList.toggle('dark'));
|
||||
await page.waitForChanges();
|
||||
|
||||
await expect(datetime).toHaveScreenshot(screenshot(`datetime-color-dark`));
|
||||
await expect(container).toHaveScreenshot(screenshot(`datetime-color`));
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
|
Before Width: | Height: | Size: 23 KiB |
|
Before Width: | Height: | Size: 27 KiB |
|
Before Width: | Height: | Size: 21 KiB |
|
Before Width: | Height: | Size: 21 KiB |
|
Before Width: | Height: | Size: 24 KiB |