@ionic/core 9.0.1-nightly.20260820 → 9.0.1-nightly.20260821
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.
- package/components/index.js +1 -1
- package/components/ion-action-sheet.js +1 -1
- package/components/ion-alert.js +1 -1
- package/components/ion-infinite-scroll-content.js +1 -1
- package/components/ion-item-sliding.js +1 -1
- package/components/ion-loading.js +1 -1
- package/components/ion-refresher-content.js +1 -1
- package/components/ion-refresher.js +1 -1
- package/components/ion-segment-button.js +1 -1
- package/components/ion-select-modal.js +1 -1
- package/components/ion-select-popover.js +1 -1
- package/components/ion-select.js +1 -1
- package/components/ion-toast.js +1 -1
- package/{dist/ionic/p-DgUL3JbO.js → components/p-BE48ZNam.js} +1 -1
- package/components/{p-CaiZOhfC.js → p-C3QTG7as.js} +1 -1
- package/components/{p-B6x5_b9w.js → p-CmpstNYe.js} +1 -1
- package/components/{p-DqAI6tg7.js → p-CrzR7nZk.js} +1 -1
- package/components/{p-Bnc0m4SW.js → p-DGwySvgi.js} +1 -1
- package/components/{p-eFI3mtEX.js → p-e8f0KKOJ.js} +1 -1
- package/dist/cjs/{index-EJLjthTK.js → index-D4T0SA6Q.js} +1 -0
- package/dist/cjs/index.cjs.js +1 -1
- package/dist/cjs/ion-action-sheet.cjs.entry.js +2 -2
- package/dist/cjs/ion-alert.cjs.entry.js +2 -2
- package/dist/cjs/ion-infinite-scroll_2.cjs.entry.js +1 -1
- package/dist/cjs/ion-item-option_3.cjs.entry.js +9 -11
- package/dist/cjs/ion-loading.cjs.entry.js +1 -1
- package/dist/cjs/ion-refresher_2.cjs.entry.js +11 -4
- package/dist/cjs/ion-segment_2.cjs.entry.js +11 -7
- package/dist/cjs/ion-select-modal.cjs.entry.js +2 -2
- package/dist/cjs/ion-select_3.cjs.entry.js +50 -40
- package/dist/cjs/ion-toast.cjs.entry.js +1 -1
- package/dist/cjs/{select-option-render-7m1WdFzF.js → select-option-render-CgnqHkpg.js} +1 -1
- package/dist/collection/components/item-sliding/item-sliding.js +10 -12
- package/dist/collection/components/refresher/refresher.js +10 -3
- package/dist/collection/components/segment-button/segment-button.js +11 -7
- package/dist/collection/components/select/select.js +49 -39
- package/dist/collection/utils/test/late-props/late-props.js +69 -0
- package/dist/docs.json +1 -1
- package/dist/esm/{index-elneMH8y.js → index-D3o-MD4_.js} +1 -1
- package/dist/esm/index.js +1 -1
- package/dist/esm/ion-action-sheet.entry.js +2 -2
- package/dist/esm/ion-alert.entry.js +2 -2
- package/dist/esm/ion-infinite-scroll_2.entry.js +1 -1
- package/dist/esm/ion-item-option_3.entry.js +10 -12
- package/dist/esm/ion-loading.entry.js +1 -1
- package/dist/esm/ion-refresher_2.entry.js +11 -4
- package/dist/esm/ion-segment_2.entry.js +11 -7
- package/dist/esm/ion-select-modal.entry.js +2 -2
- package/dist/esm/ion-select_3.entry.js +50 -40
- package/dist/esm/ion-toast.entry.js +1 -1
- package/dist/esm/{select-option-render-lIuu64EV.js → select-option-render-Dv7KImop.js} +1 -1
- package/dist/ionic/index.esm.js +1 -1
- package/dist/ionic/ionic.esm.js +1 -1
- package/dist/ionic/{p-68507e70.entry.js → p-0a9d2de8.entry.js} +1 -1
- package/dist/ionic/{p-873a315a.entry.js → p-29970df5.entry.js} +1 -1
- package/dist/ionic/p-5b906fd6.entry.js +4 -0
- package/dist/ionic/{p-886d9e66.entry.js → p-8edf9c85.entry.js} +1 -1
- package/{components/p-CqyGR9Aq.js → dist/ionic/p-BfiwBb5h.js} +1 -1
- package/dist/ionic/p-a389f473.entry.js +4 -0
- package/dist/ionic/p-bdb4c7e5.entry.js +4 -0
- package/dist/ionic/{p-34b9379b.entry.js → p-c075e3e4.entry.js} +1 -1
- package/dist/ionic/{p-05800a02.entry.js → p-c91501b7.entry.js} +1 -1
- package/dist/ionic/{p-959df5f8.entry.js → p-eeabd236.entry.js} +1 -1
- package/dist/ionic/p-f7dd1ed9.entry.js +4 -0
- package/dist/ionic/{p-BZVE25Gu.js → p-fVT-pm3r.js} +1 -1
- package/dist/types/components/refresher/refresher.d.ts +7 -0
- package/hydrate/index.js +78 -59
- package/hydrate/index.mjs +78 -59
- package/package.json +1 -1
- package/dist/ionic/p-1d694d39.entry.js +0 -4
- package/dist/ionic/p-4437015c.entry.js +0 -4
- package/dist/ionic/p-8f464a8f.entry.js +0 -4
- package/dist/ionic/p-f521b13c.entry.js +0 -4
|
@@ -11,7 +11,7 @@ var haptic = require('./haptic-Ch-X4gRx.js');
|
|
|
11
11
|
var ionicGlobal = require('./ionic-global-DvgIzM2F.js');
|
|
12
12
|
var animation = require('./animation-D-OqR4a4.js');
|
|
13
13
|
var config = require('./config-CjUbvdPW.js');
|
|
14
|
-
var index$3 = require('./index-
|
|
14
|
+
var index$3 = require('./index-D4T0SA6Q.js');
|
|
15
15
|
var index$2 = require('./index-wOmugbdg.js');
|
|
16
16
|
var spinnerConfigs = require('./spinner-configs-DxHKnd3-.js');
|
|
17
17
|
require('./dir-zwDPRE5K.js');
|
|
@@ -582,11 +582,18 @@ const Refresher = class {
|
|
|
582
582
|
componentDidUpdate() {
|
|
583
583
|
this.checkNativeRefresher();
|
|
584
584
|
}
|
|
585
|
-
|
|
585
|
+
/**
|
|
586
|
+
* Validate the slot attribute before rendering, while the host still reflects the
|
|
587
|
+
* developer's original markup. `connectedCallback` is too early: in the custom
|
|
588
|
+
* elements build it runs during insertion, before frameworks such as React assign
|
|
589
|
+
* the slot.
|
|
590
|
+
*/
|
|
591
|
+
componentWillLoad() {
|
|
586
592
|
if (this.el.getAttribute('slot') !== 'fixed') {
|
|
587
593
|
index.printIonError('[ion-refresher] - Make sure you use: <ion-refresher slot="fixed">');
|
|
588
|
-
return;
|
|
589
594
|
}
|
|
595
|
+
}
|
|
596
|
+
async connectedCallback() {
|
|
590
597
|
const contentEl = this.el.closest(index$1.ION_CONTENT_ELEMENT_SELECTOR);
|
|
591
598
|
if (!contentEl) {
|
|
592
599
|
index$1.printIonContentErrorMsg(this.el);
|
|
@@ -946,7 +953,7 @@ const Refresher = class {
|
|
|
946
953
|
}
|
|
947
954
|
render() {
|
|
948
955
|
const mode = ionicGlobal.getIonMode(this);
|
|
949
|
-
return (index.h(index.Host, { key: '
|
|
956
|
+
return (index.h(index.Host, { key: 'fd9c8e51155d56f12148e8eb547e45c05807b4b5', slot: "fixed", class: {
|
|
950
957
|
[mode]: true,
|
|
951
958
|
// Used internally for styling
|
|
952
959
|
[`refresher-${mode}`]: true,
|
|
@@ -631,11 +631,6 @@ const SegmentButton = class {
|
|
|
631
631
|
helpers.addEventListener(segmentEl, 'ionSelect', this.updateState);
|
|
632
632
|
helpers.addEventListener(segmentEl, 'ionStyle', this.updateStyle);
|
|
633
633
|
}
|
|
634
|
-
// Prevent buttons from being disabled when associated with segment content
|
|
635
|
-
if (this.contentId && this.disabled) {
|
|
636
|
-
index.printIonWarning(`[ion-segment-button] - Segment buttons cannot be disabled when associated with an <ion-segment-content>.`);
|
|
637
|
-
this.disabled = false;
|
|
638
|
-
}
|
|
639
634
|
}
|
|
640
635
|
disconnectedCallback() {
|
|
641
636
|
const segmentEl = this.segmentEl;
|
|
@@ -652,6 +647,15 @@ const SegmentButton = class {
|
|
|
652
647
|
// Return if there is no contentId defined
|
|
653
648
|
if (!this.contentId)
|
|
654
649
|
return;
|
|
650
|
+
/**
|
|
651
|
+
* Checked here rather than in `connectedCallback` so frameworks that assign element
|
|
652
|
+
* props after inserting the element have set `disabled` by now. A disabled ion-segment
|
|
653
|
+
* pushes that onto its buttons too, which this guard should not undo.
|
|
654
|
+
*/
|
|
655
|
+
if (this.disabled && this.segmentEl?.disabled !== true) {
|
|
656
|
+
index.printIonWarning(`[ion-segment-button] - Segment buttons cannot be disabled when associated with an <ion-segment-content>.`);
|
|
657
|
+
this.disabled = false;
|
|
658
|
+
}
|
|
655
659
|
// Attempt to find the Segment Content by its contentId
|
|
656
660
|
const segmentContent = document.getElementById(this.contentId);
|
|
657
661
|
// If no associated Segment Content exists, log an error and return
|
|
@@ -686,7 +690,7 @@ const SegmentButton = class {
|
|
|
686
690
|
const { checked, type, disabled, hasIcon, hasLabel, layout, segmentEl } = this;
|
|
687
691
|
const mode = ionicGlobal.getIonMode(this);
|
|
688
692
|
const hasSegmentColor = () => segmentEl?.color !== undefined;
|
|
689
|
-
return (index.h(index.Host, { key: '
|
|
693
|
+
return (index.h(index.Host, { key: 'd8acc71d87e26b32f20b2d0f9a6acc9f0dab0dee', class: {
|
|
690
694
|
[mode]: true,
|
|
691
695
|
'in-toolbar': theme.hostContext('ion-toolbar', this.el),
|
|
692
696
|
'in-toolbar-color': theme.hostContext('ion-toolbar[color]', this.el),
|
|
@@ -702,7 +706,7 @@ const SegmentButton = class {
|
|
|
702
706
|
'ion-activatable': true,
|
|
703
707
|
'ion-activatable-instant': true,
|
|
704
708
|
'ion-focusable': true,
|
|
705
|
-
} }, index.h("button", { key: '
|
|
709
|
+
} }, index.h("button", { key: 'ce65da07b1a012bce353b3c6c24eecfbd4071d54', "aria-selected": checked ? 'true' : 'false', role: "tab", ref: (el) => (this.nativeEl = el), type: type, class: "button-native", part: "native", disabled: disabled, ...this.inheritedAttributes }, index.h("span", { key: '6c4b4dcd20e407e5dc31674bea23633d8a09187a', class: "button-inner" }, index.h("slot", { key: '817145ae77a3c5ada88ab95723d881f1bde96b2a' })), mode === 'md' && index.h("ion-ripple-effect", { key: '054d7e5e2a13013914fac6bbde8efdb28d9b459e' })), index.h("div", { key: 'c48074881a302510ad4752eeb9383222cd3a54cb', part: "indicator", class: "segment-button-indicator segment-button-indicator-animated" }, index.h("div", { key: '7672a6b10ee18ad026b798fbd8207dc3cd5683f9', part: "indicator-background", class: "segment-button-indicator-background" }))));
|
|
706
710
|
}
|
|
707
711
|
get el() { return index.getElement(this); }
|
|
708
712
|
static get watchers() { return {
|
|
@@ -7,7 +7,7 @@ var index = require('./index-BrVMoqUk.js');
|
|
|
7
7
|
var ionicGlobal = require('./ionic-global-DvgIzM2F.js');
|
|
8
8
|
var overlayControlLabel = require('./overlay-control-label-D2sdL2O8.js');
|
|
9
9
|
var overlays = require('./overlays-Bg0auTQa.js');
|
|
10
|
-
var selectOptionRender = require('./select-option-render-
|
|
10
|
+
var selectOptionRender = require('./select-option-render-CgnqHkpg.js');
|
|
11
11
|
var theme = require('./theme-Bw0rpaNN.js');
|
|
12
12
|
require('./index-DkNv4J_i.js');
|
|
13
13
|
require('./helpers-Dj5o76mq.js');
|
|
@@ -15,7 +15,7 @@ require('./dir-zwDPRE5K.js');
|
|
|
15
15
|
require('./hardware-back-button-JOAEFSzc.js');
|
|
16
16
|
require('./framework-delegate-BZUx4TnE.js');
|
|
17
17
|
require('./gesture-controller-CeJslptU.js');
|
|
18
|
-
require('./index-
|
|
18
|
+
require('./index-D4T0SA6Q.js');
|
|
19
19
|
|
|
20
20
|
const ionicSelectModalMdCss = () => `.action-sheet-button-label-has-rich-content.sc-ion-select-modal-ionic,.alert-radio-label-has-rich-content.sc-ion-select-modal-ionic,.alert-checkbox-label-has-rich-content.sc-ion-select-modal-ionic,.select-option-label-has-rich-content.sc-ion-select-modal-ionic{display:-ms-flexbox;display:flex;-ms-flex-align:center;align-items:center;gap:16px}.action-sheet-button-label-has-rich-content.sc-ion-select-modal-ionic,.alert-radio-label-has-rich-content.sc-ion-select-modal-ionic,.alert-checkbox-label-has-rich-content.sc-ion-select-modal-ionic,.select-option-content.sc-ion-select-modal-ionic{-ms-flex:1;flex:1}.action-sheet-button-label-text.sc-ion-select-modal-ionic,.alert-checkbox-label-text.sc-ion-select-modal-ionic,.alert-radio-label-text.sc-ion-select-modal-ionic,.select-option-label-text.sc-ion-select-modal-ionic{display:-ms-flexbox;display:flex;-ms-flex-align:center;align-items:center;gap:12px}.select-option-start.sc-ion-select-modal-ionic,.select-option-end.sc-ion-select-modal-ionic{display:-ms-flexbox;display:flex;-ms-flex-align:center;align-items:center;gap:8px}.select-option-description.sc-ion-select-modal-ionic{padding-left:0;padding-right:0;padding-top:5px;padding-bottom:0;display:block;color:var(--ion-color-step-700, var(--ion-text-color-step-300, #4d4d4d));font-size:0.75rem}.select-option-label.sc-ion-select-modal-ionic:not(.select-option-label-has-rich-content){text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.select-option-label-has-rich-content.sc-ion-select-modal-ionic{display:-ms-flexbox;display:flex;-ms-flex-align:center;align-items:center}ion-radio.select-option-has-rich-content.sc-ion-select-modal-ionic::part(label),ion-radio.select-option-has-rich-content.sc-ion-select-modal-ionic [part~="label"],ion-checkbox.select-option-has-rich-content.sc-ion-select-modal-ionic::part(label),ion-checkbox.select-option-has-rich-content.sc-ion-select-modal-ionic [part~="label"],.select-option-content.sc-ion-select-modal-ionic{-ms-flex:1;flex:1;white-space:normal}.select-option-start.sc-ion-select-modal-ionic>ion-avatar.sc-ion-select-modal-ionic,.select-option-end.sc-ion-select-modal-ionic>ion-avatar.sc-ion-select-modal-ionic{width:40px;height:40px}.select-option-start.sc-ion-select-modal-ionic>ion-icon.sc-ion-select-modal-ionic,.select-option-end.sc-ion-select-modal-ionic>ion-icon.sc-ion-select-modal-ionic{font-size:24px}.select-option-start.sc-ion-select-modal-ionic>ion-img.sc-ion-select-modal-ionic,.select-option-start.sc-ion-select-modal-ionic>img.sc-ion-select-modal-ionic,.select-option-start.sc-ion-select-modal-ionic>svg.sc-ion-select-modal-ionic,.select-option-start.sc-ion-select-modal-ionic>ion-thumbnail.sc-ion-select-modal-ionic,.select-option-end.sc-ion-select-modal-ionic>ion-img.sc-ion-select-modal-ionic,.select-option-end.sc-ion-select-modal-ionic>img.sc-ion-select-modal-ionic,.select-option-end.sc-ion-select-modal-ionic>svg.sc-ion-select-modal-ionic,.select-option-end.sc-ion-select-modal-ionic>ion-thumbnail.sc-ion-select-modal-ionic{width:56px;height:56px}.select-option-start.sc-ion-select-modal-ionic>video.sc-ion-select-modal-ionic,.select-option-end.sc-ion-select-modal-ionic>video.sc-ion-select-modal-ionic{width:114px;height:56px}.sc-ion-select-modal-ionic-h{height:100%}ion-list.sc-ion-select-modal-ionic ion-radio.sc-ion-select-modal-ionic::part(container),ion-list.sc-ion-select-modal-ionic ion-radio.sc-ion-select-modal-ionic [part~="container"]{display:none}ion-list.sc-ion-select-modal-ionic ion-radio.sc-ion-select-modal-ionic::part(label),ion-list.sc-ion-select-modal-ionic ion-radio.sc-ion-select-modal-ionic [part~="label"]{margin-left:0;margin-right:0;margin-top:0;margin-bottom:0}ion-item.sc-ion-select-modal-ionic{--inner-border-width:0}.item-radio-checked.sc-ion-select-modal-ionic{--background:rgba(var(--ion-color-primary-rgb, 0, 84, 233), 0.08);--background-focused:var(--ion-color-primary, #0054e9);--background-focused-opacity:0.2;--background-hover:var(--ion-color-primary, #0054e9);--background-hover-opacity:0.12}.item-checkbox-checked.sc-ion-select-modal-ionic{--background-activated:var(--ion-item-color, var(--ion-text-color, #000));--background-focused:var(--ion-item-color, var(--ion-text-color, #000));--background-hover:var(--ion-item-color, var(--ion-text-color, #000));--color:var(--ion-color-primary, #0054e9)}`;
|
|
21
21
|
|
|
@@ -11,13 +11,13 @@ var validity = require('./validity-BpS37YFM.js');
|
|
|
11
11
|
var helpers = require('./helpers-Dj5o76mq.js');
|
|
12
12
|
var overlays = require('./overlays-Bg0auTQa.js');
|
|
13
13
|
var dir = require('./dir-zwDPRE5K.js');
|
|
14
|
-
var index$2 = require('./index-
|
|
14
|
+
var index$2 = require('./index-D4T0SA6Q.js');
|
|
15
15
|
var theme = require('./theme-Bw0rpaNN.js');
|
|
16
16
|
var watchOptions = require('./watch-options-CviOsrTS.js');
|
|
17
17
|
var index$1 = require('./index-wOmugbdg.js');
|
|
18
18
|
var ionicGlobal = require('./ionic-global-DvgIzM2F.js');
|
|
19
19
|
var overlayControlLabel = require('./overlay-control-label-D2sdL2O8.js');
|
|
20
|
-
var selectOptionRender = require('./select-option-render-
|
|
20
|
+
var selectOptionRender = require('./select-option-render-CgnqHkpg.js');
|
|
21
21
|
require('./index-DkNv4J_i.js');
|
|
22
22
|
require('./hardware-back-button-JOAEFSzc.js');
|
|
23
23
|
require('./framework-delegate-BZUx4TnE.js');
|
|
@@ -906,7 +906,7 @@ const Select = class {
|
|
|
906
906
|
const hasOutlineFill = mode === 'md' && fill === 'outline';
|
|
907
907
|
helpers.renderHiddenInput(true, el, name, parseValue(value), disabled);
|
|
908
908
|
const labelShouldFloat = labelPlacement === 'stacked' || (labelPlacement === 'floating' && (hasValue || hasFocus || isExpanded));
|
|
909
|
-
return (index.h(index.Host, { key: '
|
|
909
|
+
return (index.h(index.Host, { key: 'b2f161e3706e139e61440cd13e162714b1b75d72', onClick: this.onClick, class: theme.createColorClasses(this.color, {
|
|
910
910
|
[mode]: true,
|
|
911
911
|
'in-item': inItem,
|
|
912
912
|
'in-item-color': theme.hostContext('ion-item.ion-color', el),
|
|
@@ -924,7 +924,7 @@ const Select = class {
|
|
|
924
924
|
[`select-justify-${justify}`]: justifyEnabled,
|
|
925
925
|
[`select-shape-${shape}`]: shape !== undefined,
|
|
926
926
|
[`select-label-placement-${labelPlacement}`]: true,
|
|
927
|
-
}) }, index.h("label", { key: '
|
|
927
|
+
}) }, index.h("label", { key: '944a2eb468154a21260d181fdaf67828a71eb902', class: "select-wrapper", id: "select-label", onClick: this.onLabelClick, part: "wrapper" }, hasOutlineFill && this.renderOutlineContainer(), index.h("div", { key: '927200c53548b1bb4f52d6a167605b724a7b7d0d', class: "select-start", part: "start", ref: (el) => (this.startContainerEl = el) }, index.h("slot", { key: '6e14b95e9b95c116b16744d630600e90977782bc', name: "start" })), index.h("div", { key: '8451ed4300ac005963075be36a04ea8763bc0fdd', class: "select-control", part: "control" }, this.renderLabel(), index.h("div", { key: '207e7b63f3224a4870579365ac992da6784fb31f', class: "native-wrapper", ref: (el) => (this.nativeWrapperEl = el), part: "container" }, this.renderSelectText(), this.renderListbox(), !hasFloatingOrStackedLabel && this.renderSelectIcon())), index.h("div", { key: '5c17367d488db4d570f31b25e33560efa9011500', class: "select-end", part: "end" }, hasFloatingOrStackedLabel && this.renderSelectIcon(), index.h("slot", { key: '21fd8c0d9bee8cffef9ef6984cacd31e8f38211c', name: "end" })), shouldRenderHighlight && index.h("div", { key: '1fff767db9a1ec07b274ef65ff7ae8fb976e6ad2', class: "select-highlight" })), this.renderBottomContent()));
|
|
928
928
|
}
|
|
929
929
|
get el() { return index.getElement(this); }
|
|
930
930
|
static get watchers() { return {
|
|
@@ -993,29 +993,14 @@ const textForValue = (opts, value, compareWith, useHTML = false) => {
|
|
|
993
993
|
return getOptionContent(selectOpt, undefined, true);
|
|
994
994
|
}
|
|
995
995
|
/**
|
|
996
|
-
*
|
|
997
|
-
*
|
|
998
|
-
* the
|
|
996
|
+
* Every text-only context reads only the default slot, so the start
|
|
997
|
+
* and end slots stay out of the `aria-label` and the overlay labels.
|
|
998
|
+
* Both config paths derive that text through the same helper, so they
|
|
999
|
+
* cannot disagree about what an option's text is. `null` marks an
|
|
1000
|
+
* option with no text, which is dropped from the joined text of a
|
|
1001
|
+
* `multiple` select rather than joined in as an empty entry.
|
|
999
1002
|
*/
|
|
1000
|
-
|
|
1001
|
-
const content = getOptionContent(selectOpt);
|
|
1002
|
-
if (typeof content === 'string') {
|
|
1003
|
-
return content;
|
|
1004
|
-
}
|
|
1005
|
-
/**
|
|
1006
|
-
* Elements were found in the default slot, extract and concatenate
|
|
1007
|
-
* their text content while trimming whitespace.
|
|
1008
|
-
*/
|
|
1009
|
-
if (content) {
|
|
1010
|
-
const texts = Array.from(content.childNodes)
|
|
1011
|
-
.map((n) => n.textContent?.trim())
|
|
1012
|
-
.filter((t) => t);
|
|
1013
|
-
return texts.join(' ') || null;
|
|
1014
|
-
}
|
|
1015
|
-
// Empty option
|
|
1016
|
-
return null;
|
|
1017
|
-
}
|
|
1018
|
-
return getDefaultSlotPlainText(selectOpt);
|
|
1003
|
+
return getDefaultSlotPlainText(selectOpt) || null;
|
|
1019
1004
|
};
|
|
1020
1005
|
/**
|
|
1021
1006
|
* Trims whitespace from all text nodes within a DOM tree.
|
|
@@ -1071,9 +1056,13 @@ const getOptionContent = (option, slotName, useHTML = false) => {
|
|
|
1071
1056
|
if (nodes.length === 0) {
|
|
1072
1057
|
return null;
|
|
1073
1058
|
}
|
|
1074
|
-
|
|
1059
|
+
/**
|
|
1060
|
+
* Return plain text if no elements are found. This reads the option the
|
|
1061
|
+
* same way the non-custom-HTML path does, so the two do not disagree
|
|
1062
|
+
* about what an option's text is.
|
|
1063
|
+
*/
|
|
1075
1064
|
if (!slotName && nodes.every((n) => n.nodeType === Node.TEXT_NODE)) {
|
|
1076
|
-
return
|
|
1065
|
+
return getDefaultSlotPlainText(option) || null;
|
|
1077
1066
|
}
|
|
1078
1067
|
/**
|
|
1079
1068
|
* Mirror known custom-element properties (e.g. ion-icon's `icon`)
|
|
@@ -1129,22 +1118,43 @@ const getOptionDefaultSlot = (option) => {
|
|
|
1129
1118
|
}
|
|
1130
1119
|
return defaultSlotNodes;
|
|
1131
1120
|
};
|
|
1121
|
+
/**
|
|
1122
|
+
* Concatenates the text a node renders, skipping the subtrees of tags
|
|
1123
|
+
* whose contents the browser never paints (`script`, `style`, and the
|
|
1124
|
+
* rest of `blockedTags`). `textContent` includes those, so reading it
|
|
1125
|
+
* directly would put stylesheet or script source into the select text
|
|
1126
|
+
* and the `aria-label`.
|
|
1127
|
+
*
|
|
1128
|
+
* @param node - The node to read text from.
|
|
1129
|
+
* @returns The node's rendered text.
|
|
1130
|
+
*/
|
|
1131
|
+
const getRenderedTextContent = (node) => {
|
|
1132
|
+
if (node.nodeType === Node.TEXT_NODE) {
|
|
1133
|
+
return node.textContent ?? '';
|
|
1134
|
+
}
|
|
1135
|
+
if (node.nodeType !== Node.ELEMENT_NODE) {
|
|
1136
|
+
return '';
|
|
1137
|
+
}
|
|
1138
|
+
if (index$2.blockedTags.includes(node.tagName.toLowerCase())) {
|
|
1139
|
+
return '';
|
|
1140
|
+
}
|
|
1141
|
+
return Array.from(node.childNodes)
|
|
1142
|
+
.map((child) => getRenderedTextContent(child))
|
|
1143
|
+
.join('');
|
|
1144
|
+
};
|
|
1132
1145
|
/**
|
|
1133
1146
|
* Extracts plain text from only the default slot of an option,
|
|
1134
|
-
* excluding content assigned to named slots (start/end).
|
|
1147
|
+
* excluding content assigned to named slots (start/end). Text is
|
|
1148
|
+
* concatenated with no separator and collapsible whitespace is
|
|
1149
|
+
* collapsed, approximating how the browser renders the option.
|
|
1150
|
+
* NBSP is not collapsible, so it is preserved.
|
|
1151
|
+
*
|
|
1152
|
+
* @param option - The `ion-select-option` element to read text from.
|
|
1153
|
+
* @returns The option's default slot text.
|
|
1135
1154
|
*/
|
|
1136
1155
|
const getDefaultSlotPlainText = (option) => {
|
|
1137
|
-
const
|
|
1138
|
-
|
|
1139
|
-
if (node.nodeType === Node.ELEMENT_NODE) {
|
|
1140
|
-
return !node.hasAttribute('slot');
|
|
1141
|
-
}
|
|
1142
|
-
return node.nodeType === Node.TEXT_NODE;
|
|
1143
|
-
})
|
|
1144
|
-
.filter((node) => node.nodeType === Node.TEXT_NODE)
|
|
1145
|
-
.map((n) => n.textContent?.trim())
|
|
1146
|
-
.filter((t) => t);
|
|
1147
|
-
return texts.join(' ');
|
|
1156
|
+
const text = (getOptionDefaultSlot(option) ?? []).map((node) => getRenderedTextContent(node)).join('');
|
|
1157
|
+
return text.replace(/[ \t\n\r\f]+/g, ' ').replace(/^[ \t\n\r\f]+|[ \t\n\r\f]+$/g, '');
|
|
1148
1158
|
};
|
|
1149
1159
|
/**
|
|
1150
1160
|
* Extracts the rich content from an `ion-select-option`.
|
|
@@ -8,7 +8,7 @@ var config = require('./config-CjUbvdPW.js');
|
|
|
8
8
|
var helpers = require('./helpers-Dj5o76mq.js');
|
|
9
9
|
var lockController = require('./lock-controller-aDB9wrEf.js');
|
|
10
10
|
var overlays = require('./overlays-Bg0auTQa.js');
|
|
11
|
-
var index$3 = require('./index-
|
|
11
|
+
var index$3 = require('./index-D4T0SA6Q.js');
|
|
12
12
|
var theme = require('./theme-Bw0rpaNN.js');
|
|
13
13
|
var ionicGlobal = require('./ionic-global-DvgIzM2F.js');
|
|
14
14
|
var animation = require('./animation-D-OqR4a4.js');
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
*/
|
|
4
4
|
import { Host, h } from "@stencil/core";
|
|
5
5
|
import { findClosestIonContent, disableContentScrollY, resetContentScrollY } from "../../utils/content/index";
|
|
6
|
-
import { isEndSide } from "../../utils/helpers";
|
|
6
|
+
import { componentOnReady, isEndSide } from "../../utils/helpers";
|
|
7
7
|
import { printIonWarning } from "../../utils/logging/index";
|
|
8
8
|
import { watchForOptions } from "../../utils/watch-options";
|
|
9
9
|
import { getIonMode } from "../../global/ionic-global";
|
|
@@ -178,19 +178,17 @@ export class ItemSliding {
|
|
|
178
178
|
}
|
|
179
179
|
}
|
|
180
180
|
async updateOptions() {
|
|
181
|
-
const options = this.el.querySelectorAll('ion-item-options');
|
|
181
|
+
const options = Array.from(this.el.querySelectorAll('ion-item-options'));
|
|
182
|
+
/**
|
|
183
|
+
* Frameworks that assign element props after inserting the element haven't set
|
|
184
|
+
* `side` while `connectedCallback` runs, so reading it any earlier reports every
|
|
185
|
+
* option as `end`.
|
|
186
|
+
*/
|
|
187
|
+
await Promise.all(options.map((option) => new Promise((resolve) => componentOnReady(option, resolve))));
|
|
182
188
|
let sides = 0;
|
|
183
189
|
// Reset left and right options in case they were removed
|
|
184
190
|
this.leftOptions = this.rightOptions = undefined;
|
|
185
|
-
for (
|
|
186
|
-
const item = options.item(i);
|
|
187
|
-
/**
|
|
188
|
-
* We cannot use the componentOnReady helper
|
|
189
|
-
* util here since we need to wait for all of these items
|
|
190
|
-
* to be ready before we set `this.sides` and `this.optsDirty`.
|
|
191
|
-
*/
|
|
192
|
-
// eslint-disable-next-line custom-rules/no-component-on-ready-method
|
|
193
|
-
const option = item.componentOnReady !== undefined ? await item.componentOnReady() : item;
|
|
191
|
+
for (const option of options) {
|
|
194
192
|
const side = isEndSide(option.side ?? option.getAttribute('side')) ? 'end' : 'start';
|
|
195
193
|
if (side === 'start') {
|
|
196
194
|
this.leftOptions = option;
|
|
@@ -389,7 +387,7 @@ export class ItemSliding {
|
|
|
389
387
|
}
|
|
390
388
|
render() {
|
|
391
389
|
const mode = getIonMode(this);
|
|
392
|
-
return (h(Host, { key: '
|
|
390
|
+
return (h(Host, { key: '02174ca963753d3a51a4249068f3d436f8acb03d', class: {
|
|
393
391
|
[mode]: true,
|
|
394
392
|
'item-sliding-active-slide': this.state !== 2 /* SlidingState.Disabled */,
|
|
395
393
|
'item-sliding-active-options-end': (this.state & 8 /* SlidingState.End */) !== 0,
|
|
@@ -378,11 +378,18 @@ export class Refresher {
|
|
|
378
378
|
componentDidUpdate() {
|
|
379
379
|
this.checkNativeRefresher();
|
|
380
380
|
}
|
|
381
|
-
|
|
381
|
+
/**
|
|
382
|
+
* Validate the slot attribute before rendering, while the host still reflects the
|
|
383
|
+
* developer's original markup. `connectedCallback` is too early: in the custom
|
|
384
|
+
* elements build it runs during insertion, before frameworks such as React assign
|
|
385
|
+
* the slot.
|
|
386
|
+
*/
|
|
387
|
+
componentWillLoad() {
|
|
382
388
|
if (this.el.getAttribute('slot') !== 'fixed') {
|
|
383
389
|
printIonError('[ion-refresher] - Make sure you use: <ion-refresher slot="fixed">');
|
|
384
|
-
return;
|
|
385
390
|
}
|
|
391
|
+
}
|
|
392
|
+
async connectedCallback() {
|
|
386
393
|
const contentEl = this.el.closest(ION_CONTENT_ELEMENT_SELECTOR);
|
|
387
394
|
if (!contentEl) {
|
|
388
395
|
printIonContentErrorMsg(this.el);
|
|
@@ -742,7 +749,7 @@ export class Refresher {
|
|
|
742
749
|
}
|
|
743
750
|
render() {
|
|
744
751
|
const mode = getIonMode(this);
|
|
745
|
-
return (h(Host, { key: '
|
|
752
|
+
return (h(Host, { key: 'fd9c8e51155d56f12148e8eb547e45c05807b4b5', slot: "fixed", class: {
|
|
746
753
|
[mode]: true,
|
|
747
754
|
// Used internally for styling
|
|
748
755
|
[`refresher-${mode}`]: true,
|
|
@@ -58,11 +58,6 @@ export class SegmentButton {
|
|
|
58
58
|
addEventListener(segmentEl, 'ionSelect', this.updateState);
|
|
59
59
|
addEventListener(segmentEl, 'ionStyle', this.updateStyle);
|
|
60
60
|
}
|
|
61
|
-
// Prevent buttons from being disabled when associated with segment content
|
|
62
|
-
if (this.contentId && this.disabled) {
|
|
63
|
-
printIonWarning(`[ion-segment-button] - Segment buttons cannot be disabled when associated with an <ion-segment-content>.`);
|
|
64
|
-
this.disabled = false;
|
|
65
|
-
}
|
|
66
61
|
}
|
|
67
62
|
disconnectedCallback() {
|
|
68
63
|
const segmentEl = this.segmentEl;
|
|
@@ -79,6 +74,15 @@ export class SegmentButton {
|
|
|
79
74
|
// Return if there is no contentId defined
|
|
80
75
|
if (!this.contentId)
|
|
81
76
|
return;
|
|
77
|
+
/**
|
|
78
|
+
* Checked here rather than in `connectedCallback` so frameworks that assign element
|
|
79
|
+
* props after inserting the element have set `disabled` by now. A disabled ion-segment
|
|
80
|
+
* pushes that onto its buttons too, which this guard should not undo.
|
|
81
|
+
*/
|
|
82
|
+
if (this.disabled && this.segmentEl?.disabled !== true) {
|
|
83
|
+
printIonWarning(`[ion-segment-button] - Segment buttons cannot be disabled when associated with an <ion-segment-content>.`);
|
|
84
|
+
this.disabled = false;
|
|
85
|
+
}
|
|
82
86
|
// Attempt to find the Segment Content by its contentId
|
|
83
87
|
const segmentContent = document.getElementById(this.contentId);
|
|
84
88
|
// If no associated Segment Content exists, log an error and return
|
|
@@ -113,7 +117,7 @@ export class SegmentButton {
|
|
|
113
117
|
const { checked, type, disabled, hasIcon, hasLabel, layout, segmentEl } = this;
|
|
114
118
|
const mode = getIonMode(this);
|
|
115
119
|
const hasSegmentColor = () => segmentEl?.color !== undefined;
|
|
116
|
-
return (h(Host, { key: '
|
|
120
|
+
return (h(Host, { key: 'd8acc71d87e26b32f20b2d0f9a6acc9f0dab0dee', class: {
|
|
117
121
|
[mode]: true,
|
|
118
122
|
'in-toolbar': hostContext('ion-toolbar', this.el),
|
|
119
123
|
'in-toolbar-color': hostContext('ion-toolbar[color]', this.el),
|
|
@@ -129,7 +133,7 @@ export class SegmentButton {
|
|
|
129
133
|
'ion-activatable': true,
|
|
130
134
|
'ion-activatable-instant': true,
|
|
131
135
|
'ion-focusable': true,
|
|
132
|
-
} }, h("button", { key: '
|
|
136
|
+
} }, h("button", { key: 'ce65da07b1a012bce353b3c6c24eecfbd4071d54', "aria-selected": checked ? 'true' : 'false', role: "tab", ref: (el) => (this.nativeEl = el), type: type, class: "button-native", part: "native", disabled: disabled, ...this.inheritedAttributes }, h("span", { key: '6c4b4dcd20e407e5dc31674bea23633d8a09187a', class: "button-inner" }, h("slot", { key: '817145ae77a3c5ada88ab95723d881f1bde96b2a' })), mode === 'md' && h("ion-ripple-effect", { key: '054d7e5e2a13013914fac6bbde8efdb28d9b459e' })), h("div", { key: 'c48074881a302510ad4752eeb9383222cd3a54cb', part: "indicator", class: "segment-button-indicator segment-button-indicator-animated" }, h("div", { key: '7672a6b10ee18ad026b798fbd8207dc3cd5683f9', part: "indicator-background", class: "segment-button-indicator-background" }))));
|
|
133
137
|
}
|
|
134
138
|
static get is() { return "ion-segment-button"; }
|
|
135
139
|
static get encapsulation() { return "shadow"; }
|
|
@@ -8,7 +8,7 @@ import { focusVisibleElement, renderHiddenInput, inheritAttributes } from "../..
|
|
|
8
8
|
import { printIonWarning } from "../../utils/logging/index";
|
|
9
9
|
import { actionSheetController, alertController, popoverController, modalController } from "../../utils/overlays";
|
|
10
10
|
import { isRTL } from "../../utils/rtl/index";
|
|
11
|
-
import { reflectPropertiesToAttributes, sanitizeDOMTree } from "../../utils/sanitization/index";
|
|
11
|
+
import { blockedTags, reflectPropertiesToAttributes, sanitizeDOMTree } from "../../utils/sanitization/index";
|
|
12
12
|
import { createSlotMutationController } from "../../utils/slot-mutation-controller";
|
|
13
13
|
import { createColorClasses, hostContext } from "../../utils/theme";
|
|
14
14
|
import { watchForOptions } from "../../utils/watch-options";
|
|
@@ -947,7 +947,7 @@ export class Select {
|
|
|
947
947
|
const hasOutlineFill = mode === 'md' && fill === 'outline';
|
|
948
948
|
renderHiddenInput(true, el, name, parseValue(value), disabled);
|
|
949
949
|
const labelShouldFloat = labelPlacement === 'stacked' || (labelPlacement === 'floating' && (hasValue || hasFocus || isExpanded));
|
|
950
|
-
return (h(Host, { key: '
|
|
950
|
+
return (h(Host, { key: 'b2f161e3706e139e61440cd13e162714b1b75d72', onClick: this.onClick, class: createColorClasses(this.color, {
|
|
951
951
|
[mode]: true,
|
|
952
952
|
'in-item': inItem,
|
|
953
953
|
'in-item-color': hostContext('ion-item.ion-color', el),
|
|
@@ -965,7 +965,7 @@ export class Select {
|
|
|
965
965
|
[`select-justify-${justify}`]: justifyEnabled,
|
|
966
966
|
[`select-shape-${shape}`]: shape !== undefined,
|
|
967
967
|
[`select-label-placement-${labelPlacement}`]: true,
|
|
968
|
-
}) }, h("label", { key: '
|
|
968
|
+
}) }, h("label", { key: '944a2eb468154a21260d181fdaf67828a71eb902', class: "select-wrapper", id: "select-label", onClick: this.onLabelClick, part: "wrapper" }, hasOutlineFill && this.renderOutlineContainer(), h("div", { key: '927200c53548b1bb4f52d6a167605b724a7b7d0d', class: "select-start", part: "start", ref: (el) => (this.startContainerEl = el) }, h("slot", { key: '6e14b95e9b95c116b16744d630600e90977782bc', name: "start" })), h("div", { key: '8451ed4300ac005963075be36a04ea8763bc0fdd', class: "select-control", part: "control" }, this.renderLabel(), h("div", { key: '207e7b63f3224a4870579365ac992da6784fb31f', class: "native-wrapper", ref: (el) => (this.nativeWrapperEl = el), part: "container" }, this.renderSelectText(), this.renderListbox(), !hasFloatingOrStackedLabel && this.renderSelectIcon())), h("div", { key: '5c17367d488db4d570f31b25e33560efa9011500', class: "select-end", part: "end" }, hasFloatingOrStackedLabel && this.renderSelectIcon(), h("slot", { key: '21fd8c0d9bee8cffef9ef6984cacd31e8f38211c', name: "end" })), shouldRenderHighlight && h("div", { key: '1fff767db9a1ec07b274ef65ff7ae8fb976e6ad2', class: "select-highlight" })), this.renderBottomContent()));
|
|
969
969
|
}
|
|
970
970
|
static get is() { return "ion-select"; }
|
|
971
971
|
static get encapsulation() { return "shadow"; }
|
|
@@ -1663,29 +1663,14 @@ const textForValue = (opts, value, compareWith, useHTML = false) => {
|
|
|
1663
1663
|
return getOptionContent(selectOpt, undefined, true);
|
|
1664
1664
|
}
|
|
1665
1665
|
/**
|
|
1666
|
-
*
|
|
1667
|
-
*
|
|
1668
|
-
* the
|
|
1666
|
+
* Every text-only context reads only the default slot, so the start
|
|
1667
|
+
* and end slots stay out of the `aria-label` and the overlay labels.
|
|
1668
|
+
* Both config paths derive that text through the same helper, so they
|
|
1669
|
+
* cannot disagree about what an option's text is. `null` marks an
|
|
1670
|
+
* option with no text, which is dropped from the joined text of a
|
|
1671
|
+
* `multiple` select rather than joined in as an empty entry.
|
|
1669
1672
|
*/
|
|
1670
|
-
|
|
1671
|
-
const content = getOptionContent(selectOpt);
|
|
1672
|
-
if (typeof content === 'string') {
|
|
1673
|
-
return content;
|
|
1674
|
-
}
|
|
1675
|
-
/**
|
|
1676
|
-
* Elements were found in the default slot, extract and concatenate
|
|
1677
|
-
* their text content while trimming whitespace.
|
|
1678
|
-
*/
|
|
1679
|
-
if (content) {
|
|
1680
|
-
const texts = Array.from(content.childNodes)
|
|
1681
|
-
.map((n) => n.textContent?.trim())
|
|
1682
|
-
.filter((t) => t);
|
|
1683
|
-
return texts.join(' ') || null;
|
|
1684
|
-
}
|
|
1685
|
-
// Empty option
|
|
1686
|
-
return null;
|
|
1687
|
-
}
|
|
1688
|
-
return getDefaultSlotPlainText(selectOpt);
|
|
1673
|
+
return getDefaultSlotPlainText(selectOpt) || null;
|
|
1689
1674
|
};
|
|
1690
1675
|
/**
|
|
1691
1676
|
* Trims whitespace from all text nodes within a DOM tree.
|
|
@@ -1741,9 +1726,13 @@ const getOptionContent = (option, slotName, useHTML = false) => {
|
|
|
1741
1726
|
if (nodes.length === 0) {
|
|
1742
1727
|
return null;
|
|
1743
1728
|
}
|
|
1744
|
-
|
|
1729
|
+
/**
|
|
1730
|
+
* Return plain text if no elements are found. This reads the option the
|
|
1731
|
+
* same way the non-custom-HTML path does, so the two do not disagree
|
|
1732
|
+
* about what an option's text is.
|
|
1733
|
+
*/
|
|
1745
1734
|
if (!slotName && nodes.every((n) => n.nodeType === Node.TEXT_NODE)) {
|
|
1746
|
-
return
|
|
1735
|
+
return getDefaultSlotPlainText(option) || null;
|
|
1747
1736
|
}
|
|
1748
1737
|
/**
|
|
1749
1738
|
* Mirror known custom-element properties (e.g. ion-icon's `icon`)
|
|
@@ -1799,22 +1788,43 @@ const getOptionDefaultSlot = (option) => {
|
|
|
1799
1788
|
}
|
|
1800
1789
|
return defaultSlotNodes;
|
|
1801
1790
|
};
|
|
1791
|
+
/**
|
|
1792
|
+
* Concatenates the text a node renders, skipping the subtrees of tags
|
|
1793
|
+
* whose contents the browser never paints (`script`, `style`, and the
|
|
1794
|
+
* rest of `blockedTags`). `textContent` includes those, so reading it
|
|
1795
|
+
* directly would put stylesheet or script source into the select text
|
|
1796
|
+
* and the `aria-label`.
|
|
1797
|
+
*
|
|
1798
|
+
* @param node - The node to read text from.
|
|
1799
|
+
* @returns The node's rendered text.
|
|
1800
|
+
*/
|
|
1801
|
+
const getRenderedTextContent = (node) => {
|
|
1802
|
+
if (node.nodeType === Node.TEXT_NODE) {
|
|
1803
|
+
return node.textContent ?? '';
|
|
1804
|
+
}
|
|
1805
|
+
if (node.nodeType !== Node.ELEMENT_NODE) {
|
|
1806
|
+
return '';
|
|
1807
|
+
}
|
|
1808
|
+
if (blockedTags.includes(node.tagName.toLowerCase())) {
|
|
1809
|
+
return '';
|
|
1810
|
+
}
|
|
1811
|
+
return Array.from(node.childNodes)
|
|
1812
|
+
.map((child) => getRenderedTextContent(child))
|
|
1813
|
+
.join('');
|
|
1814
|
+
};
|
|
1802
1815
|
/**
|
|
1803
1816
|
* Extracts plain text from only the default slot of an option,
|
|
1804
|
-
* excluding content assigned to named slots (start/end).
|
|
1817
|
+
* excluding content assigned to named slots (start/end). Text is
|
|
1818
|
+
* concatenated with no separator and collapsible whitespace is
|
|
1819
|
+
* collapsed, approximating how the browser renders the option.
|
|
1820
|
+
* NBSP is not collapsible, so it is preserved.
|
|
1821
|
+
*
|
|
1822
|
+
* @param option - The `ion-select-option` element to read text from.
|
|
1823
|
+
* @returns The option's default slot text.
|
|
1805
1824
|
*/
|
|
1806
1825
|
const getDefaultSlotPlainText = (option) => {
|
|
1807
|
-
const
|
|
1808
|
-
|
|
1809
|
-
if (node.nodeType === Node.ELEMENT_NODE) {
|
|
1810
|
-
return !node.hasAttribute('slot');
|
|
1811
|
-
}
|
|
1812
|
-
return node.nodeType === Node.TEXT_NODE;
|
|
1813
|
-
})
|
|
1814
|
-
.filter((node) => node.nodeType === Node.TEXT_NODE)
|
|
1815
|
-
.map((n) => n.textContent?.trim())
|
|
1816
|
-
.filter((t) => t);
|
|
1817
|
-
return texts.join(' ');
|
|
1826
|
+
const text = (getOptionDefaultSlot(option) ?? []).map((node) => getRenderedTextContent(node)).join('');
|
|
1827
|
+
return text.replace(/[ \t\n\r\f]+/g, ' ').replace(/^[ \t\n\r\f]+|[ \t\n\r\f]+$/g, '');
|
|
1818
1828
|
};
|
|
1819
1829
|
/**
|
|
1820
1830
|
* Extracts the rich content from an `ion-select-option`.
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Test helpers for the custom elements build, where `connectedCallback` runs
|
|
3
|
+
* synchronously as the element is inserted. Frameworks that assign element props after
|
|
4
|
+
* inserting the element leave a window where a component can't read its own props or
|
|
5
|
+
* its children's, and it still has to work.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import { initialize } from '/components/index.js';
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Initializes Ionic in the mode the test asked for.
|
|
12
|
+
*/
|
|
13
|
+
export const initializeIonic = () => {
|
|
14
|
+
initialize({ mode: new URLSearchParams(location.search).get('ionic:mode') ?? 'ios' });
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Defines the given tags. Safe to call again for tags that are already defined, so each
|
|
19
|
+
* test can ask for whatever it needs.
|
|
20
|
+
*/
|
|
21
|
+
export const defineTags = async (tags) => {
|
|
22
|
+
await Promise.all(
|
|
23
|
+
tags.map(async (tag) => {
|
|
24
|
+
const mod = await import(`/components/${tag}.js`);
|
|
25
|
+
mod.defineCustomElement();
|
|
26
|
+
})
|
|
27
|
+
);
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Builds the tree described by `spec` and appends it to `root`. A spec node is
|
|
32
|
+
* `{ tag, props, attrs, children }`, where `children` holds specs or strings. The
|
|
33
|
+
* `attrs` are always set before the element connects, and the `props` are set before
|
|
34
|
+
* connecting when `lateProps` is false, or after the whole tree connects when it is true.
|
|
35
|
+
*/
|
|
36
|
+
export const mount = (root, spec, lateProps) => {
|
|
37
|
+
const pending = [];
|
|
38
|
+
|
|
39
|
+
const build = (node) => {
|
|
40
|
+
if (typeof node === 'string') {
|
|
41
|
+
return document.createTextNode(node);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
const el = document.createElement(node.tag);
|
|
45
|
+
|
|
46
|
+
if (node.attrs) {
|
|
47
|
+
Object.entries(node.attrs).forEach(([key, value]) => el.setAttribute(key, String(value)));
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
if (node.props) {
|
|
51
|
+
if (lateProps) {
|
|
52
|
+
pending.push([el, node.props]);
|
|
53
|
+
} else {
|
|
54
|
+
Object.assign(el, node.props);
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
(node.children || []).forEach((child) => el.appendChild(build(child)));
|
|
59
|
+
|
|
60
|
+
return el;
|
|
61
|
+
};
|
|
62
|
+
|
|
63
|
+
const tree = build(spec);
|
|
64
|
+
|
|
65
|
+
root.appendChild(tree);
|
|
66
|
+
|
|
67
|
+
// Descendants before ancestors, matching the order framework effects run in.
|
|
68
|
+
pending.reverse().forEach(([el, props]) => Object.assign(el, props));
|
|
69
|
+
};
|
package/dist/docs.json
CHANGED
|
@@ -420,4 +420,4 @@ class IonicSafeString {
|
|
|
420
420
|
}
|
|
421
421
|
}
|
|
422
422
|
|
|
423
|
-
export { IonicSafeString as I, sanitizeDOMTree as a, reflectPropertiesToAttributes as r, sanitizeDOMString as s };
|
|
423
|
+
export { IonicSafeString as I, sanitizeDOMTree as a, blockedTags as b, reflectPropertiesToAttributes as r, sanitizeDOMString as s };
|
package/dist/esm/index.js
CHANGED
|
@@ -10,7 +10,7 @@ export { createGesture } from './index-BmLuEdV7.js';
|
|
|
10
10
|
export { g as getPlatforms, i as initialize, a as isPlatform } from './ionic-global-lrowsHfi.js';
|
|
11
11
|
export { c as componentOnReady } from './helpers-BIgoInJU.js';
|
|
12
12
|
export { L as LogLevel } from './index-CKYcsw8f.js';
|
|
13
|
-
export { I as IonicSafeString } from './index-
|
|
13
|
+
export { I as IonicSafeString } from './index-D3o-MD4_.js';
|
|
14
14
|
export { g as getMode, s as setupConfig } from './config-DWCzVL3Y.js';
|
|
15
15
|
export { o as openURL } from './theme-byZM6qHV.js';
|
|
16
16
|
export { m as menuController } from './index-C5ZdL0qp.js';
|