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