mirror of
https://github.com/ionic-team/ionic-framework.git
synced 2025-11-10 00:27:41 +08:00
chore(): sync next with master
chore(): sync next with master
This commit is contained in:
@ -987,6 +987,7 @@ ion-searchbar,prop,mode,"ios" | "md",undefined,false,false
|
||||
ion-searchbar,prop,placeholder,string,'Search',false,false
|
||||
ion-searchbar,prop,searchIcon,string | undefined,undefined,false,false
|
||||
ion-searchbar,prop,showCancelButton,"always" | "focus" | "never",'never',false,false
|
||||
ion-searchbar,prop,showClearButton,"always" | "focus" | "never",'focus',false,false
|
||||
ion-searchbar,prop,spellcheck,boolean,false,false,false
|
||||
ion-searchbar,prop,type,"email" | "number" | "password" | "search" | "tel" | "text" | "url",'search',false,false
|
||||
ion-searchbar,prop,value,null | string | undefined,'',false,false
|
||||
|
||||
71
core/package-lock.json
generated
71
core/package-lock.json
generated
@ -1,12 +1,12 @@
|
||||
{
|
||||
"name": "@ionic/core",
|
||||
"version": "5.5.4",
|
||||
"version": "5.5.5",
|
||||
"lockfileVersion": 2,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "@ionic/core",
|
||||
"version": "5.5.4",
|
||||
"version": "5.5.5",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@stencil/core": "^2.4.0",
|
||||
@ -18,7 +18,7 @@
|
||||
"@rollup/plugin-node-resolve": "^8.4.0",
|
||||
"@rollup/plugin-virtual": "^2.0.3",
|
||||
"@stencil/sass": "1.3.2",
|
||||
"@stencil/vue-output-target": "0.3.0",
|
||||
"@stencil/vue-output-target": "^0.4.1",
|
||||
"@types/jest": "^26.0.20",
|
||||
"@types/node": "^14.6.0",
|
||||
"@types/puppeteer": "5.4.3",
|
||||
@ -906,7 +906,6 @@
|
||||
"jest-resolve": "^26.6.2",
|
||||
"jest-util": "^26.6.2",
|
||||
"jest-worker": "^26.6.2",
|
||||
"node-notifier": "^8.0.0",
|
||||
"slash": "^3.0.0",
|
||||
"source-map": "^0.6.0",
|
||||
"string-length": "^4.0.1",
|
||||
@ -1014,10 +1013,31 @@
|
||||
"integrity": "sha512-5O7H5c/7YlojphYNrK02LlDIV2GNPYisKwHm2QTKjNZeEzezCbwYs9swJySv2UfPMyZ0VdsmMv7jIlD/IKYQpQ==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@bcoe/v8-coverage": "^0.2.3",
|
||||
"@jest/console": "^26.6.2",
|
||||
"@jest/test-result": "^26.3.0",
|
||||
"@jest/transform": "^26.3.0",
|
||||
"@jest/types": "^26.6.2",
|
||||
"@types/istanbul-lib-coverage": "^2.0.0",
|
||||
"collect-v8-coverage": "^1.0.0"
|
||||
"chalk": "^4.0.0",
|
||||
"collect-v8-coverage": "^1.0.0",
|
||||
"exit": "^0.1.2",
|
||||
"glob": "^7.1.2",
|
||||
"graceful-fs": "^4.2.4",
|
||||
"istanbul-lib-coverage": "^3.0.0",
|
||||
"istanbul-lib-instrument": "^4.0.3",
|
||||
"istanbul-lib-report": "^3.0.0",
|
||||
"istanbul-lib-source-maps": "^4.0.0",
|
||||
"istanbul-reports": "^3.0.2",
|
||||
"jest-haste-map": "^26.3.0",
|
||||
"jest-resolve": "^26.4.0",
|
||||
"jest-util": "^26.3.0",
|
||||
"jest-worker": "^26.3.0",
|
||||
"slash": "^3.0.0",
|
||||
"source-map": "^0.6.0",
|
||||
"string-length": "^4.0.1",
|
||||
"terminal-link": "^2.0.0",
|
||||
"v8-to-istanbul": "^5.0.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 10.14.2"
|
||||
@ -1337,9 +1357,9 @@
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/@stencil/vue-output-target": {
|
||||
"version": "0.3.0",
|
||||
"resolved": "https://registry.npmjs.org/@stencil/vue-output-target/-/vue-output-target-0.3.0.tgz",
|
||||
"integrity": "sha512-uiBe+o7M+NU0gMRgJfrlepxLPBXK0lX4TL2jIPwhBfxYw++pbtg7BLRO2HxE69GR0nxw+7Uf3uJzOGbMsl+ZUQ==",
|
||||
"version": "0.4.1",
|
||||
"resolved": "https://registry.npmjs.org/@stencil/vue-output-target/-/vue-output-target-0.4.1.tgz",
|
||||
"integrity": "sha512-B4urIlIb+I95NkKeCt3Ygpor1D0x5RMezuFyCFp6DYXshUaT1TbiJcW1FgA+gfwlquNzT1AMvEbi96YLnsOg3w==",
|
||||
"dev": true,
|
||||
"peerDependencies": {
|
||||
"@stencil/core": ">=1.8.0"
|
||||
@ -2582,7 +2602,6 @@
|
||||
"dependencies": {
|
||||
"anymatch": "~3.1.1",
|
||||
"braces": "~3.0.2",
|
||||
"fsevents": "~2.1.2",
|
||||
"glob-parent": "~5.1.0",
|
||||
"is-binary-path": "~2.1.0",
|
||||
"is-glob": "~4.0.1",
|
||||
@ -4227,7 +4246,6 @@
|
||||
"integrity": "sha512-GDhU9ntwuKyGXdZBUgTIe+vXnWj0fppUEtMDL0+idd5Sta8TGpHssn/eusA9mrPr9qNDym6SxAYZjNvCn/9RBg==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@types/yauzl": "^2.9.1",
|
||||
"debug": "^4.1.1",
|
||||
"get-stream": "^5.1.0",
|
||||
"yauzl": "^2.10.0"
|
||||
@ -6724,7 +6742,6 @@
|
||||
"@types/node": "*",
|
||||
"anymatch": "^3.0.3",
|
||||
"fb-watchman": "^2.0.0",
|
||||
"fsevents": "^2.1.2",
|
||||
"graceful-fs": "^4.2.4",
|
||||
"jest-regex-util": "^26.0.0",
|
||||
"jest-serializer": "^26.6.2",
|
||||
@ -10977,9 +10994,6 @@
|
||||
"resolved": "https://registry.npmjs.org/rollup/-/rollup-2.35.1.tgz",
|
||||
"integrity": "sha512-q5KxEyWpprAIcainhVy6HfRttD9kutQpHbeqDTWnqAFNJotiojetK6uqmcydNMymBEtC4I8bCYR+J3mTMqeaUA==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"fsevents": "~2.1.2"
|
||||
},
|
||||
"bin": {
|
||||
"rollup": "dist/bin/rollup"
|
||||
},
|
||||
@ -14596,10 +14610,31 @@
|
||||
"integrity": "sha512-5O7H5c/7YlojphYNrK02LlDIV2GNPYisKwHm2QTKjNZeEzezCbwYs9swJySv2UfPMyZ0VdsmMv7jIlD/IKYQpQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@bcoe/v8-coverage": "^0.2.3",
|
||||
"@jest/console": "^26.6.2",
|
||||
"@jest/test-result": "^26.3.0",
|
||||
"@jest/transform": "^26.3.0",
|
||||
"@jest/types": "^26.6.2",
|
||||
"@types/istanbul-lib-coverage": "^2.0.0",
|
||||
"collect-v8-coverage": "^1.0.0"
|
||||
"chalk": "^4.0.0",
|
||||
"collect-v8-coverage": "^1.0.0",
|
||||
"exit": "^0.1.2",
|
||||
"glob": "^7.1.2",
|
||||
"graceful-fs": "^4.2.4",
|
||||
"istanbul-lib-coverage": "^3.0.0",
|
||||
"istanbul-lib-instrument": "^4.0.3",
|
||||
"istanbul-lib-report": "^3.0.0",
|
||||
"istanbul-lib-source-maps": "^4.0.0",
|
||||
"istanbul-reports": "^3.0.2",
|
||||
"jest-haste-map": "^26.3.0",
|
||||
"jest-resolve": "^26.4.0",
|
||||
"jest-util": "^26.3.0",
|
||||
"jest-worker": "^26.3.0",
|
||||
"slash": "^3.0.0",
|
||||
"source-map": "^0.6.0",
|
||||
"string-length": "^4.0.1",
|
||||
"terminal-link": "^2.0.0",
|
||||
"v8-to-istanbul": "^5.0.1"
|
||||
},
|
||||
"dependencies": {
|
||||
"@jest/types": {
|
||||
@ -14852,9 +14887,9 @@
|
||||
"dev": true
|
||||
},
|
||||
"@stencil/vue-output-target": {
|
||||
"version": "0.3.0",
|
||||
"resolved": "https://registry.npmjs.org/@stencil/vue-output-target/-/vue-output-target-0.3.0.tgz",
|
||||
"integrity": "sha512-uiBe+o7M+NU0gMRgJfrlepxLPBXK0lX4TL2jIPwhBfxYw++pbtg7BLRO2HxE69GR0nxw+7Uf3uJzOGbMsl+ZUQ==",
|
||||
"version": "0.4.1",
|
||||
"resolved": "https://registry.npmjs.org/@stencil/vue-output-target/-/vue-output-target-0.4.1.tgz",
|
||||
"integrity": "sha512-B4urIlIb+I95NkKeCt3Ygpor1D0x5RMezuFyCFp6DYXshUaT1TbiJcW1FgA+gfwlquNzT1AMvEbi96YLnsOg3w==",
|
||||
"dev": true
|
||||
},
|
||||
"@stylelint/postcss-css-in-js": {
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@ionic/core",
|
||||
"version": "5.5.4",
|
||||
"version": "5.5.5",
|
||||
"description": "Base components for Ionic",
|
||||
"keywords": [
|
||||
"ionic",
|
||||
@ -40,7 +40,7 @@
|
||||
"@rollup/plugin-node-resolve": "^8.4.0",
|
||||
"@rollup/plugin-virtual": "^2.0.3",
|
||||
"@stencil/sass": "1.3.2",
|
||||
"@stencil/vue-output-target": "0.3.0",
|
||||
"@stencil/vue-output-target": "^0.4.1",
|
||||
"@types/jest": "^26.0.20",
|
||||
"@types/node": "^14.6.0",
|
||||
"@types/puppeteer": "5.4.3",
|
||||
|
||||
8
core/src/components.d.ts
vendored
8
core/src/components.d.ts
vendored
@ -2034,6 +2034,10 @@ export namespace Components {
|
||||
* Sets the behavior for the cancel button. Defaults to `"never"`. Setting to `"focus"` shows the cancel button on focus. Setting to `"never"` hides the cancel button. Setting to `"always"` shows the cancel button regardless of focus state.
|
||||
*/
|
||||
"showCancelButton": 'never' | 'focus' | 'always';
|
||||
/**
|
||||
* Sets the behavior for the clear button. Defaults to `"focus"`. Setting to `"focus"` shows the clear button on focus if the input is not empty. Setting to `"never"` hides the clear button. Setting to `"always"` shows the clear button regardless of focus state, but only if the input is not empty.
|
||||
*/
|
||||
"showClearButton": 'never' | 'focus' | 'always';
|
||||
/**
|
||||
* If `true`, enable spellcheck on the input.
|
||||
*/
|
||||
@ -5336,6 +5340,10 @@ declare namespace LocalJSX {
|
||||
* Sets the behavior for the cancel button. Defaults to `"never"`. Setting to `"focus"` shows the cancel button on focus. Setting to `"never"` hides the cancel button. Setting to `"always"` shows the cancel button regardless of focus state.
|
||||
*/
|
||||
"showCancelButton"?: 'never' | 'focus' | 'always';
|
||||
/**
|
||||
* Sets the behavior for the clear button. Defaults to `"focus"`. Setting to `"focus"` shows the clear button on focus if the input is not empty. Setting to `"never"` hides the clear button. Setting to `"always"` shows the clear button regardless of focus state, but only if the input is not empty.
|
||||
*/
|
||||
"showClearButton"?: 'never' | 'focus' | 'always';
|
||||
/**
|
||||
* If `true`, enable spellcheck on the input.
|
||||
*/
|
||||
|
||||
@ -120,7 +120,7 @@ export class Header implements ComponentInterface {
|
||||
* as well as progressively showing/hiding the main header
|
||||
* border as the top-most toolbar collapses or expands.
|
||||
*/
|
||||
const toolbarIntersection = (ev: any) => { handleToolbarIntersection(ev, mainHeaderIndex, scrollHeaderIndex); };
|
||||
const toolbarIntersection = (ev: any) => { handleToolbarIntersection(ev, mainHeaderIndex, scrollHeaderIndex, this.scrollEl!); };
|
||||
|
||||
this.intersectionObserver = new IntersectionObserver(toolbarIntersection, { root: contentEl, threshold: [0.25, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1] });
|
||||
this.intersectionObserver.observe(scrollHeaderIndex.toolbars[scrollHeaderIndex.toolbars.length - 1].el);
|
||||
|
||||
@ -72,7 +72,7 @@ export const setToolbarBackgroundOpacity = (toolbar: ToolbarIndex, opacity?: num
|
||||
}
|
||||
};
|
||||
|
||||
const handleToolbarBorderIntersection = (ev: any, mainHeaderIndex: HeaderIndex) => {
|
||||
const handleToolbarBorderIntersection = (ev: any, mainHeaderIndex: HeaderIndex, scrollTop: number) => {
|
||||
if (!ev[0].isIntersecting) { return; }
|
||||
|
||||
/**
|
||||
@ -80,8 +80,13 @@ const handleToolbarBorderIntersection = (ev: any, mainHeaderIndex: HeaderIndex)
|
||||
* does not always reset the scrollTop position to 0 when letting go. It will
|
||||
* set to 1 once the rubber band effect has ended. This causes the background to
|
||||
* appear slightly on certain app setups.
|
||||
*
|
||||
* Additionally, we check if user is rubber banding (scrolling is negative)
|
||||
* as this can mean they are using pull to refresh. Once the refresher starts,
|
||||
* the content is transformed which can cause the intersection observer to erroneously
|
||||
* fire here as well.
|
||||
*/
|
||||
const scale = (ev[0].intersectionRatio > 0.9) ? 0 : ((1 - ev[0].intersectionRatio) * 100) / 75;
|
||||
const scale = (ev[0].intersectionRatio > 0.9 || scrollTop <= 0) ? 0 : ((1 - ev[0].intersectionRatio) * 100) / 75;
|
||||
|
||||
mainHeaderIndex.toolbars.forEach(toolbar => {
|
||||
setToolbarBackgroundOpacity(toolbar, (scale === 1) ? undefined : scale);
|
||||
@ -93,9 +98,10 @@ const handleToolbarBorderIntersection = (ev: any, mainHeaderIndex: HeaderIndex)
|
||||
* and show the primary toolbar content. If the toolbars are not intersecting,
|
||||
* hide the primary toolbar content and show the scrollable toolbar content
|
||||
*/
|
||||
export const handleToolbarIntersection = (ev: any, mainHeaderIndex: HeaderIndex, scrollHeaderIndex: HeaderIndex) => {
|
||||
export const handleToolbarIntersection = (ev: any, mainHeaderIndex: HeaderIndex, scrollHeaderIndex: HeaderIndex, scrollEl: HTMLElement) => {
|
||||
writeTask(() => {
|
||||
handleToolbarBorderIntersection(ev, mainHeaderIndex);
|
||||
const scrollTop = scrollEl.scrollTop;
|
||||
handleToolbarBorderIntersection(ev, mainHeaderIndex, scrollTop);
|
||||
|
||||
const event = ev[0];
|
||||
|
||||
@ -127,7 +133,7 @@ export const handleToolbarIntersection = (ev: any, mainHeaderIndex: HeaderIndex,
|
||||
|
||||
const hasValidIntersection = (intersection.x === 0 && intersection.y === 0) || (intersection.width !== 0 && intersection.height !== 0);
|
||||
|
||||
if (hasValidIntersection) {
|
||||
if (hasValidIntersection && scrollTop > 0) {
|
||||
setHeaderActive(mainHeaderIndex);
|
||||
setHeaderActive(scrollHeaderIndex, false);
|
||||
setToolbarBackgroundOpacity(mainHeaderIndex.toolbars[0]);
|
||||
|
||||
@ -10,7 +10,7 @@
|
||||
* @prop --progress-background: Color of the progress bar
|
||||
* @prop --buffer-background: Color of the buffer bar
|
||||
*/
|
||||
--background: #{ion-color(primary, base, 0.2)};
|
||||
--background: #{ion-color(primary, base, 0.3)};
|
||||
--progress-background: #{ion-color(primary, base)};
|
||||
--buffer-background: var(--background);
|
||||
display: block;
|
||||
@ -27,7 +27,7 @@
|
||||
|
||||
:host(.ion-color) {
|
||||
--progress-background: #{current-color(base)};
|
||||
--buffer-background: #{current-color(base, 0.2)};
|
||||
--buffer-background: #{current-color(base, 0.3)};
|
||||
}
|
||||
|
||||
// indeterminate has no progress-buffer-bar, so it will be added to the host
|
||||
@ -39,22 +39,34 @@
|
||||
.progress-indeterminate,
|
||||
.indeterminate-bar-primary,
|
||||
.indeterminate-bar-secondary,
|
||||
.progress-buffer-bar,
|
||||
.progress-buffer-bar:before,
|
||||
.buffer-circles {
|
||||
.progress-buffer-bar {
|
||||
@include position(0, 0, 0, 0);
|
||||
|
||||
position: absolute;
|
||||
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.buffer-circles-container,
|
||||
.buffer-circles {
|
||||
@include position(0, 0, 0, 0);
|
||||
position: absolute;
|
||||
}
|
||||
|
||||
// Extend a bit to overflow. The size of animated distance.
|
||||
.buffer-circles {
|
||||
/* stylelint-disable property-blacklist */
|
||||
right: -10px;
|
||||
left: -10px;
|
||||
/* stylelint-enable property-blacklist */
|
||||
}
|
||||
|
||||
// Determinate progress bar
|
||||
// --------------------------------------------------
|
||||
|
||||
.progress,
|
||||
.progress-buffer-bar {
|
||||
.progress-buffer-bar,
|
||||
.buffer-circles-container {
|
||||
/* stylelint-disable-next-line property-blacklist */
|
||||
transform-origin: left top;
|
||||
|
||||
@ -72,17 +84,13 @@
|
||||
}
|
||||
|
||||
.progress-buffer-bar {
|
||||
// It's currently here because --buffer-background has an alpha
|
||||
// Otherwise the buffer circles would be seen through
|
||||
background: #fff;
|
||||
|
||||
z-index: 1; // Make it behind the progress
|
||||
background: var(--buffer-background);
|
||||
|
||||
&:before {
|
||||
background: var(--buffer-background);
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
content: "";
|
||||
}
|
||||
.buffer-circles-container {
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
// MD based animation on indeterminate type
|
||||
@ -109,7 +117,7 @@
|
||||
top: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
left: -54.888891%;
|
||||
left: -54.888891%;
|
||||
/* stylelint-enable property-blacklist */
|
||||
|
||||
animation: secondary-indeterminate-translate 2s infinite linear;
|
||||
@ -136,18 +144,7 @@
|
||||
// --------------------------------------------------
|
||||
|
||||
:host(.progress-bar-reversed) {
|
||||
.progress,
|
||||
.progress-buffer-bar {
|
||||
/* stylelint-disable-next-line property-blacklist */
|
||||
transform-origin: right top;
|
||||
}
|
||||
|
||||
.buffer-circles,
|
||||
.indeterminate-bar-primary,
|
||||
.indeterminate-bar-secondary,
|
||||
.progress-indeterminate {
|
||||
animation-direction: reverse;
|
||||
}
|
||||
transform: scaleX(-1);
|
||||
}
|
||||
|
||||
// Progress paused
|
||||
|
||||
@ -89,7 +89,18 @@ const renderProgress = (value: number, buffer: number) => {
|
||||
|
||||
return [
|
||||
<div class="progress" style={{ transform: `scaleX(${finalValue})` }}></div>,
|
||||
finalBuffer !== 1 && <div class="buffer-circles"></div>,
|
||||
/**
|
||||
* Buffer circles with two container to move
|
||||
* the circles behind the buffer progress
|
||||
* with respecting the animation.
|
||||
* When finalBuffer === 1, we use display: none
|
||||
* instead of removing the element to avoid flickering.
|
||||
*/
|
||||
<div class={{ 'buffer-circles-container': true, 'ion-hide': finalBuffer === 1 }} style={{ transform: `translateX(${finalBuffer * 100}%)` }}>
|
||||
<div class="buffer-circles-container" style={{ transform: `translateX(-${finalBuffer * 100}%)` }}>
|
||||
<div class="buffer-circles"></div>
|
||||
</div>
|
||||
</div>,
|
||||
<div class="progress-buffer-bar" style={{ transform: `scaleX(${finalBuffer})` }}></div>,
|
||||
];
|
||||
};
|
||||
|
||||
@ -9,7 +9,9 @@
|
||||
<link href="../../../../../scripts/testing/styles.css" rel="stylesheet">
|
||||
<script src="../../../../../scripts/testing/scripts.js"></script>
|
||||
<script nomodule src="../../../../../dist/ionic/ionic.js"></script>
|
||||
<script type="module" src="../../../../../dist/ionic/ionic.esm.js"></script> <style>
|
||||
<script type="module" src="../../../../../dist/ionic/ionic.esm.js"></script>
|
||||
|
||||
<style>
|
||||
.custom-bar-background {
|
||||
--buffer-background: red;
|
||||
}
|
||||
@ -126,13 +128,26 @@
|
||||
</ion-list-header>
|
||||
<ion-progress-bar color="tertiary" buffer="0"></ion-progress-bar>
|
||||
|
||||
</ion-list>
|
||||
<ion-list-header>
|
||||
<ion-label>
|
||||
Buffer (change buffer with slider)
|
||||
</ion-label>
|
||||
</ion-list-header>
|
||||
<ion-progress-bar class="progressBarBuffer" value="0.20" buffer="0.4"></ion-progress-bar>
|
||||
<ion-progress-bar class="progressBarBuffer" value="0.20" buffer="0.4" reversed="true"></ion-progress-bar>
|
||||
|
||||
<ion-item>
|
||||
<ion-range pin="true" value="0" id="progressValueBuffer">
|
||||
<ion-label slot="start">0</ion-label>
|
||||
<ion-label slot="end">100</ion-label>
|
||||
</ion-range>
|
||||
</ion-item>
|
||||
</ion-list>
|
||||
</ion-content>
|
||||
|
||||
</ion-app>
|
||||
|
||||
<script>
|
||||
// Progress Bar Value
|
||||
const progressValue = document.getElementById('progressValue');
|
||||
const progressBar = document.getElementById('progressBar');
|
||||
|
||||
@ -140,6 +155,13 @@
|
||||
progressBar.value = ev.detail.value / 100;
|
||||
});
|
||||
|
||||
// Progress Bar Buffer
|
||||
const progressValueBuffer = document.getElementById('progressValueBuffer');
|
||||
const progressBarBuffer = document.querySelectorAll('.progressBarBuffer');
|
||||
|
||||
progressValueBuffer.addEventListener('ionChange', function (ev) {
|
||||
progressBarBuffer.forEach(ele => ele.buffer = ev.detail.value / 100);
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
|
||||
|
||||
@ -328,6 +328,7 @@ export default defineComponent({
|
||||
| `placeholder` | `placeholder` | Set the input's placeholder. `placeholder` can accept either plaintext or HTML as a string. To display characters normally reserved for HTML, they must be escaped. For example `<Ionic>` would become `<Ionic>` For more information: [Security Documentation](https://ionicframework.com/docs/faq/security) | `string` | `'Search'` |
|
||||
| `searchIcon` | `search-icon` | The icon to use as the search icon. Defaults to `"search-outline"` in `ios` mode and `"search-sharp"` in `md` mode. | `string \| undefined` | `undefined` |
|
||||
| `showCancelButton` | `show-cancel-button` | Sets the behavior for the cancel button. Defaults to `"never"`. Setting to `"focus"` shows the cancel button on focus. Setting to `"never"` hides the cancel button. Setting to `"always"` shows the cancel button regardless of focus state. | `"always" \| "focus" \| "never"` | `'never'` |
|
||||
| `showClearButton` | `show-clear-button` | Sets the behavior for the clear button. Defaults to `"focus"`. Setting to `"focus"` shows the clear button on focus if the input is not empty. Setting to `"never"` hides the clear button. Setting to `"always"` shows the clear button regardless of focus state, but only if the input is not empty. | `"always" \| "focus" \| "never"` | `'focus'` |
|
||||
| `spellcheck` | `spellcheck` | If `true`, enable spellcheck on the input. | `boolean` | `false` |
|
||||
| `type` | `type` | Set the type of the input. | `"email" \| "number" \| "password" \| "search" \| "tel" \| "text" \| "url"` | `'search'` |
|
||||
| `value` | `value` | the value of the searchbar. | `null \| string \| undefined` | `''` |
|
||||
|
||||
@ -145,7 +145,7 @@
|
||||
appearance: none;
|
||||
}
|
||||
|
||||
:host(.searchbar-has-value.searchbar-has-focus) .searchbar-clear-button {
|
||||
:host(.searchbar-has-value.searchbar-should-show-clear) .searchbar-clear-button {
|
||||
display: block;
|
||||
}
|
||||
|
||||
|
||||
@ -121,6 +121,16 @@ export class Searchbar implements ComponentInterface {
|
||||
*/
|
||||
@Prop() showCancelButton: 'never' | 'focus' | 'always' = 'never';
|
||||
|
||||
/**
|
||||
* Sets the behavior for the clear button. Defaults to `"focus"`.
|
||||
* Setting to `"focus"` shows the clear button on focus if the
|
||||
* input is not empty.
|
||||
* Setting to `"never"` hides the clear button.
|
||||
* Setting to `"always"` shows the clear button regardless
|
||||
* of focus state, but only if the input is not empty.
|
||||
*/
|
||||
@Prop() showClearButton: 'never' | 'focus' | 'always' = 'focus';
|
||||
|
||||
/**
|
||||
* If `true`, enable spellcheck on the input.
|
||||
*/
|
||||
@ -231,7 +241,7 @@ export class Searchbar implements ComponentInterface {
|
||||
/**
|
||||
* Clears the input field and triggers the control change.
|
||||
*/
|
||||
private onClearInput = (ev?: Event) => {
|
||||
private onClearInput = (ev?: Event, shouldFocus?: boolean) => {
|
||||
this.ionClear.emit();
|
||||
|
||||
if (ev) {
|
||||
@ -246,6 +256,16 @@ export class Searchbar implements ComponentInterface {
|
||||
if (value !== '') {
|
||||
this.value = '';
|
||||
this.ionInput.emit();
|
||||
|
||||
/**
|
||||
* When tapping clear button
|
||||
* ensure input is focused after
|
||||
* clearing input so users
|
||||
* can quickly start typing.
|
||||
*/
|
||||
if (shouldFocus && !this.focused) {
|
||||
this.setFocus();
|
||||
}
|
||||
}
|
||||
}, 16 * 4);
|
||||
}
|
||||
@ -419,6 +439,20 @@ export class Searchbar implements ComponentInterface {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines whether or not the clear button should be visible onscreen.
|
||||
* Clear button should be shown if one of two conditions applies:
|
||||
* 1. `showClearButton` is set to `always`.
|
||||
* 2. `showClearButton` is set to `focus`, and the searchbar has been focused.
|
||||
*/
|
||||
private shouldShowClearButton(): boolean {
|
||||
if ((this.showClearButton === 'never') || (this.showClearButton === 'focus' && !this.focused)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
render() {
|
||||
const { cancelButtonText } = this;
|
||||
const animated = this.animated && config.getBoolean('animated', true);
|
||||
@ -460,6 +494,7 @@ export class Searchbar implements ComponentInterface {
|
||||
'searchbar-has-value': this.hasValue(),
|
||||
'searchbar-left-aligned': this.shouldAlignLeft,
|
||||
'searchbar-has-focus': this.focused,
|
||||
'searchbar-should-show-clear': this.shouldShowClearButton(),
|
||||
'searchbar-should-show-cancel': this.shouldShowCancelButton()
|
||||
})}
|
||||
>
|
||||
@ -492,8 +527,8 @@ export class Searchbar implements ComponentInterface {
|
||||
type="button"
|
||||
no-blur
|
||||
class="searchbar-clear-button"
|
||||
onMouseDown={this.onClearInput}
|
||||
onTouchStart={this.onClearInput}
|
||||
onMouseDown={ev => this.onClearInput(ev, true)}
|
||||
onTouchStart={ev => this.onClearInput(ev, true)}
|
||||
>
|
||||
<ion-icon aria-hidden="true" mode={mode} icon={clearIcon} lazy={false} class="searchbar-clear-icon"></ion-icon>
|
||||
</button>
|
||||
|
||||
@ -49,6 +49,14 @@
|
||||
<ion-searchbar id="noCancel" value="after view" autocorrect="off" autocomplete="off" spellcheck="true" type="text" show-cancel-button="focus">
|
||||
</ion-searchbar>
|
||||
|
||||
<h5 class="ion-padding-start ion-padding-top"> Search - No Clear Button </h5>
|
||||
<ion-searchbar id="noCancel" value="after view" type="text" show-clear-button="never">
|
||||
</ion-searchbar>
|
||||
|
||||
<h5 class="ion-padding-start ion-padding-top"> Search - Always Show Clear Button </h5>
|
||||
<ion-searchbar id="noCancel" value="after view" type="text" show-clear-button="always">
|
||||
</ion-searchbar>
|
||||
|
||||
<h5 class="ion-padding-start ion-padding-top"> Search - Input mode set to numeric</h5>
|
||||
<ion-searchbar id="noCancel" value="after view" inputmode="numeric" autocorrect="off" autocomplete="off" spellcheck="true" type="text" show-cancel-button="focus">
|
||||
</ion-searchbar>
|
||||
|
||||
@ -132,4 +132,5 @@ ion-modal.ios {
|
||||
--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);
|
||||
}
|
||||
|
||||
@ -52,6 +52,9 @@
|
||||
font-size: 48px;
|
||||
}
|
||||
|
||||
ion-progress-bar {
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
@ -619,10 +622,6 @@
|
||||
|
||||
<section>
|
||||
<p>
|
||||
<ion-toolbar>
|
||||
<ion-title>Default</ion-title>
|
||||
</ion-toolbar>
|
||||
|
||||
<ion-toolbar>
|
||||
<ion-buttons slot="start">
|
||||
<ion-button color="danger">
|
||||
@ -759,6 +758,18 @@
|
||||
<ion-title>Dark</ion-title>
|
||||
</ion-toolbar>
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<ion-progress-bar value="0.5"></ion-progress-bar>
|
||||
<ion-progress-bar value="0.5" color="secondary"></ion-progress-bar>
|
||||
<ion-progress-bar value="0.5" color="tertiary"></ion-progress-bar>
|
||||
<ion-progress-bar type="indeterminate" color="danger"></ion-progress-bar>
|
||||
<ion-progress-bar type="indeterminate" color="warning"></ion-progress-bar>
|
||||
<ion-progress-bar value="0.2" buffer="0.3" color="success"></ion-progress-bar>
|
||||
<ion-progress-bar value="0.5" color="light"></ion-progress-bar>
|
||||
<ion-progress-bar value="0.5" color="medium"></ion-progress-bar>
|
||||
<ion-progress-bar value="0.2" buffer="0.3" color="dark"></ion-progress-bar>
|
||||
</p>
|
||||
</section>
|
||||
</div>
|
||||
</ion-content>
|
||||
@ -924,6 +935,9 @@
|
||||
<ion-header translucent="true">
|
||||
<ion-toolbar>
|
||||
<ion-title>Super Modal</ion-title>
|
||||
<ion-buttons slot="start">
|
||||
<ion-button class="dismiss">Close</ion-button>
|
||||
</ion-buttons>
|
||||
</ion-toolbar>
|
||||
</ion-header>
|
||||
<ion-content fullscreen="true">
|
||||
@ -932,10 +946,21 @@
|
||||
<ion-title size="large">Super Modal</ion-title>
|
||||
</ion-toolbar>
|
||||
</ion-header>
|
||||
<div class="ion-padding">
|
||||
<h1>Content of doom</h1>
|
||||
<div>Here's some more content</div>
|
||||
<ion-button class="dismiss">Dismiss Modal</ion-button>
|
||||
|
||||
<br />
|
||||
|
||||
<div>
|
||||
<ion-list>
|
||||
<ion-item>
|
||||
<ion-label>Item A</ion-label>
|
||||
</ion-item>
|
||||
<ion-item>
|
||||
<ion-label>Item B</ion-label>
|
||||
</ion-item>
|
||||
<ion-item>
|
||||
<ion-label>Item C</ion-label>
|
||||
</ion-item>
|
||||
</ion-list>
|
||||
</div>
|
||||
</ion-content>
|
||||
`;
|
||||
|
||||
@ -91,13 +91,15 @@ export const config: Config = {
|
||||
{
|
||||
elements: ['ion-checkbox', 'ion-toggle'],
|
||||
targetAttr: 'checked',
|
||||
event: 'v-ionChange',
|
||||
// TODO Ionic v6 remove in favor of v-ion-change
|
||||
event: ['v-ionChange', 'v-ion-change'],
|
||||
externalEvent: 'ionChange'
|
||||
},
|
||||
{
|
||||
elements: ['ion-datetime', 'ion-input', 'ion-radio-group', 'ion-radio', 'ion-range', 'ion-searchbar', 'ion-segment', 'ion-segment-button', 'ion-select', 'ion-textarea'],
|
||||
targetAttr: 'value',
|
||||
event: 'v-ionChange',
|
||||
// TODO Ionic v6 remove in favor of v-ion-change
|
||||
event: ['v-ionChange', 'v-ion-change'],
|
||||
externalEvent: 'ionChange'
|
||||
}
|
||||
],
|
||||
|
||||
Reference in New Issue
Block a user