@pod-os/elements 0.8.0 → 0.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (131) hide show
  1. package/dist/cjs/BrokenFile-b01d72da.js +226 -0
  2. package/dist/cjs/ResourceAware-f1aac952.js +7 -0
  3. package/dist/cjs/elements.cjs.js +1 -1
  4. package/dist/{esm/ion-app_48.entry.js → cjs/index-74c56a41.js} +8 -4122
  5. package/dist/cjs/ion-app_25.cjs.entry.js +3043 -0
  6. package/dist/cjs/ion-badge_7.cjs.entry.js +258 -0
  7. package/dist/cjs/ion-item-divider_3.cjs.entry.js +109 -0
  8. package/dist/cjs/ion-item_3.cjs.entry.js +367 -0
  9. package/dist/cjs/loader.cjs.js +1 -1
  10. package/dist/cjs/pos-app-document-viewer.cjs.entry.js +28 -0
  11. package/dist/cjs/pos-app-generic.cjs.entry.js +16 -0
  12. package/dist/cjs/pos-app-image-viewer.cjs.entry.js +29 -0
  13. package/dist/cjs/pos-app-rdf-document.cjs.entry.js +16 -0
  14. package/dist/cjs/pos-description_2.cjs.entry.js +40 -0
  15. package/dist/cjs/pos-document.cjs.entry.js +67 -0
  16. package/dist/cjs/pos-relations_2.cjs.entry.js +45 -0
  17. package/dist/cjs/pos-subjects.cjs.entry.js +28 -0
  18. package/dist/collection/apps/{pos-app-pdf-viewer/pos-app-pdf-viewer.js → pos-app-document-viewer/pos-app-document-viewer.js} +3 -3
  19. package/dist/collection/collection-manifest.json +2 -2
  20. package/dist/collection/components/{pos-pdf/pos-pdf.css → pos-document/pos-document.css} +0 -0
  21. package/dist/collection/components/{pos-pdf/pos-pdf.js → pos-document/pos-document.js} +4 -4
  22. package/dist/collection/components/pos-type-router/pos-type-router.js +3 -12
  23. package/dist/collection/components/pos-type-router/selectAppForTypes.js +24 -0
  24. package/dist/components/index.d.ts +2 -2
  25. package/dist/components/index.js +2 -2
  26. package/dist/components/pos-app-browser.js +46 -184
  27. package/dist/components/pos-app-document-viewer.d.ts +11 -0
  28. package/dist/components/{pos-app-pdf-viewer2.js → pos-app-document-viewer.js} +50 -47
  29. package/dist/components/pos-app-generic.js +192 -1
  30. package/dist/components/pos-app-image-viewer.js +160 -1
  31. package/dist/components/pos-app-rdf-document.js +168 -1
  32. package/dist/components/{pos-pdf.d.ts → pos-document.d.ts} +4 -4
  33. package/dist/components/pos-document.js +6 -0
  34. package/dist/components/{pos-pdf2.js → pos-document2.js} +8 -8
  35. package/dist/components/pos-router2.js +18 -180
  36. package/dist/components/pos-type-router2.js +28 -217
  37. package/dist/elements/elements.esm.js +1 -1
  38. package/dist/elements/{p-145ab600.entry.js → p-0ed0e3ba.entry.js} +1 -1
  39. package/dist/elements/{p-5808c505.js → p-12407693.js} +1 -1
  40. package/dist/elements/p-1688668c.entry.js +1 -0
  41. package/dist/elements/{p-85d6f579.entry.js → p-16afe2d7.entry.js} +1 -1
  42. package/dist/elements/{p-f4b358b2.entry.js → p-1a9cdd0b.entry.js} +1 -1
  43. package/dist/elements/{p-8ed61030.entry.js → p-21a6c0d5.entry.js} +1 -1
  44. package/dist/elements/{p-1e3bbab1.entry.js → p-24fffcb6.entry.js} +1 -1
  45. package/dist/elements/p-2ca5f7f2.entry.js +5 -0
  46. package/dist/elements/{p-7fc32e8d.entry.js → p-2eced374.entry.js} +1 -1
  47. package/dist/elements/p-301096a8.entry.js +1 -0
  48. package/dist/elements/{p-2a9a9bb1.entry.js → p-35faa0fa.entry.js} +1 -1
  49. package/dist/elements/{p-f851b91a.js → p-37c43290.js} +2 -2
  50. package/dist/elements/p-3f0dec28.entry.js +1 -0
  51. package/dist/elements/p-410c567f.entry.js +1 -0
  52. package/dist/elements/p-417ecc9e.js +1 -0
  53. package/dist/elements/p-43717c61.js +1 -0
  54. package/dist/elements/{p-b57b6dfe.entry.js → p-573e7d6e.entry.js} +1 -1
  55. package/dist/elements/{p-ec8c13e0.entry.js → p-59680588.entry.js} +1 -1
  56. package/dist/elements/p-5fe41c08.entry.js +1 -0
  57. package/dist/elements/p-68110709.entry.js +1 -0
  58. package/dist/elements/{p-29c0f03f.js → p-6ed079a5.js} +2 -2
  59. package/dist/elements/p-709fd743.entry.js +1 -0
  60. package/dist/elements/p-73648481.entry.js +1 -0
  61. package/dist/elements/p-784b06b3.entry.js +1 -0
  62. package/dist/elements/p-84cc1417.entry.js +1 -0
  63. package/dist/elements/p-8596ddbc.js +4 -0
  64. package/dist/elements/{p-b0d8c4f0.entry.js → p-8c0124df.entry.js} +1 -1
  65. package/dist/elements/{p-020dee35.entry.js → p-a48e16ba.entry.js} +1 -1
  66. package/dist/elements/p-ab11bb11.js +4 -0
  67. package/dist/elements/{p-8a24508e.entry.js → p-ae87571c.entry.js} +1 -1
  68. package/dist/elements/p-b2acbe46.entry.js +1 -0
  69. package/dist/elements/p-babdb154.entry.js +9 -0
  70. package/dist/elements/{p-9c719139.js → p-bb128f00.js} +1 -1
  71. package/dist/elements/{p-fe753f07.entry.js → p-c442a411.entry.js} +1 -1
  72. package/dist/elements/{p-b36873af.entry.js → p-c4d119d2.entry.js} +1 -1
  73. package/dist/elements/p-eea7ce93.js +116 -0
  74. package/dist/elements/p-f72edc68.entry.js +1 -0
  75. package/dist/elements/{p-6987a85b.entry.js → p-ffb33569.entry.js} +1 -1
  76. package/dist/esm/BrokenFile-e1e68cb6.js +223 -0
  77. package/dist/esm/ResourceAware-845001bb.js +5 -0
  78. package/dist/esm/{data-62c81c24.js → data-2c0eab05.js} +1 -1
  79. package/dist/esm/elements.js +1 -1
  80. package/dist/esm/{index-ebf7f059.js → index-38d8370e.js} +1 -1
  81. package/dist/esm/{index-1f3d8582.js → index-47f5cd9a.js} +1 -1
  82. package/dist/{cjs/ion-app_48.cjs.entry.js → esm/index-5c6f4d9d.js} +6 -4174
  83. package/dist/esm/{index-65ecd543.js → index-753825bf.js} +1 -1
  84. package/dist/esm/{input-shims-8a389148.js → input-shims-167ef062.js} +2 -2
  85. package/dist/esm/ion-accordion.entry.js +1 -1
  86. package/dist/esm/ion-app_25.entry.js +3015 -0
  87. package/dist/esm/ion-back-button.entry.js +1 -1
  88. package/dist/esm/ion-badge_7.entry.js +248 -0
  89. package/dist/esm/ion-breadcrumb.entry.js +1 -1
  90. package/dist/esm/ion-datetime-button.entry.js +2 -2
  91. package/dist/esm/ion-datetime.entry.js +3 -3
  92. package/dist/esm/ion-fab-button.entry.js +1 -1
  93. package/dist/esm/ion-infinite-scroll.entry.js +2 -2
  94. package/dist/esm/ion-input.entry.js +1 -1
  95. package/dist/esm/ion-item-divider_3.entry.js +103 -0
  96. package/dist/esm/ion-item-sliding.entry.js +2 -2
  97. package/dist/esm/ion-item_3.entry.js +361 -0
  98. package/dist/esm/ion-menu-button.entry.js +1 -1
  99. package/dist/esm/ion-modal.entry.js +2 -2
  100. package/dist/esm/ion-range.entry.js +2 -2
  101. package/dist/esm/ion-refresher-content.entry.js +1 -1
  102. package/dist/esm/ion-refresher.entry.js +2 -2
  103. package/dist/esm/ion-reorder-group.entry.js +2 -2
  104. package/dist/esm/ion-reorder.entry.js +1 -1
  105. package/dist/esm/ion-toggle.entry.js +1 -1
  106. package/dist/esm/loader.js +1 -1
  107. package/dist/esm/pos-app-document-viewer.entry.js +24 -0
  108. package/dist/esm/pos-app-generic.entry.js +12 -0
  109. package/dist/esm/pos-app-image-viewer.entry.js +25 -0
  110. package/dist/esm/pos-app-rdf-document.entry.js +12 -0
  111. package/dist/esm/pos-description_2.entry.js +35 -0
  112. package/dist/esm/pos-document.entry.js +63 -0
  113. package/dist/esm/pos-relations_2.entry.js +40 -0
  114. package/dist/esm/pos-subjects.entry.js +24 -0
  115. package/dist/esm/{status-tap-33623c88.js → status-tap-ce25f9e5.js} +2 -2
  116. package/dist/types/apps/{pos-app-pdf-viewer/pos-app-pdf-viewer.d.ts → pos-app-document-viewer/pos-app-document-viewer.d.ts} +1 -1
  117. package/dist/types/components/{pos-pdf/pos-pdf.d.ts → pos-document/pos-document.d.ts} +1 -1
  118. package/dist/types/components/pos-type-router/selectAppForTypes.d.ts +8 -0
  119. package/dist/types/components.d.ts +40 -40
  120. package/package.json +1 -1
  121. package/dist/components/pos-app-generic2.js +0 -194
  122. package/dist/components/pos-app-image-viewer2.js +0 -162
  123. package/dist/components/pos-app-pdf-viewer.d.ts +0 -11
  124. package/dist/components/pos-app-pdf-viewer.js +0 -6
  125. package/dist/components/pos-app-rdf-document2.js +0 -170
  126. package/dist/components/pos-pdf.js +0 -6
  127. package/dist/elements/p-10cae467.js +0 -4
  128. package/dist/elements/p-19e4a688.js +0 -4
  129. package/dist/elements/p-5f811ad7.entry.js +0 -1
  130. package/dist/elements/p-7a79a3cd.entry.js +0 -128
  131. package/dist/elements/p-b9a87655.entry.js +0 -1
