ion-searchbar.cjs.entry.js 34 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432
  1. /*!
  2. * (C) Ionic http://ionicframework.com - MIT License
  3. */
  4. 'use strict';
  5. Object.defineProperty(exports, '__esModule', { value: true });
  6. const index = require('./index-2e236a04.js');
  7. const helpers = require('./helpers-8a48fdea.js');
  8. const dir = require('./dir-94c21456.js');
  9. const theme = require('./theme-d1c573d2.js');
  10. const index$2 = require('./index-073c7cdc.js');
  11. const index$1 = require('./index-cc858e97.js');
  12. const ionicGlobal = require('./ionic-global-6dea5a96.js');
  13. const searchbarIosCss = ".sc-ion-searchbar-ios-h{--placeholder-color:initial;--placeholder-font-style:initial;--placeholder-font-weight:initial;--placeholder-opacity:var(--ion-placeholder-opacity, 0.6);-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:-ms-flexbox;display:flex;position:relative;-ms-flex-align:center;align-items:center;width:100%;color:var(--color);font-family:var(--ion-font-family, inherit);-webkit-box-sizing:border-box;box-sizing:border-box}.ion-color.sc-ion-searchbar-ios-h{color:var(--ion-color-contrast)}.ion-color.sc-ion-searchbar-ios-h .searchbar-input.sc-ion-searchbar-ios{background:var(--ion-color-base)}.ion-color.sc-ion-searchbar-ios-h .searchbar-clear-button.sc-ion-searchbar-ios,.ion-color.sc-ion-searchbar-ios-h .searchbar-cancel-button.sc-ion-searchbar-ios,.ion-color.sc-ion-searchbar-ios-h .searchbar-search-icon.sc-ion-searchbar-ios{color:inherit}.searchbar-search-icon.sc-ion-searchbar-ios{color:var(--icon-color);pointer-events:none}.searchbar-input-container.sc-ion-searchbar-ios{display:block;position:relative;-ms-flex-negative:1;flex-shrink:1;width:100%}.searchbar-input.sc-ion-searchbar-ios{font-family:inherit;font-size:inherit;font-style:inherit;font-weight:inherit;letter-spacing:inherit;text-decoration:inherit;text-indent:inherit;text-overflow:inherit;text-transform:inherit;text-align:inherit;white-space:inherit;color:inherit;border-radius:var(--border-radius);display:block;width:100%;min-height:inherit;border:0;outline:none;background:var(--background);font-family:inherit;-webkit-box-shadow:var(--box-shadow);box-shadow:var(--box-shadow);-webkit-box-sizing:border-box;box-sizing:border-box;-webkit-appearance:none;-moz-appearance:none;appearance:none}.searchbar-input.sc-ion-searchbar-ios::-webkit-input-placeholder{color:var(--placeholder-color);font-family:inherit;font-style:var(--placeholder-font-style);font-weight:var(--placeholder-font-weight);opacity:var(--placeholder-opacity)}.searchbar-input.sc-ion-searchbar-ios::-moz-placeholder{color:var(--placeholder-color);font-family:inherit;font-style:var(--placeholder-font-style);font-weight:var(--placeholder-font-weight);opacity:var(--placeholder-opacity)}.searchbar-input.sc-ion-searchbar-ios:-ms-input-placeholder{color:var(--placeholder-color);font-family:inherit;font-style:var(--placeholder-font-style);font-weight:var(--placeholder-font-weight);opacity:var(--placeholder-opacity)}.searchbar-input.sc-ion-searchbar-ios::-ms-input-placeholder{color:var(--placeholder-color);font-family:inherit;font-style:var(--placeholder-font-style);font-weight:var(--placeholder-font-weight);opacity:var(--placeholder-opacity)}.searchbar-input.sc-ion-searchbar-ios::placeholder{color:var(--placeholder-color);font-family:inherit;font-style:var(--placeholder-font-style);font-weight:var(--placeholder-font-weight);opacity:var(--placeholder-opacity)}.searchbar-input.sc-ion-searchbar-ios::-webkit-search-cancel-button,.searchbar-input.sc-ion-searchbar-ios::-ms-clear{display:none}.searchbar-cancel-button.sc-ion-searchbar-ios{margin-left:0;margin-right:0;margin-top:0;margin-bottom:0;display:none;height:100%;border:0;outline:none;color:var(--cancel-button-color);cursor:pointer;-webkit-appearance:none;-moz-appearance:none;appearance:none}.searchbar-cancel-button.sc-ion-searchbar-ios>div.sc-ion-searchbar-ios{display:-ms-flexbox;display:flex;-ms-flex-align:center;align-items:center;-ms-flex-pack:center;justify-content:center;width:100%;height:100%}.searchbar-clear-button.sc-ion-searchbar-ios{margin-left:0;margin-right:0;margin-top:0;margin-bottom:0;padding-left:0;padding-right:0;padding-top:0;padding-bottom:0;display:none;min-height:0;outline:none;color:var(--clear-button-color);-webkit-appearance:none;-moz-appearance:none;appearance:none}.searchbar-clear-button.sc-ion-searchbar-ios:focus{opacity:0.5}.searchbar-has-value.searchbar-should-show-clear.sc-ion-searchbar-ios-h .searchbar-clear-button.sc-ion-searchbar-ios{display:block}.searchbar-disabled.sc-ion-searchbar-ios-h{cursor:default;opacity:0.4;pointer-events:none}.sc-ion-searchbar-ios-h{--background:rgba(var(--ion-text-color-rgb, 0, 0, 0), 0.07);--border-radius:10px;--box-shadow:none;--cancel-button-color:var(--ion-color-primary, #0054e9);--clear-button-color:var(--ion-color-step-600, var(--ion-text-color-step-400, #666666));--color:var(--ion-text-color, #000);--icon-color:var(--ion-color-step-600, var(--ion-text-color-step-400, #666666));-webkit-padding-start:12px;padding-inline-start:12px;-webkit-padding-end:12px;padding-inline-end:12px;padding-top:12px;padding-bottom:12px;min-height:60px;contain:content}.searchbar-input-container.sc-ion-searchbar-ios{min-height:36px}.searchbar-search-icon.sc-ion-searchbar-ios{-webkit-margin-start:calc(50% - 60px);margin-inline-start:calc(50% - 60px);top:0;position:absolute;width:1.375rem;height:100%;contain:strict}.searchbar-search-icon.sc-ion-searchbar-ios{inset-inline-start:5px}.searchbar-input.sc-ion-searchbar-ios{-webkit-padding-start:0px;padding-inline-start:0px;-webkit-padding-end:0px;padding-inline-end:0px;padding-top:6px;padding-bottom:6px;height:100%;font-size:1.0625rem;font-weight:400;contain:strict}.searchbar-has-value.searchbar-should-show-clear.sc-ion-searchbar-ios-h .searchbar-input.sc-ion-searchbar-ios{-webkit-padding-start:1.75rem;padding-inline-start:1.75rem;-webkit-padding-end:1.75rem;padding-inline-end:1.75rem}.searchbar-clear-button.sc-ion-searchbar-ios{top:0;background-position:center;position:absolute;width:1.875rem;height:100%;border:0;background-color:transparent}.searchbar-clear-button.sc-ion-searchbar-ios{inset-inline-end:0}.searchbar-clear-icon.sc-ion-searchbar-ios{width:1.125rem;height:100%}.searchbar-cancel-button.sc-ion-searchbar-ios{-webkit-padding-start:12px;padding-inline-start:12px;-webkit-padding-end:0;padding-inline-end:0;padding-top:0;padding-bottom:0;-ms-flex-negative:0;flex-shrink:0;background-color:transparent;font-size:17px}.searchbar-left-aligned.sc-ion-searchbar-ios-h .searchbar-search-icon.sc-ion-searchbar-ios{-webkit-margin-start:0;margin-inline-start:0}.searchbar-left-aligned.sc-ion-searchbar-ios-h .searchbar-input.sc-ion-searchbar-ios{-webkit-padding-start:1.875rem;padding-inline-start:1.875rem}.searchbar-has-focus.sc-ion-searchbar-ios-h .searchbar-cancel-button.sc-ion-searchbar-ios,.searchbar-should-show-cancel.sc-ion-searchbar-ios-h .searchbar-cancel-button.sc-ion-searchbar-ios,.searchbar-animated.sc-ion-searchbar-ios-h .searchbar-cancel-button.sc-ion-searchbar-ios{display:block}.searchbar-animated.sc-ion-searchbar-ios-h .searchbar-search-icon.sc-ion-searchbar-ios,.searchbar-animated.sc-ion-searchbar-ios-h .searchbar-input.sc-ion-searchbar-ios{-webkit-transition:all 300ms ease;transition:all 300ms ease}.searchbar-animated.searchbar-has-focus.sc-ion-searchbar-ios-h .searchbar-cancel-button.sc-ion-searchbar-ios,.searchbar-animated.searchbar-should-show-cancel.sc-ion-searchbar-ios-h .searchbar-cancel-button.sc-ion-searchbar-ios{opacity:1;pointer-events:auto}.searchbar-animated.sc-ion-searchbar-ios-h .searchbar-cancel-button.sc-ion-searchbar-ios{-webkit-margin-end:-100%;margin-inline-end:-100%;-webkit-transform:translate3d(0, 0, 0);transform:translate3d(0, 0, 0);-webkit-transition:all 300ms ease;transition:all 300ms ease;opacity:0;pointer-events:none}.searchbar-no-animate.sc-ion-searchbar-ios-h .searchbar-search-icon.sc-ion-searchbar-ios,.searchbar-no-animate.sc-ion-searchbar-ios-h .searchbar-input.sc-ion-searchbar-ios,.searchbar-no-animate.sc-ion-searchbar-ios-h .searchbar-cancel-button.sc-ion-searchbar-ios{-webkit-transition-duration:0ms;transition-duration:0ms}.ion-color.sc-ion-searchbar-ios-h .searchbar-cancel-button.sc-ion-searchbar-ios{color:var(--ion-color-base)}@media (any-hover: hover){.ion-color.sc-ion-searchbar-ios-h .searchbar-cancel-button.sc-ion-searchbar-ios:hover{color:var(--ion-color-tint)}}ion-toolbar.sc-ion-searchbar-ios-h,ion-toolbar .sc-ion-searchbar-ios-h{padding-top:1px;padding-bottom:15px;min-height:52px}ion-toolbar.ion-color.sc-ion-searchbar-ios-h:not(.ion-color),ion-toolbar.ion-color .sc-ion-searchbar-ios-h:not(.ion-color){color:inherit}ion-toolbar.ion-color.sc-ion-searchbar-ios-h:not(.ion-color) .searchbar-cancel-button.sc-ion-searchbar-ios,ion-toolbar.ion-color .sc-ion-searchbar-ios-h:not(.ion-color) .searchbar-cancel-button.sc-ion-searchbar-ios{color:currentColor}ion-toolbar.ion-color.sc-ion-searchbar-ios-h .searchbar-search-icon.sc-ion-searchbar-ios,ion-toolbar.ion-color .sc-ion-searchbar-ios-h .searchbar-search-icon.sc-ion-searchbar-ios{color:currentColor;opacity:0.5}ion-toolbar.ion-color.sc-ion-searchbar-ios-h:not(.ion-color) .searchbar-input.sc-ion-searchbar-ios,ion-toolbar.ion-color .sc-ion-searchbar-ios-h:not(.ion-color) .searchbar-input.sc-ion-searchbar-ios{background:rgba(var(--ion-color-contrast-rgb), 0.07);color:currentColor}ion-toolbar.ion-color.sc-ion-searchbar-ios-h:not(.ion-color) .searchbar-clear-button.sc-ion-searchbar-ios,ion-toolbar.ion-color .sc-ion-searchbar-ios-h:not(.ion-color) .searchbar-clear-button.sc-ion-searchbar-ios{color:currentColor;opacity:0.5}";
  14. const IonSearchbarIosStyle0 = searchbarIosCss;
  15. const searchbarMdCss = ".sc-ion-searchbar-md-h{--placeholder-color:initial;--placeholder-font-style:initial;--placeholder-font-weight:initial;--placeholder-opacity:var(--ion-placeholder-opacity, 0.6);-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:-ms-flexbox;display:flex;position:relative;-ms-flex-align:center;align-items:center;width:100%;color:var(--color);font-family:var(--ion-font-family, inherit);-webkit-box-sizing:border-box;box-sizing:border-box}.ion-color.sc-ion-searchbar-md-h{color:var(--ion-color-contrast)}.ion-color.sc-ion-searchbar-md-h .searchbar-input.sc-ion-searchbar-md{background:var(--ion-color-base)}.ion-color.sc-ion-searchbar-md-h .searchbar-clear-button.sc-ion-searchbar-md,.ion-color.sc-ion-searchbar-md-h .searchbar-cancel-button.sc-ion-searchbar-md,.ion-color.sc-ion-searchbar-md-h .searchbar-search-icon.sc-ion-searchbar-md{color:inherit}.searchbar-search-icon.sc-ion-searchbar-md{color:var(--icon-color);pointer-events:none}.searchbar-input-container.sc-ion-searchbar-md{display:block;position:relative;-ms-flex-negative:1;flex-shrink:1;width:100%}.searchbar-input.sc-ion-searchbar-md{font-family:inherit;font-size:inherit;font-style:inherit;font-weight:inherit;letter-spacing:inherit;text-decoration:inherit;text-indent:inherit;text-overflow:inherit;text-transform:inherit;text-align:inherit;white-space:inherit;color:inherit;border-radius:var(--border-radius);display:block;width:100%;min-height:inherit;border:0;outline:none;background:var(--background);font-family:inherit;-webkit-box-shadow:var(--box-shadow);box-shadow:var(--box-shadow);-webkit-box-sizing:border-box;box-sizing:border-box;-webkit-appearance:none;-moz-appearance:none;appearance:none}.searchbar-input.sc-ion-searchbar-md::-webkit-input-placeholder{color:var(--placeholder-color);font-family:inherit;font-style:var(--placeholder-font-style);font-weight:var(--placeholder-font-weight);opacity:var(--placeholder-opacity)}.searchbar-input.sc-ion-searchbar-md::-moz-placeholder{color:var(--placeholder-color);font-family:inherit;font-style:var(--placeholder-font-style);font-weight:var(--placeholder-font-weight);opacity:var(--placeholder-opacity)}.searchbar-input.sc-ion-searchbar-md:-ms-input-placeholder{color:var(--placeholder-color);font-family:inherit;font-style:var(--placeholder-font-style);font-weight:var(--placeholder-font-weight);opacity:var(--placeholder-opacity)}.searchbar-input.sc-ion-searchbar-md::-ms-input-placeholder{color:var(--placeholder-color);font-family:inherit;font-style:var(--placeholder-font-style);font-weight:var(--placeholder-font-weight);opacity:var(--placeholder-opacity)}.searchbar-input.sc-ion-searchbar-md::placeholder{color:var(--placeholder-color);font-family:inherit;font-style:var(--placeholder-font-style);font-weight:var(--placeholder-font-weight);opacity:var(--placeholder-opacity)}.searchbar-input.sc-ion-searchbar-md::-webkit-search-cancel-button,.searchbar-input.sc-ion-searchbar-md::-ms-clear{display:none}.searchbar-cancel-button.sc-ion-searchbar-md{margin-left:0;margin-right:0;margin-top:0;margin-bottom:0;display:none;height:100%;border:0;outline:none;color:var(--cancel-button-color);cursor:pointer;-webkit-appearance:none;-moz-appearance:none;appearance:none}.searchbar-cancel-button.sc-ion-searchbar-md>div.sc-ion-searchbar-md{display:-ms-flexbox;display:flex;-ms-flex-align:center;align-items:center;-ms-flex-pack:center;justify-content:center;width:100%;height:100%}.searchbar-clear-button.sc-ion-searchbar-md{margin-left:0;margin-right:0;margin-top:0;margin-bottom:0;padding-left:0;padding-right:0;padding-top:0;padding-bottom:0;display:none;min-height:0;outline:none;color:var(--clear-button-color);-webkit-appearance:none;-moz-appearance:none;appearance:none}.searchbar-clear-button.sc-ion-searchbar-md:focus{opacity:0.5}.searchbar-has-value.searchbar-should-show-clear.sc-ion-searchbar-md-h .searchbar-clear-button.sc-ion-searchbar-md{display:block}.searchbar-disabled.sc-ion-searchbar-md-h{cursor:default;opacity:0.4;pointer-events:none}.sc-ion-searchbar-md-h{--background:var(--ion-background-color, #fff);--border-radius:2px;--box-shadow:0 2px 2px 0 rgba(0, 0, 0, 0.14), 0 3px 1px -2px rgba(0, 0, 0, 0.2), 0 1px 5px 0 rgba(0, 0, 0, 0.12);--cancel-button-color:var(--ion-color-step-900, var(--ion-text-color-step-100, #1a1a1a));--clear-button-color:initial;--color:var(--ion-color-step-850, var(--ion-text-color-step-150, #262626));--icon-color:var(--ion-color-step-600, var(--ion-text-color-step-400, #666666));-webkit-padding-start:8px;padding-inline-start:8px;-webkit-padding-end:8px;padding-inline-end:8px;padding-top:8px;padding-bottom:8px;background:inherit}.searchbar-search-icon.sc-ion-searchbar-md{top:11px;width:1.3125rem;height:1.3125rem}.searchbar-search-icon.sc-ion-searchbar-md{inset-inline-start:16px}.searchbar-cancel-button.sc-ion-searchbar-md{top:0;background-color:transparent;font-size:1.5em}.searchbar-cancel-button.sc-ion-searchbar-md{inset-inline-start:9px}.searchbar-search-icon.sc-ion-searchbar-md,.searchbar-cancel-button.sc-ion-searchbar-md{position:absolute}.searchbar-search-icon.ion-activated.sc-ion-searchbar-md,.searchbar-cancel-button.ion-activated.sc-ion-searchbar-md{background-color:transparent}.searchbar-input.sc-ion-searchbar-md{-webkit-padding-start:3.4375rem;padding-inline-start:3.4375rem;-webkit-padding-end:3.4375rem;padding-inline-end:3.4375rem;padding-top:0.375rem;padding-bottom:0.375rem;background-position:left 8px center;height:auto;font-size:1rem;font-weight:400;line-height:30px}[dir=rtl].sc-ion-searchbar-md-h .searchbar-input.sc-ion-searchbar-md,[dir=rtl] .sc-ion-searchbar-md-h .searchbar-input.sc-ion-searchbar-md{background-position:right 8px center}[dir=rtl].sc-ion-searchbar-md .searchbar-input.sc-ion-searchbar-md{background-position:right 8px center}@supports selector(:dir(rtl)){.searchbar-input.sc-ion-searchbar-md:dir(rtl){background-position:right 8px center}}.searchbar-clear-button.sc-ion-searchbar-md{top:0;padding-left:0;padding-right:0;padding-top:0;padding-bottom:0;position:absolute;height:100%;border:0;background-color:transparent}.searchbar-clear-button.sc-ion-searchbar-md{inset-inline-end:13px}.searchbar-clear-button.ion-activated.sc-ion-searchbar-md{background-color:transparent}.searchbar-clear-icon.sc-ion-searchbar-md{width:1.375rem;height:100%}.searchbar-has-focus.sc-ion-searchbar-md-h .searchbar-search-icon.sc-ion-searchbar-md{display:block}.searchbar-has-focus.sc-ion-searchbar-md-h .searchbar-cancel-button.sc-ion-searchbar-md,.searchbar-should-show-cancel.sc-ion-searchbar-md-h .searchbar-cancel-button.sc-ion-searchbar-md{display:block}.searchbar-has-focus.sc-ion-searchbar-md-h .searchbar-cancel-button.sc-ion-searchbar-md+.searchbar-search-icon.sc-ion-searchbar-md,.searchbar-should-show-cancel.sc-ion-searchbar-md-h .searchbar-cancel-button.sc-ion-searchbar-md+.searchbar-search-icon.sc-ion-searchbar-md{display:none}ion-toolbar.sc-ion-searchbar-md-h,ion-toolbar .sc-ion-searchbar-md-h{-webkit-padding-start:7px;padding-inline-start:7px;-webkit-padding-end:7px;padding-inline-end:7px;padding-top:3px;padding-bottom:3px}";
  16. const IonSearchbarMdStyle0 = searchbarMdCss;
  17. const Searchbar = class {
  18. constructor(hostRef) {
  19. index.registerInstance(this, hostRef);
  20. this.ionInput = index.createEvent(this, "ionInput", 7);
  21. this.ionChange = index.createEvent(this, "ionChange", 7);
  22. this.ionCancel = index.createEvent(this, "ionCancel", 7);
  23. this.ionClear = index.createEvent(this, "ionClear", 7);
  24. this.ionBlur = index.createEvent(this, "ionBlur", 7);
  25. this.ionFocus = index.createEvent(this, "ionFocus", 7);
  26. this.ionStyle = index.createEvent(this, "ionStyle", 7);
  27. this.isCancelVisible = false;
  28. this.shouldAlignLeft = true;
  29. this.inputId = `ion-searchbar-${searchbarIds++}`;
  30. this.inheritedAttributes = {};
  31. /**
  32. * Clears the input field and triggers the control change.
  33. */
  34. this.onClearInput = async (shouldFocus) => {
  35. this.ionClear.emit();
  36. return new Promise((resolve) => {
  37. // setTimeout() fixes https://github.com/ionic-team/ionic-framework/issues/7527
  38. // wait for 4 frames
  39. setTimeout(() => {
  40. const value = this.getValue();
  41. if (value !== '') {
  42. this.value = '';
  43. this.emitInputChange();
  44. /**
  45. * When tapping clear button
  46. * ensure input is focused after
  47. * clearing input so users
  48. * can quickly start typing.
  49. */
  50. if (shouldFocus && !this.focused) {
  51. this.setFocus();
  52. /**
  53. * The setFocus call above will clear focusedValue,
  54. * but ionChange will never have gotten a chance to
  55. * fire. Manually revert focusedValue so onBlur can
  56. * compare against what was in the box before the clear.
  57. */
  58. this.focusedValue = value;
  59. }
  60. }
  61. resolve();
  62. }, 16 * 4);
  63. });
  64. };
  65. /**
  66. * Clears the input field and tells the input to blur since
  67. * the clearInput function doesn't want the input to blur
  68. * then calls the custom cancel function if the user passed one in.
  69. */
  70. this.onCancelSearchbar = async (ev) => {
  71. if (ev) {
  72. ev.preventDefault();
  73. ev.stopPropagation();
  74. }
  75. this.ionCancel.emit();
  76. // get cached values before clearing the input
  77. const value = this.getValue();
  78. const focused = this.focused;
  79. await this.onClearInput();
  80. /**
  81. * If there used to be something in the box, and we weren't focused
  82. * beforehand (meaning no blur fired that would already handle this),
  83. * manually fire ionChange.
  84. */
  85. if (value && !focused) {
  86. this.emitValueChange(ev);
  87. }
  88. if (this.nativeInput) {
  89. this.nativeInput.blur();
  90. }
  91. };
  92. /**
  93. * Update the Searchbar input value when the input changes
  94. */
  95. this.onInput = (ev) => {
  96. const input = ev.target;
  97. if (input) {
  98. this.value = input.value;
  99. }
  100. this.emitInputChange(ev);
  101. };
  102. this.onChange = (ev) => {
  103. this.emitValueChange(ev);
  104. };
  105. /**
  106. * Sets the Searchbar to not focused and checks if it should align left
  107. * based on whether there is a value in the searchbar or not.
  108. */
  109. this.onBlur = (ev) => {
  110. this.focused = false;
  111. this.ionBlur.emit();
  112. this.positionElements();
  113. if (this.focusedValue !== this.value) {
  114. this.emitValueChange(ev);
  115. }
  116. this.focusedValue = undefined;
  117. };
  118. /**
  119. * Sets the Searchbar to focused and active on input focus.
  120. */
  121. this.onFocus = () => {
  122. this.focused = true;
  123. this.focusedValue = this.value;
  124. this.ionFocus.emit();
  125. this.positionElements();
  126. };
  127. this.focused = false;
  128. this.noAnimate = true;
  129. this.color = undefined;
  130. this.animated = false;
  131. this.autocapitalize = 'off';
  132. this.autocomplete = 'off';
  133. this.autocorrect = 'off';
  134. this.cancelButtonIcon = index$1.config.get('backButtonIcon', index$2.arrowBackSharp);
  135. this.cancelButtonText = 'Cancel';
  136. this.clearIcon = undefined;
  137. this.debounce = undefined;
  138. this.disabled = false;
  139. this.inputmode = undefined;
  140. this.enterkeyhint = undefined;
  141. this.maxlength = undefined;
  142. this.minlength = undefined;
  143. this.name = this.inputId;
  144. this.placeholder = 'Search';
  145. this.searchIcon = undefined;
  146. this.showCancelButton = 'never';
  147. this.showClearButton = 'always';
  148. this.spellcheck = false;
  149. this.type = 'search';
  150. this.value = '';
  151. }
  152. /**
  153. * lang and dir are globally enumerated attributes.
  154. * As a result, creating these as properties
  155. * can have unintended side effects. Instead, we
  156. * listen for attribute changes and inherit them
  157. * to the inner `<input>` element.
  158. */
  159. onLangChanged(newValue) {
  160. this.inheritedAttributes = Object.assign(Object.assign({}, this.inheritedAttributes), { lang: newValue });
  161. index.forceUpdate(this);
  162. }
  163. onDirChanged(newValue) {
  164. this.inheritedAttributes = Object.assign(Object.assign({}, this.inheritedAttributes), { dir: newValue });
  165. index.forceUpdate(this);
  166. }
  167. debounceChanged() {
  168. const { ionInput, debounce, originalIonInput } = this;
  169. /**
  170. * If debounce is undefined, we have to manually revert the ionInput emitter in case
  171. * debounce used to be set to a number. Otherwise, the event would stay debounced.
  172. */
  173. this.ionInput = debounce === undefined ? originalIonInput !== null && originalIonInput !== void 0 ? originalIonInput : ionInput : helpers.debounceEvent(ionInput, debounce);
  174. }
  175. valueChanged() {
  176. const inputEl = this.nativeInput;
  177. const value = this.getValue();
  178. if (inputEl && inputEl.value !== value) {
  179. inputEl.value = value;
  180. }
  181. }
  182. showCancelButtonChanged() {
  183. requestAnimationFrame(() => {
  184. this.positionElements();
  185. index.forceUpdate(this);
  186. });
  187. }
  188. connectedCallback() {
  189. this.emitStyle();
  190. }
  191. componentWillLoad() {
  192. this.inheritedAttributes = Object.assign({}, helpers.inheritAttributes(this.el, ['lang', 'dir']));
  193. }
  194. componentDidLoad() {
  195. this.originalIonInput = this.ionInput;
  196. this.positionElements();
  197. this.debounceChanged();
  198. setTimeout(() => {
  199. this.noAnimate = false;
  200. }, 300);
  201. }
  202. emitStyle() {
  203. this.ionStyle.emit({
  204. searchbar: true,
  205. });
  206. }
  207. /**
  208. * Sets focus on the native `input` in `ion-searchbar`. Use this method instead of the global
  209. * `input.focus()`.
  210. *
  211. * Developers who wish to focus an input when a page enters
  212. * should call `setFocus()` in the `ionViewDidEnter()` lifecycle method.
  213. *
  214. * Developers who wish to focus an input when an overlay is presented
  215. * should call `setFocus` after `didPresent` has resolved.
  216. *
  217. * See [managing focus](/docs/developing/managing-focus) for more information.
  218. */
  219. async setFocus() {
  220. if (this.nativeInput) {
  221. this.nativeInput.focus();
  222. }
  223. }
  224. /**
  225. * Returns the native `<input>` element used under the hood.
  226. */
  227. async getInputElement() {
  228. /**
  229. * If this gets called in certain early lifecycle hooks (ex: Vue onMounted),
  230. * nativeInput won't be defined yet with the custom elements build, so wait for it to load in.
  231. */
  232. if (!this.nativeInput) {
  233. await new Promise((resolve) => helpers.componentOnReady(this.el, resolve));
  234. }
  235. return Promise.resolve(this.nativeInput);
  236. }
  237. /**
  238. * Emits an `ionChange` event.
  239. *
  240. * This API should be called for user committed changes.
  241. * This API should not be used for external value changes.
  242. */
  243. emitValueChange(event) {
  244. const { value } = this;
  245. // Checks for both null and undefined values
  246. const newValue = value == null ? value : value.toString();
  247. // Emitting a value change should update the internal state for tracking the focused value
  248. this.focusedValue = newValue;
  249. this.ionChange.emit({ value: newValue, event });
  250. }
  251. /**
  252. * Emits an `ionInput` event.
  253. */
  254. emitInputChange(event) {
  255. const { value } = this;
  256. this.ionInput.emit({ value, event });
  257. }
  258. /**
  259. * Positions the input search icon, placeholder, and the cancel button
  260. * based on the input value and if it is focused. (ios only)
  261. */
  262. positionElements() {
  263. const value = this.getValue();
  264. const prevAlignLeft = this.shouldAlignLeft;
  265. const mode = ionicGlobal.getIonMode(this);
  266. const shouldAlignLeft = !this.animated || value.trim() !== '' || !!this.focused;
  267. this.shouldAlignLeft = shouldAlignLeft;
  268. if (mode !== 'ios') {
  269. return;
  270. }
  271. if (prevAlignLeft !== shouldAlignLeft) {
  272. this.positionPlaceholder();
  273. }
  274. if (this.animated) {
  275. this.positionCancelButton();
  276. }
  277. }
  278. /**
  279. * Positions the input placeholder
  280. */
  281. positionPlaceholder() {
  282. const inputEl = this.nativeInput;
  283. if (!inputEl) {
  284. return;
  285. }
  286. const rtl = dir.isRTL(this.el);
  287. const iconEl = (this.el.shadowRoot || this.el).querySelector('.searchbar-search-icon');
  288. if (this.shouldAlignLeft) {
  289. inputEl.removeAttribute('style');
  290. iconEl.removeAttribute('style');
  291. }
  292. else {
  293. // Create a dummy span to get the placeholder width
  294. const doc = document;
  295. const tempSpan = doc.createElement('span');
  296. tempSpan.innerText = this.placeholder || '';
  297. doc.body.appendChild(tempSpan);
  298. // Get the width of the span then remove it
  299. helpers.raf(() => {
  300. const textWidth = tempSpan.offsetWidth;
  301. tempSpan.remove();
  302. // Calculate the input padding
  303. const inputLeft = 'calc(50% - ' + textWidth / 2 + 'px)';
  304. // Calculate the icon margin
  305. /**
  306. * We take the icon width to account
  307. * for any text scales applied to the icon
  308. * such as Dynamic Type on iOS as well as 8px
  309. * of padding.
  310. */
  311. const iconLeft = 'calc(50% - ' + (textWidth / 2 + iconEl.clientWidth + 8) + 'px)';
  312. // Set the input padding start and icon margin start
  313. if (rtl) {
  314. inputEl.style.paddingRight = inputLeft;
  315. iconEl.style.marginRight = iconLeft;
  316. }
  317. else {
  318. inputEl.style.paddingLeft = inputLeft;
  319. iconEl.style.marginLeft = iconLeft;
  320. }
  321. });
  322. }
  323. }
  324. /**
  325. * Show the iOS Cancel button on focus, hide it offscreen otherwise
  326. */
  327. positionCancelButton() {
  328. const rtl = dir.isRTL(this.el);
  329. const cancelButton = (this.el.shadowRoot || this.el).querySelector('.searchbar-cancel-button');
  330. const shouldShowCancel = this.shouldShowCancelButton();
  331. if (cancelButton !== null && shouldShowCancel !== this.isCancelVisible) {
  332. const cancelStyle = cancelButton.style;
  333. this.isCancelVisible = shouldShowCancel;
  334. if (shouldShowCancel) {
  335. if (rtl) {
  336. cancelStyle.marginLeft = '0';
  337. }
  338. else {
  339. cancelStyle.marginRight = '0';
  340. }
  341. }
  342. else {
  343. const offset = cancelButton.offsetWidth;
  344. if (offset > 0) {
  345. if (rtl) {
  346. cancelStyle.marginLeft = -offset + 'px';
  347. }
  348. else {
  349. cancelStyle.marginRight = -offset + 'px';
  350. }
  351. }
  352. }
  353. }
  354. }
  355. getValue() {
  356. return this.value || '';
  357. }
  358. hasValue() {
  359. return this.getValue() !== '';
  360. }
  361. /**
  362. * Determines whether or not the cancel button should be visible onscreen.
  363. * Cancel button should be shown if one of two conditions applies:
  364. * 1. `showCancelButton` is set to `always`.
  365. * 2. `showCancelButton` is set to `focus`, and the searchbar has been focused.
  366. */
  367. shouldShowCancelButton() {
  368. if (this.showCancelButton === 'never' || (this.showCancelButton === 'focus' && !this.focused)) {
  369. return false;
  370. }
  371. return true;
  372. }
  373. /**
  374. * Determines whether or not the clear button should be visible onscreen.
  375. * Clear button should be shown if one of two conditions applies:
  376. * 1. `showClearButton` is set to `always`.
  377. * 2. `showClearButton` is set to `focus`, and the searchbar has been focused.
  378. */
  379. shouldShowClearButton() {
  380. if (this.showClearButton === 'never' || (this.showClearButton === 'focus' && !this.focused)) {
  381. return false;
  382. }
  383. return true;
  384. }
  385. render() {
  386. const { cancelButtonText, autocapitalize } = this;
  387. const animated = this.animated && index$1.config.getBoolean('animated', true);
  388. const mode = ionicGlobal.getIonMode(this);
  389. const clearIcon = this.clearIcon || (mode === 'ios' ? index$2.closeCircle : index$2.closeSharp);
  390. const searchIcon = this.searchIcon || (mode === 'ios' ? index$2.searchOutline : index$2.searchSharp);
  391. const shouldShowCancelButton = this.shouldShowCancelButton();
  392. const cancelButton = this.showCancelButton !== 'never' && (index.h("button", { key: '989f3e84c472ada6e66dd9b249d0d268bf17ce26', "aria-label": cancelButtonText, "aria-hidden": shouldShowCancelButton ? undefined : 'true', type: "button", tabIndex: mode === 'ios' && !shouldShowCancelButton ? -1 : undefined, onMouseDown: this.onCancelSearchbar, onTouchStart: this.onCancelSearchbar, class: "searchbar-cancel-button" }, index.h("div", { key: '7d335d4fde33822dc79d26b748ba2e98db7494bb', "aria-hidden": "true" }, mode === 'md' ? (index.h("ion-icon", { "aria-hidden": "true", mode: mode, icon: this.cancelButtonIcon, lazy: false })) : (cancelButtonText))));
  393. return (index.h(index.Host, { key: 'd1a1972725e949fb102c91487aaa7b9d10c2d718', role: "search", "aria-disabled": this.disabled ? 'true' : null, class: theme.createColorClasses(this.color, {
  394. [mode]: true,
  395. 'searchbar-animated': animated,
  396. 'searchbar-disabled': this.disabled,
  397. 'searchbar-no-animate': animated && this.noAnimate,
  398. 'searchbar-has-value': this.hasValue(),
  399. 'searchbar-left-aligned': this.shouldAlignLeft,
  400. 'searchbar-has-focus': this.focused,
  401. 'searchbar-should-show-clear': this.shouldShowClearButton(),
  402. 'searchbar-should-show-cancel': this.shouldShowCancelButton(),
  403. }) }, index.h("div", { key: 'add53640b2994cb6b2bf02792dafe51aba6b1684', class: "searchbar-input-container" }, index.h("input", Object.assign({ key: '160cc36459a4a652e7f41ccd14dcdc782278779e', "aria-label": "search text", disabled: this.disabled, ref: (el) => (this.nativeInput = el), class: "searchbar-input", inputMode: this.inputmode, enterKeyHint: this.enterkeyhint, name: this.name, onInput: this.onInput, onChange: this.onChange, onBlur: this.onBlur, onFocus: this.onFocus, minLength: this.minlength, maxLength: this.maxlength, placeholder: this.placeholder, type: this.type, value: this.getValue(), autoCapitalize: autocapitalize === 'default' ? undefined : autocapitalize, autoComplete: this.autocomplete, autoCorrect: this.autocorrect, spellcheck: this.spellcheck }, this.inheritedAttributes)), mode === 'md' && cancelButton, index.h("ion-icon", { key: '8825fd13af0d2dea451ccc0e00ae7b5021dc01c4', "aria-hidden": "true", mode: mode, icon: searchIcon, lazy: false, class: "searchbar-search-icon" }), index.h("button", { key: '8a7b56da278b9ca5c4f5a4ee9c01924fd5ae29d8', "aria-label": "reset", type: "button", "no-blur": true, class: "searchbar-clear-button", onPointerDown: (ev) => {
  404. /**
  405. * This prevents mobile browsers from
  406. * blurring the input when the clear
  407. * button is activated.
  408. */
  409. ev.preventDefault();
  410. }, onClick: () => this.onClearInput(true) }, index.h("ion-icon", { key: '24c55274516ab012d8c25f03525c6cdb9409e52f', "aria-hidden": "true", mode: mode, icon: clearIcon, lazy: false, class: "searchbar-clear-icon" }))), mode === 'ios' && cancelButton));
  411. }
  412. get el() { return index.getElement(this); }
  413. static get watchers() { return {
  414. "lang": ["onLangChanged"],
  415. "dir": ["onDirChanged"],
  416. "debounce": ["debounceChanged"],
  417. "value": ["valueChanged"],
  418. "showCancelButton": ["showCancelButtonChanged"]
  419. }; }
  420. };
  421. let searchbarIds = 0;
  422. Searchbar.style = {
  423. ios: IonSearchbarIosStyle0,
  424. md: IonSearchbarMdStyle0
  425. };
  426. exports.ion_searchbar = Searchbar;