Compare commits

..

7 Commits

Author SHA1 Message Date
Liam DeBeasi
12cae824b1 typo 2023-09-14 09:36:14 -04:00
Liam DeBeasi
504c90beae update types 2023-09-14 09:33:28 -04:00
Liam DeBeasi
f663b41644 add types 2023-09-13 17:12:47 -04:00
Liam DeBeasi
1a99036fd1 fix(scroll-assist): run when keyboard dimension changes 2023-09-13 16:58:39 -04:00
Liam DeBeasi
578981b2d0 fix(scroll-assist): improve input scroll accuracy 2023-09-12 16:00:53 -04:00
dependabot[bot]
875091b9ad chore(deps): Bump @stencil/core from 4.2.0 to 4.2.1 in /core (#28157)
Bumps [@stencil/core](https://github.com/ionic-team/stencil) from 4.2.0
to 4.2.1.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/ionic-team/stencil/releases"><code>@​stencil/core</code>'s
releases</a>.</em></p>
<blockquote>
<h2>😀  v4.2.1 (2023-09-11)</h2>
<h3>Bug Fixes</h3>
<ul>
<li><strong>compiler:</strong> add heritage clauses earlier in native
transform (<a
href="https://redirect.github.com/ionic-team/stencil/issues/4769">#4769</a>)
(<a
href="9a92ad12f6">9a92ad1</a>)</li>
</ul>
</blockquote>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/ionic-team/stencil/blob/main/CHANGELOG.md"><code>@​stencil/core</code>'s
changelog</a>.</em></p>
<blockquote>
<h2>🌝 <a
href="https://github.com/ionic-team/stencil/compare/v4.2.0...v4.2.1">4.2.1</a>
(2023-09-11)</h2>
<h3>Bug Fixes</h3>
<ul>
<li><strong>compiler:</strong> add heritage clauses earlier in native
transform (<a
href="https://redirect.github.com/ionic-team/stencil/issues/4769">#4769</a>)
(<a
href="9a92ad12f6">9a92ad1</a>)</li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="29fa4b38c4"><code>29fa4b3</code></a>
v4.2.1 (<a
href="https://redirect.github.com/ionic-team/stencil/issues/4780">#4780</a>)</li>
<li><a
href="9a92ad12f6"><code>9a92ad1</code></a>
fix(compiler): add heritage clauses earlier in native transform (<a
href="https://redirect.github.com/ionic-team/stencil/issues/4769">#4769</a>)</li>
<li><a
href="9ee02c518f"><code>9ee02c5</code></a>
chore(deps): update typescript-eslint to v6.6.0 (<a
href="https://redirect.github.com/ionic-team/stencil/issues/4777">#4777</a>)</li>
<li><a
href="9229a62033"><code>9229a62</code></a>
chore(deps): update actions/upload-artifact action to v3.1.3 (<a
href="https://redirect.github.com/ionic-team/stencil/issues/4773">#4773</a>)</li>
<li><a
href="25fcaa9e8e"><code>25fcaa9</code></a>
chore(deps): update dependency terser to v5.19.4 (<a
href="https://redirect.github.com/ionic-team/stencil/issues/4774">#4774</a>)</li>
<li><a
href="81a1e2c67c"><code>81a1e2c</code></a>
chore(deps): update node.js to v20.6.0 (<a
href="https://redirect.github.com/ionic-team/stencil/issues/4776">#4776</a>)</li>
<li><a
href="f4724f6341"><code>f4724f6</code></a>
chore(deps): update actions/checkout action to v4 (<a
href="https://redirect.github.com/ionic-team/stencil/issues/4778">#4778</a>)</li>
<li><a
href="a1ab21bdeb"><code>a1ab21b</code></a>
chore(deps): update dependency npm to v10 (<a
href="https://redirect.github.com/ionic-team/stencil/issues/4766">#4766</a>)</li>
<li><a
href="dd1fe1d0b0"><code>dd1fe1d</code></a>
chore(deps): update node.js to v20.5.1 (<a
href="https://redirect.github.com/ionic-team/stencil/issues/4607">#4607</a>)</li>
<li><a
href="4d8ff00915"><code>4d8ff00</code></a>
refactor(compiler): use updateConstructor in lazy transform (<a
href="https://redirect.github.com/ionic-team/stencil/issues/4768">#4768</a>)</li>
<li>Additional commits viewable in <a
href="https://github.com/ionic-team/stencil/compare/v4.2.0...v4.2.1">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=@stencil/core&package-manager=npm_and_yarn&previous-version=4.2.0&new-version=4.2.1)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot merge` will merge this PR after your CI passes on it
- `@dependabot squash and merge` will squash and merge this PR after
your CI passes on it
- `@dependabot cancel merge` will cancel a previously requested merge
and block automerging
- `@dependabot reopen` will reopen this PR if it is closed
- `@dependabot close` will close this PR and stop Dependabot recreating
it. You can achieve the same result by closing it manually
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)


</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-09-12 14:42:53 +00:00
dependabot[bot]
c782c91185 chore(deps-dev): Bump @stencil/angular-output-target from 0.7.1 to 0.8.2 in /core (#28149)
Bumps
[@stencil/angular-output-target](https://github.com/ionic-team/stencil-ds-output-targets)
from 0.7.1 to 0.8.2.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/ionic-team/stencil-ds-output-targets/releases"><code>@​stencil/angular-output-target</code>'s
releases</a>.</em></p>
<blockquote>
<h2><code>@​stencil/angular-output-target</code><a
href="https://github.com/0"><code>@​0</code></a>.8.2</h2>
<h2>What's Changed</h2>
<ul>
<li>fix(angular-output-target): rewrite nested generics for custom
events by <a
href="https://github.com/sean-perkins"><code>@​sean-perkins</code></a>
in <a
href="https://redirect.github.com/ionic-team/stencil-ds-output-targets/pull/371">ionic-team/stencil-ds-output-targets#371</a></li>
</ul>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/ionic-team/stencil-ds-output-targets/compare/@stencil/angular-output-target@0.8.1...@stencil/angular-output-target@0.8.2">https://github.com/ionic-team/stencil-ds-output-targets/compare/<code>@​stencil/angular-output-target</code><code>@​0.8.1...</code><code>@​stencil/angular-output-target</code><code>@​0.8.2</code></a></p>
<h2><code>@​stencil/angular-output-target</code><a
href="https://github.com/0"><code>@​0</code></a>.8.1</h2>
<h2>What's Changed</h2>
<ul>
<li>fix(angular-output-target): multiple targets do not overwrite each
other by <a
href="https://github.com/sean-perkins"><code>@​sean-perkins</code></a>
in <a
href="https://redirect.github.com/ionic-team/stencil-ds-output-targets/pull/376">ionic-team/stencil-ds-output-targets#376</a></li>
</ul>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/ionic-team/stencil-ds-output-targets/compare/@stencil/angular-output-target@0.8.0...@stencil/angular-output-target@0.8.1">https://github.com/ionic-team/stencil-ds-output-targets/compare/<code>@​stencil/angular-output-target</code><code>@​0.8.0...</code><code>@​stencil/angular-output-target</code><code>@​0.8.1</code></a></p>
<h2><code>@​stencil/angular-output-target</code><a
href="https://github.com/0"><code>@​0</code></a>.8.0</h2>
<h2>What's Changed</h2>
<ul>
<li>feat(angular-output-target): generate standalone components by <a
href="https://github.com/sean-perkins"><code>@​sean-perkins</code></a>
in <a
href="https://redirect.github.com/ionic-team/stencil-ds-output-targets/pull/367">ionic-team/stencil-ds-output-targets#367</a></li>
</ul>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/ionic-team/stencil-ds-output-targets/compare/@stencil/angular-output-target@0.7.1...@stencil/angular-output-target@0.8.0">https://github.com/ionic-team/stencil-ds-output-targets/compare/<code>@​stencil/angular-output-target</code><code>@​0.7.1...</code><code>@​stencil/angular-output-target</code><code>@​0.8.0</code></a></p>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="afe862ef60"><code>afe862e</code></a>
chore(angular-output-target): manually bumping the package version (<a
href="https://redirect.github.com/ionic-team/stencil-ds-output-targets/issues/387">#387</a>)</li>
<li><a
href="126dc39e5b"><code>126dc39</code></a>
fix(angular-output-target): rewrite nested generics for custom events
(<a
href="https://redirect.github.com/ionic-team/stencil-ds-output-targets/issues/372">#372</a>)</li>
<li><a
href="d37ebd7955"><code>d37ebd7</code></a>
chore(deps): update actions/checkout action to v4 (<a
href="https://redirect.github.com/ionic-team/stencil-ds-output-targets/issues/386">#386</a>)</li>
<li><a
href="7dabd06b2d"><code>7dabd06</code></a>
chore(deps): update actions/checkout action to v3.6.0 (<a
href="https://redirect.github.com/ionic-team/stencil-ds-output-targets/issues/384">#384</a>)</li>
<li><a
href="0b022bc2ef"><code>0b022bc</code></a>
chore(deps): update actions/setup-node action to v3.8.1 (<a
href="https://redirect.github.com/ionic-team/stencil-ds-output-targets/issues/380">#380</a>)</li>
<li><a
href="c23bbfbbca"><code>c23bbfb</code></a>
chore(angular-output-target): manually bumping the package version (<a
href="https://redirect.github.com/ionic-team/stencil-ds-output-targets/issues/377">#377</a>)</li>
<li><a
href="3c6a3252c7"><code>3c6a325</code></a>
fix(angular-output-target): multiple targets do not overwrite each other
(<a
href="https://redirect.github.com/ionic-team/stencil-ds-output-targets/issues/376">#376</a>)</li>
<li><a
href="2de5d649c3"><code>2de5d64</code></a>
chore(deps): update actions/setup-node action to v3.8.0 (<a
href="https://redirect.github.com/ionic-team/stencil-ds-output-targets/issues/375">#375</a>)</li>
<li><a
href="ae79bf7651"><code>ae79bf7</code></a>
chore(angular-output-target): manually bumping the package version (<a
href="https://redirect.github.com/ionic-team/stencil-ds-output-targets/issues/373">#373</a>)</li>
<li><a
href="01c9c09819"><code>01c9c09</code></a>
chore: publish-npm workflow uses local lerna version (<a
href="https://redirect.github.com/ionic-team/stencil-ds-output-targets/issues/371">#371</a>)</li>
<li>Additional commits viewable in <a
href="https://github.com/ionic-team/stencil-ds-output-targets/compare/@stencil/angular-output-target@0.7.1...@stencil/angular-output-target@0.8.2">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=@stencil/angular-output-target&package-manager=npm_and_yarn&previous-version=0.7.1&new-version=0.8.2)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot merge` will merge this PR after your CI passes on it
- `@dependabot squash and merge` will squash and merge this PR after
your CI passes on it
- `@dependabot cancel merge` will cancel a previously requested merge
and block automerging
- `@dependabot reopen` will reopen this PR if it is closed
- `@dependabot close` will close this PR and stop Dependabot recreating
it. You can achieve the same result by closing it manually
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)


</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-09-11 13:05:03 +00:00
343 changed files with 461 additions and 1252 deletions

View File

@@ -289,13 +289,12 @@ ion-card-title,prop,mode,"ios" | "md",undefined,false,false
ion-card-title,css-prop,--color
ion-checkbox,shadow
ion-checkbox,prop,alignment,"center" | "start",'center',false,false
ion-checkbox,prop,checked,boolean,false,false,false
ion-checkbox,prop,color,"danger" | "dark" | "light" | "medium" | "primary" | "secondary" | "success" | "tertiary" | "warning" | string & Record<never, never> | undefined,undefined,false,true
ion-checkbox,prop,disabled,boolean,false,false,false
ion-checkbox,prop,indeterminate,boolean,false,false,false
ion-checkbox,prop,justify,"end" | "space-between" | "start",'space-between',false,false
ion-checkbox,prop,labelPlacement,"end" | "fixed" | "stacked" | "start",'start',false,false
ion-checkbox,prop,labelPlacement,"end" | "fixed" | "start",'start',false,false
ion-checkbox,prop,legacy,boolean | undefined,undefined,false,false
ion-checkbox,prop,mode,"ios" | "md",undefined,false,false
ion-checkbox,prop,name,string,this.inputId,false,false
@@ -428,10 +427,6 @@ ion-datetime,css-prop,--background-rgb
ion-datetime,css-prop,--title-color
ion-datetime,css-prop,--wheel-fade-background-rgb
ion-datetime,css-prop,--wheel-highlight-background
ion-datetime,part,calendar-day
ion-datetime,part,calendar-day active
ion-datetime,part,calendar-day disabled
ion-datetime,part,calendar-day today
ion-datetime,part,month-year-button
ion-datetime,part,time-button
ion-datetime,part,time-button active
@@ -1013,11 +1008,10 @@ ion-progress-bar,part,stream
ion-progress-bar,part,track
ion-radio,shadow
ion-radio,prop,alignment,"center" | "start",'center',false,false
ion-radio,prop,color,"danger" | "dark" | "light" | "medium" | "primary" | "secondary" | "success" | "tertiary" | "warning" | string & Record<never, never> | undefined,undefined,false,true
ion-radio,prop,disabled,boolean,false,false,false
ion-radio,prop,justify,"end" | "space-between" | "start",'space-between',false,false
ion-radio,prop,labelPlacement,"end" | "fixed" | "stacked" | "start",'start',false,false
ion-radio,prop,labelPlacement,"end" | "fixed" | "start",'start',false,false
ion-radio,prop,legacy,boolean | undefined,undefined,false,false
ion-radio,prop,mode,"ios" | "md",undefined,false,false
ion-radio,prop,name,string,this.inputId,false,false
@@ -1044,7 +1038,7 @@ ion-range,prop,debounce,number | undefined,undefined,false,false
ion-range,prop,disabled,boolean,false,false,false
ion-range,prop,dualKnobs,boolean,false,false,false
ion-range,prop,label,string | undefined,undefined,false,false
ion-range,prop,labelPlacement,"end" | "fixed" | "stacked" | "start",'start',false,false
ion-range,prop,labelPlacement,"end" | "fixed" | "start",'start',false,false
ion-range,prop,legacy,boolean | undefined,undefined,false,false
ion-range,prop,max,number,100,false,false
ion-range,prop,min,number,0,false,false
@@ -1484,13 +1478,12 @@ ion-toast,part,icon
ion-toast,part,message
ion-toggle,shadow
ion-toggle,prop,alignment,"center" | "start",'center',false,false
ion-toggle,prop,checked,boolean,false,false,false
ion-toggle,prop,color,"danger" | "dark" | "light" | "medium" | "primary" | "secondary" | "success" | "tertiary" | "warning" | string & Record<never, never> | undefined,undefined,false,true
ion-toggle,prop,disabled,boolean,false,false,false
ion-toggle,prop,enableOnOffLabels,boolean | undefined,config.get('toggleOnOffLabels'),false,false
ion-toggle,prop,justify,"end" | "space-between" | "start",'space-between',false,false
ion-toggle,prop,labelPlacement,"end" | "fixed" | "stacked" | "start",'start',false,false
ion-toggle,prop,labelPlacement,"end" | "fixed" | "start",'start',false,false
ion-toggle,prop,legacy,boolean | undefined,undefined,false,false
ion-toggle,prop,mode,"ios" | "md",undefined,false,false
ion-toggle,prop,name,string,this.inputId,false,false

28
core/package-lock.json generated
View File

@@ -9,7 +9,7 @@
"version": "7.3.3",
"license": "MIT",
"dependencies": {
"@stencil/core": "^4.2.0",
"@stencil/core": "^4.2.1",
"ionicons": "7.1.0",
"tslib": "^2.1.0"
},
@@ -25,7 +25,7 @@
"@playwright/test": "^1.37.1",
"@rollup/plugin-node-resolve": "^8.4.0",
"@rollup/plugin-virtual": "^2.0.3",
"@stencil/angular-output-target": "^0.7.1",
"@stencil/angular-output-target": "^0.8.2",
"@stencil/react-output-target": "^0.5.3",
"@stencil/sass": "^3.0.5",
"@stencil/vue-output-target": "^0.8.6",
@@ -1625,18 +1625,18 @@
}
},
"node_modules/@stencil/angular-output-target": {
"version": "0.7.1",
"resolved": "https://registry.npmjs.org/@stencil/angular-output-target/-/angular-output-target-0.7.1.tgz",
"integrity": "sha512-lxJbCAbyAQVAKGgEpNTjSF7GZZszbrJnNdNVgzuD1hLRFJyElA6kUSL0GQrZMbiPG5lC/cYdbQwpyWHX4xN8mw==",
"version": "0.8.2",
"resolved": "https://registry.npmjs.org/@stencil/angular-output-target/-/angular-output-target-0.8.2.tgz",
"integrity": "sha512-i2Oxq2VPQTo1OoP3iDN39N2f/CDO9crS8oUfGEtjwzMgMNuYSMB2VprFoVDUTwqaCP6N409M8+/wJK3oApTDuQ==",
"dev": true,
"peerDependencies": {
"@stencil/core": ">=2.0.0 || >=3 || >= 4.0.0-beta.0 || >= 4.0.0"
}
},
"node_modules/@stencil/core": {
"version": "4.2.0",
"resolved": "https://registry.npmjs.org/@stencil/core/-/core-4.2.0.tgz",
"integrity": "sha512-HhxRs/b/VHTCM35lunFCzYajRQeYezsJQGgalENNpkrKUOPMvzv0dalXe8Yn/8p9eyn+GZVZuWLd0CAR4VWBbA==",
"version": "4.2.1",
"resolved": "https://registry.npmjs.org/@stencil/core/-/core-4.2.1.tgz",
"integrity": "sha512-alYwqVwxfD0n6HKRVJqJoTzQNnf44n/sddvjNu3JMEn3sfY/Ag7rpmwUntYjtJmRut+or+9gPPgIJviCuKi4yQ==",
"bin": {
"stencil": "bin/stencil"
},
@@ -11517,16 +11517,16 @@
}
},
"@stencil/angular-output-target": {
"version": "0.7.1",
"resolved": "https://registry.npmjs.org/@stencil/angular-output-target/-/angular-output-target-0.7.1.tgz",
"integrity": "sha512-lxJbCAbyAQVAKGgEpNTjSF7GZZszbrJnNdNVgzuD1hLRFJyElA6kUSL0GQrZMbiPG5lC/cYdbQwpyWHX4xN8mw==",
"version": "0.8.2",
"resolved": "https://registry.npmjs.org/@stencil/angular-output-target/-/angular-output-target-0.8.2.tgz",
"integrity": "sha512-i2Oxq2VPQTo1OoP3iDN39N2f/CDO9crS8oUfGEtjwzMgMNuYSMB2VprFoVDUTwqaCP6N409M8+/wJK3oApTDuQ==",
"dev": true,
"requires": {}
},
"@stencil/core": {
"version": "4.2.0",
"resolved": "https://registry.npmjs.org/@stencil/core/-/core-4.2.0.tgz",
"integrity": "sha512-HhxRs/b/VHTCM35lunFCzYajRQeYezsJQGgalENNpkrKUOPMvzv0dalXe8Yn/8p9eyn+GZVZuWLd0CAR4VWBbA=="
"version": "4.2.1",
"resolved": "https://registry.npmjs.org/@stencil/core/-/core-4.2.1.tgz",
"integrity": "sha512-alYwqVwxfD0n6HKRVJqJoTzQNnf44n/sddvjNu3JMEn3sfY/Ag7rpmwUntYjtJmRut+or+9gPPgIJviCuKi4yQ=="
},
"@stencil/react-output-target": {
"version": "0.5.3",

View File

@@ -31,7 +31,7 @@
"loader/"
],
"dependencies": {
"@stencil/core": "^4.2.0",
"@stencil/core": "^4.2.1",
"ionicons": "7.1.0",
"tslib": "^2.1.0"
},
@@ -47,7 +47,7 @@
"@playwright/test": "^1.37.1",
"@rollup/plugin-node-resolve": "^8.4.0",
"@rollup/plugin-virtual": "^2.0.3",
"@stencil/angular-output-target": "^0.7.1",
"@stencil/angular-output-target": "^0.8.2",
"@stencil/react-output-target": "^0.5.3",
"@stencil/sass": "^3.0.5",
"@stencil/vue-output-target": "^0.8.6",

View File

@@ -602,10 +602,6 @@ export namespace Components {
"mode"?: "ios" | "md";
}
interface IonCheckbox {
/**
* How to control the alignment of the checkbox 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';
/**
* If `true`, the checkbox is selected.
*/
@@ -627,9 +623,9 @@ export namespace Components {
*/
"justify": 'start' | 'end' | 'space-between';
/**
* Where to place the label relative to the checkbox. `"start"`: The label will appear to the left of the checkbox in LTR and to the right in RTL. `"end"`: The label will appear to the right of the checkbox in LTR and to the left in RTL. `"fixed"`: The label has the same behavior as `"start"` except it also has a fixed width. Long text will be truncated with ellipses ("..."). `"stacked"`: The label will appear above the checkbox regardless of the direction. The alignment of the label can be controlled with the `alignment` property.
* Where to place the label relative to the checkbox. `"start"`: The label will appear to the left of the checkbox in LTR and to the right in RTL. `"end"`: The label will appear to the right of the checkbox in LTR and to the left in RTL. `"fixed"`: The label has the same behavior as `"start"` except it also has a fixed width. Long text will be truncated with ellipses ("...").
*/
"labelPlacement": 'start' | 'end' | 'fixed' | 'stacked';
"labelPlacement": 'start' | 'end' | 'fixed';
/**
* Set the `legacy` property to `true` to forcibly use the legacy form control markup. Ionic will only opt checkboxes in to the modern form markup when they are using either the `aria-label` attribute or have text in the default slot. As a result, the `legacy` property should only be used as an escape hatch when you want to avoid this automatic opt-in behavior. Note that this property will be removed in an upcoming major release of Ionic, and all form components will be opted-in to using the modern form markup.
*/
@@ -2220,10 +2216,6 @@ export namespace Components {
"value": number;
}
interface IonRadio {
/**
* How to control the alignment of the radio 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';
/**
* 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).
*/
@@ -2237,9 +2229,9 @@ export namespace Components {
*/
"justify": 'start' | 'end' | 'space-between';
/**
* Where to place the label relative to the radio. `"start"`: The label will appear to the left of the radio in LTR and to the right in RTL. `"end"`: The label will appear to the right of the radio in LTR and to the left in RTL. `"fixed"`: The label has the same behavior as `"start"` except it also has a fixed width. Long text will be truncated with ellipses ("..."). `"stacked"`: The label will appear above the radio regardless of the direction. The alignment of the label can be controlled with the `alignment` property.
* Where to place the label relative to the radio. `"start"`: The label will appear to the left of the radio in LTR and to the right in RTL. `"end"`: The label will appear to the right of the radio in LTR and to the left in RTL. `"fixed"`: The label has the same behavior as `"start"` except it also has a fixed width. Long text will be truncated with ellipses ("...").
*/
"labelPlacement": 'start' | 'end' | 'fixed' | 'stacked';
"labelPlacement": 'start' | 'end' | 'fixed';
/**
* Set the `legacy` property to `true` to forcibly use the legacy form control markup. Ionic will only opt components in to the modern form markup when they are using either the `aria-label` attribute or the default slot that contains the label text. As a result, the `legacy` property should only be used as an escape hatch when you want to avoid this automatic opt-in behavior. Note that this property will be removed in an upcoming major release of Ionic, and all form components will be opted-in to using the modern form markup.
*/
@@ -2299,9 +2291,9 @@ export namespace Components {
*/
"label"?: string;
/**
* Where to place the label relative to the range. `"start"`: The label will appear to the left of the range in LTR and to the right in RTL. `"end"`: The label will appear to the right of the range in LTR and to the left in RTL. `"fixed"`: The label has the same behavior as `"start"` except it also has a fixed width. Long text will be truncated with ellipses ("..."). `"stacked"`: The label will appear above the range regardless of the direction.
* Where to place the label relative to the range. `"start"`: The label will appear to the left of the range in LTR and to the right in RTL. `"end"`: The label will appear to the right of the range in LTR and to the left in RTL. `"fixed"`: The label has the same behavior as `"start"` except it also has a fixed width. Long text will be truncated with ellipses ("...").
*/
"labelPlacement": 'start' | 'end' | 'fixed' | 'stacked';
"labelPlacement": 'start' | 'end' | 'fixed';
/**
* Set the `legacy` property to `true` to forcibly use the legacy form control markup. Ionic will only opt components in to the modern form markup when they are using either the `aria-label` attribute or the `label` property. As a result, the `legacy` property should only be used as an escape hatch when you want to avoid this automatic opt-in behavior. Note that this property will be removed in an upcoming major release of Ionic, and all form components will be opted-in to using the modern form markup.
*/
@@ -3173,10 +3165,6 @@ export namespace Components {
"trigger": string | undefined;
}
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.
*/
"alignment": 'start' | 'center';
/**
* If `true`, the toggle is selected.
*/
@@ -3198,9 +3186,9 @@ export namespace Components {
*/
"justify": 'start' | 'end' | 'space-between';
/**
* Where to place the label relative to the input. `"start"`: The label will appear to the left of the toggle in LTR and to the right in RTL. `"end"`: The label will appear to the right of the toggle in LTR and to the left in RTL. `"fixed"`: The label has the same behavior as `"start"` except it also has a fixed width. Long text will be truncated with ellipses ("..."). `"stacked"`: The label will appear above the toggle regardless of the direction. The alignment of the label can be controlled with the `alignment` property.
* Where to place the label relative to the input. `"start"`: The label will appear to the left of the toggle in LTR and to the right in RTL. `"end"`: The label will appear to the right of the toggle in LTR and to the left in RTL. `"fixed"`: The label has the same behavior as `"start"` except it also has a fixed width. Long text will be truncated with ellipses ("...").
*/
"labelPlacement": 'start' | 'end' | 'fixed' | 'stacked';
"labelPlacement": 'start' | 'end' | 'fixed';
/**
* Set the `legacy` property to `true` to forcibly use the legacy form control markup. Ionic will only opt components in to the modern form markup when they are using either the `aria-label` attribute or the default slot that contains the label text. As a result, the `legacy` property should only be used as an escape hatch when you want to avoid this automatic opt-in behavior. Note that this property will be removed in an upcoming major release of Ionic, and all form components will be opted-in to using the modern form markup.
*/
@@ -4637,10 +4625,6 @@ declare namespace LocalJSX {
"mode"?: "ios" | "md";
}
interface IonCheckbox {
/**
* How to control the alignment of the checkbox 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';
/**
* If `true`, the checkbox is selected.
*/
@@ -4662,9 +4646,9 @@ declare namespace LocalJSX {
*/
"justify"?: 'start' | 'end' | 'space-between';
/**
* Where to place the label relative to the checkbox. `"start"`: The label will appear to the left of the checkbox in LTR and to the right in RTL. `"end"`: The label will appear to the right of the checkbox in LTR and to the left in RTL. `"fixed"`: The label has the same behavior as `"start"` except it also has a fixed width. Long text will be truncated with ellipses ("..."). `"stacked"`: The label will appear above the checkbox regardless of the direction. The alignment of the label can be controlled with the `alignment` property.
* Where to place the label relative to the checkbox. `"start"`: The label will appear to the left of the checkbox in LTR and to the right in RTL. `"end"`: The label will appear to the right of the checkbox in LTR and to the left in RTL. `"fixed"`: The label has the same behavior as `"start"` except it also has a fixed width. Long text will be truncated with ellipses ("...").
*/
"labelPlacement"?: 'start' | 'end' | 'fixed' | 'stacked';
"labelPlacement"?: 'start' | 'end' | 'fixed';
/**
* Set the `legacy` property to `true` to forcibly use the legacy form control markup. Ionic will only opt checkboxes in to the modern form markup when they are using either the `aria-label` attribute or have text in the default slot. As a result, the `legacy` property should only be used as an escape hatch when you want to avoid this automatic opt-in behavior. Note that this property will be removed in an upcoming major release of Ionic, and all form components will be opted-in to using the modern form markup.
*/
@@ -6242,10 +6226,6 @@ declare namespace LocalJSX {
"value"?: number;
}
interface IonRadio {
/**
* How to control the alignment of the radio 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';
/**
* 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).
*/
@@ -6259,9 +6239,9 @@ declare namespace LocalJSX {
*/
"justify"?: 'start' | 'end' | 'space-between';
/**
* Where to place the label relative to the radio. `"start"`: The label will appear to the left of the radio in LTR and to the right in RTL. `"end"`: The label will appear to the right of the radio in LTR and to the left in RTL. `"fixed"`: The label has the same behavior as `"start"` except it also has a fixed width. Long text will be truncated with ellipses ("..."). `"stacked"`: The label will appear above the radio regardless of the direction. The alignment of the label can be controlled with the `alignment` property.
* Where to place the label relative to the radio. `"start"`: The label will appear to the left of the radio in LTR and to the right in RTL. `"end"`: The label will appear to the right of the radio in LTR and to the left in RTL. `"fixed"`: The label has the same behavior as `"start"` except it also has a fixed width. Long text will be truncated with ellipses ("...").
*/
"labelPlacement"?: 'start' | 'end' | 'fixed' | 'stacked';
"labelPlacement"?: 'start' | 'end' | 'fixed';
/**
* Set the `legacy` property to `true` to forcibly use the legacy form control markup. Ionic will only opt components in to the modern form markup when they are using either the `aria-label` attribute or the default slot that contains the label text. As a result, the `legacy` property should only be used as an escape hatch when you want to avoid this automatic opt-in behavior. Note that this property will be removed in an upcoming major release of Ionic, and all form components will be opted-in to using the modern form markup.
*/
@@ -6339,9 +6319,9 @@ declare namespace LocalJSX {
*/
"label"?: string;
/**
* Where to place the label relative to the range. `"start"`: The label will appear to the left of the range in LTR and to the right in RTL. `"end"`: The label will appear to the right of the range in LTR and to the left in RTL. `"fixed"`: The label has the same behavior as `"start"` except it also has a fixed width. Long text will be truncated with ellipses ("..."). `"stacked"`: The label will appear above the range regardless of the direction.
* Where to place the label relative to the range. `"start"`: The label will appear to the left of the range in LTR and to the right in RTL. `"end"`: The label will appear to the right of the range in LTR and to the left in RTL. `"fixed"`: The label has the same behavior as `"start"` except it also has a fixed width. Long text will be truncated with ellipses ("...").
*/
"labelPlacement"?: 'start' | 'end' | 'fixed' | 'stacked';
"labelPlacement"?: 'start' | 'end' | 'fixed';
/**
* Set the `legacy` property to `true` to forcibly use the legacy form control markup. Ionic will only opt components in to the modern form markup when they are using either the `aria-label` attribute or the `label` property. As a result, the `legacy` property should only be used as an escape hatch when you want to avoid this automatic opt-in behavior. Note that this property will be removed in an upcoming major release of Ionic, and all form components will be opted-in to using the modern form markup.
*/
@@ -7318,10 +7298,6 @@ declare namespace LocalJSX {
"trigger"?: string | undefined;
}
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.
*/
"alignment"?: 'start' | 'center';
/**
* If `true`, the toggle is selected.
*/
@@ -7343,9 +7319,9 @@ declare namespace LocalJSX {
*/
"justify"?: 'start' | 'end' | 'space-between';
/**
* Where to place the label relative to the input. `"start"`: The label will appear to the left of the toggle in LTR and to the right in RTL. `"end"`: The label will appear to the right of the toggle in LTR and to the left in RTL. `"fixed"`: The label has the same behavior as `"start"` except it also has a fixed width. Long text will be truncated with ellipses ("..."). `"stacked"`: The label will appear above the toggle regardless of the direction. The alignment of the label can be controlled with the `alignment` property.
* Where to place the label relative to the input. `"start"`: The label will appear to the left of the toggle in LTR and to the right in RTL. `"end"`: The label will appear to the right of the toggle in LTR and to the left in RTL. `"fixed"`: The label has the same behavior as `"start"` except it also has a fixed width. Long text will be truncated with ellipses ("...").
*/
"labelPlacement"?: 'start' | 'end' | 'fixed' | 'stacked';
"labelPlacement"?: 'start' | 'end' | 'fixed';
/**
* Set the `legacy` property to `true` to forcibly use the legacy form control markup. Ionic will only opt components in to the modern form markup when they are using either the `aria-label` attribute or the default slot that contains the label text. As a result, the `legacy` property should only be used as an escape hatch when you want to avoid this automatic opt-in behavior. Note that this property will be removed in an upcoming major release of Ionic, and all form components will be opted-in to using the modern form markup.
*/

View File

@@ -108,14 +108,6 @@
@include margin($checkbox-item-label-margin-top, null, $checkbox-item-label-margin-bottom, null);
}
:host(.in-item.checkbox-label-placement-stacked) .label-text-wrapper {
@include margin($checkbox-item-label-margin-top, null, $form-control-label-margin, null);
}
:host(.in-item.checkbox-label-placement-stacked) .native-wrapper {
@include margin(null, null, $checkbox-item-label-margin-bottom, null);
}
/**
* If no label text is placed into the slot
* then the element should be hidden otherwise
@@ -189,17 +181,6 @@ input {
justify-content: end;
}
// Align Items
// ---------------------------------------------
:host(.checkbox-alignment-start) .checkbox-wrapper {
align-items: start;
}
:host(.checkbox-alignment-center) .checkbox-wrapper {
align-items: center;
}
// Label Placement - Start
// ----------------------------------------------------------------
@@ -267,24 +248,6 @@ input {
max-width: 200px;
}
// Label Placement - Stacked
// ----------------------------------------------------------------
/**
* Label is on top of the checkbox.
*/
:host(.checkbox-label-placement-stacked) .checkbox-wrapper {
flex-direction: column;
}
:host(.checkbox-label-placement-stacked) .label-text-wrapper {
/**
* The margin between the label and
* the checkbox should be on the bottom
* when the label sits at the top.
*/
@include margin(null, 0, $form-control-label-margin, 0);
}
// Checked / Indeterminate Checkbox
// ---------------------------------------------

View File

@@ -81,9 +81,8 @@ export class Checkbox implements ComponentInterface {
* `"start"`: The label will appear to the left of the checkbox in LTR and to the right in RTL.
* `"end"`: The label will appear to the right of the checkbox in LTR and to the left in RTL.
* `"fixed"`: The label has the same behavior as `"start"` except it also has a fixed width. Long text will be truncated with ellipses ("...").
* `"stacked"`: The label will appear above the checkbox regardless of the direction. The alignment of the label can be controlled with the `alignment` property.
*/
@Prop() labelPlacement: 'start' | 'end' | 'fixed' | 'stacked' = 'start';
@Prop() labelPlacement: 'start' | 'end' | 'fixed' = 'start';
/**
* How to pack the label and checkbox within a line.
@@ -96,13 +95,6 @@ export class Checkbox implements ComponentInterface {
*/
@Prop() justify: 'start' | 'end' | 'space-between' = 'space-between';
/**
* How to control the alignment of the checkbox 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.
*/
@Prop() alignment: 'start' | 'center' = 'center';
// TODO(FW-3100): remove this
/**
* Set the `legacy` property to `true` to forcibly use the legacy form control markup.
@@ -232,7 +224,6 @@ export class Checkbox implements ComponentInterface {
labelPlacement,
name,
value,
alignment,
} = this;
const mode = getIonMode(this);
const path = getSVGPath(mode, indeterminate);
@@ -249,7 +240,6 @@ export class Checkbox implements ComponentInterface {
'checkbox-indeterminate': indeterminate,
interactive: true,
[`checkbox-justify-${justify}`]: true,
[`checkbox-alignment-${alignment}`]: true,
[`checkbox-label-placement-${labelPlacement}`]: true,
})}
>

View File

@@ -70,21 +70,4 @@ configs({ directions: ['ltr'], modes: ['md'] }).forEach(({ title, screenshot, co
await expect(list).toHaveScreenshot(screenshot(`checkbox-long-label-in-item`));
});
});
test.describe(title('checkbox: stacked label in item'), () => {
test('should render margins correctly when using stacked label in item', async ({ page }) => {
await page.setContent(
`
<ion-list>
<ion-item>
<ion-checkbox label-placement="stacked">Enable Notifications</ion-checkbox>
</ion-item>
</ion-list>
`,
config
);
const list = page.locator('ion-list');
await expect(list).toHaveScreenshot(screenshot(`checkbox-stacked-label-in-item`));
});
});
});

View File

@@ -137,27 +137,6 @@
</div>
</div>
<h1>Placement Stacked</h1>
<div class="grid">
<div class="grid-item">
<h2>Align Start</h2>
<ion-list>
<ion-item>
<ion-checkbox label-placement="stacked" alignment="start">Enable Notifications</ion-checkbox>
</ion-item>
</ion-list>
</div>
<div class="grid-item">
<h2>Align Center</h2>
<ion-list>
<ion-item>
<ion-checkbox label-placement="stacked" alignment="center">Enable Notifications</ion-checkbox>
</ion-item>
</ion-list>
</div>
</div>
<h1>States</h1>
<div class="grid">
<div class="grid-item">

View File

@@ -138,31 +138,5 @@ configs().forEach(({ title, screenshot, config }) => {
await expect(checkbox).toHaveScreenshot(screenshot(`checkbox-label-fixed-justify-space-between`));
});
});
test.describe('checkbox: stacked placement', () => {
test('should align the label to the start of the container in the stacked position', async ({ page }) => {
await page.setContent(
`
<ion-checkbox label-placement="stacked" alignment="start" style="width: 200px">This is a long label</ion-checkbox>
`,
config
);
const checkbox = page.locator('ion-checkbox');
await expect(checkbox).toHaveScreenshot(screenshot(`checkbox-label-stacked-align-start`));
});
test('should align the label to the center of the container in the stacked position', async ({ page }) => {
await page.setContent(
`
<ion-checkbox label-placement="stacked" alignment="center" style="width: 200px">This is a long label</ion-checkbox>
`,
config
);
const checkbox = page.locator('ion-checkbox');
await expect(checkbox).toHaveScreenshot(screenshot(`checkbox-label-stacked-align-center`));
});
});
});
});

View File

@@ -104,19 +104,6 @@
<ion-checkbox label-placement="fixed" justify="space-between">Enable Notifications</ion-checkbox>
</div>
</div>
<h1>Placement Stacked</h1>
<div class="grid">
<div class="grid-item">
<h2>Align Start</h2>
<ion-checkbox label-placement="stacked" alignment="start">Enable Notifications</ion-checkbox>
</div>
<div class="grid-item">
<h2>Align Center</h2>
<ion-checkbox label-placement="stacked" alignment="center">Enable Notifications</ion-checkbox>
</div>
</div>
</ion-content>
</ion-app>
</body>

View File

@@ -206,10 +206,6 @@ export class DatetimeButton implements ComponentInterface {
*/
const parsedDatetimes = parseDate(parsedValues.length > 0 ? parsedValues : [getToday()]);
if (!parsedDatetimes) {
return;
}
/**
* If developers incorrectly use multiple="true"
* with non "date" datetimes, then just select

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 28 KiB

After

Width:  |  Height:  |  Size: 28 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 33 KiB

After

Width:  |  Height:  |  Size: 34 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 22 KiB

After

Width:  |  Height:  |  Size: 22 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 30 KiB

After

Width:  |  Height:  |  Size: 30 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 28 KiB

After

Width:  |  Height:  |  Size: 28 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 22 KiB

After

Width:  |  Height:  |  Size: 22 KiB

View File

@@ -20,7 +20,7 @@
@include padding($datetime-ios-padding, $datetime-ios-padding, $datetime-ios-padding, $datetime-ios-padding);
border-bottom: $datetime-ios-border-color;
font-size: 14px;
}
@@ -85,32 +85,27 @@
*/
@include padding($datetime-ios-padding * 0.5, $datetime-ios-padding * 0.5, $datetime-ios-padding * 0.5, $datetime-ios-padding * 0.5);
align-items: center;
height: calc(100% - #{$datetime-ios-padding});
}
:host .calendar-day-wrapper {
@include padding(4px);
// This is required so that the calendar day wrapper
// will collapse instead of expanding to fill the button
height: 0;
min-height: 16px;
}
:host .calendar-day {
width: $datetime-ios-day-width;
min-width: $datetime-ios-day-width;
height: $datetime-ios-day-height;
font-size: 20px;
}
.calendar-day.calendar-day-active {
background: current-color(base, 0.2);
.calendar-day:focus .calendar-day-highlight,
.calendar-day.calendar-day-active .calendar-day-highlight {
opacity: 0.2;
}
.calendar-day.calendar-day-active .calendar-day-highlight {
background: current-color(base);
}
// !important is needed here to overwrite custom highlight background, which is inline.
// Does not apply to the active state because highlights aren't applied at all there.
.calendar-day:focus .calendar-day-highlight {
/* stylelint-disable-next-line declaration-no-important */
background: current-color(base) !important;
}
/**
@@ -140,6 +135,12 @@
color: current-color(contrast);
}
.calendar-day.calendar-day-today.calendar-day-active .calendar-day-highlight {
background: current-color(base);
opacity: 1;
}
// Time / Header
// -----------------------------------
:host .datetime-time {

View File

@@ -15,9 +15,3 @@ $datetime-ios-time-width: 68px !default;
/// @prop - Border radius of the time picker
$datetime-ios-time-border-radius: 8px !default;
/// @prop - Width of the calendar day
$datetime-ios-day-width: 40px !default;
/// @prop - Height of the calendar day
$datetime-ios-day-height: $datetime-ios-day-width !default;

View File

@@ -69,24 +69,29 @@
// Individual day button in month
:host .calendar-day {
width: $datetime-md-day-width;
min-width: $datetime-md-day-width;
height: $datetime-md-day-height;
@include padding(13px, 0, 13px, 0px);
font-size: $datetime-md-calendar-item-font-size;
}
.calendar-day:focus .calendar-day-highlight {
background: current-color(base, 0.2);
box-shadow: 0px 0px 0px 4px current-color(base, 0.2);
}
/**
* Day that today but not selected
* should have ion-color for text color.
*/
:host .calendar-day.calendar-day-today {
border: 1px solid current-color(base);
color: current-color(base);
}
.calendar-day.calendar-day-today .calendar-day-highlight {
border: 1px solid current-color(base);
}
/**
* Day that is not today but
* is selected should have ion-color for
@@ -96,7 +101,7 @@
color: current-color(contrast);
}
.calendar-day.calendar-day-active {
.calendar-day.calendar-day-active .calendar-day-highlight {
border: 1px solid current-color(base);
background: current-color(base);

View File

@@ -15,9 +15,3 @@ $datetime-md-header-padding: 20px !default;
/// @prop - Padding for content
$datetime-md-padding: 16px !default;
/// @prop - Width of the calendar day
$datetime-md-day-width: 42px !default;
/// @prop - Height of the calendar day
$datetime-md-day-height: $datetime-md-day-width !default;

View File

@@ -290,10 +290,6 @@ ion-picker-column-internal {
}
:host .calendar-body .calendar-month {
display: flex;
flex-flow: column;
/**
* Swiping should snap to at
* most one month at a time.
@@ -329,31 +325,13 @@ ion-picker-column-internal {
grid-template-columns: repeat(7, 1fr);
}
:host .calendar-day-wrapper {
display: flex;
align-items: center;
justify-content: center;
// Adding a min width and min height allows
// it to shrink smaller than its content
// which keeps the calendar day highlight
// larger while letting the grid items shrink
min-width: 0;
min-height: 0;
overflow: visible;
}
/**
* Center the day text vertically
* and horizontally within its grid cell.
*/
:host .calendar-day {
@include border-radius(50%);
@include padding(0px);
@include margin(0px);
@include padding(0px, 0px, 0px, 0px);
@include margin(0px, 0px, 0px, 0px);
display: flex;
@@ -384,10 +362,16 @@ ion-picker-column-internal {
opacity: 0.4;
}
.calendar-day:focus {
background: current-color(base, 0.2);
.calendar-day-highlight {
@include border-radius(32px, 32px, 32px, 32px);
@include padding(4px, 4px, 4px, 4px);
box-shadow: 0px 0px 0px 4px current-color(base, 0.2);
position: absolute;
width: 32px;
height: 32px;
z-index: -1;
}
// Time / Header

View File

@@ -85,12 +85,6 @@ import {
*
* @part month-year-button - The button that opens the month/year picker when
* using a grid style layout.
*
* @part calendar-day - The individual buttons that display a day inside of the datetime
* calendar.
* @part calendar-day active - The currently selected calendar day.
* @part calendar-day today - The calendar day that contains the current day.
* @part calendar-day disabled - The calendar day that is disabled.
*/
@Component({
tag: 'ion-datetime',
@@ -123,7 +117,11 @@ export class Datetime implements ComponentInterface {
private prevPresentation: string | null = null;
private resolveForceDateScrolling?: () => void;
/**
* Duplicate reference to `activeParts` that does not trigger a re-render of the component.
* Allows caching an instance of the `activeParts` in between render cycles.
*/
private activePartsClone: DatetimeParts | DatetimeParts[] = [];
@State() showMonthAndYear = false;
@@ -142,17 +140,6 @@ export class Datetime implements ComponentInterface {
@State() isTimePopoverOpen = false;
/**
* When defined, will force the datetime to render the month
* containing the specified date. Currently, this should only
* be used to enable immediately auto-scrolling to the new month,
* and should then be reset to undefined once the transition is
* finished and the forced month is now in view.
*
* Applies to grid-style datetimes only.
*/
@State() forceRenderDate?: DatetimeParts;
/**
* The color to use from your application's color palette.
* Default options are: `"primary"`, `"secondary"`, `"tertiary"`, `"success"`, `"warning"`, `"danger"`, `"light"`, `"medium"`, and `"dark"`.
@@ -234,12 +221,6 @@ export class Datetime implements ComponentInterface {
*/
@Prop() presentation: DatetimePresentation = 'date-time';
private get isGridStyle() {
const { presentation, preferWheel } = this;
const hasDatePresentation = presentation === 'date' || presentation === 'date-time' || presentation === 'time-date';
return hasDatePresentation && !preferWheel;
}
/**
* The text to display on the picker's cancel button.
*/
@@ -321,6 +302,11 @@ export class Datetime implements ComponentInterface {
this.parsedMinuteValues = convertToArrayOfNumbers(this.minuteValues);
}
@Watch('activeParts')
protected activePartsChanged() {
this.activePartsClone = this.activeParts;
}
/**
* The locale to use for `ion-datetime`. This
* impacts month and day name formatting.
@@ -370,11 +356,54 @@ export class Datetime implements ComponentInterface {
* Update the datetime value when the value changes
*/
@Watch('value')
protected async valueChanged() {
const { value } = this;
protected valueChanged() {
const { value, minParts, maxParts, workingParts } = this;
if (this.hasValue()) {
this.processValue(value);
this.warnIfIncorrectValueUsage();
/**
* Clones the value of the `activeParts` to the private clone, to update
* the date display on the current render cycle without causing another render.
*
* This allows us to update the current value's date/time display without
* refocusing or shifting the user's display (leaves the user in place).
*/
const valueDateParts = parseDate(value);
if (valueDateParts) {
warnIfValueOutOfBounds(valueDateParts, minParts, maxParts);
if (Array.isArray(valueDateParts)) {
this.activePartsClone = [...valueDateParts];
} else {
const { month, day, year, hour, minute } = valueDateParts;
const ampm = hour != null ? (hour >= 12 ? 'pm' : 'am') : undefined;
this.activePartsClone = {
...this.activeParts,
month,
day,
year,
hour,
minute,
ampm,
};
/**
* The working parts am/pm value must be updated when the value changes, to
* ensure the time picker hour column values are generated correctly.
*
* Note that we don't need to do this if valueDateParts is an array, since
* multiple="true" does not apply to time pickers.
*/
this.setWorkingParts({
...workingParts,
ampm,
});
}
} else {
printIonWarning(`Unable to parse date string: ${value}. Please provide a valid ISO 8601 datetime string.`);
}
}
this.emitStyle();
@@ -567,9 +596,9 @@ export class Datetime implements ComponentInterface {
* data. This should be used when rendering an
* interface in an environment where the `value`
* may not be set. This function works
* by returning the first selected date and then
* falling back to defaultParts if no active date
* is selected.
* by returning the first selected date in
* "activePartsClone" and then falling back to
* defaultParts if no active date is selected.
*/
private getActivePartsWithFallback = () => {
const { defaultParts } = this;
@@ -577,8 +606,8 @@ export class Datetime implements ComponentInterface {
};
private getActivePart = () => {
const { activeParts } = this;
return Array.isArray(activeParts) ? activeParts[0] : activeParts;
const { activePartsClone } = this;
return Array.isArray(activePartsClone) ? activePartsClone[0] : activePartsClone;
};
private closeParentOverlay = () => {
@@ -598,7 +627,7 @@ export class Datetime implements ComponentInterface {
};
private setActiveParts = (parts: DatetimeParts, removeDate = false) => {
const { multiple, minParts, maxParts, activeParts } = this;
const { multiple, minParts, maxParts, activePartsClone } = this;
/**
* When setting the active parts, it is possible
@@ -614,7 +643,16 @@ export class Datetime implements ComponentInterface {
this.setWorkingParts(validatedParts);
if (multiple) {
const activePartsArray = Array.isArray(activeParts) ? activeParts : [activeParts];
/**
* We read from activePartsClone here because valueChanged() only updates that,
* so it's the more reliable source of truth. If we read from activeParts, then
* if you click July 1, manually set the value to July 2, and then click July 3,
* the new value would be [July 1, July 3], ignoring the value set.
*
* We can then pass the new value to activeParts (rather than activePartsClone)
* since the clone will be updated automatically by activePartsChanged().
*/
const activePartsArray = Array.isArray(activePartsClone) ? activePartsClone : [activePartsClone];
if (removeDate) {
this.activeParts = activePartsArray.filter((p) => !isSameDay(p, validatedParts));
} else {
@@ -762,7 +800,7 @@ export class Datetime implements ComponentInterface {
/**
* Get the number of padding days so
* we know how much to offset our next selector by
* to grab the correct calendar-day element.
* to grab the correct calenday-day element.
*/
const padding = currentMonth.querySelectorAll('.calendar-day-padding');
const { day } = this.workingParts;
@@ -776,7 +814,7 @@ export class Datetime implements ComponentInterface {
* and focus it.
*/
const dayEl = currentMonth.querySelector(
`.calendar-day-wrapper:nth-of-type(${padding.length + day}) .calendar-day`
`.calendar-day:nth-of-type(${padding.length + day})`
) as HTMLElement | null;
if (dayEl) {
dayEl.focus();
@@ -870,20 +908,6 @@ export class Datetime implements ComponentInterface {
const monthBox = month.getBoundingClientRect();
if (Math.abs(monthBox.x - box.x) > 2) return;
/**
* If we're force-rendering a month, assume we've
* scrolled to that and return it.
*
* If forceRenderDate is ever used in a context where the
* forced month is not immediately auto-scrolled to, this
* should be updated to also check whether `month` has the
* same month and year as the forced date.
*/
const { forceRenderDate } = this;
if (forceRenderDate !== undefined) {
return { month: forceRenderDate.month, year: forceRenderDate.year, day: forceRenderDate.day };
}
/**
* From here, we can determine if the start
* month or the end month was scrolled into view.
@@ -952,10 +976,6 @@ export class Datetime implements ComponentInterface {
calendarBodyRef.scrollLeft = workingMonth.clientWidth * (isRTL(this.el) ? -1 : 1);
calendarBodyRef.style.removeProperty('overflow');
if (this.resolveForceDateScrolling) {
this.resolveForceDateScrolling();
}
});
};
@@ -1173,21 +1193,13 @@ export class Datetime implements ComponentInterface {
}
private processValue = (value?: string | string[] | null) => {
const hasValue = value !== null && value !== undefined && (!Array.isArray(value) || value.length > 0);
const hasValue = value !== null && value !== undefined;
const valueToProcess = hasValue ? parseDate(value) : this.defaultParts;
const { minParts, maxParts, workingParts, el } = this;
const { minParts, maxParts } = this;
this.warnIfIncorrectValueUsage();
/**
* Return early if the value wasn't parsed correctly, such as
* if an improperly formatted date string was provided.
*/
if (!valueToProcess) {
return;
}
/**
* Datetime should only warn of out of bounds values
* if set by the user. If the `value` is undefined,
@@ -1206,11 +1218,19 @@ export class Datetime implements ComponentInterface {
* that the values don't necessarily have to be in order.
*/
const singleValue = Array.isArray(valueToProcess) ? valueToProcess[0] : valueToProcess;
const targetValue = clampDate(singleValue, minParts, maxParts);
const { month, day, year, hour, minute } = targetValue;
const { month, day, year, hour, minute } = clampDate(singleValue, minParts, maxParts);
const ampm = parseAmPm(hour!);
this.setWorkingParts({
month,
day,
year,
hour,
minute,
ampm,
});
/**
* Since `activeParts` indicates a value that
* been explicitly selected either by the
@@ -1238,67 +1258,6 @@ export class Datetime implements ComponentInterface {
*/
this.activeParts = [];
}
/**
* Only animate if:
* 1. We're using grid style (wheel style pickers should just jump to new value)
* 2. The month and/or year actually changed, and both are defined (otherwise there's nothing to animate to)
* 3. The calendar body is visible (prevents animation when in collapsed datetime-button, for example)
* 4. The month/year picker is not open (since you wouldn't see the animation anyway)
*/
const didChangeMonth =
(month !== undefined && month !== workingParts.month) || (year !== undefined && year !== workingParts.year);
const bodyIsVisible = el.classList.contains('datetime-ready');
const { isGridStyle, showMonthAndYear } = this;
if (isGridStyle && didChangeMonth && bodyIsVisible && !showMonthAndYear) {
this.animateToDate(targetValue);
} else {
/**
* We only need to do this if we didn't just animate to a new month,
* since that calls prevMonth/nextMonth which calls setWorkingParts for us.
*/
this.setWorkingParts({
month,
day,
year,
hour,
minute,
ampm,
});
}
};
private animateToDate = async (targetValue: DatetimeParts) => {
const { workingParts } = this;
/**
* Tell other render functions that we need to force the
* target month to appear in place of the actual next/prev month.
* Because this is a State variable, a rerender will be triggered
* automatically, updating the rendered months.
*/
this.forceRenderDate = targetValue;
/**
* Flag that we've started scrolling to the forced date.
* The resolve function will be called by the datetime's
* scroll listener when it's done updating everything.
* This is a replacement for making prev/nextMonth async,
* since the logic we're waiting on is in a listener.
*/
const forceDateScrollingPromise = new Promise<void>((resolve) => {
this.resolveForceDateScrolling = resolve;
});
/**
* Animate smoothly to the forced month. This will also update
* workingParts and correct the surrounding months for us.
*/
const targetMonthIsBefore = isBefore(targetValue, workingParts);
targetMonthIsBefore ? this.prevMonth() : this.nextMonth();
await forceDateScrollingPromise;
this.resolveForceDateScrolling = undefined;
this.forceRenderDate = undefined;
};
componentWillLoad() {
@@ -1327,18 +1286,16 @@ export class Datetime implements ComponentInterface {
}
}
this.processMinParts();
this.processMaxParts();
const hourValues = (this.parsedHourValues = convertToArrayOfNumbers(this.hourValues));
const minuteValues = (this.parsedMinuteValues = convertToArrayOfNumbers(this.minuteValues));
const monthValues = (this.parsedMonthValues = convertToArrayOfNumbers(this.monthValues));
const yearValues = (this.parsedYearValues = convertToArrayOfNumbers(this.yearValues));
const dayValues = (this.parsedDayValues = convertToArrayOfNumbers(this.dayValues));
const todayParts = (this.todayParts = parseDate(getToday())!);
const todayParts = (this.todayParts = parseDate(getToday()));
this.defaultParts = getClosestValidDate(todayParts, monthValues, dayValues, yearValues, hourValues, minuteValues);
this.processMinParts();
this.processMaxParts();
this.processValue(this.value);
this.emitStyle();
@@ -2085,7 +2042,7 @@ export class Datetime implements ComponentInterface {
const { isActive, isToday, ariaLabel, ariaSelected, disabled, text } = getCalendarDayState(
this.locale,
referenceParts,
this.activeParts,
this.activePartsClone,
this.todayParts,
this.minParts,
this.maxParts,
@@ -2122,87 +2079,69 @@ export class Datetime implements ComponentInterface {
dateStyle = getHighlightStyles(highlightedDates, dateIsoString, el);
}
let dateParts = undefined;
// "Filler days" at the beginning of the grid should not get the calendar day
// CSS parts added to them
if (!isCalendarPadding) {
dateParts = `calendar-day${isActive ? ' active' : ''}${isToday ? ' today' : ''}${
isCalDayDisabled ? ' disabled' : ''
}`;
}
return (
<div class="calendar-day-wrapper">
<button
// We need to use !important for the inline styles here because
// otherwise the CSS shadow parts will override these styles.
// See https://github.com/WICG/webcomponents/issues/847
// Both the CSS shadow parts and highlightedDates styles are
// provided by the developer, but highlightedDates styles should
// always take priority.
ref={(el) => {
if (el) {
el.style.setProperty('color', `${dateStyle ? dateStyle.textColor : ''}`, 'important');
el.style.setProperty(
'background-color',
`${dateStyle ? dateStyle.backgroundColor : ''}`,
'important'
);
}
}}
tabindex="-1"
data-day={day}
data-month={month}
data-year={year}
data-index={index}
data-day-of-week={dayOfWeek}
disabled={isCalDayDisabled}
class={{
'calendar-day-padding': isCalendarPadding,
'calendar-day': true,
'calendar-day-active': isActive,
'calendar-day-today': isToday,
}}
part={dateParts}
aria-hidden={isCalendarPadding ? 'true' : null}
aria-selected={ariaSelected}
aria-label={ariaLabel}
onClick={() => {
if (isCalendarPadding) {
return;
}
<button
tabindex="-1"
data-day={day}
data-month={month}
data-year={year}
data-index={index}
data-day-of-week={dayOfWeek}
disabled={isCalDayDisabled}
class={{
'calendar-day-padding': isCalendarPadding,
'calendar-day': true,
'calendar-day-active': isActive,
'calendar-day-today': isToday,
}}
style={
dateStyle && {
color: dateStyle.textColor,
}
}
aria-hidden={isCalendarPadding ? 'true' : null}
aria-selected={ariaSelected}
aria-label={ariaLabel}
onClick={() => {
if (isCalendarPadding) {
return;
}
this.setWorkingParts({
...this.workingParts,
this.setWorkingParts({
...this.workingParts,
month,
day,
year,
});
// multiple only needs date info, so we can wipe out other fields like time
if (multiple) {
this.setActiveParts(
{
month,
day,
year,
},
isActive
);
} else {
this.setActiveParts({
...activePart,
month,
day,
year,
});
// multiple only needs date info, so we can wipe out other fields like time
if (multiple) {
this.setActiveParts(
{
month,
day,
year,
},
isActive
);
} else {
this.setActiveParts({
...activePart,
month,
day,
year,
});
}
}
}}
>
<div
class="calendar-day-highlight"
style={{
backgroundColor: dateStyle?.backgroundColor,
}}
>
{text}
</button>
</div>
></div>
{text}
</button>
);
})}
</div>
@@ -2212,7 +2151,7 @@ export class Datetime implements ComponentInterface {
private renderCalendarBody() {
return (
<div class="calendar-body ion-focusable" ref={(el) => (this.calendarBodyRef = el)} tabindex="0">
{generateMonths(this.workingParts, this.forceRenderDate).map(({ month, year }) => {
{generateMonths(this.workingParts).map(({ month, year }) => {
return this.renderMonth(month, year);
})}
</div>
@@ -2421,19 +2360,7 @@ export class Datetime implements ComponentInterface {
}
render() {
const {
name,
value,
disabled,
el,
color,
readonly,
showMonthAndYear,
preferWheel,
presentation,
size,
isGridStyle,
} = this;
const { name, value, disabled, el, color, readonly, showMonthAndYear, preferWheel, presentation, size } = this;
const mode = getIonMode(this);
const isMonthAndYearPresentation =
presentation === 'year' || presentation === 'month' || presentation === 'month-year';
@@ -2441,6 +2368,7 @@ export class Datetime implements ComponentInterface {
const monthYearPickerOpen = showMonthAndYear && !isMonthAndYearPresentation;
const hasDatePresentation = presentation === 'date' || presentation === 'date-time' || presentation === 'time-date';
const hasWheelVariant = hasDatePresentation && preferWheel;
const hasGrid = hasDatePresentation && !preferWheel;
renderHiddenInput(true, el, name, formatValue(value), disabled);
@@ -2459,7 +2387,7 @@ export class Datetime implements ComponentInterface {
[`datetime-presentation-${presentation}`]: true,
[`datetime-size-${size}`]: true,
[`datetime-prefer-wheel`]: hasWheelVariant,
[`datetime-grid`]: isGridStyle,
[`datetime-grid`]: hasGrid,
}),
}}
>

View File

@@ -490,40 +490,3 @@ configs({ modes: ['md'], directions: ['ltr'] }).forEach(({ title, screenshot, co
});
});
});
/**
* This behavior does not differ across
* directions.
*/
configs({ directions: ['ltr'] }).forEach(({ title, screenshot, config }) => {
test.describe(title('datetime: focus'), () => {
test('should focus the selected day and then the day after', async ({ page }) => {
await page.setContent(
`
<ion-datetime value="2023-08-01"></ion-datetime>
`,
config
);
await page.waitForSelector('.datetime-ready');
const datetime = page.locator('ion-datetime');
const day = datetime.locator(`.calendar-day[data-day='1'][data-month='8']`);
await day.focus();
await page.waitForChanges();
await expect(day).toBeFocused();
await expect(datetime).toHaveScreenshot(screenshot(`datetime-focus-selected-calendar-day`));
await page.keyboard.press('ArrowRight');
await page.waitForChanges();
const nextDay = datetime.locator(`.calendar-day[data-day='2'][data-month='8']`);
await expect(nextDay).toBeFocused();
await expect(datetime).toHaveScreenshot(screenshot(`datetime-focus-calendar-day`));
});
});
});

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 18 KiB

After

Width:  |  Height:  |  Size: 18 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 18 KiB

After

Width:  |  Height:  |  Size: 18 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 21 KiB

After

Width:  |  Height:  |  Size: 21 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 19 KiB

After

Width:  |  Height:  |  Size: 19 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 23 KiB

After

Width:  |  Height:  |  Size: 23 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 19 KiB

After

Width:  |  Height:  |  Size: 19 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 19 KiB

After

Width:  |  Height:  |  Size: 19 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 21 KiB

After

Width:  |  Height:  |  Size: 21 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 18 KiB

After

Width:  |  Height:  |  Size: 18 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 23 KiB

After

Width:  |  Height:  |  Size: 23 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 19 KiB

After

Width:  |  Height:  |  Size: 19 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 19 KiB

After

Width:  |  Height:  |  Size: 19 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 22 KiB

After

Width:  |  Height:  |  Size: 22 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 19 KiB

After

Width:  |  Height:  |  Size: 19 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 24 KiB

After

Width:  |  Height:  |  Size: 24 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 20 KiB

After

Width:  |  Height:  |  Size: 20 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 20 KiB

After

Width:  |  Height:  |  Size: 20 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 22 KiB

After

Width:  |  Height:  |  Size: 22 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 20 KiB

After

Width:  |  Height:  |  Size: 20 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 24 KiB

After

Width:  |  Height:  |  Size: 24 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 21 KiB

After

Width:  |  Height:  |  Size: 21 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 20 KiB

After

Width:  |  Height:  |  Size: 20 KiB

View File

@@ -9,7 +9,7 @@ configs({ directions: ['ltr'] }).forEach(({ title, screenshot, config }) => {
test('should not have visual regressions', async ({ page }) => {
await page.goto('/src/components/datetime/test/color', config);
const datetime = page.locator('#color-datetime');
const datetime = page.locator('ion-datetime');
await expect(datetime).toHaveScreenshot(screenshot(`datetime-color`));

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 23 KiB

After

Width:  |  Height:  |  Size: 22 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 27 KiB

After

Width:  |  Height:  |  Size: 27 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 21 KiB

After

Width:  |  Height:  |  Size: 21 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 24 KiB

After

Width:  |  Height:  |  Size: 24 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 22 KiB

After

Width:  |  Height:  |  Size: 22 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 24 KiB

After

Width:  |  Height:  |  Size: 24 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 20 KiB

After

Width:  |  Height:  |  Size: 20 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 25 KiB

After

Width:  |  Height:  |  Size: 25 KiB

View File

@@ -9,18 +9,11 @@
<script src="../../../../../scripts/testing/scripts.js"></script>
<script type="module" src="../../../../../dist/ionic/ionic.esm.js"></script>
<style>
ion-checkbox,
ion-select {
margin-inline-start: 10px;
margin-inline-end: 10px;
}
.grid {
display: grid;
grid-template-columns: repeat(auto-fill, 250px);
grid-template-columns: repeat(2, minmax(250px, 1fr));
grid-gap: 20px;
}
h2 {
font-size: 12px;
font-weight: normal;
@@ -36,14 +29,10 @@
border-radius: 8px;
}
#color-name::first-letter {
text-transform: capitalize;
}
/*
* Dark Theme
* -------------------------------------------
*/
* Dark Colors
* -------------------------------------------
*/
body.dark {
--ion-color-primary: #428cff;
@@ -111,9 +100,9 @@
}
/*
* iOS Dark Theme
* -------------------------------------------
*/
* iOS Dark Theme
* -------------------------------------------
*/
.ios body.dark {
--ion-background-color: #000000;
@@ -155,9 +144,9 @@
}
/*
* Material Design Dark Theme
* -------------------------------------------
*/
* Material Design Dark Theme
* -------------------------------------------
*/
.md body.dark {
--ion-background-color: #121212;
@@ -202,23 +191,30 @@
<ion-app>
<ion-header translucent="true">
<ion-toolbar>
<ion-checkbox>Dark Mode</ion-checkbox>
<ion-select label="Color" justify="end" slot="end" value="danger">
<ion-select-option value="primary">Primary</ion-select-option>
<ion-select-option value="secondary">Secondary</ion-select-option>
<ion-select-option value="tertiary">Tertiary</ion-select-option>
<ion-select-option value="success">Success</ion-select-option>
<ion-select-option value="warning">Warning</ion-select-option>
<ion-select-option value="danger">Danger</ion-select-option>
</ion-select>
<ion-title>Datetime - Color</ion-title>
<ion-item lines="none" slot="end">
<ion-label>Dark Mode</ion-label>
<ion-checkbox slot="end"></ion-checkbox>
</ion-item>
<ion-item lines="none" slot="end">
<ion-label>Color</ion-label>
<ion-select value="danger">
<ion-select-option value="primary">Primary</ion-select-option>
<ion-select-option value="secondary">Secondary</ion-select-option>
<ion-select-option value="tertiary">Tertiary</ion-select-option>
<ion-select-option value="success">Success</ion-select-option>
<ion-select-option value="warning">Warning</ion-select-option>
<ion-select-option value="danger">Danger</ion-select-option>
</ion-select>
</ion-item>
</ion-toolbar>
</ion-header>
<ion-content class="ion-padding">
<div class="grid">
<div class="grid-item">
<h2 id="color-name">Danger</h2>
<h2>Default</h2>
<ion-datetime
id="color-datetime"
color="danger"
value="2022-05-03"
show-default-title="true"
@@ -228,14 +224,14 @@
</div>
</ion-content>
<script>
const colorDatetime = document.querySelector('#color-datetime');
const colorName = document.querySelector('#color-name');
const colorSelect = document.querySelector('ion-select');
const darkModeToggle = document.querySelector('ion-checkbox');
const datetimes = document.querySelectorAll('ion-datetime');
colorSelect.addEventListener('ionChange', (ev) => {
colorDatetime.color = ev.detail.value;
colorName.innerHTML = ev.detail.value;
datetimes.forEach((datetime) => {
datetime.color = ev.detail.value;
});
});
darkModeToggle.addEventListener('ionChange', (ev) => {

View File

@@ -14,7 +14,7 @@ configs({ directions: ['ltr'] }).forEach(({ title, screenshot, config }) => {
});
test('should allow styling time picker in grid style datetimes', async ({ page }) => {
const timeButton = page.locator('#custom-grid .time-body');
const timeButton = page.locator('ion-datetime .time-body');
const popover = page.locator('.popover-viewport');
const ionPopoverDidPresent = await page.spyOnEvent('ionPopoverDidPresent');
@@ -26,41 +26,5 @@ configs({ directions: ['ltr'] }).forEach(({ title, screenshot, config }) => {
await expect(popover).toHaveScreenshot(screenshot(`datetime-custom-time-picker`));
await expect(timeButton).toHaveScreenshot(screenshot(`datetime-custom-time-button-active`));
});
test('should allow styling calendar days in grid style datetimes', async ({ page }) => {
const datetime = page.locator('#custom-calendar-days');
await expect(datetime).toHaveScreenshot(screenshot(`datetime-custom-calendar-days`));
});
});
});
/**
* This behavior does not differ across
* directions.
*/
configs({ directions: ['ltr'] }).forEach(({ title, screenshot, config }) => {
test.describe(title('datetime: custom focus'), () => {
test('should focus the selected day and then the day after', async ({ page }) => {
await page.goto(`/src/components/datetime/test/custom`, config);
const datetime = page.locator('#custom-calendar-days');
const day = datetime.locator(`.calendar-day[data-day='15'][data-month='6']`);
await day.focus();
await page.waitForChanges();
await expect(day).toBeFocused();
await expect(datetime).toHaveScreenshot(screenshot(`datetime-custom-focus-selected-calendar-day`));
await page.keyboard.press('ArrowRight');
await page.waitForChanges();
const nextDay = datetime.locator(`.calendar-day[data-day='16'][data-month='6']`);
await expect(nextDay).toBeFocused();
await expect(datetime).toHaveScreenshot(screenshot(`datetime-custom-focus-calendar-day`));
});
});
});

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