@@ -0,0 +1,3015 @@
1
+ import { r as registerInstance, h, H as Host, c as getElement, d as createEvent, e as readTask, f as forceUpdate, w as writeTask, i as getAssetPath, j as getRenderingRef } from './index-1058e225.js';
2
+ import { g as getIonMode$1, c as config, a as isPlatform } from './ionic-global-a2c7ad8b.js';
3
+ import { h as hasShadowDom, i as inheritAriaAttributes, a as inheritAttributes$1, c as componentOnReady, b as clamp, d as debounceEvent, r as raf } from './helpers-aeff219b.js';
4
+ import { p as printIonWarning } from './index-47f5cd9a.js';
5
+ import { o as openURL, c as createColorClasses$1, h as hostContext } from './theme-7cf2cab0.js';
6
+ import { i as isRTL$1 } from './dir-defb16c6.js';
7
+ import { f as findIonContent, p as printIonContentErrorMsg, g as getScrollElement } from './index-38d8370e.js';
8
+ import { c as createKeyboardController } from './keyboard-controller-33693bc2.js';
9
+ import { a as arrowBackSharp, c as closeCircle, b as closeSharp, s as searchOutline, d as searchSharp } from './index-753825bf.js';
10
+ import { s as store, B as BrokenFile } from './BrokenFile-e1e68cb6.js';
11
+ import { P as PodOS } from './index-5c6f4d9d.js';
12
+ import { s as subscribeResource } from './ResourceAware-845001bb.js';
13
+ import './index-0dbaca1a.js';
14
+
15
+ const appCss = "html.plt-mobile ion-app{user-select:none}html.plt-mobile ion-app [contenteditable]{user-select:text}ion-app.force-statusbar-padding{--ion-safe-area-top:20px}";
16
+
17
+ const App = class {
18
+ constructor(hostRef) {
19
+ registerInstance(this, hostRef);
20
+ }
21
+ componentDidLoad() {
22
+ {
23
+ rIC(async () => {
24
+ const isHybrid = isPlatform(window, 'hybrid');
25
+ if (!config.getBoolean('_testing')) {
26
+ import('./index-b212db1c.js').then((module) => module.startTapClick(config));
27
+ }
28
+ if (config.getBoolean('statusTap', isHybrid)) {
29
+ import('./status-tap-ce25f9e5.js').then((module) => module.startStatusTap());
30
+ }
31
+ if (config.getBoolean('inputShims', needInputShims())) {
32
+ /**
33
+ * needInputShims() ensures that only iOS and Android
34
+ * platforms proceed into this block.
35
+ */
36
+ const platform = isPlatform(window, 'ios') ? 'ios' : 'android';
37
+ import('./input-shims-167ef062.js').then((module) => module.startInputShims(config, platform));
38
+ }
39
+ const hardwareBackButtonModule = await import('./hardware-back-button-242191a7.js');
40
+ if (config.getBoolean('hardwareBackButton', isHybrid)) {
41
+ hardwareBackButtonModule.startHardwareBackButton();
42
+ }
43
+ else {
44
+ hardwareBackButtonModule.blockHardwareBackButton();
45
+ }
46
+ if (typeof window !== 'undefined') {
47
+ import('./keyboard-413afe04.js').then((module) => module.startKeyboardAssist(window));
48
+ }
49
+ import('./focus-visible-78d55799.js').then((module) => (this.focusVisible = module.startFocusVisible()));
50
+ });
51
+ }
52
+ }
53
+ /**
54
+ * @internal
55
+ * Used to set focus on an element that uses `ion-focusable`.
56
+ * Do not use this if focusing the element as a result of a keyboard
57
+ * event as the focus utility should handle this for us. This method
58
+ * should be used when we want to programmatically focus an element as
59
+ * a result of another user action. (Ex: We focus the first element
60
+ * inside of a popover when the user presents it, but the popover is not always
61
+ * presented as a result of keyboard action.)
62
+ */
63
+ async setFocus(elements) {
64
+ if (this.focusVisible) {
65
+ this.focusVisible.setFocus(elements);
66
+ }
67
+ }
68
+ render() {
69
+ const mode = getIonMode$1(this);
70
+ return (h(Host, { class: {
71
+ [mode]: true,
72
+ 'ion-page': true,
73
+ 'force-statusbar-padding': config.getBoolean('_forceStatusbarPadding'),
74
+ } }));
75
+ }
76
+ get el() { return getElement(this); }
77
+ };
78
+ const needInputShims = () => {
79
+ /**
80
+ * iOS always needs input shims
81
+ */
82
+ const needsShimsIOS = isPlatform(window, 'ios') && isPlatform(window, 'mobile');
83
+ if (needsShimsIOS) {
84
+ return true;
85
+ }
86
+ /**
87
+ * Android only needs input shims when running
88
+ * in the browser and only if the browser is using the
89
+ * new Chrome 108+ resize behavior: https://developer.chrome.com/blog/viewport-resize-behavior/
90
+ */
91
+ const isAndroidMobileWeb = isPlatform(window, 'android') && isPlatform(window, 'mobileweb');
92
+ if (isAndroidMobileWeb) {
93
+ return true;
94
+ }
95
+ return false;
96
+ };
97
+ const rIC = (callback) => {
98
+ if ('requestIdleCallback' in window) {
99
+ window.requestIdleCallback(callback);
100
+ }
101
+ else {
102
+ setTimeout(callback, 32);
103
+ }
104
+ };
105
+ App.style = appCss;
106
+
107
+ const buttonIosCss = ":host{--overflow:hidden;--ripple-color:currentColor;--border-width:initial;--border-color:initial;--border-style:initial;--color-activated:var(--color);--color-focused:var(--color);--color-hover:var(--color);--box-shadow:none;display:inline-block;width:auto;color:var(--color);font-family:var(--ion-font-family, inherit);text-align:center;text-decoration:none;text-overflow:ellipsis;white-space:nowrap;user-select:none;vertical-align:top;vertical-align:-webkit-baseline-middle;font-kerning:none}:host(.button-disabled){cursor:default;opacity:0.5;pointer-events:none}:host(.button-solid){--background:var(--ion-color-primary, #3880ff);--color:var(--ion-color-primary-contrast, #fff)}:host(.button-outline){--border-color:var(--ion-color-primary, #3880ff);--background:transparent;--color:var(--ion-color-primary, #3880ff)}:host(.button-clear){--border-width:0;--background:transparent;--color:var(--ion-color-primary, #3880ff)}:host(.button-block){display:block}:host(.button-block) .button-native{margin-left:0;margin-right:0;display:block;width:100%;clear:both;contain:content}:host(.button-block) .button-native::after{clear:both}:host(.button-full){display:block}:host(.button-full) .button-native{margin-left:0;margin-right:0;display:block;width:100%;contain:content}:host(.button-full:not(.button-round)) .button-native{border-radius:0;border-right-width:0;border-left-width:0}.button-native{border-radius:var(--border-radius);-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;margin-left:0;margin-right:0;margin-top:0;margin-bottom:0;padding-left:var(--padding-start);padding-right:var(--padding-end);padding-top:var(--padding-top);padding-bottom:var(--padding-bottom);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;display:block;position:relative;width:100%;height:100%;transition:var(--transition);border-width:var(--border-width);border-style:var(--border-style);border-color:var(--border-color);outline:none;background:var(--background);line-height:1;box-shadow:var(--box-shadow);contain:layout style;cursor:pointer;opacity:var(--opacity);overflow:var(--overflow);z-index:0;box-sizing:border-box;appearance:none}@supports (margin-inline-start: 0) or (-webkit-margin-start: 0){.button-native{padding-left:unset;padding-right:unset;-webkit-padding-start:var(--padding-start);padding-inline-start:var(--padding-start);-webkit-padding-end:var(--padding-end);padding-inline-end:var(--padding-end)}}.button-native::-moz-focus-inner{border:0}.button-inner{display:flex;position:relative;flex-flow:row nowrap;flex-shrink:0;align-items:center;justify-content:center;width:100%;height:100%;z-index:1}::slotted(ion-icon){font-size:1.4em;pointer-events:none}::slotted(ion-icon[slot=start]){margin-left:-0.3em;margin-right:0.3em;margin-top:0;margin-bottom:0}@supports (margin-inline-start: 0) or (-webkit-margin-start: 0){::slotted(ion-icon[slot=start]){margin-left:unset;margin-right:unset;-webkit-margin-start:-0.3em;margin-inline-start:-0.3em;-webkit-margin-end:0.3em;margin-inline-end:0.3em}}::slotted(ion-icon[slot=end]){margin-left:0.3em;margin-right:-0.2em;margin-top:0;margin-bottom:0}@supports (margin-inline-start: 0) or (-webkit-margin-start: 0){::slotted(ion-icon[slot=end]){margin-left:unset;margin-right:unset;-webkit-margin-start:0.3em;margin-inline-start:0.3em;-webkit-margin-end:-0.2em;margin-inline-end:-0.2em}}::slotted(ion-icon[slot=icon-only]){font-size:1.8em}ion-ripple-effect{color:var(--ripple-color)}.button-native::after{left:0;right:0;top:0;bottom:0;position:absolute;content:\"\";opacity:0}:host(.ion-activated){color:var(--color-activated)}:host(.ion-activated) .button-native::after{background:var(--background-activated);opacity:var(--background-activated-opacity)}:host(.ion-focused){color:var(--color-focused)}:host(.ion-focused) .button-native::after{background:var(--background-focused);opacity:var(--background-focused-opacity)}@media (any-hover: hover){:host(:hover){color:var(--color-hover)}:host(:hover) .button-native::after{background:var(--background-hover);opacity:var(--background-hover-opacity)}}:host(.button-solid.ion-color) .button-native{background:var(--ion-color-base);color:var(--ion-color-contrast)}:host(.button-outline.ion-color) .button-native{border-color:var(--ion-color-base);background:transparent;color:var(--ion-color-base)}:host(.button-clear.ion-color) .button-native{background:transparent;color:var(--ion-color-base)}:host(.in-toolbar:not(.ion-color):not(.in-toolbar-color)) .button-native{color:var(--ion-toolbar-color, var(--color))}:host(.button-outline.in-toolbar:not(.ion-color):not(.in-toolbar-color)) .button-native{border-color:var(--ion-toolbar-color, var(--color, var(--border-color)))}:host(.button-solid.in-toolbar:not(.ion-color):not(.in-toolbar-color)) .button-native{background:var(--ion-toolbar-color, var(--background));color:var(--ion-toolbar-background, var(--color))}:host{--border-radius:10px;--padding-top:0;--padding-bottom:0;--padding-start:1em;--padding-end:1em;--transition:background-color, opacity 100ms linear;margin-left:2px;margin-right:2px;margin-top:4px;margin-bottom:4px;height:2.8em;font-size:16px;font-weight:500;letter-spacing:-0.03em}@supports (margin-inline-start: 0) or (-webkit-margin-start: 0){:host{margin-left:unset;margin-right:unset;-webkit-margin-start:2px;margin-inline-start:2px;-webkit-margin-end:2px;margin-inline-end:2px}}:host(.button-solid){--background-activated:var(--ion-color-primary-shade, #3171e0);--background-focused:var(--ion-color-primary-shade, #3171e0);--background-hover:var(--ion-color-primary-tint, #4c8dff);--background-activated-opacity:1;--background-focused-opacity:1;--background-hover-opacity:1}:host(.button-outline){--border-radius:10px;--border-width:1px;--border-style:solid;--background-activated:var(--ion-color-primary, #3880ff);--background-focused:var(--ion-color-primary, #3880ff);--background-hover:transparent;--background-focused-opacity:.1;--color-activated:var(--ion-color-primary-contrast, #fff)}:host(.button-clear){--background-activated:transparent;--background-focused:var(--ion-color-primary, #3880ff);--background-hover:transparent;--background-focused-opacity:.1;font-size:17px;font-weight:normal;letter-spacing:0}:host(.button-large){--border-radius:12px;--padding-top:0;--padding-start:1em;--padding-end:1em;--padding-bottom:0;height:2.8em;font-size:20px}:host(.button-small){--border-radius:6px;--padding-top:0;--padding-start:0.9em;--padding-end:0.9em;--padding-bottom:0;height:2.1em;font-size:13px}:host(.button-round){--border-radius:64px;--padding-top:0;--padding-start:26px;--padding-end:26px;--padding-bottom:0}:host(.button-strong){font-weight:600}:host(.button-clear.ion-activated){opacity:0.4}:host(.button-outline.ion-activated.ion-color) .button-native{color:var(--ion-color-contrast)}:host(.button-outline.ion-activated.ion-color) .button-native::after{background:var(--ion-color-base)}:host(.button-solid.ion-color.ion-activated) .button-native::after{background:var(--ion-color-shade)}:host(.button-outline.ion-focused.ion-color) .button-native,:host(.button-clear.ion-focused.ion-color) .button-native{color:var(--ion-color-base)}:host(.button-outline.ion-focused.ion-color) .button-native::after,:host(.button-clear.ion-focused.ion-color) .button-native::after{background:var(--ion-color-base)}:host(.button-solid.ion-color.ion-focused) .button-native::after{background:var(--ion-color-shade)}@media (any-hover: hover){:host(.button-clear:hover),:host(.button-outline:hover){opacity:0.6}:host(.button-clear.ion-color:hover) .button-native,:host(.button-outline.ion-color:hover) .button-native{color:var(--ion-color-base)}:host(.button-clear.ion-color:hover) .button-native::after,:host(.button-outline.ion-color:hover) .button-native::after{background:transparent}:host(.button-solid.ion-color:hover) .button-native::after{background:var(--ion-color-tint)}:host(:hover.button-solid.in-toolbar:not(.ion-color):not(.in-toolbar-color)) .button-native::after{background:#fff;opacity:0.1}}";
108
+
109
+ const buttonMdCss = ":host{--overflow:hidden;--ripple-color:currentColor;--border-width:initial;--border-color:initial;--border-style:initial;--color-activated:var(--color);--color-focused:var(--color);--color-hover:var(--color);--box-shadow:none;display:inline-block;width:auto;color:var(--color);font-family:var(--ion-font-family, inherit);text-align:center;text-decoration:none;text-overflow:ellipsis;white-space:nowrap;user-select:none;vertical-align:top;vertical-align:-webkit-baseline-middle;font-kerning:none}:host(.button-disabled){cursor:default;opacity:0.5;pointer-events:none}:host(.button-solid){--background:var(--ion-color-primary, #3880ff);--color:var(--ion-color-primary-contrast, #fff)}:host(.button-outline){--border-color:var(--ion-color-primary, #3880ff);--background:transparent;--color:var(--ion-color-primary, #3880ff)}:host(.button-clear){--border-width:0;--background:transparent;--color:var(--ion-color-primary, #3880ff)}:host(.button-block){display:block}:host(.button-block) .button-native{margin-left:0;margin-right:0;display:block;width:100%;clear:both;contain:content}:host(.button-block) .button-native::after{clear:both}:host(.button-full){display:block}:host(.button-full) .button-native{margin-left:0;margin-right:0;display:block;width:100%;contain:content}:host(.button-full:not(.button-round)) .button-native{border-radius:0;border-right-width:0;border-left-width:0}.button-native{border-radius:var(--border-radius);-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;margin-left:0;margin-right:0;margin-top:0;margin-bottom:0;padding-left:var(--padding-start);padding-right:var(--padding-end);padding-top:var(--padding-top);padding-bottom:var(--padding-bottom);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;display:block;position:relative;width:100%;height:100%;transition:var(--transition);border-width:var(--border-width);border-style:var(--border-style);border-color:var(--border-color);outline:none;background:var(--background);line-height:1;box-shadow:var(--box-shadow);contain:layout style;cursor:pointer;opacity:var(--opacity);overflow:var(--overflow);z-index:0;box-sizing:border-box;appearance:none}@supports (margin-inline-start: 0) or (-webkit-margin-start: 0){.button-native{padding-left:unset;padding-right:unset;-webkit-padding-start:var(--padding-start);padding-inline-start:var(--padding-start);-webkit-padding-end:var(--padding-end);padding-inline-end:var(--padding-end)}}.button-native::-moz-focus-inner{border:0}.button-inner{display:flex;position:relative;flex-flow:row nowrap;flex-shrink:0;align-items:center;justify-content:center;width:100%;height:100%;z-index:1}::slotted(ion-icon){font-size:1.4em;pointer-events:none}::slotted(ion-icon[slot=start]){margin-left:-0.3em;margin-right:0.3em;margin-top:0;margin-bottom:0}@supports (margin-inline-start: 0) or (-webkit-margin-start: 0){::slotted(ion-icon[slot=start]){margin-left:unset;margin-right:unset;-webkit-margin-start:-0.3em;margin-inline-start:-0.3em;-webkit-margin-end:0.3em;margin-inline-end:0.3em}}::slotted(ion-icon[slot=end]){margin-left:0.3em;margin-right:-0.2em;margin-top:0;margin-bottom:0}@supports (margin-inline-start: 0) or (-webkit-margin-start: 0){::slotted(ion-icon[slot=end]){margin-left:unset;margin-right:unset;-webkit-margin-start:0.3em;margin-inline-start:0.3em;-webkit-margin-end:-0.2em;margin-inline-end:-0.2em}}::slotted(ion-icon[slot=icon-only]){font-size:1.8em}ion-ripple-effect{color:var(--ripple-color)}.button-native::after{left:0;right:0;top:0;bottom:0;position:absolute;content:\"\";opacity:0}:host(.ion-activated){color:var(--color-activated)}:host(.ion-activated) .button-native::after{background:var(--background-activated);opacity:var(--background-activated-opacity)}:host(.ion-focused){color:var(--color-focused)}:host(.ion-focused) .button-native::after{background:var(--background-focused);opacity:var(--background-focused-opacity)}@media (any-hover: hover){:host(:hover){color:var(--color-hover)}:host(:hover) .button-native::after{background:var(--background-hover);opacity:var(--background-hover-opacity)}}:host(.button-solid.ion-color) .button-native{background:var(--ion-color-base);color:var(--ion-color-contrast)}:host(.button-outline.ion-color) .button-native{border-color:var(--ion-color-base);background:transparent;color:var(--ion-color-base)}:host(.button-clear.ion-color) .button-native{background:transparent;color:var(--ion-color-base)}:host(.in-toolbar:not(.ion-color):not(.in-toolbar-color)) .button-native{color:var(--ion-toolbar-color, var(--color))}:host(.button-outline.in-toolbar:not(.ion-color):not(.in-toolbar-color)) .button-native{border-color:var(--ion-toolbar-color, var(--color, var(--border-color)))}:host(.button-solid.in-toolbar:not(.ion-color):not(.in-toolbar-color)) .button-native{background:var(--ion-toolbar-color, var(--background));color:var(--ion-toolbar-background, var(--color))}:host{--border-radius:4px;--padding-top:0;--padding-bottom:0;--padding-start:1.1em;--padding-end:1.1em;--transition:box-shadow 280ms cubic-bezier(.4, 0, .2, 1),\n background-color 15ms linear,\n color 15ms linear;margin-left:2px;margin-right:2px;margin-top:4px;margin-bottom:4px;height:36px;font-size:14px;font-weight:500;letter-spacing:0.06em;text-transform:uppercase}@supports (margin-inline-start: 0) or (-webkit-margin-start: 0){:host{margin-left:unset;margin-right:unset;-webkit-margin-start:2px;margin-inline-start:2px;-webkit-margin-end:2px;margin-inline-end:2px}}:host(.button-solid){--background-activated:transparent;--background-hover:var(--ion-color-primary-contrast, #fff);--background-focused:var(--ion-color-primary-contrast, #fff);--background-activated-opacity:0;--background-focused-opacity:.24;--background-hover-opacity:.08;--box-shadow:0 3px 1px -2px rgba(0, 0, 0, 0.2), 0 2px 2px 0 rgba(0, 0, 0, 0.14), 0 1px 5px 0 rgba(0, 0, 0, 0.12)}:host(.button-solid.ion-activated){--box-shadow:0 5px 5px -3px rgba(0, 0, 0, 0.2), 0 8px 10px 1px rgba(0, 0, 0, 0.14), 0 3px 14px 2px rgba(0, 0, 0, 0.12)}:host(.button-outline){--border-width:2px;--border-style:solid;--box-shadow:none;--background-activated:transparent;--background-focused:var(--ion-color-primary, #3880ff);--background-hover:var(--ion-color-primary, #3880ff);--background-activated-opacity:0;--background-focused-opacity:.12;--background-hover-opacity:.04}:host(.button-outline.ion-activated.ion-color) .button-native{background:transparent}:host(.button-clear){--background-activated:transparent;--background-focused:var(--ion-color-primary, #3880ff);--background-hover:var(--ion-color-primary, #3880ff);--background-activated-opacity:0;--background-focused-opacity:.12;--background-hover-opacity:.04}:host(.button-round){--border-radius:64px;--padding-top:0;--padding-start:26px;--padding-end:26px;--padding-bottom:0}:host(.button-large){--padding-top:0;--padding-start:1em;--padding-end:1em;--padding-bottom:0;height:2.8em;font-size:20px}:host(.button-small){--padding-top:0;--padding-start:0.9em;--padding-end:0.9em;--padding-bottom:0;height:2.1em;font-size:13px}:host(.button-strong){font-weight:bold}::slotted(ion-icon[slot=icon-only]){padding-left:0;padding-right:0;padding-top:0;padding-bottom:0}:host(.button-solid.ion-color.ion-focused) .button-native::after{background:var(--ion-color-contrast)}:host(.button-clear.ion-color.ion-focused) .button-native::after,:host(.button-outline.ion-color.ion-focused) .button-native::after{background:var(--ion-color-base)}@media (any-hover: hover){:host(.button-solid.ion-color:hover) .button-native::after{background:var(--ion-color-contrast)}:host(.button-clear.ion-color:hover) .button-native::after,:host(.button-outline.ion-color:hover) .button-native::after{background:var(--ion-color-base)}}";
110
+
111
+ const Button = class {
112
+ constructor(hostRef) {
113
+ registerInstance(this, hostRef);
114
+ this.ionFocus = createEvent(this, "ionFocus", 7);
115
+ this.ionBlur = createEvent(this, "ionBlur", 7);
116
+ this.inItem = false;
117
+ this.inListHeader = false;
118
+ this.inToolbar = false;
119
+ this.inheritedAttributes = {};
120
+ /**
121
+ * The type of button.
122
+ */
123
+ this.buttonType = 'button';
124
+ /**
125
+ * If `true`, the user cannot interact with the button.
126
+ */
127
+ this.disabled = false;
128
+ /**
129
+ * When using a router, it specifies the transition direction when navigating to
130
+ * another page using `href`.
131
+ */
132
+ this.routerDirection = 'forward';
133
+ /**
134
+ * If `true`, activates a button with a heavier font weight.
135
+ */
136
+ this.strong = false;
137
+ /**
138
+ * The type of the button.
139
+ */
140
+ this.type = 'button';
141
+ this.handleClick = (ev) => {
142
+ const { el } = this;
143
+ if (this.type === 'button') {
144
+ openURL(this.href, ev, this.routerDirection, this.routerAnimation);
145
+ }
146
+ else if (hasShadowDom(el)) {
147
+ // this button wants to specifically submit a form
148
+ // climb up the dom to see if we're in a <form>
149
+ // and if so, then use JS to submit it
150
+ let formEl = this.findForm();
151
+ const { form } = this;
152
+ if (!formEl && form !== undefined) {
153
+ /**
154
+ * The developer specified a form selector for
155
+ * the button to submit, but it was not found.
156
+ */
157
+ if (typeof form === 'string') {
158
+ printIonWarning(`Form with selector: "#${form}" could not be found. Verify that the id is correct and the form is rendered in the DOM.`, el);
159
+ }
160
+ else {
161
+ printIonWarning(`The provided "form" element is invalid. Verify that the form is a HTMLFormElement and rendered in the DOM.`, el);
162
+ }
163
+ return;
164
+ }
165
+ if (!formEl) {
166
+ /**
167
+ * If the form element is not set, the button may be inside
168
+ * of a form element. Query the closest form element to the button.
169
+ */
170
+ formEl = el.closest('form');
171
+ }
172
+ if (formEl) {
173
+ ev.preventDefault();
174
+ const fakeButton = document.createElement('button');
175
+ fakeButton.type = this.type;
176
+ fakeButton.style.display = 'none';
177
+ formEl.appendChild(fakeButton);
178
+ fakeButton.click();
179
+ fakeButton.remove();
180
+ }
181
+ }
182
+ };
183
+ this.onFocus = () => {
184
+ this.ionFocus.emit();
185
+ };
186
+ this.onBlur = () => {
187
+ this.ionBlur.emit();
188
+ };
189
+ }
190
+ componentWillLoad() {
191
+ this.inToolbar = !!this.el.closest('ion-buttons');
192
+ this.inListHeader = !!this.el.closest('ion-list-header');
193
+ this.inItem = !!this.el.closest('ion-item') || !!this.el.closest('ion-item-divider');
194
+ this.inheritedAttributes = inheritAriaAttributes(this.el);
195
+ }
196
+ get hasIconOnly() {
197
+ return !!this.el.querySelector('[slot="icon-only"]');
198
+ }
199
+ get rippleType() {
200
+ const hasClearFill = this.fill === undefined || this.fill === 'clear';
201
+ // If the button is in a toolbar, has a clear fill (which is the default)
202
+ // and only has an icon we use the unbounded "circular" ripple effect
203
+ if (hasClearFill && this.hasIconOnly && this.inToolbar) {
204
+ return 'unbounded';
205
+ }
206
+ return 'bounded';
207
+ }
208
+ /**
209
+ * Finds the form element based on the provided `form` selector
210
+ * or element reference provided.
211
+ */
212
+ findForm() {
213
+ const { form } = this;
214
+ if (form instanceof HTMLFormElement) {
215
+ return form;
216
+ }
217
+ if (typeof form === 'string') {
218
+ const el = document.getElementById(form);
219
+ if (el instanceof HTMLFormElement) {
220
+ return el;
221
+ }
222
+ }
223
+ return null;
224
+ }
225
+ render() {
226
+ const mode = getIonMode$1(this);
227
+ const { buttonType, type, disabled, rel, target, size, href, color, expand, hasIconOnly, shape, strong, inheritedAttributes, } = this;
228
+ const finalSize = size === undefined && this.inItem ? 'small' : size;
229
+ const TagType = href === undefined ? 'button' : 'a';
230
+ const attrs = TagType === 'button'
231
+ ? { type }
232
+ : {
233
+ download: this.download,
234
+ href,
235
+ rel,
236
+ target,
237
+ };
238
+ let fill = this.fill;
239
+ /**
240
+ * We check both undefined and null to
241
+ * work around https://github.com/ionic-team/stencil/issues/3586.
242
+ */
243
+ if (fill == null) {
244
+ fill = this.inToolbar || this.inListHeader ? 'clear' : 'solid';
245
+ }
246
+ return (h(Host, { onClick: this.handleClick, "aria-disabled": disabled ? 'true' : null, class: createColorClasses$1(color, {
247
+ [mode]: true,
248
+ [buttonType]: true,
249
+ [`${buttonType}-${expand}`]: expand !== undefined,
250
+ [`${buttonType}-${finalSize}`]: finalSize !== undefined,
251
+ [`${buttonType}-${shape}`]: shape !== undefined,
252
+ [`${buttonType}-${fill}`]: true,
253
+ [`${buttonType}-strong`]: strong,
254
+ 'in-toolbar': hostContext('ion-toolbar', this.el),
255
+ 'in-toolbar-color': hostContext('ion-toolbar[color]', this.el),
256
+ 'button-has-icon-only': hasIconOnly,
257
+ 'button-disabled': disabled,
258
+ 'ion-activatable': true,
259
+ 'ion-focusable': true,
260
+ }) }, h(TagType, Object.assign({}, attrs, { class: "button-native", part: "native", disabled: disabled, onFocus: this.onFocus, onBlur: this.onBlur }, inheritedAttributes), h("span", { class: "button-inner" }, h("slot", { name: "icon-only" }), h("slot", { name: "start" }), h("slot", null), h("slot", { name: "end" })), mode === 'md' && h("ion-ripple-effect", { type: this.rippleType }))));
261
+ }
262
+ get el() { return getElement(this); }
263
+ };
264
+ Button.style = {
265
+ ios: buttonIosCss,
266
+ md: buttonMdCss
267
+ };
268
+
269
+ const cardIosCss = ":host{--ion-safe-area-left:0px;--ion-safe-area-right:0px;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:block;position:relative;background:var(--background);color:var(--color);font-family:var(--ion-font-family, inherit);overflow:hidden}:host(.ion-color){background:var(--ion-color-base);color:var(--ion-color-contrast)}:host(.card-disabled){cursor:default;opacity:0.3;pointer-events:none}.card-native{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;padding-left:0;padding-right:0;padding-top:0;padding-bottom:0;margin-left:0;margin-right:0;margin-top:0;margin-bottom:0;display:block;width:100%;min-height:var(--min-height);transition:var(--transition);border-width:var(--border-width);border-style:var(--border-style);border-color:var(--border-color);outline:none;background:inherit}.card-native::-moz-focus-inner{border:0}button,a{cursor:pointer;user-select:none;-webkit-user-drag:none}ion-ripple-effect{color:var(--ripple-color)}:host{--background:var(--ion-card-background, var(--ion-item-background, var(--ion-background-color, #fff)));--color:var(--ion-card-color, var(--ion-item-color, var(--ion-color-step-600, #666666)));margin-left:16px;margin-right:16px;margin-top:24px;margin-bottom:24px;border-radius:8px;transition:transform 500ms cubic-bezier(0.12, 0.72, 0.29, 1);font-size:14px;box-shadow:0 4px 16px rgba(0, 0, 0, 0.12)}@supports (margin-inline-start: 0) or (-webkit-margin-start: 0){:host{margin-left:unset;margin-right:unset;-webkit-margin-start:16px;margin-inline-start:16px;-webkit-margin-end:16px;margin-inline-end:16px}}:host(.ion-activated){transform:scale3d(0.97, 0.97, 1)}";
270
+
271
+ const cardMdCss = ":host{--ion-safe-area-left:0px;--ion-safe-area-right:0px;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:block;position:relative;background:var(--background);color:var(--color);font-family:var(--ion-font-family, inherit);overflow:hidden}:host(.ion-color){background:var(--ion-color-base);color:var(--ion-color-contrast)}:host(.card-disabled){cursor:default;opacity:0.3;pointer-events:none}.card-native{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;padding-left:0;padding-right:0;padding-top:0;padding-bottom:0;margin-left:0;margin-right:0;margin-top:0;margin-bottom:0;display:block;width:100%;min-height:var(--min-height);transition:var(--transition);border-width:var(--border-width);border-style:var(--border-style);border-color:var(--border-color);outline:none;background:inherit}.card-native::-moz-focus-inner{border:0}button,a{cursor:pointer;user-select:none;-webkit-user-drag:none}ion-ripple-effect{color:var(--ripple-color)}:host{--background:var(--ion-card-background, var(--ion-item-background, var(--ion-background-color, #fff)));--color:var(--ion-card-color, var(--ion-item-color, var(--ion-color-step-550, #737373)));margin-left:10px;margin-right:10px;margin-top:10px;margin-bottom:10px;border-radius:4px;font-size:14px;box-shadow:0 3px 1px -2px rgba(0, 0, 0, 0.2), 0 2px 2px 0 rgba(0, 0, 0, 0.14), 0 1px 5px 0 rgba(0, 0, 0, 0.12)}@supports (margin-inline-start: 0) or (-webkit-margin-start: 0){:host{margin-left:unset;margin-right:unset;-webkit-margin-start:10px;margin-inline-start:10px;-webkit-margin-end:10px;margin-inline-end:10px}}";
272
+
273
+ const Card = class {
274
+ constructor(hostRef) {
275
+ registerInstance(this, hostRef);
276
+ this.inheritedAriaAttributes = {};
277
+ /**
278
+ * If `true`, a button tag will be rendered and the card will be tappable.
279
+ */
280
+ this.button = false;
281
+ /**
282
+ * The type of the button. Only used when an `onclick` or `button` property is present.
283
+ */
284
+ this.type = 'button';
285
+ /**
286
+ * If `true`, the user cannot interact with the card.
287
+ */
288
+ this.disabled = false;
289
+ /**
290
+ * When using a router, it specifies the transition direction when navigating to
291
+ * another page using `href`.
292
+ */
293
+ this.routerDirection = 'forward';
294
+ }
295
+ componentWillLoad() {
296
+ this.inheritedAriaAttributes = inheritAttributes$1(this.el, ['aria-label']);
297
+ }
298
+ isClickable() {
299
+ return this.href !== undefined || this.button;
300
+ }
301
+ renderCard(mode) {
302
+ const clickable = this.isClickable();
303
+ if (!clickable) {
304
+ return [h("slot", null)];
305
+ }
306
+ const { href, routerAnimation, routerDirection, inheritedAriaAttributes } = this;
307
+ const TagType = clickable ? (href === undefined ? 'button' : 'a') : 'div';
308
+ const attrs = TagType === 'button'
309
+ ? { type: this.type }
310
+ : {
311
+ download: this.download,
312
+ href: this.href,
313
+ rel: this.rel,
314
+ target: this.target,
315
+ };
316
+ return (h(TagType, Object.assign({}, attrs, inheritedAriaAttributes, { class: "card-native", part: "native", disabled: this.disabled, onClick: (ev) => openURL(href, ev, routerDirection, routerAnimation) }), h("slot", null), clickable && mode === 'md' && h("ion-ripple-effect", null)));
317
+ }
318
+ render() {
319
+ const mode = getIonMode$1(this);
320
+ return (h(Host, { class: createColorClasses$1(this.color, {
321
+ [mode]: true,
322
+ 'card-disabled': this.disabled,
323
+ 'ion-activatable': this.isClickable(),
324
+ }) }, this.renderCard(mode)));
325
+ }
326
+ get el() { return getElement(this); }
327
+ };
328
+ Card.style = {
329
+ ios: cardIosCss,
330
+ md: cardMdCss
331
+ };
332
+
333
+ const cardContentIosCss = "ion-card-content{display:block;position:relative}.card-content-ios{padding-left:20px;padding-right:20px;padding-top:20px;padding-bottom:20px;font-size:16px;line-height:1.4}@supports (margin-inline-start: 0) or (-webkit-margin-start: 0){.card-content-ios{padding-left:unset;padding-right:unset;-webkit-padding-start:20px;padding-inline-start:20px;-webkit-padding-end:20px;padding-inline-end:20px}}.card-content-ios h1{margin-left:0;margin-right:0;margin-top:0;margin-bottom:2px;font-size:24px;font-weight:normal}.card-content-ios h2{margin-left:0;margin-right:0;margin-top:2px;margin-bottom:2px;font-size:16px;font-weight:normal}.card-content-ios h3,.card-content-ios h4,.card-content-ios h5,.card-content-ios h6{margin-left:0;margin-right:0;margin-top:2px;margin-bottom:2px;font-size:14px;font-weight:normal}.card-content-ios p{margin-left:0;margin-right:0;margin-top:0;margin-bottom:2px;font-size:14px}ion-card-header+.card-content-ios{padding-top:0}";
334
+
335
+ const cardContentMdCss = "ion-card-content{display:block;position:relative}.card-content-md{padding-left:16px;padding-right:16px;padding-top:13px;padding-bottom:13px;font-size:14px;line-height:1.5}@supports (margin-inline-start: 0) or (-webkit-margin-start: 0){.card-content-md{padding-left:unset;padding-right:unset;-webkit-padding-start:16px;padding-inline-start:16px;-webkit-padding-end:16px;padding-inline-end:16px}}.card-content-md h1{margin-left:0;margin-right:0;margin-top:0;margin-bottom:2px;font-size:24px;font-weight:normal}.card-content-md h2{margin-left:0;margin-right:0;margin-top:2px;margin-bottom:2px;font-size:16px;font-weight:normal}.card-content-md h3,.card-content-md h4,.card-content-md h5,.card-content-md h6{margin-left:0;margin-right:0;margin-top:2px;margin-bottom:2px;font-size:14px;font-weight:normal}.card-content-md p{margin-left:0;margin-right:0;margin-top:0;margin-bottom:2px;font-size:14px;font-weight:normal;line-height:1.5}ion-card-header+.card-content-md{padding-top:0}";
336
+
337
+ const CardContent = class {
338
+ constructor(hostRef) {
339
+ registerInstance(this, hostRef);
340
+ }
341
+ render() {
342
+ const mode = getIonMode$1(this);
343
+ return (h(Host, { class: {
344
+ [mode]: true,
345
+ // Used internally for styling
346
+ [`card-content-${mode}`]: true,
347
+ } }));
348
+ }
349
+ };
350
+ CardContent.style = {
351
+ ios: cardContentIosCss,
352
+ md: cardContentMdCss
353
+ };
354
+
355
+ const cardHeaderIosCss = ":host{--background:transparent;--color:inherit;display:block;position:relative;background:var(--background);color:var(--color)}:host(.ion-color){background:var(--ion-color-base);color:var(--ion-color-contrast)}:host{padding-left:20px;padding-right:20px;padding-top:20px;padding-bottom:16px}@supports (margin-inline-start: 0) or (-webkit-margin-start: 0){:host{padding-left:unset;padding-right:unset;-webkit-padding-start:20px;padding-inline-start:20px;-webkit-padding-end:20px;padding-inline-end:20px}}@supports (backdrop-filter: blur(0)){:host(.card-header-translucent){background-color:rgba(var(--ion-background-color-rgb, 255, 255, 255), 0.9);backdrop-filter:saturate(180%) blur(30px)}}";
356
+
357
+ const cardHeaderMdCss = ":host{--background:transparent;--color:inherit;display:block;position:relative;background:var(--background);color:var(--color)}:host(.ion-color){background:var(--ion-color-base);color:var(--ion-color-contrast)}:host{padding-left:16px;padding-right:16px;padding-top:16px;padding-bottom:16px}@supports (margin-inline-start: 0) or (-webkit-margin-start: 0){:host{padding-left:unset;padding-right:unset;-webkit-padding-start:16px;padding-inline-start:16px;-webkit-padding-end:16px;padding-inline-end:16px}}::slotted(ion-card-title:not(:first-child)),::slotted(ion-card-subtitle:not(:first-child)){margin-top:8px}";
358
+
359
+ const CardHeader = class {
360
+ constructor(hostRef) {
361
+ registerInstance(this, hostRef);
362
+ /**
363
+ * If `true`, the card header will be translucent.
364
+ * Only applies when the mode is `"ios"` and the device supports
365
+ * [`backdrop-filter`](https://developer.mozilla.org/en-US/docs/Web/CSS/backdrop-filter#Browser_compatibility).
366
+ */
367
+ this.translucent = false;
368
+ }
369
+ render() {
370
+ const mode = getIonMode$1(this);
371
+ return (h(Host, { class: createColorClasses$1(this.color, {
372
+ 'card-header-translucent': this.translucent,
373
+ 'ion-inherit-color': true,
374
+ [mode]: true,
375
+ }) }, h("slot", null)));
376
+ }
377
+ };
378
+ CardHeader.style = {
379
+ ios: cardHeaderIosCss,
380
+ md: cardHeaderMdCss
381
+ };
382
+
383
+ const contentCss = ":host{--background:var(--ion-background-color, #fff);--color:var(--ion-text-color, #000);--padding-top:0px;--padding-bottom:0px;--padding-start:0px;--padding-end:0px;--keyboard-offset:0px;--offset-top:0px;--offset-bottom:0px;--overflow:auto;display:block;position:relative;flex:1;width:100%;height:100%;margin:0 !important;padding:0 !important;font-family:var(--ion-font-family, inherit);contain:size style}:host(.ion-color) .inner-scroll{background:var(--ion-color-base);color:var(--ion-color-contrast)}:host(.outer-content){--background:var(--ion-color-step-50, #f2f2f2)}#background-content{left:0px;right:0px;top:calc(var(--offset-top) * -1);bottom:calc(var(--offset-bottom) * -1);position:absolute;background:var(--background)}.inner-scroll{left:0px;right:0px;top:calc(var(--offset-top) * -1);bottom:calc(var(--offset-bottom) * -1);padding-left:var(--padding-start);padding-right:var(--padding-end);padding-top:calc(var(--padding-top) + var(--offset-top));padding-bottom:calc(var(--padding-bottom) + var(--keyboard-offset) + var(--offset-bottom));position:absolute;color:var(--color);box-sizing:border-box;overflow:hidden;touch-action:pan-x pan-y pinch-zoom}@supports (margin-inline-start: 0) or (-webkit-margin-start: 0){.inner-scroll{padding-left:unset;padding-right:unset;-webkit-padding-start:var(--padding-start);padding-inline-start:var(--padding-start);-webkit-padding-end:var(--padding-end);padding-inline-end:var(--padding-end)}}.scroll-y,.scroll-x{-webkit-overflow-scrolling:touch;z-index:0;will-change:scroll-position}.scroll-y{overflow-y:var(--overflow);overscroll-behavior-y:contain}.scroll-x{overflow-x:var(--overflow);overscroll-behavior-x:contain}.overscroll::before,.overscroll::after{position:absolute;width:1px;height:1px;content:\"\"}.overscroll::before{bottom:-1px}.overscroll::after{top:-1px}:host(.content-sizing){display:flex;flex-direction:column;min-height:0;contain:none}:host(.content-sizing) .inner-scroll{position:relative;top:0;bottom:0;margin-top:calc(var(--offset-top) * -1);margin-bottom:calc(var(--offset-bottom) * -1)}.transition-effect{display:none;position:absolute;width:100%;height:100vh;opacity:0;pointer-events:none}:host(.content-ltr) .transition-effect{left:-100%;}:host(.content-rtl) .transition-effect{right:-100%;}.transition-cover{position:absolute;right:0;width:100%;height:100%;background:black;opacity:0.1}.transition-shadow{display:block;position:absolute;width:10px;height:100%;background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAgCAYAAAAIXrg4AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyhpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuNi1jMTQ1IDc5LjE2MzQ5OSwgMjAxOC8wOC8xMy0xNjo0MDoyMiAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENDIDIwMTkgKE1hY2ludG9zaCkiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6MTE3MDgzRkQ5QTkyMTFFOUEwNzQ5MkJFREE1NUY2MjQiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6MTE3MDgzRkU5QTkyMTFFOUEwNzQ5MkJFREE1NUY2MjQiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDoxMTcwODNGQjlBOTIxMUU5QTA3NDkyQkVEQTU1RjYyNCIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDoxMTcwODNGQzlBOTIxMUU5QTA3NDkyQkVEQTU1RjYyNCIvPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/PmePEuQAAABNSURBVHjaYvz//z8DIxAwMDAwATGMhmFmPDQuOSZks0AMmoJBaQHjkPfB0Lfg/2gQjVow+HPy/yHvg9GiYjQfjMbBqAWjFgy/4hogwADYqwdzxy5BuwAAAABJRU5ErkJggg==);background-repeat:repeat-y;background-size:10px 16px}:host(.content-ltr) .transition-shadow{right:0;}:host(.content-rtl) .transition-shadow{left:0;transform:scaleX(-1)}::slotted([slot=fixed]){position:absolute;transform:translateZ(0)}";
384
+
385
+ const Content = class {
386
+ constructor(hostRef) {
387
+ registerInstance(this, hostRef);
388
+ this.ionScrollStart = createEvent(this, "ionScrollStart", 7);
389
+ this.ionScroll = createEvent(this, "ionScroll", 7);
390
+ this.ionScrollEnd = createEvent(this, "ionScrollEnd", 7);
391
+ this.isScrolling = false;
392
+ this.lastScroll = 0;
393
+ this.queued = false;
394
+ this.cTop = -1;
395
+ this.cBottom = -1;
396
+ this.isMainContent = true;
397
+ // Detail is used in a hot loop in the scroll event, by allocating it here
398
+ // V8 will be able to inline any read/write to it since it's a monomorphic class.
399
+ // https://mrale.ph/blog/2015/01/11/whats-up-with-monomorphism.html
400
+ this.detail = {
401
+ scrollTop: 0,
402
+ scrollLeft: 0,
403
+ type: 'scroll',
404
+ event: undefined,
405
+ startX: 0,
406
+ startY: 0,
407
+ startTime: 0,
408
+ currentX: 0,
409
+ currentY: 0,
410
+ velocityX: 0,
411
+ velocityY: 0,
412
+ deltaX: 0,
413
+ deltaY: 0,
414
+ currentTime: 0,
415
+ data: undefined,
416
+ isScrolling: true,
417
+ };
418
+ /**
419
+ * If `true`, the content will scroll behind the headers
420
+ * and footers. This effect can easily be seen by setting the toolbar
421
+ * to transparent.
422
+ */
423
+ this.fullscreen = false;
424
+ /**
425
+ * If you want to enable the content scrolling in the X axis, set this property to `true`.
426
+ */
427
+ this.scrollX = false;
428
+ /**
429
+ * If you want to disable the content scrolling in the Y axis, set this property to `false`.
430
+ */
431
+ this.scrollY = true;
432
+ /**
433
+ * Because of performance reasons, ionScroll events are disabled by default, in order to enable them
434
+ * and start listening from (ionScroll), set this property to `true`.
435
+ */
436
+ this.scrollEvents = false;
437
+ }
438
+ connectedCallback() {
439
+ this.isMainContent = this.el.closest('ion-menu, ion-popover, ion-modal') === null;
440
+ }
441
+ disconnectedCallback() {
442
+ this.onScrollEnd();
443
+ }
444
+ onAppLoad() {
445
+ this.resize();
446
+ }
447
+ shouldForceOverscroll() {
448
+ const { forceOverscroll } = this;
449
+ const mode = getIonMode$1(this);
450
+ return forceOverscroll === undefined ? mode === 'ios' && isPlatform('ios') : forceOverscroll;
451
+ }
452
+ resize() {
453
+ if (this.fullscreen) {
454
+ readTask(() => this.readDimensions());
455
+ }
456
+ else if (this.cTop !== 0 || this.cBottom !== 0) {
457
+ this.cTop = this.cBottom = 0;
458
+ forceUpdate(this);
459
+ }
460
+ }
461
+ readDimensions() {
462
+ const page = getPageElement(this.el);
463
+ const top = Math.max(this.el.offsetTop, 0);
464
+ const bottom = Math.max(page.offsetHeight - top - this.el.offsetHeight, 0);
465
+ const dirty = top !== this.cTop || bottom !== this.cBottom;
466
+ if (dirty) {
467
+ this.cTop = top;
468
+ this.cBottom = bottom;
469
+ forceUpdate(this);
470
+ }
471
+ }
472
+ onScroll(ev) {
473
+ const timeStamp = Date.now();
474
+ const shouldStart = !this.isScrolling;
475
+ this.lastScroll = timeStamp;
476
+ if (shouldStart) {
477
+ this.onScrollStart();
478
+ }
479
+ if (!this.queued && this.scrollEvents) {
480
+ this.queued = true;
481
+ readTask((ts) => {
482
+ this.queued = false;
483
+ this.detail.event = ev;
484
+ updateScrollDetail(this.detail, this.scrollEl, ts, shouldStart);
485
+ this.ionScroll.emit(this.detail);
486
+ });
487
+ }
488
+ }
489
+ /**
490
+ * Get the element where the actual scrolling takes place.
491
+ * This element can be used to subscribe to `scroll` events or manually modify
492
+ * `scrollTop`. However, it's recommended to use the API provided by `ion-content`:
493
+ *
494
+ * i.e. Using `ionScroll`, `ionScrollStart`, `ionScrollEnd` for scrolling events
495
+ * and `scrollToPoint()` to scroll the content into a certain point.
496
+ */
497
+ async getScrollElement() {
498
+ /**
499
+ * If this gets called in certain early lifecycle hooks (ex: Vue onMounted),
500
+ * scrollEl won't be defined yet with the custom elements build, so wait for it to load in.
501
+ */
502
+ if (!this.scrollEl) {
503
+ await new Promise((resolve) => componentOnReady(this.el, resolve));
504
+ }
505
+ return Promise.resolve(this.scrollEl);
506
+ }
507
+ /**
508
+ * Returns the background content element.
509
+ * @internal
510
+ */
511
+ async getBackgroundElement() {
512
+ if (!this.backgroundContentEl) {
513
+ await new Promise((resolve) => componentOnReady(this.el, resolve));
514
+ }
515
+ return Promise.resolve(this.backgroundContentEl);
516
+ }
517
+ /**
518
+ * Scroll to the top of the component.
519
+ *
520
+ * @param duration The amount of time to take scrolling to the top. Defaults to `0`.
521
+ */
522
+ scrollToTop(duration = 0) {
523
+ return this.scrollToPoint(undefined, 0, duration);
524
+ }
525
+ /**
526
+ * Scroll to the bottom of the component.
527
+ *
528
+ * @param duration The amount of time to take scrolling to the bottom. Defaults to `0`.
529
+ */
530
+ async scrollToBottom(duration = 0) {
531
+ const scrollEl = await this.getScrollElement();
532
+ const y = scrollEl.scrollHeight - scrollEl.clientHeight;
533
+ return this.scrollToPoint(undefined, y, duration);
534
+ }
535
+ /**
536
+ * Scroll by a specified X/Y distance in the component.
537
+ *
538
+ * @param x The amount to scroll by on the horizontal axis.
539
+ * @param y The amount to scroll by on the vertical axis.
540
+ * @param duration The amount of time to take scrolling by that amount.
541
+ */
542
+ async scrollByPoint(x, y, duration) {
543
+ const scrollEl = await this.getScrollElement();
544
+ return this.scrollToPoint(x + scrollEl.scrollLeft, y + scrollEl.scrollTop, duration);
545
+ }
546
+ /**
547
+ * Scroll to a specified X/Y location in the component.
548
+ *
549
+ * @param x The point to scroll to on the horizontal axis.
550
+ * @param y The point to scroll to on the vertical axis.
551
+ * @param duration The amount of time to take scrolling to that point. Defaults to `0`.
552
+ */
553
+ async scrollToPoint(x, y, duration = 0) {
554
+ const el = await this.getScrollElement();
555
+ if (duration < 32) {
556
+ if (y != null) {
557
+ el.scrollTop = y;
558
+ }
559
+ if (x != null) {
560
+ el.scrollLeft = x;
561
+ }
562
+ return;
563
+ }
564
+ let resolve;
565
+ let startTime = 0;
566
+ const promise = new Promise((r) => (resolve = r));
567
+ const fromY = el.scrollTop;
568
+ const fromX = el.scrollLeft;
569
+ const deltaY = y != null ? y - fromY : 0;
570
+ const deltaX = x != null ? x - fromX : 0;
571
+ // scroll loop
572
+ const step = (timeStamp) => {
573
+ const linearTime = Math.min(1, (timeStamp - startTime) / duration) - 1;
574
+ const easedT = Math.pow(linearTime, 3) + 1;
575
+ if (deltaY !== 0) {
576
+ el.scrollTop = Math.floor(easedT * deltaY + fromY);
577
+ }
578
+ if (deltaX !== 0) {
579
+ el.scrollLeft = Math.floor(easedT * deltaX + fromX);
580
+ }
581
+ if (easedT < 1) {
582
+ // do not use DomController here
583
+ // must use nativeRaf in order to fire in the next frame
584
+ requestAnimationFrame(step);
585
+ }
586
+ else {
587
+ resolve();
588
+ }
589
+ };
590
+ // chill out for a frame first
591
+ requestAnimationFrame((ts) => {
592
+ startTime = ts;
593
+ step(ts);
594
+ });
595
+ return promise;
596
+ }
597
+ onScrollStart() {
598
+ this.isScrolling = true;
599
+ this.ionScrollStart.emit({
600
+ isScrolling: true,
601
+ });
602
+ if (this.watchDog) {
603
+ clearInterval(this.watchDog);
604
+ }
605
+ // watchdog
606
+ this.watchDog = setInterval(() => {
607
+ if (this.lastScroll < Date.now() - 120) {
608
+ this.onScrollEnd();
609
+ }
610
+ }, 100);
611
+ }
612
+ onScrollEnd() {
613
+ clearInterval(this.watchDog);
614
+ this.watchDog = null;
615
+ if (this.isScrolling) {
616
+ this.isScrolling = false;
617
+ this.ionScrollEnd.emit({
618
+ isScrolling: false,
619
+ });
620
+ }
621
+ }
622
+ render() {
623
+ const { isMainContent, scrollX, scrollY, el } = this;
624
+ const rtl = isRTL$1(el) ? 'rtl' : 'ltr';
625
+ const mode = getIonMode$1(this);
626
+ const forceOverscroll = this.shouldForceOverscroll();
627
+ const transitionShadow = mode === 'ios';
628
+ const TagType = isMainContent ? 'main' : 'div';
629
+ this.resize();
630
+ return (h(Host, { class: createColorClasses$1(this.color, {
631
+ [mode]: true,
632
+ 'content-sizing': hostContext('ion-popover', this.el),
633
+ overscroll: forceOverscroll,
634
+ [`content-${rtl}`]: true,
635
+ }), style: {
636
+ '--offset-top': `${this.cTop}px`,
637
+ '--offset-bottom': `${this.cBottom}px`,
638
+ } }, h("div", { ref: (el) => (this.backgroundContentEl = el), id: "background-content", part: "background" }), h(TagType, { class: {
639
+ 'inner-scroll': true,
640
+ 'scroll-x': scrollX,
641
+ 'scroll-y': scrollY,
642
+ overscroll: (scrollX || scrollY) && forceOverscroll,
643
+ }, ref: (scrollEl) => (this.scrollEl = scrollEl), onScroll: this.scrollEvents ? (ev) => this.onScroll(ev) : undefined, part: "scroll" }, h("slot", null)), transitionShadow ? (h("div", { class: "transition-effect" }, h("div", { class: "transition-cover" }), h("div", { class: "transition-shadow" }))) : null, h("slot", { name: "fixed" })));
644
+ }
645
+ get el() { return getElement(this); }
646
+ };
647
+ const getParentElement = (el) => {
648
+ var _a;
649
+ if (el.parentElement) {
650
+ // normal element with a parent element
651
+ return el.parentElement;
652
+ }
653
+ if ((_a = el.parentNode) === null || _a === void 0 ? void 0 : _a.host) {
654
+ // shadow dom's document fragment
655
+ return el.parentNode.host;
656
+ }
657
+ return null;
658
+ };
659
+ const getPageElement = (el) => {
660
+ const tabs = el.closest('ion-tabs');
661
+ if (tabs) {
662
+ return tabs;
663
+ }
664
+ /**
665
+ * If we're in a popover, we need to use its wrapper so we can account for space
666
+ * between the popover and the edges of the screen. But if the popover contains
667
+ * its own page element, we should use that instead.
668
+ */
669
+ const page = el.closest('ion-app, ion-page, .ion-page, page-inner, .popover-content');
670
+ if (page) {
671
+ return page;
672
+ }
673
+ return getParentElement(el);
674
+ };
675
+ // ******** DOM READ ****************
676
+ const updateScrollDetail = (detail, el, timestamp, shouldStart) => {
677
+ const prevX = detail.currentX;
678
+ const prevY = detail.currentY;
679
+ const prevT = detail.currentTime;
680
+ const currentX = el.scrollLeft;
681
+ const currentY = el.scrollTop;
682
+ const timeDelta = timestamp - prevT;
683
+ if (shouldStart) {
684
+ // remember the start positions
685
+ detail.startTime = timestamp;
686
+ detail.startX = currentX;
687
+ detail.startY = currentY;
688
+ detail.velocityX = detail.velocityY = 0;
689
+ }
690
+ detail.currentTime = timestamp;
691
+ detail.currentX = detail.scrollLeft = currentX;
692
+ detail.currentY = detail.scrollTop = currentY;
693
+ detail.deltaX = currentX - detail.startX;
694
+ detail.deltaY = currentY - detail.startY;
695
+ if (timeDelta > 0 && timeDelta < 100) {
696
+ const velocityX = (currentX - prevX) / timeDelta;
697
+ const velocityY = (currentY - prevY) / timeDelta;
698
+ detail.velocityX = velocityX * 0.7 + detail.velocityX * 0.3;
699
+ detail.velocityY = velocityY * 0.7 + detail.velocityY * 0.3;
700
+ }
701
+ };
702
+ Content.style = contentCss;
703
+
704
+ /*!
705
+ * (C) Ionic http://ionicframework.com - MIT License
706
+ */
707
+ const handleFooterFade = (scrollEl, baseEl) => {
708
+ readTask(() => {
709
+ const scrollTop = scrollEl.scrollTop;
710
+ const maxScroll = scrollEl.scrollHeight - scrollEl.clientHeight;
711
+ /**
712
+ * Toolbar background will fade
713
+ * out over fadeDuration in pixels.
714
+ */
715
+ const fadeDuration = 10;
716
+ /**
717
+ * Begin fading out maxScroll - 30px
718
+ * from the bottom of the content.
719
+ * Also determine how close we are
720
+ * to starting the fade. If we are
721
+ * before the starting point, the
722
+ * scale value will get clamped to 0.
723
+ * If we are after the maxScroll (rubber
724
+ * band scrolling), the scale value will
725
+ * get clamped to 1.
726
+ */
727
+ const fadeStart = maxScroll - fadeDuration;
728
+ const distanceToStart = scrollTop - fadeStart;
729
+ const scale = clamp(0, 1 - distanceToStart / fadeDuration, 1);
730
+ writeTask(() => {
731
+ baseEl.style.setProperty('--opacity-scale', scale.toString());
732
+ });
733
+ });
734
+ };
735
+
736
+ const footerIosCss = "ion-footer{display:block;position:relative;order:1;width:100%;z-index:10}ion-footer.footer-toolbar-padding ion-toolbar:last-of-type{padding-bottom:var(--ion-safe-area-bottom, 0)}.footer-ios ion-toolbar:first-of-type{--border-width:0.55px 0 0}@supports (backdrop-filter: blur(0)){.footer-background{left:0;right:0;top:0;bottom:0;position:absolute;backdrop-filter:saturate(180%) blur(20px)}.footer-translucent-ios ion-toolbar{--opacity:.8}}.footer-ios.ion-no-border ion-toolbar:first-of-type{--border-width:0}.footer-collapse-fade ion-toolbar{--opacity-scale:inherit}";
737
+
738
+ const footerMdCss = "ion-footer{display:block;position:relative;order:1;width:100%;z-index:10}ion-footer.footer-toolbar-padding ion-toolbar:last-of-type{padding-bottom:var(--ion-safe-area-bottom, 0)}.footer-md::before{left:0;top:-2px;bottom:auto;background-position:left 0 top 0;position:absolute;width:100%;height:2px;background-image:url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAHBAMAAADzDtBxAAAAD1BMVEUAAAAAAAAAAAAAAAAAAABPDueNAAAABXRSTlMUCS0gBIh/TXEAAAAaSURBVAjXYxCEAgY4UIICBmMogMsgFLtAAQCNSwXZKOdPxgAAAABJRU5ErkJggg==\");background-repeat:repeat-x;content:\"\"}[dir=rtl] .footer-md::before,:host-context([dir=rtl]) .footer-md::before{left:unset;right:unset;right:0}[dir=rtl] .footer-md::before,:host-context([dir=rtl]) .footer-md::before{background-position:right 0 top 0}.footer-md.ion-no-border::before{display:none}";
739
+
740
+ const Footer = class {
741
+ constructor(hostRef) {
742
+ registerInstance(this, hostRef);
743
+ this.keyboardCtrl = null;
744
+ this.keyboardVisible = false;
745
+ /**
746
+ * If `true`, the footer will be translucent.
747
+ * Only applies when the mode is `"ios"` and the device supports
748
+ * [`backdrop-filter`](https://developer.mozilla.org/en-US/docs/Web/CSS/backdrop-filter#Browser_compatibility).
749
+ *
750
+ * Note: In order to scroll content behind the footer, the `fullscreen`
751
+ * attribute needs to be set on the content.
752
+ */
753
+ this.translucent = false;
754
+ this.checkCollapsibleFooter = () => {
755
+ const mode = getIonMode$1(this);
756
+ if (mode !== 'ios') {
757
+ return;
758
+ }
759
+ const { collapse } = this;
760
+ const hasFade = collapse === 'fade';
761
+ this.destroyCollapsibleFooter();
762
+ if (hasFade) {
763
+ const pageEl = this.el.closest('ion-app,ion-page,.ion-page,page-inner');
764
+ const contentEl = pageEl ? findIonContent(pageEl) : null;
765
+ if (!contentEl) {
766
+ printIonContentErrorMsg(this.el);
767
+ return;
768
+ }
769
+ this.setupFadeFooter(contentEl);
770
+ }
771
+ };
772
+ this.setupFadeFooter = async (contentEl) => {
773
+ const scrollEl = (this.scrollEl = await getScrollElement(contentEl));
774
+ /**
775
+ * Handle fading of toolbars on scroll
776
+ */
777
+ this.contentScrollCallback = () => {
778
+ handleFooterFade(scrollEl, this.el);
779
+ };
780
+ scrollEl.addEventListener('scroll', this.contentScrollCallback);
781
+ handleFooterFade(scrollEl, this.el);
782
+ };
783
+ }
784
+ componentDidLoad() {
785
+ this.checkCollapsibleFooter();
786
+ }
787
+ componentDidUpdate() {
788
+ this.checkCollapsibleFooter();
789
+ }
790
+ connectedCallback() {
791
+ this.keyboardCtrl = createKeyboardController((keyboardOpen) => {
792
+ this.keyboardVisible = keyboardOpen; // trigger re-render by updating state
793
+ });
794
+ }
795
+ disconnectedCallback() {
796
+ if (this.keyboardCtrl) {
797
+ this.keyboardCtrl.destroy();
798
+ }
799
+ }
800
+ destroyCollapsibleFooter() {
801
+ if (this.scrollEl && this.contentScrollCallback) {
802
+ this.scrollEl.removeEventListener('scroll', this.contentScrollCallback);
803
+ this.contentScrollCallback = undefined;
804
+ }
805
+ }
806
+ render() {
807
+ const { translucent, collapse } = this;
808
+ const mode = getIonMode$1(this);
809
+ const tabs = this.el.closest('ion-tabs');
810
+ const tabBar = tabs === null || tabs === void 0 ? void 0 : tabs.querySelector(':scope > ion-tab-bar');
811
+ return (h(Host, { role: "contentinfo", class: {
812
+ [mode]: true,
813
+ // Used internally for styling
814
+ [`footer-${mode}`]: true,
815
+ [`footer-translucent`]: translucent,
816
+ [`footer-translucent-${mode}`]: translucent,
817
+ ['footer-toolbar-padding']: !this.keyboardVisible && (!tabBar || tabBar.slot !== 'bottom'),
818
+ [`footer-collapse-${collapse}`]: collapse !== undefined,
819
+ } }, mode === 'ios' && translucent && h("div", { class: "footer-background" }), h("slot", null)));
820
+ }
821
+ get el() { return getElement(this); }
822
+ };
823
+ Footer.style = {
824
+ ios: footerIosCss,
825
+ md: footerMdCss
826
+ };
827
+
828
+ /*!
829
+ * (C) Ionic http://ionicframework.com - MIT License
830
+ */
831
+ const TRANSITION = 'all 0.2s ease-in-out';
832
+ const cloneElement = (tagName) => {
833
+ const getCachedEl = document.querySelector(`${tagName}.ion-cloned-element`);
834
+ if (getCachedEl !== null) {
835
+ return getCachedEl;
836
+ }
837
+ const clonedEl = document.createElement(tagName);
838
+ clonedEl.classList.add('ion-cloned-element');
839
+ clonedEl.style.setProperty('display', 'none');
840
+ document.body.appendChild(clonedEl);
841
+ return clonedEl;
842
+ };
843
+ const createHeaderIndex = (headerEl) => {
844
+ if (!headerEl) {
845
+ return;
846
+ }
847
+ const toolbars = headerEl.querySelectorAll('ion-toolbar');
848
+ return {
849
+ el: headerEl,
850
+ toolbars: Array.from(toolbars).map((toolbar) => {
851
+ const ionTitleEl = toolbar.querySelector('ion-title');
852
+ return {
853
+ el: toolbar,
854
+ background: toolbar.shadowRoot.querySelector('.toolbar-background'),
855
+ ionTitleEl,
856
+ innerTitleEl: ionTitleEl ? ionTitleEl.shadowRoot.querySelector('.toolbar-title') : null,
857
+ ionButtonsEl: Array.from(toolbar.querySelectorAll('ion-buttons')),
858
+ };
859
+ }),
860
+ };
861
+ };
862
+ const handleContentScroll = (scrollEl, scrollHeaderIndex, contentEl) => {
863
+ readTask(() => {
864
+ const scrollTop = scrollEl.scrollTop;
865
+ const scale = clamp(1, 1 + -scrollTop / 500, 1.1);
866
+ // Native refresher should not cause titles to scale
867
+ const nativeRefresher = contentEl.querySelector('ion-refresher.refresher-native');
868
+ if (nativeRefresher === null) {
869
+ writeTask(() => {
870
+ scaleLargeTitles(scrollHeaderIndex.toolbars, scale);
871
+ });
872
+ }
873
+ });
874
+ };
875
+ const setToolbarBackgroundOpacity = (headerEl, opacity) => {
876
+ /**
877
+ * Fading in the backdrop opacity
878
+ * should happen after the large title
879
+ * has collapsed, so it is handled
880
+ * by handleHeaderFade()
881
+ */
882
+ if (headerEl.collapse === 'fade') {
883
+ return;
884
+ }
885
+ if (opacity === undefined) {
886
+ headerEl.style.removeProperty('--opacity-scale');
887
+ }
888
+ else {
889
+ headerEl.style.setProperty('--opacity-scale', opacity.toString());
890
+ }
891
+ };
892
+ const handleToolbarBorderIntersection = (ev, mainHeaderIndex, scrollTop) => {
893
+ if (!ev[0].isIntersecting) {
894
+ return;
895
+ }
896
+ /**
897
+ * There is a bug in Safari where overflow scrolling on a non-body element
898
+ * does not always reset the scrollTop position to 0 when letting go. It will
899
+ * set to 1 once the rubber band effect has ended. This causes the background to
900
+ * appear slightly on certain app setups.
901
+ *
902
+ * Additionally, we check if user is rubber banding (scrolling is negative)
903
+ * as this can mean they are using pull to refresh. Once the refresher starts,
904
+ * the content is transformed which can cause the intersection observer to erroneously
905
+ * fire here as well.
906
+ */
907
+ const scale = ev[0].intersectionRatio > 0.9 || scrollTop <= 0 ? 0 : ((1 - ev[0].intersectionRatio) * 100) / 75;
908
+ setToolbarBackgroundOpacity(mainHeaderIndex.el, scale === 1 ? undefined : scale);
909
+ };
910
+ /**
911
+ * If toolbars are intersecting, hide the scrollable toolbar content
912
+ * and show the primary toolbar content. If the toolbars are not intersecting,
913
+ * hide the primary toolbar content and show the scrollable toolbar content
914
+ */
915
+ const handleToolbarIntersection = (ev, mainHeaderIndex, scrollHeaderIndex, scrollEl) => {
916
+ writeTask(() => {
917
+ const scrollTop = scrollEl.scrollTop;
918
+ handleToolbarBorderIntersection(ev, mainHeaderIndex, scrollTop);
919
+ const event = ev[0];
920
+ const intersection = event.intersectionRect;
921
+ const intersectionArea = intersection.width * intersection.height;
922
+ const rootArea = event.rootBounds.width * event.rootBounds.height;
923
+ const isPageHidden = intersectionArea === 0 && rootArea === 0;
924
+ const leftDiff = Math.abs(intersection.left - event.boundingClientRect.left);
925
+ const rightDiff = Math.abs(intersection.right - event.boundingClientRect.right);
926
+ const isPageTransitioning = intersectionArea > 0 && (leftDiff >= 5 || rightDiff >= 5);
927
+ if (isPageHidden || isPageTransitioning) {
928
+ return;
929
+ }
930
+ if (event.isIntersecting) {
931
+ setHeaderActive(mainHeaderIndex, false);
932
+ setHeaderActive(scrollHeaderIndex);
933
+ }
934
+ else {
935
+ /**
936
+ * There is a bug with IntersectionObserver on Safari
937
+ * where `event.isIntersecting === false` when cancelling
938
+ * a swipe to go back gesture. Checking the intersection
939
+ * x, y, width, and height provides a workaround. This bug
940
+ * does not happen when using Safari + Web Animations,
941
+ * only Safari + CSS Animations.
942
+ */
943
+ const hasValidIntersection = (intersection.x === 0 && intersection.y === 0) || (intersection.width !== 0 && intersection.height !== 0);
944
+ if (hasValidIntersection && scrollTop > 0) {
945
+ setHeaderActive(mainHeaderIndex);
946
+ setHeaderActive(scrollHeaderIndex, false);
947
+ setToolbarBackgroundOpacity(mainHeaderIndex.el);
948
+ }
949
+ }
950
+ });
951
+ };
952
+ const setHeaderActive = (headerIndex, active = true) => {
953
+ const headerEl = headerIndex.el;
954
+ if (active) {
955
+ headerEl.classList.remove('header-collapse-condense-inactive');
956
+ headerEl.removeAttribute('aria-hidden');
957
+ }
958
+ else {
959
+ headerEl.classList.add('header-collapse-condense-inactive');
960
+ headerEl.setAttribute('aria-hidden', 'true');
961
+ }
962
+ };
963
+ const scaleLargeTitles = (toolbars = [], scale = 1, transition = false) => {
964
+ toolbars.forEach((toolbar) => {
965
+ const ionTitle = toolbar.ionTitleEl;
966
+ const titleDiv = toolbar.innerTitleEl;
967
+ if (!ionTitle || ionTitle.size !== 'large') {
968
+ return;
969
+ }
970
+ titleDiv.style.transition = transition ? TRANSITION : '';
971
+ titleDiv.style.transform = `scale3d(${scale}, ${scale}, 1)`;
972
+ });
973
+ };
974
+ const handleHeaderFade = (scrollEl, baseEl, condenseHeader) => {
975
+ readTask(() => {
976
+ const scrollTop = scrollEl.scrollTop;
977
+ const baseElHeight = baseEl.clientHeight;
978
+ const fadeStart = condenseHeader ? condenseHeader.clientHeight : 0;
979
+ /**
980
+ * If we are using fade header with a condense
981
+ * header, then the toolbar backgrounds should
982
+ * not begin to fade in until the condense
983
+ * header has fully collapsed.
984
+ *
985
+ * Additionally, the main content should not
986
+ * overflow out of the container until the
987
+ * condense header has fully collapsed. When
988
+ * using just the condense header the content
989
+ * should overflow out of the container.
990
+ */
991
+ if (condenseHeader !== null && scrollTop < fadeStart) {
992
+ baseEl.style.setProperty('--opacity-scale', '0');
993
+ scrollEl.style.setProperty('clip-path', `inset(${baseElHeight}px 0px 0px 0px)`);
994
+ return;
995
+ }
996
+ const distanceToStart = scrollTop - fadeStart;
997
+ const fadeDuration = 10;
998
+ const scale = clamp(0, distanceToStart / fadeDuration, 1);
999
+ writeTask(() => {
1000
+ scrollEl.style.removeProperty('clip-path');
1001
+ baseEl.style.setProperty('--opacity-scale', scale.toString());
1002
+ });
1003
+ });
1004
+ };
1005
+
1006
+ const headerIosCss = "ion-header{display:block;position:relative;order:-1;width:100%;z-index:10}ion-header ion-toolbar:first-of-type{padding-top:var(--ion-safe-area-top, 0)}.header-ios ion-toolbar:last-of-type{--border-width:0 0 0.55px}@supports (backdrop-filter: blur(0)){.header-background{left:0;right:0;top:0;bottom:0;position:absolute;backdrop-filter:saturate(180%) blur(20px)}.header-translucent-ios ion-toolbar{--opacity:.8}.header-collapse-condense-inactive .header-background{backdrop-filter:blur(20px)}}.header-ios.ion-no-border ion-toolbar:last-of-type{--border-width:0}.header-collapse-fade ion-toolbar{--opacity-scale:inherit}.header-collapse-condense{z-index:9}.header-collapse-condense ion-toolbar{position:sticky;top:0}.header-collapse-condense ion-toolbar:first-of-type{padding-top:7px;z-index:1}.header-collapse-condense ion-toolbar{--background:var(--ion-background-color, #fff);z-index:0}.header-collapse-condense ion-toolbar:last-of-type{--border-width:0px}.header-collapse-condense ion-toolbar ion-searchbar{height:48px;padding-top:0px;padding-bottom:13px}.header-collapse-main{--opacity-scale:1}.header-collapse-main ion-toolbar{--opacity-scale:inherit}.header-collapse-main ion-toolbar.in-toolbar ion-title,.header-collapse-main ion-toolbar.in-toolbar ion-buttons{transition:all 0.2s ease-in-out}.header-collapse-condense-inactive:not(.header-collapse-condense) ion-toolbar.in-toolbar ion-title,.header-collapse-condense-inactive:not(.header-collapse-condense) ion-toolbar.in-toolbar ion-buttons.buttons-collapse{opacity:0;pointer-events:none}.header-collapse-condense-inactive.header-collapse-condense ion-toolbar.in-toolbar ion-title,.header-collapse-condense-inactive.header-collapse-condense ion-toolbar.in-toolbar ion-buttons.buttons-collapse{visibility:hidden}";
1007
+
1008
+ const headerMdCss = "ion-header{display:block;position:relative;order:-1;width:100%;z-index:10}ion-header ion-toolbar:first-of-type{padding-top:var(--ion-safe-area-top, 0)}.header-md::after{left:0;bottom:-5px;background-position:left 0 top -2px;position:absolute;width:100%;height:5px;background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAHBAMAAADzDtBxAAAAD1BMVEUAAAAAAAAAAAAAAAAAAABPDueNAAAABXRSTlMUCS0gBIh/TXEAAAAaSURBVAjXYxCEAgY4UIICBmMogMsgFLtAAQCNSwXZKOdPxgAAAABJRU5ErkJggg==);background-repeat:repeat-x;content:\"\"}[dir=rtl] .header-md::after,:host-context([dir=rtl]) .header-md::after{left:unset;right:unset;right:0}[dir=rtl] .header-md::after,:host-context([dir=rtl]) .header-md::after{background-position:right 0 top -2px}.header-collapse-condense{display:none}.header-md.ion-no-border::after{display:none}";
1009
+
1010
+ const Header = class {
1011
+ constructor(hostRef) {
1012
+ registerInstance(this, hostRef);
1013
+ this.inheritedAttributes = {};
1014
+ /**
1015
+ * If `true`, the header will be translucent.
1016
+ * Only applies when the mode is `"ios"` and the device supports
1017
+ * [`backdrop-filter`](https://developer.mozilla.org/en-US/docs/Web/CSS/backdrop-filter#Browser_compatibility).
1018
+ *
1019
+ * Note: In order to scroll content behind the header, the `fullscreen`
1020
+ * attribute needs to be set on the content.
1021
+ */
1022
+ this.translucent = false;
1023
+ this.setupFadeHeader = async (contentEl, condenseHeader) => {
1024
+ const scrollEl = (this.scrollEl = await getScrollElement(contentEl));
1025
+ /**
1026
+ * Handle fading of toolbars on scroll
1027
+ */
1028
+ this.contentScrollCallback = () => {
1029
+ handleHeaderFade(this.scrollEl, this.el, condenseHeader);
1030
+ };
1031
+ scrollEl.addEventListener('scroll', this.contentScrollCallback);
1032
+ handleHeaderFade(this.scrollEl, this.el, condenseHeader);
1033
+ };
1034
+ }
1035
+ componentWillLoad() {
1036
+ this.inheritedAttributes = inheritAriaAttributes(this.el);
1037
+ }
1038
+ componentDidLoad() {
1039
+ this.checkCollapsibleHeader();
1040
+ }
1041
+ componentDidUpdate() {
1042
+ this.checkCollapsibleHeader();
1043
+ }
1044
+ disconnectedCallback() {
1045
+ this.destroyCollapsibleHeader();
1046
+ }
1047
+ async checkCollapsibleHeader() {
1048
+ const mode = getIonMode$1(this);
1049
+ if (mode !== 'ios') {
1050
+ return;
1051
+ }
1052
+ const { collapse } = this;
1053
+ const hasCondense = collapse === 'condense';
1054
+ const hasFade = collapse === 'fade';
1055
+ this.destroyCollapsibleHeader();
1056
+ if (hasCondense) {
1057
+ const pageEl = this.el.closest('ion-app,ion-page,.ion-page,page-inner');
1058
+ const contentEl = pageEl ? findIonContent(pageEl) : null;
1059
+ // Cloned elements are always needed in iOS transition
1060
+ writeTask(() => {
1061
+ const title = cloneElement('ion-title');
1062
+ title.size = 'large';
1063
+ cloneElement('ion-back-button');
1064
+ });
1065
+ await this.setupCondenseHeader(contentEl, pageEl);
1066
+ }
1067
+ else if (hasFade) {
1068
+ const pageEl = this.el.closest('ion-app,ion-page,.ion-page,page-inner');
1069
+ const contentEl = pageEl ? findIonContent(pageEl) : null;
1070
+ if (!contentEl) {
1071
+ printIonContentErrorMsg(this.el);
1072
+ return;
1073
+ }
1074
+ const condenseHeader = contentEl.querySelector('ion-header[collapse="condense"]');
1075
+ await this.setupFadeHeader(contentEl, condenseHeader);
1076
+ }
1077
+ }
1078
+ destroyCollapsibleHeader() {
1079
+ if (this.intersectionObserver) {
1080
+ this.intersectionObserver.disconnect();
1081
+ this.intersectionObserver = undefined;
1082
+ }
1083
+ if (this.scrollEl && this.contentScrollCallback) {
1084
+ this.scrollEl.removeEventListener('scroll', this.contentScrollCallback);
1085
+ this.contentScrollCallback = undefined;
1086
+ }
1087
+ if (this.collapsibleMainHeader) {
1088
+ this.collapsibleMainHeader.classList.remove('header-collapse-main');
1089
+ this.collapsibleMainHeader = undefined;
1090
+ }
1091
+ }
1092
+ async setupCondenseHeader(contentEl, pageEl) {
1093
+ if (!contentEl || !pageEl) {
1094
+ printIonContentErrorMsg(this.el);
1095
+ return;
1096
+ }
1097
+ if (typeof IntersectionObserver === 'undefined') {
1098
+ return;
1099
+ }
1100
+ this.scrollEl = await getScrollElement(contentEl);
1101
+ const headers = pageEl.querySelectorAll('ion-header');
1102
+ this.collapsibleMainHeader = Array.from(headers).find((header) => header.collapse !== 'condense');
1103
+ if (!this.collapsibleMainHeader) {
1104
+ return;
1105
+ }
1106
+ const mainHeaderIndex = createHeaderIndex(this.collapsibleMainHeader);
1107
+ const scrollHeaderIndex = createHeaderIndex(this.el);
1108
+ if (!mainHeaderIndex || !scrollHeaderIndex) {
1109
+ return;
1110
+ }
1111
+ setHeaderActive(mainHeaderIndex, false);
1112
+ setToolbarBackgroundOpacity(mainHeaderIndex.el, 0);
1113
+ /**
1114
+ * Handle interaction between toolbar collapse and
1115
+ * showing/hiding content in the primary ion-header
1116
+ * as well as progressively showing/hiding the main header
1117
+ * border as the top-most toolbar collapses or expands.
1118
+ */
1119
+ const toolbarIntersection = (ev) => {
1120
+ handleToolbarIntersection(ev, mainHeaderIndex, scrollHeaderIndex, this.scrollEl);
1121
+ };
1122
+ this.intersectionObserver = new IntersectionObserver(toolbarIntersection, {
1123
+ root: contentEl,
1124
+ threshold: [0.25, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1],
1125
+ });
1126
+ this.intersectionObserver.observe(scrollHeaderIndex.toolbars[scrollHeaderIndex.toolbars.length - 1].el);
1127
+ /**
1128
+ * Handle scaling of large iOS titles and
1129
+ * showing/hiding border on last toolbar
1130
+ * in primary header
1131
+ */
1132
+ this.contentScrollCallback = () => {
1133
+ handleContentScroll(this.scrollEl, scrollHeaderIndex, contentEl);
1134
+ };
1135
+ this.scrollEl.addEventListener('scroll', this.contentScrollCallback);
1136
+ writeTask(() => {
1137
+ if (this.collapsibleMainHeader !== undefined) {
1138
+ this.collapsibleMainHeader.classList.add('header-collapse-main');
1139
+ }
1140
+ });
1141
+ }
1142
+ render() {
1143
+ const { translucent, inheritedAttributes } = this;
1144
+ const mode = getIonMode$1(this);
1145
+ const collapse = this.collapse || 'none';
1146
+ // banner role must be at top level, so remove role if inside a menu
1147
+ const roleType = hostContext('ion-menu', this.el) ? 'none' : 'banner';
1148
+ return (h(Host, Object.assign({ role: roleType, class: {
1149
+ [mode]: true,
1150
+ // Used internally for styling
1151
+ [`header-${mode}`]: true,
1152
+ [`header-translucent`]: this.translucent,
1153
+ [`header-collapse-${collapse}`]: true,
1154
+ [`header-translucent-${mode}`]: this.translucent,
1155
+ } }, inheritedAttributes), mode === 'ios' && translucent && h("div", { class: "header-background" }), h("slot", null)));
1156
+ }
1157
+ get el() { return getElement(this); }
1158
+ };
1159
+ Header.style = {
1160
+ ios: headerIosCss,
1161
+ md: headerMdCss
1162
+ };
1163
+
1164
+ let CACHED_MAP;
1165
+ const getIconMap = () => {
1166
+ if (typeof window === 'undefined') {
1167
+ return new Map();
1168
+ }
1169
+ else {
1170
+ if (!CACHED_MAP) {
1171
+ const win = window;
1172
+ win.Ionicons = win.Ionicons || {};
1173
+ CACHED_MAP = win.Ionicons.map = win.Ionicons.map || new Map();
1174
+ }
1175
+ return CACHED_MAP;
1176
+ }
1177
+ };
1178
+ const getUrl = (i) => {
1179
+ let url = getSrc(i.src);
1180
+ if (url) {
1181
+ return url;
1182
+ }
1183
+ url = getName(i.name, i.icon, i.mode, i.ios, i.md);
1184
+ if (url) {
1185
+ return getNamedUrl(url);
1186
+ }
1187
+ if (i.icon) {
1188
+ url = getSrc(i.icon);
1189
+ if (url) {
1190
+ return url;
1191
+ }
1192
+ url = getSrc(i.icon[i.mode]);
1193
+ if (url) {
1194
+ return url;
1195
+ }
1196
+ }
1197
+ return null;
1198
+ };
1199
+ const getNamedUrl = (iconName) => {
1200
+ const url = getIconMap().get(iconName);
1201
+ if (url) {
1202
+ return url;
1203
+ }
1204
+ return getAssetPath(`svg/${iconName}.svg`);
1205
+ };
1206
+ const getName = (iconName, icon, mode, ios, md) => {
1207
+ // default to "md" if somehow the mode wasn't set
1208
+ mode = (mode && toLower(mode)) === 'ios' ? 'ios' : 'md';
1209
+ // if an icon was passed in using the ios or md attributes
1210
+ // set the iconName to whatever was passed in
1211
+ if (ios && mode === 'ios') {
1212
+ iconName = toLower(ios);
1213
+ }
1214
+ else if (md && mode === 'md') {
1215
+ iconName = toLower(md);
1216
+ }
1217
+ else {
1218
+ if (!iconName && icon && !isSrc(icon)) {
1219
+ iconName = icon;
1220
+ }
1221
+ if (isStr(iconName)) {
1222
+ iconName = toLower(iconName);
1223
+ }
1224
+ }
1225
+ if (!isStr(iconName) || iconName.trim() === '') {
1226
+ return null;
1227
+ }
1228
+ // only allow alpha characters and dash
1229
+ const invalidChars = iconName.replace(/[a-z]|-|\d/gi, '');
1230
+ if (invalidChars !== '') {
1231
+ return null;
1232
+ }
1233
+ return iconName;
1234
+ };
1235
+ const getSrc = (src) => {
1236
+ if (isStr(src)) {
1237
+ src = src.trim();
1238
+ if (isSrc(src)) {
1239
+ return src;
1240
+ }
1241
+ }
1242
+ return null;
1243
+ };
1244
+ const isSrc = (str) => str.length > 0 && /(\/|\.)/.test(str);
1245
+ const isStr = (val) => typeof val === 'string';
1246
+ const toLower = (val) => val.toLowerCase();
1247
+ /**
1248
+ * Elements inside of web components sometimes need to inherit global attributes
1249
+ * set on the host. For example, the inner input in `ion-input` should inherit
1250
+ * the `title` attribute that developers set directly on `ion-input`. This
1251
+ * helper function should be called in componentWillLoad and assigned to a variable
1252
+ * that is later used in the render function.
1253
+ *
1254
+ * This does not need to be reactive as changing attributes on the host element
1255
+ * does not trigger a re-render.
1256
+ */
1257
+ const inheritAttributes = (el, attributes = []) => {
1258
+ const attributeObject = {};
1259
+ attributes.forEach(attr => {
1260
+ if (el.hasAttribute(attr)) {
1261
+ const value = el.getAttribute(attr);
1262
+ if (value !== null) {
1263
+ attributeObject[attr] = el.getAttribute(attr);
1264
+ }
1265
+ el.removeAttribute(attr);
1266
+ }
1267
+ });
1268
+ return attributeObject;
1269
+ };
1270
+ /**
1271
+ * Returns `true` if the document or host element
1272
+ * has a `dir` set to `rtl`. The host value will always
1273
+ * take priority over the root document value.
1274
+ */
1275
+ const isRTL = (hostEl) => {
1276
+ if (hostEl) {
1277
+ if (hostEl.dir !== '') {
1278
+ return hostEl.dir.toLowerCase() === 'rtl';
1279
+ }
1280
+ }
1281
+ return (document === null || document === void 0 ? void 0 : document.dir.toLowerCase()) === 'rtl';
1282
+ };
1283
+
1284
+ const validateContent = (svgContent) => {
1285
+ const div = document.createElement('div');
1286
+ div.innerHTML = svgContent;
1287
+ // setup this way to ensure it works on our buddy IE
1288
+ for (let i = div.childNodes.length - 1; i >= 0; i--) {
1289
+ if (div.childNodes[i].nodeName.toLowerCase() !== 'svg') {
1290
+ div.removeChild(div.childNodes[i]);
1291
+ }
1292
+ }
1293
+ // must only have 1 root element
1294
+ const svgElm = div.firstElementChild;
1295
+ if (svgElm && svgElm.nodeName.toLowerCase() === 'svg') {
1296
+ const svgClass = svgElm.getAttribute('class') || '';
1297
+ svgElm.setAttribute('class', (svgClass + ' s-ion-icon').trim());
1298
+ // root element must be an svg
1299
+ // lets double check we've got valid elements
1300
+ // do not allow scripts
1301
+ if (isValid(svgElm)) {
1302
+ return div.innerHTML;
1303
+ }
1304
+ }
1305
+ return '';
1306
+ };
1307
+ const isValid = (elm) => {
1308
+ if (elm.nodeType === 1) {
1309
+ if (elm.nodeName.toLowerCase() === 'script') {
1310
+ return false;
1311
+ }
1312
+ for (let i = 0; i < elm.attributes.length; i++) {
1313
+ const name = elm.attributes[i].name;
1314
+ if (isStr(name) && name.toLowerCase().indexOf('on') === 0) {
1315
+ return false;
1316
+ }
1317
+ }
1318
+ for (let i = 0; i < elm.childNodes.length; i++) {
1319
+ if (!isValid(elm.childNodes[i])) {
1320
+ return false;
1321
+ }
1322
+ }
1323
+ }
1324
+ return true;
1325
+ };
1326
+
1327
+ const ioniconContent = new Map();
1328
+ const requests = new Map();
1329
+ const getSvgContent = (url, sanitize) => {
1330
+ // see if we already have a request for this url
1331
+ let req = requests.get(url);
1332
+ if (!req) {
1333
+ if (typeof fetch !== 'undefined' && typeof document !== 'undefined') {
1334
+ // we don't already have a request
1335
+ req = fetch(url).then((rsp) => {
1336
+ if (rsp.ok) {
1337
+ return rsp.text().then((svgContent) => {
1338
+ if (svgContent && sanitize !== false) {
1339
+ svgContent = validateContent(svgContent);
1340
+ }
1341
+ ioniconContent.set(url, svgContent || '');
1342
+ });
1343
+ }
1344
+ ioniconContent.set(url, '');
1345
+ });
1346
+ // cache for the same requests
1347
+ requests.set(url, req);
1348
+ }
1349
+ else {
1350
+ // set to empty for ssr scenarios and resolve promise
1351
+ ioniconContent.set(url, '');
1352
+ return Promise.resolve();
1353
+ }
1354
+ }
1355
+ return req;
1356
+ };
1357
+
1358
+ const iconCss = ":host{display:inline-block;width:1em;height:1em;contain:strict;fill:currentColor;box-sizing:content-box !important}:host .ionicon{stroke:currentColor}.ionicon-fill-none{fill:none}.ionicon-stroke-width{stroke-width:32px;stroke-width:var(--ionicon-stroke-width, 32px)}.icon-inner,.ionicon,svg{display:block;height:100%;width:100%}:host(.flip-rtl) .icon-inner{transform:scaleX(-1)}:host(.icon-small){font-size:18px !important}:host(.icon-large){font-size:32px !important}:host(.ion-color){color:var(--ion-color-base) !important}:host(.ion-color-primary){--ion-color-base:var(--ion-color-primary, #3880ff)}:host(.ion-color-secondary){--ion-color-base:var(--ion-color-secondary, #0cd1e8)}:host(.ion-color-tertiary){--ion-color-base:var(--ion-color-tertiary, #f4a942)}:host(.ion-color-success){--ion-color-base:var(--ion-color-success, #10dc60)}:host(.ion-color-warning){--ion-color-base:var(--ion-color-warning, #ffce00)}:host(.ion-color-danger){--ion-color-base:var(--ion-color-danger, #f14141)}:host(.ion-color-light){--ion-color-base:var(--ion-color-light, #f4f5f8)}:host(.ion-color-medium){--ion-color-base:var(--ion-color-medium, #989aa2)}:host(.ion-color-dark){--ion-color-base:var(--ion-color-dark, #222428)}";
1359
+
1360
+ let parser;
1361
+ const Icon = class {
1362
+ constructor(hostRef) {
1363
+ registerInstance(this, hostRef);
1364
+ this.iconName = null;
1365
+ this.inheritedAttributes = {};
1366
+ this.isVisible = false;
1367
+ /**
1368
+ * The mode determines which platform styles to use.
1369
+ */
1370
+ this.mode = getIonMode();
1371
+ /**
1372
+ * If enabled, ion-icon will be loaded lazily when it's visible in the viewport.
1373
+ * Default, `false`.
1374
+ */
1375
+ this.lazy = false;
1376
+ /**
1377
+ * When set to `false`, SVG content that is HTTP fetched will not be checked
1378
+ * if the response SVG content has any `<script>` elements, or any attributes
1379
+ * that start with `on`, such as `onclick`.
1380
+ * @default true
1381
+ */
1382
+ this.sanitize = true;
1383
+ this.hasAriaHidden = () => {
1384
+ const { el } = this;
1385
+ return el.hasAttribute('aria-hidden') && el.getAttribute('aria-hidden') === 'true';
1386
+ };
1387
+ }
1388
+ componentWillLoad() {
1389
+ this.inheritedAttributes = inheritAttributes(this.el, ['aria-label']);
1390
+ }
1391
+ connectedCallback() {
1392
+ // purposely do not return the promise here because loading
1393
+ // the svg file should not hold up loading the app
1394
+ // only load the svg if it's visible
1395
+ this.waitUntilVisible(this.el, '50px', () => {
1396
+ this.isVisible = true;
1397
+ this.loadIcon();
1398
+ });
1399
+ }
1400
+ disconnectedCallback() {
1401
+ if (this.io) {
1402
+ this.io.disconnect();
1403
+ this.io = undefined;
1404
+ }
1405
+ }
1406
+ waitUntilVisible(el, rootMargin, cb) {
1407
+ if (this.lazy && typeof window !== 'undefined' && window.IntersectionObserver) {
1408
+ const io = (this.io = new window.IntersectionObserver((data) => {
1409
+ if (data[0].isIntersecting) {
1410
+ io.disconnect();
1411
+ this.io = undefined;
1412
+ cb();
1413
+ }
1414
+ }, { rootMargin }));
1415
+ io.observe(el);
1416
+ }
1417
+ else {
1418
+ // browser doesn't support IntersectionObserver
1419
+ // so just fallback to always show it
1420
+ cb();
1421
+ }
1422
+ }
1423
+ loadIcon() {
1424
+ if (this.isVisible) {
1425
+ if (!parser) {
1426
+ /**
1427
+ * Create an instance of the DOM parser. This creates a single
1428
+ * parser instance for the entire app, which is more efficient.
1429
+ */
1430
+ parser = new DOMParser();
1431
+ }
1432
+ const url = getUrl(this);
1433
+ if (url) {
1434
+ if (ioniconContent.has(url)) {
1435
+ // sync if it's already loaded
1436
+ this.svgContent = ioniconContent.get(url);
1437
+ }
1438
+ else if (url.startsWith('data:')) {
1439
+ const doc = parser.parseFromString(url, 'text/html');
1440
+ const svgEl = doc.body.querySelector('svg');
1441
+ if (svgEl !== null) {
1442
+ this.svgContent = svgEl.outerHTML;
1443
+ }
1444
+ else {
1445
+ this.svgContent = '';
1446
+ }
1447
+ }
1448
+ else {
1449
+ // async if it hasn't been loaded
1450
+ getSvgContent(url, this.sanitize).then(() => (this.svgContent = ioniconContent.get(url)));
1451
+ }
1452
+ }
1453
+ }
1454
+ const label = this.iconName = getName(this.name, this.icon, this.mode, this.ios, this.md);
1455
+ /**
1456
+ * Come up with a default label
1457
+ * in case user does not provide their own.
1458
+ */
1459
+ if (label) {
1460
+ this.ariaLabel = label.replace(/\-/g, ' ');
1461
+ }
1462
+ }
1463
+ render() {
1464
+ const { iconName, ariaLabel, el, inheritedAttributes } = this;
1465
+ const mode = this.mode || 'md';
1466
+ const flipRtl = this.flipRtl ||
1467
+ (iconName &&
1468
+ (iconName.indexOf('arrow') > -1 || iconName.indexOf('chevron') > -1) &&
1469
+ this.flipRtl !== false);
1470
+ /**
1471
+ * Only set the aria-label if a) we have generated
1472
+ * one for the icon and if aria-hidden is not set to "true".
1473
+ * If developer wants to set their own aria-label, then
1474
+ * inheritedAttributes down below will override whatever
1475
+ * default label we have set.
1476
+ */
1477
+ return (h(Host, Object.assign({ "aria-label": ariaLabel !== undefined && !this.hasAriaHidden() ? ariaLabel : null, role: "img", class: Object.assign(Object.assign({ [mode]: true }, createColorClasses(this.color)), { [`icon-${this.size}`]: !!this.size, 'flip-rtl': !!flipRtl && isRTL(el) }) }, inheritedAttributes), this.svgContent ? (h("div", { class: "icon-inner", innerHTML: this.svgContent })) : (h("div", { class: "icon-inner" }))));
1478
+ }
1479
+ static get assetsDirs() { return ["svg"]; }
1480
+ get el() { return getElement(this); }
1481
+ static get watchers() { return {
1482
+ "name": ["loadIcon"],
1483
+ "src": ["loadIcon"],
1484
+ "icon": ["loadIcon"]
1485
+ }; }
1486
+ };
1487
+ const getIonMode = () => (typeof document !== 'undefined' && document.documentElement.getAttribute('mode')) || 'md';
1488
+ const createColorClasses = (color) => {
1489
+ return color
1490
+ ? {
1491
+ 'ion-color': true,
1492
+ [`ion-color-${color}`]: true,
1493
+ }
1494
+ : null;
1495
+ };
1496
+ Icon.style = iconCss;
1497
+
1498
+ const progressBarIosCss = ":host{--background:rgba(var(--ion-color-primary-rgb, 56, 128, 255), 0.3);--progress-background:var(--ion-color-primary, #3880ff);--buffer-background:var(--background);display:block;position:relative;width:100%;contain:strict;direction:ltr;overflow:hidden}.progress,.progress-indeterminate,.indeterminate-bar-primary,.indeterminate-bar-secondary,.progress-buffer-bar{left:0;right:0;top:0;bottom:0;position:absolute;width:100%;height:100%}.buffer-circles-container,.buffer-circles{left:0;right:0;top:0;bottom:0;position:absolute}.buffer-circles{right:-10px;left:-10px;}.progress,.progress-buffer-bar,.buffer-circles-container{transform-origin:left top;transition:transform 150ms linear}.progress,.progress-indeterminate{background:var(--progress-background);z-index:2}.progress-buffer-bar{background:var(--buffer-background);z-index:1}.buffer-circles-container{overflow:hidden}.indeterminate-bar-primary{top:0;right:0;bottom:0;left:-145.166611%;animation:primary-indeterminate-translate 2s infinite linear}.indeterminate-bar-primary .progress-indeterminate{animation:primary-indeterminate-scale 2s infinite linear;animation-play-state:inherit}.indeterminate-bar-secondary{top:0;right:0;bottom:0;left:-54.888891%;animation:secondary-indeterminate-translate 2s infinite linear}.indeterminate-bar-secondary .progress-indeterminate{animation:secondary-indeterminate-scale 2s infinite linear;animation-play-state:inherit}.buffer-circles{background-image:radial-gradient(ellipse at center, var(--buffer-background) 0%, var(--buffer-background) 30%, transparent 30%);background-repeat:repeat-x;background-position:5px center;background-size:10px 10px;z-index:0;animation:buffering 450ms infinite linear}:host(.progress-bar-reversed){transform:scaleX(-1)}:host(.progress-paused) .indeterminate-bar-secondary,:host(.progress-paused) .indeterminate-bar-primary,:host(.progress-paused) .buffer-circles{animation-play-state:paused}:host(.ion-color) .progress-buffer-bar{background:rgba(var(--ion-color-base-rgb), 0.3)}:host(.ion-color) .buffer-circles{background-image:radial-gradient(ellipse at center, rgba(var(--ion-color-base-rgb), 0.3) 0%, rgba(var(--ion-color-base-rgb), 0.3) 30%, transparent 30%)}:host(.ion-color) .progress,:host(.ion-color) .progress-indeterminate{background:var(--ion-color-base)}@keyframes primary-indeterminate-translate{0%{transform:translateX(0)}20%{animation-timing-function:cubic-bezier(0.5, 0, 0.701732, 0.495819);transform:translateX(0)}59.15%{animation-timing-function:cubic-bezier(0.302435, 0.381352, 0.55, 0.956352);transform:translateX(83.67142%)}100%{transform:translateX(200.611057%)}}@keyframes primary-indeterminate-scale{0%{transform:scaleX(0.08)}36.65%{animation-timing-function:cubic-bezier(0.334731, 0.12482, 0.785844, 1);transform:scaleX(0.08)}69.15%{animation-timing-function:cubic-bezier(0.06, 0.11, 0.6, 1);transform:scaleX(0.661479)}100%{transform:scaleX(0.08)}}@keyframes secondary-indeterminate-translate{0%{animation-timing-function:cubic-bezier(0.15, 0, 0.515058, 0.409685);transform:translateX(0)}25%{animation-timing-function:cubic-bezier(0.31033, 0.284058, 0.8, 0.733712);transform:translateX(37.651913%)}48.35%{animation-timing-function:cubic-bezier(0.4, 0.627035, 0.6, 0.902026);transform:translateX(84.386165%)}100%{transform:translateX(160.277782%)}}@keyframes secondary-indeterminate-scale{0%{animation-timing-function:cubic-bezier(0.205028, 0.057051, 0.57661, 0.453971);transform:scaleX(0.08)}19.15%{animation-timing-function:cubic-bezier(0.152313, 0.196432, 0.648374, 1.004315);transform:scaleX(0.457104)}44.15%{animation-timing-function:cubic-bezier(0.257759, -0.003163, 0.211762, 1.38179);transform:scaleX(0.72796)}100%{transform:scaleX(0.08)}}@keyframes buffering{to{transform:translateX(-10px)}}:host{height:3px}";
1499
+
1500
+ const progressBarMdCss = ":host{--background:rgba(var(--ion-color-primary-rgb, 56, 128, 255), 0.3);--progress-background:var(--ion-color-primary, #3880ff);--buffer-background:var(--background);display:block;position:relative;width:100%;contain:strict;direction:ltr;overflow:hidden}.progress,.progress-indeterminate,.indeterminate-bar-primary,.indeterminate-bar-secondary,.progress-buffer-bar{left:0;right:0;top:0;bottom:0;position:absolute;width:100%;height:100%}.buffer-circles-container,.buffer-circles{left:0;right:0;top:0;bottom:0;position:absolute}.buffer-circles{right:-10px;left:-10px;}.progress,.progress-buffer-bar,.buffer-circles-container{transform-origin:left top;transition:transform 150ms linear}.progress,.progress-indeterminate{background:var(--progress-background);z-index:2}.progress-buffer-bar{background:var(--buffer-background);z-index:1}.buffer-circles-container{overflow:hidden}.indeterminate-bar-primary{top:0;right:0;bottom:0;left:-145.166611%;animation:primary-indeterminate-translate 2s infinite linear}.indeterminate-bar-primary .progress-indeterminate{animation:primary-indeterminate-scale 2s infinite linear;animation-play-state:inherit}.indeterminate-bar-secondary{top:0;right:0;bottom:0;left:-54.888891%;animation:secondary-indeterminate-translate 2s infinite linear}.indeterminate-bar-secondary .progress-indeterminate{animation:secondary-indeterminate-scale 2s infinite linear;animation-play-state:inherit}.buffer-circles{background-image:radial-gradient(ellipse at center, var(--buffer-background) 0%, var(--buffer-background) 30%, transparent 30%);background-repeat:repeat-x;background-position:5px center;background-size:10px 10px;z-index:0;animation:buffering 450ms infinite linear}:host(.progress-bar-reversed){transform:scaleX(-1)}:host(.progress-paused) .indeterminate-bar-secondary,:host(.progress-paused) .indeterminate-bar-primary,:host(.progress-paused) .buffer-circles{animation-play-state:paused}:host(.ion-color) .progress-buffer-bar{background:rgba(var(--ion-color-base-rgb), 0.3)}:host(.ion-color) .buffer-circles{background-image:radial-gradient(ellipse at center, rgba(var(--ion-color-base-rgb), 0.3) 0%, rgba(var(--ion-color-base-rgb), 0.3) 30%, transparent 30%)}:host(.ion-color) .progress,:host(.ion-color) .progress-indeterminate{background:var(--ion-color-base)}@keyframes primary-indeterminate-translate{0%{transform:translateX(0)}20%{animation-timing-function:cubic-bezier(0.5, 0, 0.701732, 0.495819);transform:translateX(0)}59.15%{animation-timing-function:cubic-bezier(0.302435, 0.381352, 0.55, 0.956352);transform:translateX(83.67142%)}100%{transform:translateX(200.611057%)}}@keyframes primary-indeterminate-scale{0%{transform:scaleX(0.08)}36.65%{animation-timing-function:cubic-bezier(0.334731, 0.12482, 0.785844, 1);transform:scaleX(0.08)}69.15%{animation-timing-function:cubic-bezier(0.06, 0.11, 0.6, 1);transform:scaleX(0.661479)}100%{transform:scaleX(0.08)}}@keyframes secondary-indeterminate-translate{0%{animation-timing-function:cubic-bezier(0.15, 0, 0.515058, 0.409685);transform:translateX(0)}25%{animation-timing-function:cubic-bezier(0.31033, 0.284058, 0.8, 0.733712);transform:translateX(37.651913%)}48.35%{animation-timing-function:cubic-bezier(0.4, 0.627035, 0.6, 0.902026);transform:translateX(84.386165%)}100%{transform:translateX(160.277782%)}}@keyframes secondary-indeterminate-scale{0%{animation-timing-function:cubic-bezier(0.205028, 0.057051, 0.57661, 0.453971);transform:scaleX(0.08)}19.15%{animation-timing-function:cubic-bezier(0.152313, 0.196432, 0.648374, 1.004315);transform:scaleX(0.457104)}44.15%{animation-timing-function:cubic-bezier(0.257759, -0.003163, 0.211762, 1.38179);transform:scaleX(0.72796)}100%{transform:scaleX(0.08)}}@keyframes buffering{to{transform:translateX(-10px)}}:host{height:4px}";
1501
+
1502
+ const ProgressBar = class {
1503
+ constructor(hostRef) {
1504
+ registerInstance(this, hostRef);
1505
+ /**
1506
+ * The state of the progress bar, based on if the time the process takes is known or not.
1507
+ * Default options are: `"determinate"` (no animation), `"indeterminate"` (animate from left to right).
1508
+ */
1509
+ this.type = 'determinate';
1510
+ /**
1511
+ * If true, reverse the progress bar direction.
1512
+ */
1513
+ this.reversed = false;
1514
+ /**
1515
+ * The value determines how much of the active bar should display when the
1516
+ * `type` is `"determinate"`.
1517
+ * The value should be between [0, 1].
1518
+ */
1519
+ this.value = 0;
1520
+ /**
1521
+ * If the buffer and value are smaller than 1, the buffer circles will show.
1522
+ * The buffer should be between [0, 1].
1523
+ */
1524
+ this.buffer = 1;
1525
+ }
1526
+ render() {
1527
+ const { color, type, reversed, value, buffer } = this;
1528
+ const paused = config.getBoolean('_testing');
1529
+ const mode = getIonMode$1(this);
1530
+ return (h(Host, { role: "progressbar", "aria-valuenow": type === 'determinate' ? value : null, "aria-valuemin": "0", "aria-valuemax": "1", class: createColorClasses$1(color, {
1531
+ [mode]: true,
1532
+ [`progress-bar-${type}`]: true,
1533
+ 'progress-paused': paused,
1534
+ 'progress-bar-reversed': document.dir === 'rtl' ? !reversed : reversed,
1535
+ }) }, type === 'indeterminate' ? renderIndeterminate() : renderProgress(value, buffer)));
1536
+ }
1537
+ };
1538
+ const renderIndeterminate = () => {
1539
+ return (h("div", { part: "track", class: "progress-buffer-bar" }, h("div", { class: "indeterminate-bar-primary" }, h("span", { part: "progress", class: "progress-indeterminate" })), h("div", { class: "indeterminate-bar-secondary" }, h("span", { part: "progress", class: "progress-indeterminate" }))));
1540
+ };
1541
+ const renderProgress = (value, buffer) => {
1542
+ const finalValue = clamp(0, value, 1);
1543
+ const finalBuffer = clamp(0, buffer, 1);
1544
+ return [
1545
+ h("div", { part: "progress", class: "progress", style: { transform: `scaleX(${finalValue})` } }),
1546
+ /**
1547
+ * Buffer circles with two container to move
1548
+ * the circles behind the buffer progress
1549
+ * with respecting the animation.
1550
+ * When finalBuffer === 1, we use display: none
1551
+ * instead of removing the element to avoid flickering.
1552
+ */
1553
+ h("div", { class: { 'buffer-circles-container': true, 'ion-hide': finalBuffer === 1 }, style: { transform: `translateX(${finalBuffer * 100}%)` } }, h("div", { class: "buffer-circles-container", style: { transform: `translateX(-${finalBuffer * 100}%)` } }, h("div", { part: "stream", class: "buffer-circles" }))),
1554
+ h("div", { part: "track", class: "progress-buffer-bar", style: { transform: `scaleX(${finalBuffer})` } }),
1555
+ ];
1556
+ };
1557
+ ProgressBar.style = {
1558
+ ios: progressBarIosCss,
1559
+ md: progressBarMdCss
1560
+ };
1561
+
1562
+ const rippleEffectCss = ":host{left:0;right:0;top:0;bottom:0;position:absolute;contain:strict;pointer-events:none}:host(.unbounded){contain:layout size style}.ripple-effect{border-radius:50%;position:absolute;background-color:currentColor;color:inherit;contain:strict;opacity:0;animation:225ms rippleAnimation forwards, 75ms fadeInAnimation forwards;will-change:transform, opacity;pointer-events:none}.fade-out{transform:translate(var(--translate-end)) scale(var(--final-scale, 1));animation:150ms fadeOutAnimation forwards}@keyframes rippleAnimation{from{animation-timing-function:cubic-bezier(0.4, 0, 0.2, 1);transform:scale(1)}to{transform:translate(var(--translate-end)) scale(var(--final-scale, 1))}}@keyframes fadeInAnimation{from{animation-timing-function:linear;opacity:0}to{opacity:0.16}}@keyframes fadeOutAnimation{from{animation-timing-function:linear;opacity:0.16}to{opacity:0}}";
1563
+
1564
+ const RippleEffect = class {
1565
+ constructor(hostRef) {
1566
+ registerInstance(this, hostRef);
1567
+ /**
1568
+ * Sets the type of ripple-effect:
1569
+ *
1570
+ * - `bounded`: the ripple effect expands from the user's click position
1571
+ * - `unbounded`: the ripple effect expands from the center of the button and overflows the container.
1572
+ *
1573
+ * NOTE: Surfaces for bounded ripples should have the overflow property set to hidden,
1574
+ * while surfaces for unbounded ripples should have it set to visible.
1575
+ */
1576
+ this.type = 'bounded';
1577
+ }
1578
+ /**
1579
+ * Adds the ripple effect to the parent element.
1580
+ *
1581
+ * @param x The horizontal coordinate of where the ripple should start.
1582
+ * @param y The vertical coordinate of where the ripple should start.
1583
+ */
1584
+ async addRipple(x, y) {
1585
+ return new Promise((resolve) => {
1586
+ readTask(() => {
1587
+ const rect = this.el.getBoundingClientRect();
1588
+ const width = rect.width;
1589
+ const height = rect.height;
1590
+ const hypotenuse = Math.sqrt(width * width + height * height);
1591
+ const maxDim = Math.max(height, width);
1592
+ const maxRadius = this.unbounded ? maxDim : hypotenuse + PADDING;
1593
+ const initialSize = Math.floor(maxDim * INITIAL_ORIGIN_SCALE);
1594
+ const finalScale = maxRadius / initialSize;
1595
+ let posX = x - rect.left;
1596
+ let posY = y - rect.top;
1597
+ if (this.unbounded) {
1598
+ posX = width * 0.5;
1599
+ posY = height * 0.5;
1600
+ }
1601
+ const styleX = posX - initialSize * 0.5;
1602
+ const styleY = posY - initialSize * 0.5;
1603
+ const moveX = width * 0.5 - posX;
1604
+ const moveY = height * 0.5 - posY;
1605
+ writeTask(() => {
1606
+ const div = document.createElement('div');
1607
+ div.classList.add('ripple-effect');
1608
+ const style = div.style;
1609
+ style.top = styleY + 'px';
1610
+ style.left = styleX + 'px';
1611
+ style.width = style.height = initialSize + 'px';
1612
+ style.setProperty('--final-scale', `${finalScale}`);
1613
+ style.setProperty('--translate-end', `${moveX}px, ${moveY}px`);
1614
+ const container = this.el.shadowRoot || this.el;
1615
+ container.appendChild(div);
1616
+ setTimeout(() => {
1617
+ resolve(() => {
1618
+ removeRipple(div);
1619
+ });
1620
+ }, 225 + 100);
1621
+ });
1622
+ });
1623
+ });
1624
+ }
1625
+ get unbounded() {
1626
+ return this.type === 'unbounded';
1627
+ }
1628
+ render() {
1629
+ const mode = getIonMode$1(this);
1630
+ return (h(Host, { role: "presentation", class: {
1631
+ [mode]: true,
1632
+ unbounded: this.unbounded,
1633
+ } }));
1634
+ }
1635
+ get el() { return getElement(this); }
1636
+ };
1637
+ const removeRipple = (ripple) => {
1638
+ ripple.classList.add('fade-out');
1639
+ setTimeout(() => {
1640
+ ripple.remove();
1641
+ }, 200);
1642
+ };
1643
+ const PADDING = 10;
1644
+ const INITIAL_ORIGIN_SCALE = 0.5;
1645
+ RippleEffect.style = rippleEffectCss;
1646
+
1647
+ const searchbarIosCss = ".sc-ion-searchbar-ios-h{--placeholder-color:initial;--placeholder-font-style:initial;--placeholder-font-weight:initial;--placeholder-opacity:.5;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:flex;position:relative;align-items:center;width:100%;color:var(--color);font-family:var(--ion-font-family, inherit);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;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%;border:0;outline:none;background:var(--background);font-family:inherit;box-shadow:var(--box-shadow);box-sizing:border-box;appearance:none}.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;appearance:none}.searchbar-cancel-button.sc-ion-searchbar-ios>div.sc-ion-searchbar-ios{display:flex;align-items: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);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, #3880ff);--clear-button-color:var(--ion-color-step-600, #666666);--color:var(--ion-text-color, #000);--icon-color:var(--ion-color-step-600, #666666);padding-left:12px;padding-right:12px;padding-top:12px;padding-bottom:12px;height:60px;contain:strict}@supports (margin-inline-start: 0) or (-webkit-margin-start: 0){.sc-ion-searchbar-ios-h{padding-left:unset;padding-right:unset;-webkit-padding-start:12px;padding-inline-start:12px;-webkit-padding-end:12px;padding-inline-end:12px}}.searchbar-input-container.sc-ion-searchbar-ios{height:36px}.searchbar-search-icon.sc-ion-searchbar-ios{margin-left:calc(50% - 60px);left:5px;top:0;position:absolute;width:22px;height:100%;contain:strict}@supports (margin-inline-start: 0) or (-webkit-margin-start: 0){.searchbar-search-icon.sc-ion-searchbar-ios{margin-left:unset;-webkit-margin-start:calc(50% - 60px);margin-inline-start:calc(50% - 60px)}}[dir=rtl].sc-ion-searchbar-ios .searchbar-search-icon.sc-ion-searchbar-ios,[dir=rtl].sc-ion-searchbar-ios-h .searchbar-search-icon.sc-ion-searchbar-ios,[dir=rtl] .sc-ion-searchbar-ios-h .searchbar-search-icon.sc-ion-searchbar-ios{left:unset;right:unset;right:5px}.searchbar-input.sc-ion-searchbar-ios{padding-left:28px;padding-right:28px;padding-top:0;padding-bottom:0;height:100%;font-size:17px;font-weight:400;contain:strict}@supports (margin-inline-start: 0) or (-webkit-margin-start: 0){.searchbar-input.sc-ion-searchbar-ios{padding-left:unset;padding-right:unset;-webkit-padding-start:28px;padding-inline-start:28px;-webkit-padding-end:28px;padding-inline-end:28px}}.searchbar-clear-button.sc-ion-searchbar-ios{right:0;top:0;background-position:center;position:absolute;width:30px;height:100%;border:0;background-color:transparent}[dir=rtl].sc-ion-searchbar-ios .searchbar-clear-button.sc-ion-searchbar-ios,[dir=rtl].sc-ion-searchbar-ios-h .searchbar-clear-button.sc-ion-searchbar-ios,[dir=rtl] .sc-ion-searchbar-ios-h .searchbar-clear-button.sc-ion-searchbar-ios{left:unset;right:unset;left:0}.searchbar-clear-icon.sc-ion-searchbar-ios{width:18px;height:100%}.searchbar-cancel-button.sc-ion-searchbar-ios{padding-left:8px;padding-right:0;padding-top:0;padding-bottom:0;flex-shrink:0;background-color:transparent;font-size:16px}@supports (margin-inline-start: 0) or (-webkit-margin-start: 0){.searchbar-cancel-button.sc-ion-searchbar-ios{padding-left:unset;padding-right:unset;-webkit-padding-start:8px;padding-inline-start:8px;-webkit-padding-end:0;padding-inline-end:0}}.searchbar-left-aligned.sc-ion-searchbar-ios-h .searchbar-search-icon.sc-ion-searchbar-ios{margin-left:0}@supports (margin-inline-start: 0) or (-webkit-margin-start: 0){.searchbar-left-aligned.sc-ion-searchbar-ios-h .searchbar-search-icon.sc-ion-searchbar-ios{margin-left:unset;-webkit-margin-start:0;margin-inline-start:0}}.searchbar-left-aligned.sc-ion-searchbar-ios-h .searchbar-input.sc-ion-searchbar-ios{padding-left:30px}@supports (margin-inline-start: 0) or (-webkit-margin-start: 0){.searchbar-left-aligned.sc-ion-searchbar-ios-h .searchbar-input.sc-ion-searchbar-ios{padding-left:unset;-webkit-padding-start:30px;padding-inline-start:30px}}.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{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{margin-right:-100%;transform:translate3d(0, 0, 0);transition:all 300ms ease;opacity:0;pointer-events:none}@supports (margin-inline-start: 0) or (-webkit-margin-start: 0){.searchbar-animated.sc-ion-searchbar-ios-h .searchbar-cancel-button.sc-ion-searchbar-ios{margin-right:unset;-webkit-margin-end:-100%;margin-inline-end:-100%}}.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{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;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}";
1648
+
1649
+ const searchbarMdCss = ".sc-ion-searchbar-md-h{--placeholder-color:initial;--placeholder-font-style:initial;--placeholder-font-weight:initial;--placeholder-opacity:.5;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:flex;position:relative;align-items:center;width:100%;color:var(--color);font-family:var(--ion-font-family, inherit);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;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%;border:0;outline:none;background:var(--background);font-family:inherit;box-shadow:var(--box-shadow);box-sizing:border-box;appearance:none}.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;appearance:none}.searchbar-cancel-button.sc-ion-searchbar-md>div.sc-ion-searchbar-md{display:flex;align-items: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);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, #1a1a1a);--clear-button-color:initial;--color:var(--ion-color-step-850, #262626);--icon-color:var(--ion-color-step-600, #666666);padding-left:8px;padding-right:8px;padding-top:8px;padding-bottom:8px;background:inherit}@supports (margin-inline-start: 0) or (-webkit-margin-start: 0){.sc-ion-searchbar-md-h{padding-left:unset;padding-right:unset;-webkit-padding-start:8px;padding-inline-start:8px;-webkit-padding-end:8px;padding-inline-end:8px}}.searchbar-search-icon.sc-ion-searchbar-md{left:16px;top:11px;width:21px;height:21px}[dir=rtl].sc-ion-searchbar-md .searchbar-search-icon.sc-ion-searchbar-md,[dir=rtl].sc-ion-searchbar-md-h .searchbar-search-icon.sc-ion-searchbar-md,[dir=rtl] .sc-ion-searchbar-md-h .searchbar-search-icon.sc-ion-searchbar-md{left:unset;right:unset;right:16px}.searchbar-cancel-button.sc-ion-searchbar-md{left:5px;top:0;background-color:transparent;font-size:1.6em}[dir=rtl].sc-ion-searchbar-md .searchbar-cancel-button.sc-ion-searchbar-md,[dir=rtl].sc-ion-searchbar-md-h .searchbar-cancel-button.sc-ion-searchbar-md,[dir=rtl] .sc-ion-searchbar-md-h .searchbar-cancel-button.sc-ion-searchbar-md{left:unset;right:unset;right:5px}.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{padding-left:55px;padding-right:55px;padding-top:6px;padding-bottom:6px;background-position:left 8px center;height:auto;font-size:16px;font-weight:400;line-height:30px}@supports (margin-inline-start: 0) or (-webkit-margin-start: 0){.searchbar-input.sc-ion-searchbar-md{padding-left:unset;padding-right:unset;-webkit-padding-start:55px;padding-inline-start:55px;-webkit-padding-end:55px;padding-inline-end:55px}}[dir=rtl].sc-ion-searchbar-md .searchbar-input.sc-ion-searchbar-md,[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}.searchbar-clear-button.sc-ion-searchbar-md{right:13px;top:0;padding-left:0;padding-right:0;padding-top:0;padding-bottom:0;position:absolute;height:100%;border:0;background-color:transparent}[dir=rtl].sc-ion-searchbar-md .searchbar-clear-button.sc-ion-searchbar-md,[dir=rtl].sc-ion-searchbar-md-h .searchbar-clear-button.sc-ion-searchbar-md,[dir=rtl] .sc-ion-searchbar-md-h .searchbar-clear-button.sc-ion-searchbar-md{left:unset;right:unset;left:13px}.searchbar-clear-button.ion-activated.sc-ion-searchbar-md{background-color:transparent}.searchbar-clear-icon.sc-ion-searchbar-md{width:22px;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{padding-left:7px;padding-right:7px;padding-top:3px;padding-bottom:3px}@supports (margin-inline-start: 0) or (-webkit-margin-start: 0){ion-toolbar.sc-ion-searchbar-md-h,ion-toolbar .sc-ion-searchbar-md-h{padding-left:unset;padding-right:unset;-webkit-padding-start:7px;padding-inline-start:7px;-webkit-padding-end:7px;padding-inline-end:7px}}";
1650
+
1651
+ const Searchbar = class {
1652
+ constructor(hostRef) {
1653
+ registerInstance(this, hostRef);
1654
+ this.ionInput = createEvent(this, "ionInput", 7);
1655
+ this.ionChange = createEvent(this, "ionChange", 7);
1656
+ this.ionCancel = createEvent(this, "ionCancel", 7);
1657
+ this.ionClear = createEvent(this, "ionClear", 7);
1658
+ this.ionBlur = createEvent(this, "ionBlur", 7);
1659
+ this.ionFocus = createEvent(this, "ionFocus", 7);
1660
+ this.ionStyle = createEvent(this, "ionStyle", 7);
1661
+ this.isCancelVisible = false;
1662
+ this.shouldAlignLeft = true;
1663
+ this.focused = false;
1664
+ this.noAnimate = true;
1665
+ /**
1666
+ * If `true`, enable searchbar animation.
1667
+ */
1668
+ this.animated = false;
1669
+ /**
1670
+ * Set the input's autocomplete property.
1671
+ */
1672
+ this.autocomplete = 'off';
1673
+ /**
1674
+ * Set the input's autocorrect property.
1675
+ */
1676
+ this.autocorrect = 'off';
1677
+ /**
1678
+ * Set the cancel button icon. Only applies to `md` mode.
1679
+ * Defaults to `arrow-back-sharp`.
1680
+ */
1681
+ this.cancelButtonIcon = config.get('backButtonIcon', arrowBackSharp);
1682
+ /**
1683
+ * Set the the cancel button text. Only applies to `ios` mode.
1684
+ */
1685
+ this.cancelButtonText = 'Cancel';
1686
+ /**
1687
+ * Set the amount of time, in milliseconds, to wait to trigger the `ionChange` event after each keystroke. This also impacts form bindings such as `ngModel` or `v-model`.
1688
+ */
1689
+ this.debounce = 250;
1690
+ /**
1691
+ * If `true`, the user cannot interact with the input.
1692
+ */
1693
+ this.disabled = false;
1694
+ /**
1695
+ * Set the input's placeholder.
1696
+ * `placeholder` can accept either plaintext or HTML as a string.
1697
+ * To display characters normally reserved for HTML, they
1698
+ * must be escaped. For example `<Ionic>` would become
1699
+ * `&lt;Ionic&gt;`
1700
+ *
1701
+ * For more information: [Security Documentation](https://ionicframework.com/docs/faq/security)
1702
+ */
1703
+ this.placeholder = 'Search';
1704
+ /**
1705
+ * Sets the behavior for the cancel button. Defaults to `"never"`.
1706
+ * Setting to `"focus"` shows the cancel button on focus.
1707
+ * Setting to `"never"` hides the cancel button.
1708
+ * Setting to `"always"` shows the cancel button regardless
1709
+ * of focus state.
1710
+ */
1711
+ this.showCancelButton = 'never';
1712
+ /**
1713
+ * Sets the behavior for the clear button. Defaults to `"focus"`.
1714
+ * Setting to `"focus"` shows the clear button on focus if the
1715
+ * input is not empty.
1716
+ * Setting to `"never"` hides the clear button.
1717
+ * Setting to `"always"` shows the clear button regardless
1718
+ * of focus state, but only if the input is not empty.
1719
+ */
1720
+ this.showClearButton = 'always';
1721
+ /**
1722
+ * If `true`, enable spellcheck on the input.
1723
+ */
1724
+ this.spellcheck = false;
1725
+ /**
1726
+ * Set the type of the input.
1727
+ */
1728
+ this.type = 'search';
1729
+ /**
1730
+ * the value of the searchbar.
1731
+ */
1732
+ this.value = '';
1733
+ /**
1734
+ * Clears the input field and triggers the control change.
1735
+ */
1736
+ this.onClearInput = (shouldFocus) => {
1737
+ this.ionClear.emit();
1738
+ // setTimeout() fixes https://github.com/ionic-team/ionic/issues/7527
1739
+ // wait for 4 frames
1740
+ setTimeout(() => {
1741
+ const value = this.getValue();
1742
+ if (value !== '') {
1743
+ this.value = '';
1744
+ this.ionInput.emit();
1745
+ /**
1746
+ * When tapping clear button
1747
+ * ensure input is focused after
1748
+ * clearing input so users
1749
+ * can quickly start typing.
1750
+ */
1751
+ if (shouldFocus && !this.focused) {
1752
+ this.setFocus();
1753
+ }
1754
+ }
1755
+ }, 16 * 4);
1756
+ };
1757
+ /**
1758
+ * Clears the input field and tells the input to blur since
1759
+ * the clearInput function doesn't want the input to blur
1760
+ * then calls the custom cancel function if the user passed one in.
1761
+ */
1762
+ this.onCancelSearchbar = (ev) => {
1763
+ if (ev) {
1764
+ ev.preventDefault();
1765
+ ev.stopPropagation();
1766
+ }
1767
+ this.ionCancel.emit();
1768
+ this.onClearInput();
1769
+ if (this.nativeInput) {
1770
+ this.nativeInput.blur();
1771
+ }
1772
+ };
1773
+ /**
1774
+ * Update the Searchbar input value when the input changes
1775
+ */
1776
+ this.onInput = (ev) => {
1777
+ const input = ev.target;
1778
+ if (input) {
1779
+ this.value = input.value;
1780
+ }
1781
+ this.ionInput.emit(ev);
1782
+ };
1783
+ /**
1784
+ * Sets the Searchbar to not focused and checks if it should align left
1785
+ * based on whether there is a value in the searchbar or not.
1786
+ */
1787
+ this.onBlur = () => {
1788
+ this.focused = false;
1789
+ this.ionBlur.emit();
1790
+ this.positionElements();
1791
+ };
1792
+ /**
1793
+ * Sets the Searchbar to focused and active on input focus.
1794
+ */
1795
+ this.onFocus = () => {
1796
+ this.focused = true;
1797
+ this.ionFocus.emit();
1798
+ this.positionElements();
1799
+ };
1800
+ }
1801
+ debounceChanged() {
1802
+ this.ionChange = debounceEvent(this.ionChange, this.debounce);
1803
+ }
1804
+ valueChanged() {
1805
+ const inputEl = this.nativeInput;
1806
+ const value = this.getValue();
1807
+ if (inputEl && inputEl.value !== value) {
1808
+ inputEl.value = value;
1809
+ }
1810
+ this.ionChange.emit({ value });
1811
+ }
1812
+ showCancelButtonChanged() {
1813
+ requestAnimationFrame(() => {
1814
+ this.positionElements();
1815
+ forceUpdate(this);
1816
+ });
1817
+ }
1818
+ connectedCallback() {
1819
+ this.emitStyle();
1820
+ }
1821
+ componentDidLoad() {
1822
+ this.positionElements();
1823
+ this.debounceChanged();
1824
+ setTimeout(() => {
1825
+ this.noAnimate = false;
1826
+ }, 300);
1827
+ }
1828
+ emitStyle() {
1829
+ this.ionStyle.emit({
1830
+ searchbar: true,
1831
+ });
1832
+ }
1833
+ /**
1834
+ * Sets focus on the specified `ion-searchbar`. Use this method instead of the global
1835
+ * `input.focus()`.
1836
+ */
1837
+ async setFocus() {
1838
+ if (this.nativeInput) {
1839
+ this.nativeInput.focus();
1840
+ }
1841
+ }
1842
+ /**
1843
+ * Returns the native `<input>` element used under the hood.
1844
+ */
1845
+ getInputElement() {
1846
+ return Promise.resolve(this.nativeInput);
1847
+ }
1848
+ /**
1849
+ * Positions the input search icon, placeholder, and the cancel button
1850
+ * based on the input value and if it is focused. (ios only)
1851
+ */
1852
+ positionElements() {
1853
+ const value = this.getValue();
1854
+ const prevAlignLeft = this.shouldAlignLeft;
1855
+ const mode = getIonMode$1(this);
1856
+ const shouldAlignLeft = !this.animated || value.trim() !== '' || !!this.focused;
1857
+ this.shouldAlignLeft = shouldAlignLeft;
1858
+ if (mode !== 'ios') {
1859
+ return;
1860
+ }
1861
+ if (prevAlignLeft !== shouldAlignLeft) {
1862
+ this.positionPlaceholder();
1863
+ }
1864
+ if (this.animated) {
1865
+ this.positionCancelButton();
1866
+ }
1867
+ }
1868
+ /**
1869
+ * Positions the input placeholder
1870
+ */
1871
+ positionPlaceholder() {
1872
+ const inputEl = this.nativeInput;
1873
+ if (!inputEl) {
1874
+ return;
1875
+ }
1876
+ const rtl = isRTL$1(this.el);
1877
+ const iconEl = (this.el.shadowRoot || this.el).querySelector('.searchbar-search-icon');
1878
+ if (this.shouldAlignLeft) {
1879
+ inputEl.removeAttribute('style');
1880
+ iconEl.removeAttribute('style');
1881
+ }
1882
+ else {
1883
+ // Create a dummy span to get the placeholder width
1884
+ const doc = document;
1885
+ const tempSpan = doc.createElement('span');
1886
+ tempSpan.innerText = this.placeholder || '';
1887
+ doc.body.appendChild(tempSpan);
1888
+ // Get the width of the span then remove it
1889
+ raf(() => {
1890
+ const textWidth = tempSpan.offsetWidth;
1891
+ tempSpan.remove();
1892
+ // Calculate the input padding
1893
+ const inputLeft = 'calc(50% - ' + textWidth / 2 + 'px)';
1894
+ // Calculate the icon margin
1895
+ const iconLeft = 'calc(50% - ' + (textWidth / 2 + 30) + 'px)';
1896
+ // Set the input padding start and icon margin start
1897
+ if (rtl) {
1898
+ inputEl.style.paddingRight = inputLeft;
1899
+ iconEl.style.marginRight = iconLeft;
1900
+ }
1901
+ else {
1902
+ inputEl.style.paddingLeft = inputLeft;
1903
+ iconEl.style.marginLeft = iconLeft;
1904
+ }
1905
+ });
1906
+ }
1907
+ }
1908
+ /**
1909
+ * Show the iOS Cancel button on focus, hide it offscreen otherwise
1910
+ */
1911
+ positionCancelButton() {
1912
+ const rtl = isRTL$1(this.el);
1913
+ const cancelButton = (this.el.shadowRoot || this.el).querySelector('.searchbar-cancel-button');
1914
+ const shouldShowCancel = this.shouldShowCancelButton();
1915
+ if (cancelButton !== null && shouldShowCancel !== this.isCancelVisible) {
1916
+ const cancelStyle = cancelButton.style;
1917
+ this.isCancelVisible = shouldShowCancel;
1918
+ if (shouldShowCancel) {
1919
+ if (rtl) {
1920
+ cancelStyle.marginLeft = '0';
1921
+ }
1922
+ else {
1923
+ cancelStyle.marginRight = '0';
1924
+ }
1925
+ }
1926
+ else {
1927
+ const offset = cancelButton.offsetWidth;
1928
+ if (offset > 0) {
1929
+ if (rtl) {
1930
+ cancelStyle.marginLeft = -offset + 'px';
1931
+ }
1932
+ else {
1933
+ cancelStyle.marginRight = -offset + 'px';
1934
+ }
1935
+ }
1936
+ }
1937
+ }
1938
+ }
1939
+ getValue() {
1940
+ return this.value || '';
1941
+ }
1942
+ hasValue() {
1943
+ return this.getValue() !== '';
1944
+ }
1945
+ /**
1946
+ * Determines whether or not the cancel button should be visible onscreen.
1947
+ * Cancel button should be shown if one of two conditions applies:
1948
+ * 1. `showCancelButton` is set to `always`.
1949
+ * 2. `showCancelButton` is set to `focus`, and the searchbar has been focused.
1950
+ */
1951
+ shouldShowCancelButton() {
1952
+ if (this.showCancelButton === 'never' || (this.showCancelButton === 'focus' && !this.focused)) {
1953
+ return false;
1954
+ }
1955
+ return true;
1956
+ }
1957
+ /**
1958
+ * Determines whether or not the clear button should be visible onscreen.
1959
+ * Clear button should be shown if one of two conditions applies:
1960
+ * 1. `showClearButton` is set to `always`.
1961
+ * 2. `showClearButton` is set to `focus`, and the searchbar has been focused.
1962
+ */
1963
+ shouldShowClearButton() {
1964
+ if (this.showClearButton === 'never' || (this.showClearButton === 'focus' && !this.focused)) {
1965
+ return false;
1966
+ }
1967
+ return true;
1968
+ }
1969
+ render() {
1970
+ const { cancelButtonText } = this;
1971
+ const animated = this.animated && config.getBoolean('animated', true);
1972
+ const mode = getIonMode$1(this);
1973
+ const clearIcon = this.clearIcon || (mode === 'ios' ? closeCircle : closeSharp);
1974
+ const searchIcon = this.searchIcon || (mode === 'ios' ? searchOutline : searchSharp);
1975
+ const shouldShowCancelButton = this.shouldShowCancelButton();
1976
+ const cancelButton = this.showCancelButton !== 'never' && (h("button", { "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" }, h("div", { "aria-hidden": "true" }, mode === 'md' ? (h("ion-icon", { "aria-hidden": "true", mode: mode, icon: this.cancelButtonIcon, lazy: false })) : (cancelButtonText))));
1977
+ return (h(Host, { role: "search", "aria-disabled": this.disabled ? 'true' : null, class: createColorClasses$1(this.color, {
1978
+ [mode]: true,
1979
+ 'searchbar-animated': animated,
1980
+ 'searchbar-disabled': this.disabled,
1981
+ 'searchbar-no-animate': animated && this.noAnimate,
1982
+ 'searchbar-has-value': this.hasValue(),
1983
+ 'searchbar-left-aligned': this.shouldAlignLeft,
1984
+ 'searchbar-has-focus': this.focused,
1985
+ 'searchbar-should-show-clear': this.shouldShowClearButton(),
1986
+ 'searchbar-should-show-cancel': this.shouldShowCancelButton(),
1987
+ }) }, h("div", { class: "searchbar-input-container" }, h("input", { "aria-label": "search text", disabled: this.disabled, ref: (el) => (this.nativeInput = el), class: "searchbar-input", inputMode: this.inputmode, enterKeyHint: this.enterkeyhint, onInput: this.onInput, onBlur: this.onBlur, onFocus: this.onFocus, placeholder: this.placeholder, type: this.type, value: this.getValue(), autoComplete: this.autocomplete, autoCorrect: this.autocorrect, spellcheck: this.spellcheck }), mode === 'md' && cancelButton, h("ion-icon", { "aria-hidden": "true", mode: mode, icon: searchIcon, lazy: false, class: "searchbar-search-icon" }), h("button", { "aria-label": "reset", type: "button", "no-blur": true, class: "searchbar-clear-button", onPointerDown: (ev) => {
1988
+ /**
1989
+ * This prevents mobile browsers from
1990
+ * blurring the input when the clear
1991
+ * button is activated.
1992
+ */
1993
+ ev.preventDefault();
1994
+ }, onClick: () => this.onClearInput(true) }, h("ion-icon", { "aria-hidden": "true", mode: mode, icon: clearIcon, lazy: false, class: "searchbar-clear-icon" }))), mode === 'ios' && cancelButton));
1995
+ }
1996
+ get el() { return getElement(this); }
1997
+ static get watchers() { return {
1998
+ "debounce": ["debounceChanged"],
1999
+ "value": ["valueChanged"],
2000
+ "showCancelButton": ["showCancelButtonChanged"]
2001
+ }; }
2002
+ };
2003
+ Searchbar.style = {
2004
+ ios: searchbarIosCss,
2005
+ md: searchbarMdCss
2006
+ };
2007
+
2008
+ const skeletonTextCss = ":host{--background:rgba(var(--background-rgb, var(--ion-text-color-rgb, 0, 0, 0)), 0.065);border-radius:var(--border-radius, inherit);display:block;width:100%;height:inherit;margin-top:4px;margin-bottom:4px;background:var(--background);line-height:10px;user-select:none;pointer-events:none}span{display:inline-block}:host(.in-media){margin-left:0;margin-right:0;margin-top:0;margin-bottom:0;height:100%}:host(.skeleton-text-animated){position:relative;background:linear-gradient(to right, rgba(var(--background-rgb, var(--ion-text-color-rgb, 0, 0, 0)), 0.065) 8%, rgba(var(--background-rgb, var(--ion-text-color-rgb, 0, 0, 0)), 0.135) 18%, rgba(var(--background-rgb, var(--ion-text-color-rgb, 0, 0, 0)), 0.065) 33%);background-size:800px 104px;animation-duration:1s;animation-fill-mode:forwards;animation-iteration-count:infinite;animation-name:shimmer;animation-timing-function:linear}@keyframes shimmer{0%{background-position:-400px 0}100%{background-position:400px 0}}";
2009
+
2010
+ const SkeletonText = class {
2011
+ constructor(hostRef) {
2012
+ registerInstance(this, hostRef);
2013
+ /**
2014
+ * If `true`, the skeleton text will animate.
2015
+ */
2016
+ this.animated = false;
2017
+ }
2018
+ render() {
2019
+ const animated = this.animated && config.getBoolean('animated', true);
2020
+ const inMedia = hostContext('ion-avatar', this.el) || hostContext('ion-thumbnail', this.el);
2021
+ const mode = getIonMode$1(this);
2022
+ return (h(Host, { class: {
2023
+ [mode]: true,
2024
+ 'skeleton-text-animated': animated,
2025
+ 'in-media': inMedia,
2026
+ } }, h("span", null, "\u00A0")));
2027
+ }
2028
+ get el() { return getElement(this); }
2029
+ };
2030
+ SkeletonText.style = skeletonTextCss;
2031
+
2032
+ const titleIosCss = ":host{--color:initial;display:flex;flex:1;align-items:center;transform:translateZ(0);color:var(--color)}:host(.ion-color){color:var(--ion-color-base)}.toolbar-title{display:block;width:100%;text-overflow:ellipsis;white-space:nowrap;overflow:hidden;pointer-events:auto}:host(.title-small) .toolbar-title{white-space:normal}:host{left:0;top:0;padding-left:90px;padding-right:90px;padding-top:var(--padding-top);padding-bottom:var(--padding-bottom);position:absolute;width:100%;height:100%;transform:translateZ(0);font-size:17px;font-weight:600;text-align:center;box-sizing:border-box;pointer-events:none}:host-context([dir=rtl]){left:unset;right:unset;right:0}@supports (margin-inline-start: 0) or (-webkit-margin-start: 0){:host{padding-left:unset;padding-right:unset;-webkit-padding-start:90px;padding-inline-start:90px;-webkit-padding-end:90px;padding-inline-end:90px}}:host(.title-small){padding-left:9px;padding-right:9px;padding-top:6px;padding-bottom:16px;position:relative;font-size:13px;font-weight:normal}@supports (margin-inline-start: 0) or (-webkit-margin-start: 0){:host(.title-small){padding-left:unset;padding-right:unset;-webkit-padding-start:9px;padding-inline-start:9px;-webkit-padding-end:9px;padding-inline-end:9px}}:host(.title-large){padding-left:16px;padding-right:16px;padding-top:0;padding-bottom:0;transform-origin:left center;bottom:0;align-items:flex-end;min-width:100%;padding-bottom:6px;font-size:34px;font-weight:700;text-align:start}@supports (margin-inline-start: 0) or (-webkit-margin-start: 0){:host(.title-large){padding-left:unset;padding-right:unset;-webkit-padding-start:16px;padding-inline-start:16px;-webkit-padding-end:16px;padding-inline-end:16px}}:host(.title-large.title-rtl){transform-origin:right center}:host(.title-large.ion-cloned-element){--color:var(--ion-text-color, #000)}:host(.title-large) .toolbar-title{transform-origin:inherit}:host-context([dir=rtl]):host(.title-large) .toolbar-title,:host-context([dir=rtl]).title-large .toolbar-title{transform-origin:calc(100% - inherit)}";
2033
+
2034
+ const titleMdCss = ":host{--color:initial;display:flex;flex:1;align-items:center;transform:translateZ(0);color:var(--color)}:host(.ion-color){color:var(--ion-color-base)}.toolbar-title{display:block;width:100%;text-overflow:ellipsis;white-space:nowrap;overflow:hidden;pointer-events:auto}:host(.title-small) .toolbar-title{white-space:normal}:host{padding-left:20px;padding-right:20px;padding-top:0;padding-bottom:0;font-size:20px;font-weight:500;letter-spacing:0.0125em}@supports (margin-inline-start: 0) or (-webkit-margin-start: 0){:host{padding-left:unset;padding-right:unset;-webkit-padding-start:20px;padding-inline-start:20px;-webkit-padding-end:20px;padding-inline-end:20px}}:host(.title-small){width:100%;height:100%;font-size:15px;font-weight:normal}";
2035
+
2036
+ const ToolbarTitle = class {
2037
+ constructor(hostRef) {
2038
+ registerInstance(this, hostRef);
2039
+ this.ionStyle = createEvent(this, "ionStyle", 7);
2040
+ }
2041
+ sizeChanged() {
2042
+ this.emitStyle();
2043
+ }
2044
+ connectedCallback() {
2045
+ this.emitStyle();
2046
+ }
2047
+ emitStyle() {
2048
+ const size = this.getSize();
2049
+ this.ionStyle.emit({
2050
+ [`title-${size}`]: true,
2051
+ });
2052
+ }
2053
+ getSize() {
2054
+ return this.size !== undefined ? this.size : 'default';
2055
+ }
2056
+ render() {
2057
+ const mode = getIonMode$1(this);
2058
+ const size = this.getSize();
2059
+ return (h(Host, { class: createColorClasses$1(this.color, {
2060
+ [mode]: true,
2061
+ [`title-${size}`]: true,
2062
+ 'title-rtl': document.dir === 'rtl',
2063
+ }) }, h("div", { class: "toolbar-title" }, h("slot", null))));
2064
+ }
2065
+ get el() { return getElement(this); }
2066
+ static get watchers() { return {
2067
+ "size": ["sizeChanged"]
2068
+ }; }
2069
+ };
2070
+ ToolbarTitle.style = {
2071
+ ios: titleIosCss,
2072
+ md: titleMdCss
2073
+ };
2074
+
2075
+ const toolbarIosCss = ":host{--border-width:0;--border-style:solid;--opacity:1;--opacity-scale:1;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;padding-left:var(--ion-safe-area-left);padding-right:var(--ion-safe-area-right);display:block;position:relative;width:100%;color:var(--color);font-family:var(--ion-font-family, inherit);contain:content;z-index:10;box-sizing:border-box}@supports (margin-inline-start: 0) or (-webkit-margin-start: 0){:host{padding-left:unset;padding-right:unset;-webkit-padding-start:var(--ion-safe-area-left);padding-inline-start:var(--ion-safe-area-left);-webkit-padding-end:var(--ion-safe-area-right);padding-inline-end:var(--ion-safe-area-right)}}:host(.ion-color){color:var(--ion-color-contrast)}:host(.ion-color) .toolbar-background{background:var(--ion-color-base)}.toolbar-container{padding-left:var(--padding-start);padding-right:var(--padding-end);padding-top:var(--padding-top);padding-bottom:var(--padding-bottom);display:flex;position:relative;flex-direction:row;align-items:center;justify-content:space-between;width:100%;min-height:var(--min-height);contain:content;overflow:hidden;z-index:10;box-sizing:border-box}@supports (margin-inline-start: 0) or (-webkit-margin-start: 0){.toolbar-container{padding-left:unset;padding-right:unset;-webkit-padding-start:var(--padding-start);padding-inline-start:var(--padding-start);-webkit-padding-end:var(--padding-end);padding-inline-end:var(--padding-end)}}.toolbar-background{left:0;right:0;top:0;bottom:0;position:absolute;transform:translateZ(0);border-width:var(--border-width);border-style:var(--border-style);border-color:var(--border-color);background:var(--background);contain:strict;opacity:calc(var(--opacity) * var(--opacity-scale));z-index:-1;pointer-events:none}::slotted(ion-progress-bar){left:0;right:0;bottom:0;position:absolute}:host{--background:var(--ion-toolbar-background, var(--ion-color-step-50, #f7f7f7));--color:var(--ion-toolbar-color, var(--ion-text-color, #000));--border-color:var(--ion-toolbar-border-color, var(--ion-border-color, var(--ion-color-step-150, rgba(0, 0, 0, 0.2))));--padding-top:3px;--padding-bottom:3px;--padding-start:4px;--padding-end:4px;--min-height:44px}.toolbar-content{flex:1;order:4;min-width:0}:host(.toolbar-segment) .toolbar-content{display:inline-flex}:host(.toolbar-searchbar) .toolbar-container{padding-top:0;padding-bottom:0}:host(.toolbar-searchbar) ::slotted(*){align-self:start}:host(.toolbar-searchbar) ::slotted(ion-chip){margin-top:3px}:host(.toolbar-searchbar) ::slotted(ion-back-button){height:38px}::slotted(ion-buttons){min-height:38px}::slotted([slot=start]){order:2}::slotted([slot=secondary]){order:3}::slotted([slot=primary]){order:5;text-align:end}::slotted([slot=end]){order:6;text-align:end}:host(.toolbar-title-large) .toolbar-container{flex-wrap:wrap;align-items:flex-start}:host(.toolbar-title-large) .toolbar-content ion-title{flex:1;order:8;min-width:100%}";
2076
+
2077
+ const toolbarMdCss = ":host{--border-width:0;--border-style:solid;--opacity:1;--opacity-scale:1;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;padding-left:var(--ion-safe-area-left);padding-right:var(--ion-safe-area-right);display:block;position:relative;width:100%;color:var(--color);font-family:var(--ion-font-family, inherit);contain:content;z-index:10;box-sizing:border-box}@supports (margin-inline-start: 0) or (-webkit-margin-start: 0){:host{padding-left:unset;padding-right:unset;-webkit-padding-start:var(--ion-safe-area-left);padding-inline-start:var(--ion-safe-area-left);-webkit-padding-end:var(--ion-safe-area-right);padding-inline-end:var(--ion-safe-area-right)}}:host(.ion-color){color:var(--ion-color-contrast)}:host(.ion-color) .toolbar-background{background:var(--ion-color-base)}.toolbar-container{padding-left:var(--padding-start);padding-right:var(--padding-end);padding-top:var(--padding-top);padding-bottom:var(--padding-bottom);display:flex;position:relative;flex-direction:row;align-items:center;justify-content:space-between;width:100%;min-height:var(--min-height);contain:content;overflow:hidden;z-index:10;box-sizing:border-box}@supports (margin-inline-start: 0) or (-webkit-margin-start: 0){.toolbar-container{padding-left:unset;padding-right:unset;-webkit-padding-start:var(--padding-start);padding-inline-start:var(--padding-start);-webkit-padding-end:var(--padding-end);padding-inline-end:var(--padding-end)}}.toolbar-background{left:0;right:0;top:0;bottom:0;position:absolute;transform:translateZ(0);border-width:var(--border-width);border-style:var(--border-style);border-color:var(--border-color);background:var(--background);contain:strict;opacity:calc(var(--opacity) * var(--opacity-scale));z-index:-1;pointer-events:none}::slotted(ion-progress-bar){left:0;right:0;bottom:0;position:absolute}:host{--background:var(--ion-toolbar-background, var(--ion-background-color, #fff));--color:var(--ion-toolbar-color, var(--ion-text-color, #424242));--border-color:var(--ion-toolbar-border-color, var(--ion-border-color, var(--ion-color-step-150, #c1c4cd)));--padding-top:0;--padding-bottom:0;--padding-start:0;--padding-end:0;--min-height:56px}.toolbar-content{flex:1;order:3;min-width:0;max-width:100%}::slotted(.buttons-first-slot){margin-left:4px}@supports (margin-inline-start: 0) or (-webkit-margin-start: 0){::slotted(.buttons-first-slot){margin-left:unset;-webkit-margin-start:4px;margin-inline-start:4px}}::slotted(.buttons-last-slot){margin-right:4px}@supports (margin-inline-start: 0) or (-webkit-margin-start: 0){::slotted(.buttons-last-slot){margin-right:unset;-webkit-margin-end:4px;margin-inline-end:4px}}::slotted([slot=start]){order:2}::slotted([slot=secondary]){order:4}::slotted([slot=primary]){order:5;text-align:end}::slotted([slot=end]){order:6;text-align:end}";
2078
+
2079
+ const Toolbar = class {
2080
+ constructor(hostRef) {
2081
+ registerInstance(this, hostRef);
2082
+ this.childrenStyles = new Map();
2083
+ }
2084
+ componentWillLoad() {
2085
+ const buttons = Array.from(this.el.querySelectorAll('ion-buttons'));
2086
+ const firstButtons = buttons.find((button) => {
2087
+ return button.slot === 'start';
2088
+ });
2089
+ if (firstButtons) {
2090
+ firstButtons.classList.add('buttons-first-slot');
2091
+ }
2092
+ const buttonsReversed = buttons.reverse();
2093
+ const lastButtons = buttonsReversed.find((button) => button.slot === 'end') ||
2094
+ buttonsReversed.find((button) => button.slot === 'primary') ||
2095
+ buttonsReversed.find((button) => button.slot === 'secondary');
2096
+ if (lastButtons) {
2097
+ lastButtons.classList.add('buttons-last-slot');
2098
+ }
2099
+ }
2100
+ childrenStyle(ev) {
2101
+ ev.stopPropagation();
2102
+ const tagName = ev.target.tagName;
2103
+ const updatedStyles = ev.detail;
2104
+ const newStyles = {};
2105
+ const childStyles = this.childrenStyles.get(tagName) || {};
2106
+ let hasStyleChange = false;
2107
+ Object.keys(updatedStyles).forEach((key) => {
2108
+ const childKey = `toolbar-${key}`;
2109
+ const newValue = updatedStyles[key];
2110
+ if (newValue !== childStyles[childKey]) {
2111
+ hasStyleChange = true;
2112
+ }
2113
+ if (newValue) {
2114
+ newStyles[childKey] = true;
2115
+ }
2116
+ });
2117
+ if (hasStyleChange) {
2118
+ this.childrenStyles.set(tagName, newStyles);
2119
+ forceUpdate(this);
2120
+ }
2121
+ }
2122
+ render() {
2123
+ const mode = getIonMode$1(this);
2124
+ const childStyles = {};
2125
+ this.childrenStyles.forEach((value) => {
2126
+ Object.assign(childStyles, value);
2127
+ });
2128
+ return (h(Host, { class: Object.assign(Object.assign({}, childStyles), createColorClasses$1(this.color, {
2129
+ [mode]: true,
2130
+ 'in-toolbar': hostContext('ion-toolbar', this.el),
2131
+ })) }, h("div", { class: "toolbar-background" }), h("div", { class: "toolbar-container" }, h("slot", { name: "start" }), h("slot", { name: "secondary" }), h("div", { class: "toolbar-content" }, h("slot", null)), h("slot", { name: "primary" }), h("slot", { name: "end" }))));
2132
+ }
2133
+ get el() { return getElement(this); }
2134
+ };
2135
+ Toolbar.style = {
2136
+ ios: toolbarIosCss,
2137
+ md: toolbarMdCss
2138
+ };
2139
+
2140
+ const createPodOS = () => {
2141
+ return new PodOS();
2142
+ };
2143
+
2144
+ const PosApp = class {
2145
+ constructor(hostRef) {
2146
+ registerInstance(this, hostRef);
2147
+ this.os = undefined;
2148
+ }
2149
+ componentWillLoad() {
2150
+ this.os = createPodOS();
2151
+ this.os.handleIncomingRedirect();
2152
+ this.os.trackSession(sessionInfo => {
2153
+ store.state.isLoggedIn = sessionInfo.isLoggedIn;
2154
+ store.state.webId = sessionInfo.webId;
2155
+ });
2156
+ }
2157
+ async initializeOs(event) {
2158
+ event.stopPropagation();
2159
+ event.detail(this.os);
2160
+ }
2161
+ render() {
2162
+ return (h("ion-app", null, h("slot", null)));
2163
+ }
2164
+ };
2165
+
2166
+ const PosAppBrowser = class {
2167
+ constructor(hostRef) {
2168
+ registerInstance(this, hostRef);
2169
+ }
2170
+ render() {
2171
+ return (h("pos-app", null, h("ion-header", null, h("ion-toolbar", null, h("ion-title", { slot: "start" }, "PodOS"), h("pos-login", null))), h("ion-content", null, h("pos-router", null)), h("ion-footer", null, h("ion-toolbar", null, h("ion-title", null, "PodOS Browser")))));
2172
+ }
2173
+ };
2174
+
2175
+ const posImageCss = ":host{}img,ion-skeleton-text,div.error{border-radius:var(--border-radius);width:var(--width);height:var(--height);max-width:var(--max-width);max-height:var(--max-height)}.error{display:flex;opacity:0.8;background:repeating-linear-gradient( -45deg, rgba(150, 0, 0, 0.1), rgba(150, 0, 0, 0.1) 10px, #fff 5px, #fff 25px );flex-direction:column;border:1px solid red;color:black;align-items:center;justify-content:center;word-break:break-all;padding:1rem;box-sizing:border-box}.error ion-icon{color:#282828;--ionicon-stroke-width:calc(var(--width) / 5);font-size:calc(var(--width) / 2)}a{text-decoration:none;width:var(--width);height:var(--height)}.code{font-weight:bold;font-size:calc(var(--width) / 8)}.text{font-size:calc(var(--width) / 20)}";
2176
+
2177
+ const PosImage = class {
2178
+ constructor(hostRef) {
2179
+ registerInstance(this, hostRef);
2180
+ this.initializeOsEmitter = createEvent(this, "pod-os:init", 7);
2181
+ this.setOs = async (os) => {
2182
+ this.os = os;
2183
+ };
2184
+ this.src = undefined;
2185
+ this.alt = undefined;
2186
+ this.os = undefined;
2187
+ this.dataUri = undefined;
2188
+ this.brokenFile = undefined;
2189
+ this.error = undefined;
2190
+ this.loading = true;
2191
+ }
2192
+ componentWillLoad() {
2193
+ store.onChange('isLoggedIn', () => this.fetchBlob());
2194
+ this.initializeOsEmitter.emit(this.setOs);
2195
+ }
2196
+ async fetchBlob() {
2197
+ try {
2198
+ this.loading = true;
2199
+ const file = await this.os.fetchFile(this.src);
2200
+ if (file.blob()) {
2201
+ this.dataUri = URL.createObjectURL(file.blob());
2202
+ this.error = null;
2203
+ }
2204
+ else {
2205
+ this.brokenFile = file;
2206
+ }
2207
+ }
2208
+ catch (err) {
2209
+ this.error = err;
2210
+ }
2211
+ finally {
2212
+ this.loading = false;
2213
+ }
2214
+ }
2215
+ render() {
2216
+ if (this.loading) {
2217
+ return h("ion-skeleton-text", { animated: true });
2218
+ }
2219
+ if (this.error) {
2220
+ return h("div", { class: "error" }, this.error.message);
2221
+ }
2222
+ if (this.brokenFile) {
2223
+ return h(BrokenFile, { file: this.brokenFile });
2224
+ }
2225
+ return h("img", { src: this.dataUri, alt: this.alt });
2226
+ }
2227
+ static get watchers() { return {
2228
+ "os": ["fetchBlob"],
2229
+ "src": ["fetchBlob"]
2230
+ }; }
2231
+ };
2232
+ PosImage.style = posImageCss;
2233
+
2234
+ const PosLabel = class {
2235
+ constructor(hostRef) {
2236
+ registerInstance(this, hostRef);
2237
+ this.subscribeResource = createEvent(this, "pod-os:resource", 7);
2238
+ this.receiveResource = (resource) => {
2239
+ this.resource = resource;
2240
+ };
2241
+ this.resource = undefined;
2242
+ }
2243
+ componentWillLoad() {
2244
+ subscribeResource(this);
2245
+ }
2246
+ render() {
2247
+ return this.resource ? this.resource.label() : null;
2248
+ }
2249
+ };
2250
+
2251
+ const posLoginCss = ":host{display:flex;gap:10px}.user-data{align-items:center;display:inline-flex;gap:10px}.user-data pos-picture{--width:40px;--height:40px;--border-radius:50%}";
2252
+
2253
+ const PosLogin = class {
2254
+ constructor(hostRef) {
2255
+ registerInstance(this, hostRef);
2256
+ this.initializeOsEmitter = createEvent(this, "pod-os:init", 7);
2257
+ this.setOs = async (os) => {
2258
+ this.os = os;
2259
+ };
2260
+ this.os = undefined;
2261
+ }
2262
+ componentWillLoad() {
2263
+ this.initializeOsEmitter.emit(this.setOs);
2264
+ }
2265
+ login() {
2266
+ const idp = store.state.getIdpUrl();
2267
+ this.os.login(idp);
2268
+ }
2269
+ logout() {
2270
+ this.os.logout();
2271
+ }
2272
+ render() {
2273
+ return (h(Host, null, store.state.isLoggedIn ? (h("pos-resource", { uri: store.state.webId }, h("span", { class: "user-data" }, h("pos-picture", null), h("pos-label", null)))) : (''), !store.state.isLoggedIn && h("ion-button", { onClick: () => this.login() }, "Login"), store.state.isLoggedIn && h("ion-button", { onClick: () => this.logout() }, "Logout")));
2274
+ }
2275
+ };
2276
+ PosLogin.style = posLoginCss;
2277
+
2278
+ const PosNavigationBar = class {
2279
+ constructor(hostRef) {
2280
+ registerInstance(this, hostRef);
2281
+ this.linkEmitter = createEvent(this, "pod-os:link", 7);
2282
+ this.uri = '';
2283
+ this.value = this.uri;
2284
+ }
2285
+ onChange(event) {
2286
+ this.value = event.detail.value;
2287
+ }
2288
+ onSubmit(event) {
2289
+ event.preventDefault();
2290
+ this.linkEmitter.emit(this.value);
2291
+ }
2292
+ render() {
2293
+ return (h("form", { onSubmit: e => this.onSubmit(e) }, h("ion-searchbar", { enterkeyhint: "search", placeholder: "Enter URI", value: this.uri, debounce: 0, onIonChange: e => this.onChange(e) })));
2294
+ }
2295
+ };
2296
+
2297
+ const posPictureCss = ":host{--width:300px;--height:300px;--border-radius:var(--border-radius, 0)}";
2298
+
2299
+ const PosPicture = class {
2300
+ constructor(hostRef) {
2301
+ registerInstance(this, hostRef);
2302
+ this.subscribeResource = createEvent(this, "pod-os:resource", 7);
2303
+ this.receiveResource = (resource) => {
2304
+ this.resource = resource;
2305
+ };
2306
+ this.resource = undefined;
2307
+ }
2308
+ componentWillLoad() {
2309
+ subscribeResource(this);
2310
+ }
2311
+ render() {
2312
+ const pic = this.resource ? this.resource.picture() : null;
2313
+ if (!pic)
2314
+ return null;
2315
+ return h("pos-image", { src: pic.url, alt: this.resource.label() });
2316
+ }
2317
+ };
2318
+ PosPicture.style = posPictureCss;
2319
+
2320
+ const PosResource = class {
2321
+ constructor(hostRef) {
2322
+ registerInstance(this, hostRef);
2323
+ this.initializeOsEmitter = createEvent(this, "pod-os:init", 7);
2324
+ this.setOs = async (os) => {
2325
+ this.os = os;
2326
+ };
2327
+ this.os = undefined;
2328
+ this.resource = undefined;
2329
+ this.consumers = [];
2330
+ this.uri = undefined;
2331
+ this.lazy = false;
2332
+ this.error = undefined;
2333
+ this.loading = true;
2334
+ }
2335
+ componentWillLoad() {
2336
+ store.onChange('isLoggedIn', () => this.loadResource());
2337
+ this.initializeOsEmitter.emit(this.setOs);
2338
+ }
2339
+ async provideResource(event) {
2340
+ event.stopPropagation();
2341
+ if (this.resource) {
2342
+ event.detail(this.resource);
2343
+ }
2344
+ this.consumers.push(event);
2345
+ }
2346
+ async loadResource() {
2347
+ await this.getResource(!this.lazy);
2348
+ }
2349
+ async fetch() {
2350
+ await this.getResource(true);
2351
+ }
2352
+ async getResource(fetch = false) {
2353
+ try {
2354
+ if (fetch) {
2355
+ this.loading = true;
2356
+ await this.os.fetch(this.uri);
2357
+ }
2358
+ this.resource = this.os.store.get(this.uri);
2359
+ this.error = null;
2360
+ this.consumers.forEach(consumer => {
2361
+ consumer.detail(this.resource);
2362
+ });
2363
+ }
2364
+ catch (err) {
2365
+ this.error = err;
2366
+ }
2367
+ finally {
2368
+ this.loading = false;
2369
+ }
2370
+ }
2371
+ render() {
2372
+ if (this.loading) {
2373
+ return h("ion-progress-bar", { type: "indeterminate" });
2374
+ }
2375
+ if (this.error) {
2376
+ return (h("ion-card", null, h("ion-card-header", null, h("p", null, "Sorry, something went wrong"), h("p", null, "Status:",
2377
+ // @ts-ignore
2378
+ this.error.status), h("details", null, this.error.message)), h("ion-card-content", null, h("p", null, "You can try to open the link outside PodOS:"), h("a", { href: this.uri }, this.uri))));
2379
+ }
2380
+ return h("slot", null);
2381
+ }
2382
+ static get watchers() { return {
2383
+ "os": ["loadResource"],
2384
+ "uri": ["loadResource"]
2385
+ }; }
2386
+ };
2387
+
2388
+ const appendToMap = (map, propName, value) => {
2389
+ const items = map.get(propName);
2390
+ if (!items) {
2391
+ map.set(propName, [value]);
2392
+ }
2393
+ else if (!items.includes(value)) {
2394
+ items.push(value);
2395
+ }
2396
+ };
2397
+ const debounce = (fn, ms) => {
2398
+ let timeoutId;
2399
+ return (...args) => {
2400
+ if (timeoutId) {
2401
+ clearTimeout(timeoutId);
2402
+ }
2403
+ timeoutId = setTimeout(() => {
2404
+ timeoutId = 0;
2405
+ fn(...args);
2406
+ }, ms);
2407
+ };
2408
+ };
2409
+
2410
+ /**
2411
+ * Check if a possible element isConnected.
2412
+ * The property might not be there, so we check for it.
2413
+ *
2414
+ * We want it to return true if isConnected is not a property,
2415
+ * otherwise we would remove these elements and would not update.
2416
+ *
2417
+ * Better leak in Edge than to be useless.
2418
+ */
2419
+ const isConnected = (maybeElement) => !('isConnected' in maybeElement) || maybeElement.isConnected;
2420
+ const cleanupElements = debounce((map) => {
2421
+ for (let key of map.keys()) {
2422
+ map.set(key, map.get(key).filter(isConnected));
2423
+ }
2424
+ }, 2000);
2425
+ const stencilSubscription = () => {
2426
+ if (typeof getRenderingRef !== 'function') {
2427
+ // If we are not in a stencil project, we do nothing.
2428
+ // This function is not really exported by @stencil/core.
2429
+ return {};
2430
+ }
2431
+ const elmsToUpdate = new Map();
2432
+ return {
2433
+ dispose: () => elmsToUpdate.clear(),
2434
+ get: (propName) => {
2435
+ const elm = getRenderingRef();
2436
+ if (elm) {
2437
+ appendToMap(elmsToUpdate, propName, elm);
2438
+ }
2439
+ },
2440
+ set: (propName) => {
2441
+ const elements = elmsToUpdate.get(propName);
2442
+ if (elements) {
2443
+ elmsToUpdate.set(propName, elements.filter(forceUpdate));
2444
+ }
2445
+ cleanupElements(elmsToUpdate);
2446
+ },
2447
+ reset: () => {
2448
+ elmsToUpdate.forEach((elms) => elms.forEach(forceUpdate));
2449
+ cleanupElements(elmsToUpdate);
2450
+ },
2451
+ };
2452
+ };
2453
+
2454
+ const createObservableMap = (defaultState, shouldUpdate = (a, b) => a !== b) => {
2455
+ let states = new Map(Object.entries(defaultState !== null && defaultState !== void 0 ? defaultState : {}));
2456
+ const handlers = {
2457
+ dispose: [],
2458
+ get: [],
2459
+ set: [],
2460
+ reset: [],
2461
+ };
2462
+ const reset = () => {
2463
+ states = new Map(Object.entries(defaultState !== null && defaultState !== void 0 ? defaultState : {}));
2464
+ handlers.reset.forEach((cb) => cb());
2465
+ };
2466
+ const dispose = () => {
2467
+ // Call first dispose as resetting the state would
2468
+ // cause less updates ;)
2469
+ handlers.dispose.forEach((cb) => cb());
2470
+ reset();
2471
+ };
2472
+ const get = (propName) => {
2473
+ handlers.get.forEach((cb) => cb(propName));
2474
+ return states.get(propName);
2475
+ };
2476
+ const set = (propName, value) => {
2477
+ const oldValue = states.get(propName);
2478
+ if (shouldUpdate(value, oldValue, propName)) {
2479
+ states.set(propName, value);
2480
+ handlers.set.forEach((cb) => cb(propName, value, oldValue));
2481
+ }
2482
+ };
2483
+ const state = (typeof Proxy === 'undefined'
2484
+ ? {}
2485
+ : new Proxy(defaultState, {
2486
+ get(_, propName) {
2487
+ return get(propName);
2488
+ },
2489
+ ownKeys(_) {
2490
+ return Array.from(states.keys());
2491
+ },
2492
+ getOwnPropertyDescriptor() {
2493
+ return {
2494
+ enumerable: true,
2495
+ configurable: true,
2496
+ };
2497
+ },
2498
+ has(_, propName) {
2499
+ return states.has(propName);
2500
+ },
2501
+ set(_, propName, value) {
2502
+ set(propName, value);
2503
+ return true;
2504
+ },
2505
+ }));
2506
+ const on = (eventName, callback) => {
2507
+ handlers[eventName].push(callback);
2508
+ return () => {
2509
+ removeFromArray(handlers[eventName], callback);
2510
+ };
2511
+ };
2512
+ const onChange = (propName, cb) => {
2513
+ const unSet = on('set', (key, newValue) => {
2514
+ if (key === propName) {
2515
+ cb(newValue);
2516
+ }
2517
+ });
2518
+ const unReset = on('reset', () => cb(defaultState[propName]));
2519
+ return () => {
2520
+ unSet();
2521
+ unReset();
2522
+ };
2523
+ };
2524
+ const use = (...subscriptions) => {
2525
+ const unsubs = subscriptions.reduce((unsubs, subscription) => {
2526
+ if (subscription.set) {
2527
+ unsubs.push(on('set', subscription.set));
2528
+ }
2529
+ if (subscription.get) {
2530
+ unsubs.push(on('get', subscription.get));
2531
+ }
2532
+ if (subscription.reset) {
2533
+ unsubs.push(on('reset', subscription.reset));
2534
+ }
2535
+ if (subscription.dispose) {
2536
+ unsubs.push(on('dispose', subscription.dispose));
2537
+ }
2538
+ return unsubs;
2539
+ }, []);
2540
+ return () => unsubs.forEach((unsub) => unsub());
2541
+ };
2542
+ const forceUpdate = (key) => {
2543
+ const oldValue = states.get(key);
2544
+ handlers.set.forEach((cb) => cb(key, oldValue, oldValue));
2545
+ };
2546
+ return {
2547
+ state,
2548
+ get,
2549
+ set,
2550
+ on,
2551
+ onChange,
2552
+ use,
2553
+ dispose,
2554
+ reset,
2555
+ forceUpdate,
2556
+ };
2557
+ };
2558
+ const removeFromArray = (array, item) => {
2559
+ const index = array.indexOf(item);
2560
+ if (index >= 0) {
2561
+ array[index] = array[array.length - 1];
2562
+ array.length--;
2563
+ }
2564
+ };
2565
+
2566
+ const createStore = (defaultState, shouldUpdate) => {
2567
+ const map = createObservableMap(defaultState, shouldUpdate);
2568
+ map.use(stencilSubscription());
2569
+ return map;
2570
+ };
2571
+
2572
+ const createRouter = (opts) => {
2573
+ var _a;
2574
+ const win = window;
2575
+ const url = new URL(win.location.href);
2576
+ const parseURL = (_a = opts === null || opts === void 0 ? void 0 : opts.parseURL) !== null && _a !== void 0 ? _a : DEFAULT_PARSE_URL;
2577
+ const { state, onChange, dispose } = createStore({
2578
+ url,
2579
+ activePath: parseURL(url)
2580
+ }, (newV, oldV, prop) => {
2581
+ if (prop === 'url') {
2582
+ return newV.href !== oldV.href;
2583
+ }
2584
+ return newV !== oldV;
2585
+ });
2586
+ const push = (href) => {
2587
+ history.pushState(null, null, href);
2588
+ const url = new URL(href, document.baseURI);
2589
+ state.url = url;
2590
+ state.activePath = parseURL(url);
2591
+ };
2592
+ const match = (routes) => {
2593
+ const { activePath } = state;
2594
+ for (let route of routes) {
2595
+ const params = matchPath(activePath, route.path);
2596
+ if (params) {
2597
+ if (route.to != null) {
2598
+ const to = (typeof route.to === 'string')
2599
+ ? route.to
2600
+ : route.to(activePath);
2601
+ push(to);
2602
+ return match(routes);
2603
+ }
2604
+ else {
2605
+ return { params, route };
2606
+ }
2607
+ }
2608
+ }
2609
+ return undefined;
2610
+ };
2611
+ const navigationChanged = () => {
2612
+ const url = new URL(win.location.href);
2613
+ state.url = url;
2614
+ state.activePath = parseURL(url);
2615
+ };
2616
+ const Switch = (_, childrenRoutes) => {
2617
+ const result = match(childrenRoutes);
2618
+ if (result) {
2619
+ if (typeof result.route.jsx === 'function') {
2620
+ return result.route.jsx(result.params);
2621
+ }
2622
+ else {
2623
+ return result.route.jsx;
2624
+ }
2625
+ }
2626
+ };
2627
+ const disposeRouter = () => {
2628
+ win.removeEventListener('popstate', navigationChanged);
2629
+ dispose();
2630
+ };
2631
+ const router = {
2632
+ Switch,
2633
+ get url() {
2634
+ return state.url;
2635
+ },
2636
+ get activePath() {
2637
+ return state.activePath;
2638
+ },
2639
+ push,
2640
+ onChange: onChange,
2641
+ dispose: disposeRouter,
2642
+ };
2643
+ // Initial update
2644
+ navigationChanged();
2645
+ // Listen URL changes
2646
+ win.addEventListener('popstate', navigationChanged);
2647
+ return router;
2648
+ };
2649
+ const Route = (props, children) => {
2650
+ var _a;
2651
+ if ('to' in props) {
2652
+ return {
2653
+ path: props.path,
2654
+ to: props.to,
2655
+ };
2656
+ }
2657
+ return {
2658
+ path: props.path,
2659
+ id: props.id,
2660
+ jsx: (_a = props.render) !== null && _a !== void 0 ? _a : children,
2661
+ };
2662
+ };
2663
+ const matchPath = (pathname, path) => {
2664
+ if (typeof path === 'string') {
2665
+ if (path === pathname) {
2666
+ return {};
2667
+ }
2668
+ }
2669
+ else if (typeof path === 'function') {
2670
+ const params = path(pathname);
2671
+ if (params) {
2672
+ return params === true
2673
+ ? {}
2674
+ : { ...params };
2675
+ }
2676
+ }
2677
+ else {
2678
+ const results = path.exec(pathname);
2679
+ if (results) {
2680
+ path.lastIndex = 0;
2681
+ return { ...results };
2682
+ }
2683
+ }
2684
+ return undefined;
2685
+ };
2686
+ const DEFAULT_PARSE_URL = (url) => {
2687
+ return url.pathname.toLowerCase();
2688
+ };
2689
+
2690
+ /**
2691
+ * TS adaption of https://github.com/pillarjs/path-to-regexp/blob/master/index.js
2692
+ */
2693
+ /**
2694
+ * Default configs.
2695
+ */
2696
+ const DEFAULT_DELIMITER = '/';
2697
+ const DEFAULT_DELIMITERS = './';
2698
+ /**
2699
+ * The main path matching regexp utility.
2700
+ */
2701
+ const PATH_REGEXP = new RegExp([
2702
+ // Match escaped characters that would otherwise appear in future matches.
2703
+ // This allows the user to escape special characters that won't transform.
2704
+ '(\\\\.)',
2705
+ // Match Express-style parameters and un-named parameters with a prefix
2706
+ // and optional suffixes. Matches appear as:
2707
+ //
2708
+ // "/:test(\\d+)?" => ["/", "test", "\d+", undefined, "?"]
2709
+ // "/route(\\d+)" => [undefined, undefined, undefined, "\d+", undefined]
2710
+ '(?:\\:(\\w+)(?:\\(((?:\\\\.|[^\\\\()])+)\\))?|\\(((?:\\\\.|[^\\\\()])+)\\))([+*?])?'
2711
+ ].join('|'), 'g');
2712
+ /**
2713
+ * Parse a string for the raw tokens.
2714
+ */
2715
+ const parse = (str, options) => {
2716
+ var tokens = [];
2717
+ var key = 0;
2718
+ var index = 0;
2719
+ var path = '';
2720
+ var defaultDelimiter = (options && options.delimiter) || DEFAULT_DELIMITER;
2721
+ var delimiters = (options && options.delimiters) || DEFAULT_DELIMITERS;
2722
+ var pathEscaped = false;
2723
+ var res;
2724
+ while ((res = PATH_REGEXP.exec(str)) !== null) {
2725
+ var m = res[0];
2726
+ var escaped = res[1];
2727
+ var offset = res.index;
2728
+ path += str.slice(index, offset);
2729
+ index = offset + m.length;
2730
+ // Ignore already escaped sequences.
2731
+ if (escaped) {
2732
+ path += escaped[1];
2733
+ pathEscaped = true;
2734
+ continue;
2735
+ }
2736
+ var prev = '';
2737
+ var next = str[index];
2738
+ var name = res[2];
2739
+ var capture = res[3];
2740
+ var group = res[4];
2741
+ var modifier = res[5];
2742
+ if (!pathEscaped && path.length) {
2743
+ var k = path.length - 1;
2744
+ if (delimiters.indexOf(path[k]) > -1) {
2745
+ prev = path[k];
2746
+ path = path.slice(0, k);
2747
+ }
2748
+ }
2749
+ // Push the current path onto the tokens.
2750
+ if (path) {
2751
+ tokens.push(path);
2752
+ path = '';
2753
+ pathEscaped = false;
2754
+ }
2755
+ var partial = prev !== '' && next !== undefined && next !== prev;
2756
+ var repeat = modifier === '+' || modifier === '*';
2757
+ var optional = modifier === '?' || modifier === '*';
2758
+ var delimiter = prev || defaultDelimiter;
2759
+ var pattern = capture || group;
2760
+ tokens.push({
2761
+ name: name || key++,
2762
+ prefix: prev,
2763
+ delimiter: delimiter,
2764
+ optional: optional,
2765
+ repeat: repeat,
2766
+ partial: partial,
2767
+ pattern: pattern ? escapeGroup(pattern) : '[^' + escapeString(delimiter) + ']+?'
2768
+ });
2769
+ }
2770
+ // Push any remaining characters.
2771
+ if (path || index < str.length) {
2772
+ tokens.push(path + str.substr(index));
2773
+ }
2774
+ return tokens;
2775
+ };
2776
+ /**
2777
+ * Escape a regular expression string.
2778
+ */
2779
+ const escapeString = (str) => {
2780
+ return str.replace(/([.+*?=^!:${}()[\]|/\\])/g, '\\$1');
2781
+ };
2782
+ /**
2783
+ * Escape the capturing group by escaping special characters and meaning.
2784
+ */
2785
+ const escapeGroup = (group) => {
2786
+ return group.replace(/([=!:$/()])/g, '\\$1');
2787
+ };
2788
+ /**
2789
+ * Get the flags for a regexp from the options.
2790
+ */
2791
+ const flags = (options) => {
2792
+ return options && options.sensitive ? '' : 'i';
2793
+ };
2794
+ /**
2795
+ * Pull out keys from a regexp.
2796
+ */
2797
+ const regexpToRegexp = (path, keys) => {
2798
+ if (!keys)
2799
+ return path;
2800
+ // Use a negative lookahead to match only capturing groups.
2801
+ var groups = path.source.match(/\((?!\?)/g);
2802
+ if (groups) {
2803
+ for (var i = 0; i < groups.length; i++) {
2804
+ keys.push({
2805
+ name: i,
2806
+ prefix: null,
2807
+ delimiter: null,
2808
+ optional: false,
2809
+ repeat: false,
2810
+ partial: false,
2811
+ pattern: null
2812
+ });
2813
+ }
2814
+ }
2815
+ return path;
2816
+ };
2817
+ /**
2818
+ * Transform an array into a regexp.
2819
+ */
2820
+ const arrayToRegexp = (path, keys, options) => {
2821
+ var parts = [];
2822
+ for (var i = 0; i < path.length; i++) {
2823
+ parts.push(pathToRegexp(path[i], keys, options).source);
2824
+ }
2825
+ return new RegExp('(?:' + parts.join('|') + ')', flags(options));
2826
+ };
2827
+ /**
2828
+ * Create a path regexp from string input.
2829
+ */
2830
+ const stringToRegexp = (path, keys, options) => {
2831
+ return tokensToRegExp(parse(path, options), keys, options);
2832
+ };
2833
+ /**
2834
+ * Expose a function for taking tokens and returning a RegExp.
2835
+ */
2836
+ const tokensToRegExp = (tokens, keys, options) => {
2837
+ options = options || {};
2838
+ var strict = options.strict;
2839
+ var end = options.end !== false;
2840
+ var delimiter = escapeString(options.delimiter || DEFAULT_DELIMITER);
2841
+ var delimiters = options.delimiters || DEFAULT_DELIMITERS;
2842
+ var endsWith = [].concat(options.endsWith || []).map(escapeString).concat('$').join('|');
2843
+ var route = '';
2844
+ var isEndDelimited = false;
2845
+ // Iterate over the tokens and create our regexp string.
2846
+ for (var i = 0; i < tokens.length; i++) {
2847
+ var token = tokens[i];
2848
+ if (typeof token === 'string') {
2849
+ route += escapeString(token);
2850
+ isEndDelimited = i === tokens.length - 1 && delimiters.indexOf(token[token.length - 1]) > -1;
2851
+ }
2852
+ else {
2853
+ var prefix = escapeString(token.prefix || '');
2854
+ var capture = token.repeat
2855
+ ? '(?:' + token.pattern + ')(?:' + prefix + '(?:' + token.pattern + '))*'
2856
+ : token.pattern;
2857
+ if (keys)
2858
+ keys.push(token);
2859
+ if (token.optional) {
2860
+ if (token.partial) {
2861
+ route += prefix + '(' + capture + ')?';
2862
+ }
2863
+ else {
2864
+ route += '(?:' + prefix + '(' + capture + '))?';
2865
+ }
2866
+ }
2867
+ else {
2868
+ route += prefix + '(' + capture + ')';
2869
+ }
2870
+ }
2871
+ }
2872
+ if (end) {
2873
+ if (!strict)
2874
+ route += '(?:' + delimiter + ')?';
2875
+ route += endsWith === '$' ? '$' : '(?=' + endsWith + ')';
2876
+ }
2877
+ else {
2878
+ if (!strict)
2879
+ route += '(?:' + delimiter + '(?=' + endsWith + '))?';
2880
+ if (!isEndDelimited)
2881
+ route += '(?=' + delimiter + '|' + endsWith + ')';
2882
+ }
2883
+ return new RegExp('^' + route, flags(options));
2884
+ };
2885
+ /**
2886
+ * Normalize the given path string, returning a regular expression.
2887
+ *
2888
+ * An empty array can be passed in for the keys, which will hold the
2889
+ * placeholder key descriptions. For example, using `/user/:id`, `keys` will
2890
+ * contain `[{ name: 'id', delimiter: '/', optional: false, repeat: false }]`.
2891
+ */
2892
+ const pathToRegexp = (path, keys, options) => {
2893
+ if (path instanceof RegExp) {
2894
+ return regexpToRegexp(path, keys);
2895
+ }
2896
+ if (Array.isArray(path)) {
2897
+ return arrayToRegexp(path, keys, options);
2898
+ }
2899
+ return stringToRegexp(path, keys, options);
2900
+ };
2901
+
2902
+ let cacheCount = 0;
2903
+ const patternCache = {};
2904
+ const cacheLimit = 10000;
2905
+ // Memoized function for creating the path match regex
2906
+ const compilePath = (pattern, options) => {
2907
+ const cacheKey = `${options.end}${options.strict}`;
2908
+ const cache = patternCache[cacheKey] || (patternCache[cacheKey] = {});
2909
+ const cachePattern = JSON.stringify(pattern);
2910
+ if (cache[cachePattern]) {
2911
+ return cache[cachePattern];
2912
+ }
2913
+ const keys = [];
2914
+ const re = pathToRegexp(pattern, keys, options);
2915
+ const compiledPattern = { re, keys };
2916
+ if (cacheCount < cacheLimit) {
2917
+ cache[cachePattern] = compiledPattern;
2918
+ cacheCount += 1;
2919
+ }
2920
+ return compiledPattern;
2921
+ };
2922
+ const match = (pathname, options = {}) => {
2923
+ const { exact = false, strict = false } = options;
2924
+ const { re, keys } = compilePath(pathname, { end: exact, strict });
2925
+ return (path) => {
2926
+ const match = re.exec(path);
2927
+ if (!match) {
2928
+ return undefined;
2929
+ }
2930
+ const [url, ...values] = match;
2931
+ const isExact = path === url;
2932
+ if (exact && !isExact) {
2933
+ return undefined;
2934
+ }
2935
+ return keys.reduce((memo, key, index) => {
2936
+ memo[key.name] = values[index];
2937
+ return memo;
2938
+ }, {});
2939
+ };
2940
+ };
2941
+
2942
+ const Router = createRouter();
2943
+ const PosRouter = class {
2944
+ constructor(hostRef) {
2945
+ registerInstance(this, hostRef);
2946
+ this.uri = undefined;
2947
+ }
2948
+ linkClicked(e) {
2949
+ this.navigate(e.detail);
2950
+ }
2951
+ componentWillLoad() {
2952
+ this.updateUri();
2953
+ Router.onChange('url', () => {
2954
+ this.updateUri();
2955
+ });
2956
+ }
2957
+ navigate(uri) {
2958
+ Router.push('?uri=' + encodeURIComponent(uri));
2959
+ }
2960
+ updateUri() {
2961
+ this.uri = new URLSearchParams(window.location.search).get('uri') || window.location.href;
2962
+ }
2963
+ render() {
2964
+ console.log('render router', this.uri);
2965
+ return (h(Router.Switch, null, h(Route, { path: match('', { exact: false }) }, h("pos-navigation-bar", { uri: this.uri }), h("pos-resource", { key: this.uri, uri: this.uri }, h("pos-type-router", null)))));
2966
+ }
2967
+ };
2968
+
2969
+ var AvailableApps;
2970
+ (function (AvailableApps) {
2971
+ AvailableApps["Generic"] = "pos-app-generic";
2972
+ AvailableApps["RdfDocument"] = "pos-app-rdf-document";
2973
+ AvailableApps["DocumentViewer"] = "pos-app-document-viewer";
2974
+ AvailableApps["ImageViewer"] = "pos-app-image-viewer";
2975
+ })(AvailableApps || (AvailableApps = {}));
2976
+ function selectAppForTypes(types) {
2977
+ if (types.some(type => type.uri === 'http://www.w3.org/2007/ont/link#RDFDocument')) {
2978
+ return AvailableApps.RdfDocument;
2979
+ }
2980
+ else if (types.some(type => type.uri === 'http://www.w3.org/ns/iana/media-types/application/pdf#Resource')) {
2981
+ return AvailableApps.DocumentViewer;
2982
+ }
2983
+ else if (types.some(type => type.uri === 'http://purl.org/dc/terms/Image')) {
2984
+ return AvailableApps.ImageViewer;
2985
+ }
2986
+ else if (types.some(type => type.uri === 'http://www.w3.org/2007/ont/link#Document')) {
2987
+ return AvailableApps.DocumentViewer;
2988
+ }
2989
+ else {
2990
+ return AvailableApps.Generic;
2991
+ }
2992
+ }
2993
+
2994
+ const PosTypeRouter = class {
2995
+ constructor(hostRef) {
2996
+ registerInstance(this, hostRef);
2997
+ this.subscribeResource = createEvent(this, "pod-os:resource", 7);
2998
+ this.receiveResource = (resource) => {
2999
+ this.types = resource.types();
3000
+ };
3001
+ this.types = undefined;
3002
+ }
3003
+ componentWillLoad() {
3004
+ subscribeResource(this);
3005
+ }
3006
+ render() {
3007
+ return this.types ? this.renderApp() : null;
3008
+ }
3009
+ renderApp() {
3010
+ const App = selectAppForTypes(this.types);
3011
+ return h(App, null);
3012
+ }
3013
+ };
3014
+
3015
+ export { App as ion_app, Button as ion_button, Card as ion_card, CardContent as ion_card_content, CardHeader as ion_card_header, Content as ion_content, Footer as ion_footer, Header as ion_header, Icon as ion_icon, ProgressBar as ion_progress_bar, RippleEffect as ion_ripple_effect, Searchbar as ion_searchbar, SkeletonText as ion_skeleton_text, ToolbarTitle as ion_title, Toolbar as ion_toolbar, PosApp as pos_app, PosAppBrowser as pos_app_browser, PosImage as pos_image, PosLabel as pos_label, PosLogin as pos_login, PosNavigationBar as pos_navigation_bar, PosPicture as pos_picture, PosResource as pos_resource, PosRouter as pos_router, PosTypeRouter as pos_type_router };