voyager-ionic-core 8.7.9 → 8.7.11
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/checkbox.js +63 -9
- package/components/ion-datetime.js +35 -2
- package/components/ion-input.js +2 -1
- package/components/ion-select.js +7 -6
- package/components/ion-textarea.js +2 -1
- package/components/ion-toggle.js +62 -12
- package/components/notch-controller.js +153 -0
- package/components/radio-group.js +60 -7
- package/components/validity.js +1 -150
- package/dist/cjs/ion-checkbox.cjs.entry.js +60 -8
- package/dist/cjs/ion-datetime_3.cjs.entry.js +35 -2
- package/dist/cjs/ion-input.cjs.entry.js +3 -2
- package/dist/cjs/ion-radio_2.cjs.entry.js +57 -6
- package/dist/cjs/ion-select_3.cjs.entry.js +7 -6
- package/dist/cjs/ion-textarea.cjs.entry.js +3 -2
- package/dist/cjs/ion-toggle.cjs.entry.js +58 -10
- package/dist/cjs/ionic.cjs.js +1 -1
- package/dist/cjs/loader.cjs.js +1 -1
- package/dist/cjs/{validity-C8QoAYT2.js → notch-controller-Bzqhjm4f.js} +0 -14
- package/dist/cjs/validity-BpS37YFM.js +19 -0
- package/dist/collection/components/checkbox/checkbox.js +67 -9
- package/dist/collection/components/datetime/datetime.js +35 -2
- package/dist/collection/components/radio-group/radio-group.js +64 -7
- package/dist/collection/components/select/select.js +5 -5
- package/dist/collection/components/toggle/toggle.js +62 -12
- package/dist/collection/utils/test/playwright/page/utils/set-content.js +7 -0
- package/dist/docs.json +1 -1
- package/dist/esm/ion-checkbox.entry.js +60 -8
- package/dist/esm/ion-datetime_3.entry.js +35 -2
- package/dist/esm/ion-input.entry.js +2 -1
- package/dist/esm/ion-radio_2.entry.js +57 -6
- package/dist/esm/ion-select_3.entry.js +6 -5
- package/dist/esm/ion-textarea.entry.js +2 -1
- package/dist/esm/ion-toggle.entry.js +58 -10
- package/dist/esm/ionic.js +1 -1
- package/dist/esm/loader.js +1 -1
- package/dist/esm/{validity-B8oWougr.js → notch-controller-BwelN_JM.js} +1 -14
- package/dist/esm/validity-DJztqcrH.js +17 -0
- package/dist/ionic/ionic.esm.js +1 -1
- package/dist/ionic/p-40c261a3.entry.js +4 -0
- package/dist/ionic/p-4e41ea20.entry.js +4 -0
- package/dist/ionic/p-7380261c.entry.js +4 -0
- package/dist/ionic/{p-DieJyvMP.js → p-DCv9sLH2.js} +1 -1
- package/dist/ionic/p-DJztqcrH.js +4 -0
- package/dist/ionic/p-c19f63d0.entry.js +4 -0
- package/dist/ionic/p-cb93126d.entry.js +4 -0
- package/dist/ionic/p-d1f54e28.entry.js +4 -0
- package/dist/ionic/p-d3014190.entry.js +4 -0
- package/dist/types/components/checkbox/checkbox.d.ts +9 -1
- package/dist/types/components/datetime/datetime.d.ts +10 -0
- package/dist/types/components/radio-group/radio-group.d.ts +9 -1
- package/dist/types/components/select/select.d.ts +2 -2
- package/dist/types/components/toggle/toggle.d.ts +7 -1
- package/dist/types/utils/forms/validity.d.ts +1 -1
- package/hydrate/index.js +312 -227
- package/hydrate/index.mjs +312 -227
- package/package.json +2 -2
- package/dist/ionic/p-4cc26913.entry.js +0 -4
- package/dist/ionic/p-4efea47a.entry.js +0 -4
- package/dist/ionic/p-7bcfc421.entry.js +0 -4
- package/dist/ionic/p-8bdfc8f6.entry.js +0 -4
- package/dist/ionic/p-dc2e126d.entry.js +0 -4
- package/dist/ionic/p-f65f9308.entry.js +0 -4
- package/dist/ionic/p-fc278823.entry.js +0 -4
package/hydrate/index.js
CHANGED
|
@@ -9685,6 +9685,202 @@ class CardTitle {
|
|
|
9685
9685
|
}; }
|
|
9686
9686
|
}
|
|
9687
9687
|
|
|
9688
|
+
/**
|
|
9689
|
+
* A utility to calculate the size of an outline notch
|
|
9690
|
+
* width relative to the content passed. This is used in
|
|
9691
|
+
* components such as `ion-select` with `fill="outline"`
|
|
9692
|
+
* where we need to pass slotted HTML content. This is not
|
|
9693
|
+
* needed when rendering plaintext content because we can
|
|
9694
|
+
* render the plaintext again hidden with `opacity: 0` inside
|
|
9695
|
+
* of the notch. As a result we can rely on the intrinsic size
|
|
9696
|
+
* of the element to correctly compute the notch width. We
|
|
9697
|
+
* cannot do this with slotted content because we cannot project
|
|
9698
|
+
* it into 2 places at once.
|
|
9699
|
+
*
|
|
9700
|
+
* @internal
|
|
9701
|
+
* @param el: The host element
|
|
9702
|
+
* @param getNotchSpacerEl: A function that returns a reference to the notch spacer element inside of the component template.
|
|
9703
|
+
* @param getLabelSlot: A function that returns a reference to the slotted content.
|
|
9704
|
+
*/
|
|
9705
|
+
const createNotchController = (el, getNotchSpacerEl, getLabelSlot) => {
|
|
9706
|
+
let notchVisibilityIO;
|
|
9707
|
+
const needsExplicitNotchWidth = () => {
|
|
9708
|
+
const notchSpacerEl = getNotchSpacerEl();
|
|
9709
|
+
if (
|
|
9710
|
+
/**
|
|
9711
|
+
* If the notch is not being used
|
|
9712
|
+
* then we do not need to set the notch width.
|
|
9713
|
+
*/
|
|
9714
|
+
notchSpacerEl === undefined ||
|
|
9715
|
+
/**
|
|
9716
|
+
* If either the label property is being
|
|
9717
|
+
* used or the label slot is not defined,
|
|
9718
|
+
* then we do not need to estimate the notch width.
|
|
9719
|
+
*/
|
|
9720
|
+
el.label !== undefined ||
|
|
9721
|
+
getLabelSlot() === null) {
|
|
9722
|
+
return false;
|
|
9723
|
+
}
|
|
9724
|
+
return true;
|
|
9725
|
+
};
|
|
9726
|
+
const calculateNotchWidth = () => {
|
|
9727
|
+
if (needsExplicitNotchWidth()) {
|
|
9728
|
+
/**
|
|
9729
|
+
* Run this the frame after
|
|
9730
|
+
* the browser has re-painted the host element.
|
|
9731
|
+
* Otherwise, the label element may have a width
|
|
9732
|
+
* of 0 and the IntersectionObserver will be used.
|
|
9733
|
+
*/
|
|
9734
|
+
raf(() => {
|
|
9735
|
+
setNotchWidth();
|
|
9736
|
+
});
|
|
9737
|
+
}
|
|
9738
|
+
};
|
|
9739
|
+
/**
|
|
9740
|
+
* When using a label prop we can render
|
|
9741
|
+
* the label value inside of the notch and
|
|
9742
|
+
* let the browser calculate the size of the notch.
|
|
9743
|
+
* However, we cannot render the label slot in multiple
|
|
9744
|
+
* places so we need to manually calculate the notch dimension
|
|
9745
|
+
* based on the size of the slotted content.
|
|
9746
|
+
*
|
|
9747
|
+
* This function should only be used to set the notch width
|
|
9748
|
+
* on slotted label content. The notch width for label prop
|
|
9749
|
+
* content is automatically calculated based on the
|
|
9750
|
+
* intrinsic size of the label text.
|
|
9751
|
+
*/
|
|
9752
|
+
const setNotchWidth = () => {
|
|
9753
|
+
const notchSpacerEl = getNotchSpacerEl();
|
|
9754
|
+
if (notchSpacerEl === undefined) {
|
|
9755
|
+
return;
|
|
9756
|
+
}
|
|
9757
|
+
if (!needsExplicitNotchWidth()) {
|
|
9758
|
+
notchSpacerEl.style.removeProperty('width');
|
|
9759
|
+
return;
|
|
9760
|
+
}
|
|
9761
|
+
const width = getLabelSlot().scrollWidth;
|
|
9762
|
+
if (
|
|
9763
|
+
/**
|
|
9764
|
+
* If the computed width of the label is 0
|
|
9765
|
+
* and notchSpacerEl's offsetParent is null
|
|
9766
|
+
* then that means the element is hidden.
|
|
9767
|
+
* As a result, we need to wait for the element
|
|
9768
|
+
* to become visible before setting the notch width.
|
|
9769
|
+
*
|
|
9770
|
+
* We do not check el.offsetParent because
|
|
9771
|
+
* that can be null if the host element has
|
|
9772
|
+
* position: fixed applied to it.
|
|
9773
|
+
* notchSpacerEl does not have position: fixed.
|
|
9774
|
+
*/
|
|
9775
|
+
width === 0 &&
|
|
9776
|
+
notchSpacerEl.offsetParent === null &&
|
|
9777
|
+
win$1 !== undefined &&
|
|
9778
|
+
'IntersectionObserver' in win$1) {
|
|
9779
|
+
/**
|
|
9780
|
+
* If there is an IO already attached
|
|
9781
|
+
* then that will update the notch
|
|
9782
|
+
* once the element becomes visible.
|
|
9783
|
+
* As a result, there is no need to create
|
|
9784
|
+
* another one.
|
|
9785
|
+
*/
|
|
9786
|
+
if (notchVisibilityIO !== undefined) {
|
|
9787
|
+
return;
|
|
9788
|
+
}
|
|
9789
|
+
const io = (notchVisibilityIO = new IntersectionObserver((ev) => {
|
|
9790
|
+
/**
|
|
9791
|
+
* If the element is visible then we
|
|
9792
|
+
* can try setting the notch width again.
|
|
9793
|
+
*/
|
|
9794
|
+
if (ev[0].intersectionRatio === 1) {
|
|
9795
|
+
setNotchWidth();
|
|
9796
|
+
io.disconnect();
|
|
9797
|
+
notchVisibilityIO = undefined;
|
|
9798
|
+
}
|
|
9799
|
+
},
|
|
9800
|
+
/**
|
|
9801
|
+
* Set the root to be the host element
|
|
9802
|
+
* This causes the IO callback
|
|
9803
|
+
* to be fired in WebKit as soon as the element
|
|
9804
|
+
* is visible. If we used the default root value
|
|
9805
|
+
* then WebKit would only fire the IO callback
|
|
9806
|
+
* after any animations (such as a modal transition)
|
|
9807
|
+
* finished, and there would potentially be a flicker.
|
|
9808
|
+
*/
|
|
9809
|
+
{ threshold: 0.01, root: el }));
|
|
9810
|
+
io.observe(notchSpacerEl);
|
|
9811
|
+
return;
|
|
9812
|
+
}
|
|
9813
|
+
/**
|
|
9814
|
+
* If the element is visible then we can set the notch width.
|
|
9815
|
+
* The notch is only visible when the label is scaled,
|
|
9816
|
+
* which is why we multiply the width by 0.75 as this is
|
|
9817
|
+
* the same amount the label element is scaled by in the host CSS.
|
|
9818
|
+
* (See $form-control-label-stacked-scale in ionic.globals.scss).
|
|
9819
|
+
*/
|
|
9820
|
+
notchSpacerEl.style.setProperty('width', `${width * 0.75}px`);
|
|
9821
|
+
};
|
|
9822
|
+
const destroy = () => {
|
|
9823
|
+
if (notchVisibilityIO) {
|
|
9824
|
+
notchVisibilityIO.disconnect();
|
|
9825
|
+
notchVisibilityIO = undefined;
|
|
9826
|
+
}
|
|
9827
|
+
};
|
|
9828
|
+
return {
|
|
9829
|
+
calculateNotchWidth,
|
|
9830
|
+
destroy,
|
|
9831
|
+
};
|
|
9832
|
+
};
|
|
9833
|
+
|
|
9834
|
+
/**
|
|
9835
|
+
* Uses the compareWith param to compare two values to determine if they are equal.
|
|
9836
|
+
*
|
|
9837
|
+
* @param currentValue The current value of the control.
|
|
9838
|
+
* @param compareValue The value to compare against.
|
|
9839
|
+
* @param compareWith The function or property name to use to compare values.
|
|
9840
|
+
*/
|
|
9841
|
+
const compareOptions = (currentValue, compareValue, compareWith) => {
|
|
9842
|
+
if (typeof compareWith === 'function') {
|
|
9843
|
+
return compareWith(currentValue, compareValue);
|
|
9844
|
+
}
|
|
9845
|
+
else if (typeof compareWith === 'string') {
|
|
9846
|
+
return currentValue[compareWith] === compareValue[compareWith];
|
|
9847
|
+
}
|
|
9848
|
+
else {
|
|
9849
|
+
return Array.isArray(compareValue) ? compareValue.includes(currentValue) : currentValue === compareValue;
|
|
9850
|
+
}
|
|
9851
|
+
};
|
|
9852
|
+
/**
|
|
9853
|
+
* Compares a value against the current value(s) to determine if it is selected.
|
|
9854
|
+
*
|
|
9855
|
+
* @param currentValue The current value of the control.
|
|
9856
|
+
* @param compareValue The value to compare against.
|
|
9857
|
+
* @param compareWith The function or property name to use to compare values.
|
|
9858
|
+
*/
|
|
9859
|
+
const isOptionSelected = (currentValue, compareValue, compareWith) => {
|
|
9860
|
+
if (currentValue === undefined) {
|
|
9861
|
+
return false;
|
|
9862
|
+
}
|
|
9863
|
+
if (Array.isArray(currentValue)) {
|
|
9864
|
+
return currentValue.some((val) => compareOptions(val, compareValue, compareWith));
|
|
9865
|
+
}
|
|
9866
|
+
else {
|
|
9867
|
+
return compareOptions(currentValue, compareValue, compareWith);
|
|
9868
|
+
}
|
|
9869
|
+
};
|
|
9870
|
+
|
|
9871
|
+
/**
|
|
9872
|
+
* Checks if the form element is in an invalid state based on
|
|
9873
|
+
* Ionic validation classes.
|
|
9874
|
+
*
|
|
9875
|
+
* @param el The form element to check.
|
|
9876
|
+
* @returns `true` if the element is invalid, `false` otherwise.
|
|
9877
|
+
*/
|
|
9878
|
+
const checkInvalidState = (el) => {
|
|
9879
|
+
const hasIonTouched = el.classList.contains('ion-touched');
|
|
9880
|
+
const hasIonInvalid = el.classList.contains('ion-invalid');
|
|
9881
|
+
return hasIonTouched && hasIonInvalid;
|
|
9882
|
+
};
|
|
9883
|
+
|
|
9688
9884
|
const checkboxIosCss = ":host{--checkbox-background-checked:var(--ion-color-primary, #0054e9);--border-color-checked:var(--ion-color-primary, #0054e9);--checkmark-color:var(--ion-color-primary-contrast, #fff);--transition:none;display:inline-block;position:relative;cursor:pointer;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;z-index:2}:host(.in-item){-ms-flex:1 1 0px;flex:1 1 0;width:100%;height:100%}:host([slot=start]),:host([slot=end]){-ms-flex:initial;flex:initial;width:auto}:host(.ion-color){--checkbox-background-checked:var(--ion-color-base);--border-color-checked:var(--ion-color-base);--checkmark-color:var(--ion-color-contrast)}.checkbox-wrapper{display:-ms-flexbox;display:flex;-ms-flex-positive:1;flex-grow:1;-ms-flex-align:center;align-items:center;-ms-flex-pack:justify;justify-content:space-between;height:inherit;cursor:inherit}.label-text-wrapper{text-overflow:ellipsis;white-space:nowrap;overflow:hidden}:host(.in-item) .label-text-wrapper,:host(.in-item:not(.checkbox-label-placement-stacked):not([slot])) .native-wrapper{margin-top:10px;margin-bottom:10px}:host(.in-item.checkbox-label-placement-stacked) .label-text-wrapper{margin-top:10px;margin-bottom:16px}:host(.in-item.checkbox-label-placement-stacked) .native-wrapper{margin-bottom:10px}.label-text-wrapper-hidden{display:none}input{display:none}.native-wrapper{display:-ms-flexbox;display:flex;-ms-flex-align:center;align-items:center}.checkbox-icon{border-radius:var(--border-radius);position:relative;width:var(--size);height:var(--size);-webkit-transition:var(--transition);transition:var(--transition);border-width:var(--border-width);border-style:var(--border-style);border-color:var(--border-color);background:var(--checkbox-background);-webkit-box-sizing:border-box;box-sizing:border-box}.checkbox-icon path{fill:none;stroke:var(--checkmark-color);stroke-width:var(--checkmark-width);opacity:0}.checkbox-bottom{padding-top:4px;display:-ms-flexbox;display:flex;-ms-flex-pack:justify;justify-content:space-between;font-size:0.75rem;white-space:normal}:host(.checkbox-label-placement-stacked) .checkbox-bottom{font-size:1rem}.checkbox-bottom .error-text{display:none;color:var(--ion-color-danger, #c5000f)}.checkbox-bottom .helper-text{display:block;color:var(--ion-color-step-700, var(--ion-text-color-step-300, #4d4d4d))}:host(.ion-touched.ion-invalid) .checkbox-bottom .error-text{display:block}:host(.ion-touched.ion-invalid) .checkbox-bottom .helper-text{display:none}:host(.checkbox-label-placement-start) .checkbox-wrapper{-ms-flex-direction:row;flex-direction:row}:host(.checkbox-label-placement-start) .label-text-wrapper{-webkit-margin-start:0;margin-inline-start:0;-webkit-margin-end:16px;margin-inline-end:16px}:host(.checkbox-label-placement-end) .checkbox-wrapper{-ms-flex-direction:row-reverse;flex-direction:row-reverse;-ms-flex-pack:start;justify-content:start}:host(.checkbox-label-placement-end) .label-text-wrapper{-webkit-margin-start:16px;margin-inline-start:16px;-webkit-margin-end:0;margin-inline-end:0}:host(.checkbox-label-placement-fixed) .label-text-wrapper{-webkit-margin-start:0;margin-inline-start:0;-webkit-margin-end:16px;margin-inline-end:16px}:host(.checkbox-label-placement-fixed) .label-text-wrapper{-ms-flex:0 0 100px;flex:0 0 100px;width:100px;min-width:100px;max-width:200px}:host(.checkbox-label-placement-stacked) .checkbox-wrapper{-ms-flex-direction:column;flex-direction:column;text-align:center}:host(.checkbox-label-placement-stacked) .label-text-wrapper{-webkit-transform:scale(0.75);transform:scale(0.75);margin-left:0;margin-right:0;margin-bottom:16px;max-width:calc(100% / 0.75)}:host(.checkbox-label-placement-stacked.checkbox-alignment-start) .label-text-wrapper{-webkit-transform-origin:left top;transform-origin:left top}:host-context([dir=rtl]):host(.checkbox-label-placement-stacked.checkbox-alignment-start) .label-text-wrapper,:host-context([dir=rtl]).checkbox-label-placement-stacked.checkbox-alignment-start .label-text-wrapper{-webkit-transform-origin:right top;transform-origin:right top}@supports selector(:dir(rtl)){:host(.checkbox-label-placement-stacked.checkbox-alignment-start:dir(rtl)) .label-text-wrapper{-webkit-transform-origin:right top;transform-origin:right top}}:host(.checkbox-label-placement-stacked.checkbox-alignment-center) .label-text-wrapper{-webkit-transform-origin:center top;transform-origin:center top}:host-context([dir=rtl]):host(.checkbox-label-placement-stacked.checkbox-alignment-center) .label-text-wrapper,:host-context([dir=rtl]).checkbox-label-placement-stacked.checkbox-alignment-center .label-text-wrapper{-webkit-transform-origin:calc(100% - center) top;transform-origin:calc(100% - center) top}@supports selector(:dir(rtl)){:host(.checkbox-label-placement-stacked.checkbox-alignment-center:dir(rtl)) .label-text-wrapper{-webkit-transform-origin:calc(100% - center) top;transform-origin:calc(100% - center) top}}:host(.checkbox-justify-space-between) .checkbox-wrapper{-ms-flex-pack:justify;justify-content:space-between}:host(.checkbox-justify-start) .checkbox-wrapper{-ms-flex-pack:start;justify-content:start}:host(.checkbox-justify-end) .checkbox-wrapper{-ms-flex-pack:end;justify-content:end}:host(.checkbox-alignment-start) .checkbox-wrapper{-ms-flex-align:start;align-items:start}:host(.checkbox-alignment-center) .checkbox-wrapper{-ms-flex-align:center;align-items:center}:host(.checkbox-justify-space-between),:host(.checkbox-justify-start),:host(.checkbox-justify-end),:host(.checkbox-alignment-start),:host(.checkbox-alignment-center){display:block}:host(.checkbox-checked) .checkbox-icon,:host(.checkbox-indeterminate) .checkbox-icon{border-color:var(--border-color-checked);background:var(--checkbox-background-checked)}:host(.checkbox-checked) .checkbox-icon path,:host(.checkbox-indeterminate) .checkbox-icon path{opacity:1}:host(.checkbox-disabled){pointer-events:none}:host{--border-radius:50%;--border-width:0.125rem;--border-style:solid;--border-color:rgba(var(--ion-text-color-rgb, 0, 0, 0), 0.23);--checkbox-background:var(--ion-item-background, var(--ion-background-color, #fff));--size:min(1.375rem, 55.836px);--checkmark-width:1.5px}:host(.checkbox-disabled){opacity:0.3}";
|
|
9689
9885
|
|
|
9690
9886
|
const checkboxMdCss = ":host{--checkbox-background-checked:var(--ion-color-primary, #0054e9);--border-color-checked:var(--ion-color-primary, #0054e9);--checkmark-color:var(--ion-color-primary-contrast, #fff);--transition:none;display:inline-block;position:relative;cursor:pointer;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;z-index:2}:host(.in-item){-ms-flex:1 1 0px;flex:1 1 0;width:100%;height:100%}:host([slot=start]),:host([slot=end]){-ms-flex:initial;flex:initial;width:auto}:host(.ion-color){--checkbox-background-checked:var(--ion-color-base);--border-color-checked:var(--ion-color-base);--checkmark-color:var(--ion-color-contrast)}.checkbox-wrapper{display:-ms-flexbox;display:flex;-ms-flex-positive:1;flex-grow:1;-ms-flex-align:center;align-items:center;-ms-flex-pack:justify;justify-content:space-between;height:inherit;cursor:inherit}.label-text-wrapper{text-overflow:ellipsis;white-space:nowrap;overflow:hidden}:host(.in-item) .label-text-wrapper,:host(.in-item:not(.checkbox-label-placement-stacked):not([slot])) .native-wrapper{margin-top:10px;margin-bottom:10px}:host(.in-item.checkbox-label-placement-stacked) .label-text-wrapper{margin-top:10px;margin-bottom:16px}:host(.in-item.checkbox-label-placement-stacked) .native-wrapper{margin-bottom:10px}.label-text-wrapper-hidden{display:none}input{display:none}.native-wrapper{display:-ms-flexbox;display:flex;-ms-flex-align:center;align-items:center}.checkbox-icon{border-radius:var(--border-radius);position:relative;width:var(--size);height:var(--size);-webkit-transition:var(--transition);transition:var(--transition);border-width:var(--border-width);border-style:var(--border-style);border-color:var(--border-color);background:var(--checkbox-background);-webkit-box-sizing:border-box;box-sizing:border-box}.checkbox-icon path{fill:none;stroke:var(--checkmark-color);stroke-width:var(--checkmark-width);opacity:0}.checkbox-bottom{padding-top:4px;display:-ms-flexbox;display:flex;-ms-flex-pack:justify;justify-content:space-between;font-size:0.75rem;white-space:normal}:host(.checkbox-label-placement-stacked) .checkbox-bottom{font-size:1rem}.checkbox-bottom .error-text{display:none;color:var(--ion-color-danger, #c5000f)}.checkbox-bottom .helper-text{display:block;color:var(--ion-color-step-700, var(--ion-text-color-step-300, #4d4d4d))}:host(.ion-touched.ion-invalid) .checkbox-bottom .error-text{display:block}:host(.ion-touched.ion-invalid) .checkbox-bottom .helper-text{display:none}:host(.checkbox-label-placement-start) .checkbox-wrapper{-ms-flex-direction:row;flex-direction:row}:host(.checkbox-label-placement-start) .label-text-wrapper{-webkit-margin-start:0;margin-inline-start:0;-webkit-margin-end:16px;margin-inline-end:16px}:host(.checkbox-label-placement-end) .checkbox-wrapper{-ms-flex-direction:row-reverse;flex-direction:row-reverse;-ms-flex-pack:start;justify-content:start}:host(.checkbox-label-placement-end) .label-text-wrapper{-webkit-margin-start:16px;margin-inline-start:16px;-webkit-margin-end:0;margin-inline-end:0}:host(.checkbox-label-placement-fixed) .label-text-wrapper{-webkit-margin-start:0;margin-inline-start:0;-webkit-margin-end:16px;margin-inline-end:16px}:host(.checkbox-label-placement-fixed) .label-text-wrapper{-ms-flex:0 0 100px;flex:0 0 100px;width:100px;min-width:100px;max-width:200px}:host(.checkbox-label-placement-stacked) .checkbox-wrapper{-ms-flex-direction:column;flex-direction:column;text-align:center}:host(.checkbox-label-placement-stacked) .label-text-wrapper{-webkit-transform:scale(0.75);transform:scale(0.75);margin-left:0;margin-right:0;margin-bottom:16px;max-width:calc(100% / 0.75)}:host(.checkbox-label-placement-stacked.checkbox-alignment-start) .label-text-wrapper{-webkit-transform-origin:left top;transform-origin:left top}:host-context([dir=rtl]):host(.checkbox-label-placement-stacked.checkbox-alignment-start) .label-text-wrapper,:host-context([dir=rtl]).checkbox-label-placement-stacked.checkbox-alignment-start .label-text-wrapper{-webkit-transform-origin:right top;transform-origin:right top}@supports selector(:dir(rtl)){:host(.checkbox-label-placement-stacked.checkbox-alignment-start:dir(rtl)) .label-text-wrapper{-webkit-transform-origin:right top;transform-origin:right top}}:host(.checkbox-label-placement-stacked.checkbox-alignment-center) .label-text-wrapper{-webkit-transform-origin:center top;transform-origin:center top}:host-context([dir=rtl]):host(.checkbox-label-placement-stacked.checkbox-alignment-center) .label-text-wrapper,:host-context([dir=rtl]).checkbox-label-placement-stacked.checkbox-alignment-center .label-text-wrapper{-webkit-transform-origin:calc(100% - center) top;transform-origin:calc(100% - center) top}@supports selector(:dir(rtl)){:host(.checkbox-label-placement-stacked.checkbox-alignment-center:dir(rtl)) .label-text-wrapper{-webkit-transform-origin:calc(100% - center) top;transform-origin:calc(100% - center) top}}:host(.checkbox-justify-space-between) .checkbox-wrapper{-ms-flex-pack:justify;justify-content:space-between}:host(.checkbox-justify-start) .checkbox-wrapper{-ms-flex-pack:start;justify-content:start}:host(.checkbox-justify-end) .checkbox-wrapper{-ms-flex-pack:end;justify-content:end}:host(.checkbox-alignment-start) .checkbox-wrapper{-ms-flex-align:start;align-items:start}:host(.checkbox-alignment-center) .checkbox-wrapper{-ms-flex-align:center;align-items:center}:host(.checkbox-justify-space-between),:host(.checkbox-justify-start),:host(.checkbox-justify-end),:host(.checkbox-alignment-start),:host(.checkbox-alignment-center){display:block}:host(.checkbox-checked) .checkbox-icon,:host(.checkbox-indeterminate) .checkbox-icon{border-color:var(--border-color-checked);background:var(--checkbox-background-checked)}:host(.checkbox-checked) .checkbox-icon path,:host(.checkbox-indeterminate) .checkbox-icon path{opacity:1}:host(.checkbox-disabled){pointer-events:none}:host{--border-radius:calc(var(--size) * .125);--border-width:2px;--border-style:solid;--border-color:rgb(var(--ion-text-color-rgb, 0, 0, 0), 0.6);--checkmark-width:3;--checkbox-background:var(--ion-item-background, var(--ion-background-color, #fff));--transition:background 180ms cubic-bezier(0.4, 0, 0.2, 1);--size:18px}.checkbox-icon path{stroke-dasharray:30;stroke-dashoffset:30}:host(.checkbox-checked) .checkbox-icon path,:host(.checkbox-indeterminate) .checkbox-icon path{stroke-dashoffset:0;-webkit-transition:stroke-dashoffset 90ms linear 90ms;transition:stroke-dashoffset 90ms linear 90ms}:host(.checkbox-disabled) .label-text-wrapper{opacity:0.38}:host(.checkbox-disabled) .native-wrapper{opacity:0.63}";
|
|
@@ -9750,6 +9946,10 @@ class Checkbox {
|
|
|
9750
9946
|
* submitting if the value is invalid.
|
|
9751
9947
|
*/
|
|
9752
9948
|
this.required = false;
|
|
9949
|
+
/**
|
|
9950
|
+
* Track validation state for proper aria-live announcements.
|
|
9951
|
+
*/
|
|
9952
|
+
this.isInvalid = false;
|
|
9753
9953
|
/**
|
|
9754
9954
|
* Sets the checked property and emits
|
|
9755
9955
|
* the ionChange event. Use this to update the
|
|
@@ -9796,16 +9996,29 @@ class Checkbox {
|
|
|
9796
9996
|
ev.stopPropagation();
|
|
9797
9997
|
};
|
|
9798
9998
|
}
|
|
9999
|
+
connectedCallback() {
|
|
10000
|
+
const { el } = this;
|
|
10001
|
+
// Always set initial state
|
|
10002
|
+
this.isInvalid = checkInvalidState(el);
|
|
10003
|
+
}
|
|
9799
10004
|
componentWillLoad() {
|
|
9800
10005
|
this.inheritedAttributes = Object.assign({}, inheritAriaAttributes(this.el));
|
|
10006
|
+
this.hintTextId = this.getHintTextId();
|
|
10007
|
+
}
|
|
10008
|
+
disconnectedCallback() {
|
|
10009
|
+
// Clean up validation observer to prevent memory leaks.
|
|
10010
|
+
if (this.validationObserver) {
|
|
10011
|
+
this.validationObserver.disconnect();
|
|
10012
|
+
this.validationObserver = undefined;
|
|
10013
|
+
}
|
|
9801
10014
|
}
|
|
9802
10015
|
/** @internal */
|
|
9803
10016
|
async setFocus() {
|
|
9804
10017
|
this.el.focus();
|
|
9805
10018
|
}
|
|
9806
|
-
|
|
9807
|
-
const {
|
|
9808
|
-
if (
|
|
10019
|
+
getHintTextId() {
|
|
10020
|
+
const { helperText, errorText, helperTextId, errorTextId, isInvalid } = this;
|
|
10021
|
+
if (isInvalid && errorText) {
|
|
9809
10022
|
return errorTextId;
|
|
9810
10023
|
}
|
|
9811
10024
|
if (helperText) {
|
|
@@ -9818,7 +10031,7 @@ class Checkbox {
|
|
|
9818
10031
|
* This element should only be rendered if hint text is set.
|
|
9819
10032
|
*/
|
|
9820
10033
|
renderHintText() {
|
|
9821
|
-
const { helperText, errorText, helperTextId, errorTextId } = this;
|
|
10034
|
+
const { helperText, errorText, helperTextId, errorTextId, isInvalid } = this;
|
|
9822
10035
|
/**
|
|
9823
10036
|
* undefined and empty string values should
|
|
9824
10037
|
* be treated as not having helper/error text.
|
|
@@ -9827,7 +10040,7 @@ class Checkbox {
|
|
|
9827
10040
|
if (!hasHintText) {
|
|
9828
10041
|
return;
|
|
9829
10042
|
}
|
|
9830
|
-
return (hAsync("div", { class: "checkbox-bottom" }, hAsync("div", { id: helperTextId, class: "helper-text", part: "supporting-text helper-text" }, helperText), hAsync("div", { id: errorTextId, class: "error-text", part: "supporting-text error-text" }, errorText)));
|
|
10043
|
+
return (hAsync("div", { class: "checkbox-bottom" }, hAsync("div", { id: helperTextId, class: "helper-text", part: "supporting-text helper-text", "aria-live": "polite" }, !isInvalid ? helperText : null), hAsync("div", { id: errorTextId, class: "error-text", part: "supporting-text error-text", role: "alert" }, isInvalid ? errorText : null)));
|
|
9831
10044
|
}
|
|
9832
10045
|
render() {
|
|
9833
10046
|
const { color, checked, disabled, el, getSVGPath, indeterminate, inheritedAttributes, inputId, justify, labelPlacement, name, value, alignment, required, } = this;
|
|
@@ -9837,7 +10050,7 @@ class Checkbox {
|
|
|
9837
10050
|
renderHiddenInput(true, el, name, checked ? value : '', disabled);
|
|
9838
10051
|
// The host element must have a checkbox role to ensure proper VoiceOver
|
|
9839
10052
|
// support in Safari for accessibility.
|
|
9840
|
-
return (hAsync(Host, { key: '
|
|
10053
|
+
return (hAsync(Host, { key: 'ae0fbd4b21accbac132e6b85c513512ad9179394', role: "checkbox", "aria-checked": indeterminate ? 'mixed' : `${checked}`, "aria-describedby": this.hintTextId, "aria-invalid": this.isInvalid ? 'true' : undefined, "aria-labelledby": hasLabelContent ? this.inputLabelId : null, "aria-label": inheritedAttributes['aria-label'] || null, "aria-disabled": disabled ? 'true' : null, "aria-required": required ? 'true' : undefined, tabindex: disabled ? undefined : 0, onKeyDown: this.onKeyDown, onFocus: this.onFocus, onBlur: this.onBlur, onClick: this.onClick, class: createColorClasses$1(color, {
|
|
9841
10054
|
[mode]: true,
|
|
9842
10055
|
'in-item': hostContext('ion-item', el),
|
|
9843
10056
|
'checkbox-checked': checked,
|
|
@@ -9847,10 +10060,10 @@ class Checkbox {
|
|
|
9847
10060
|
[`checkbox-justify-${justify}`]: justify !== undefined,
|
|
9848
10061
|
[`checkbox-alignment-${alignment}`]: alignment !== undefined,
|
|
9849
10062
|
[`checkbox-label-placement-${labelPlacement}`]: true,
|
|
9850
|
-
}) }, hAsync("label", { key: '
|
|
10063
|
+
}) }, hAsync("label", { key: '7a3d7f3c27dde514f2dbf2e34f4629fad33ec3bf', class: "checkbox-wrapper", htmlFor: inputId }, hAsync("input", Object.assign({ key: '4130d77ddf034271fecccda14e101a5a809921b6', type: "checkbox", checked: checked ? true : undefined, disabled: disabled, id: inputId, onChange: this.toggleChecked, required: required }, inheritedAttributes)), hAsync("div", { key: '5daa74f4e62b0947e37764762524001ee42609d9', class: {
|
|
9851
10064
|
'label-text-wrapper': true,
|
|
9852
10065
|
'label-text-wrapper-hidden': !hasLabelContent,
|
|
9853
|
-
}, part: "label", id: this.inputLabelId, onClick: this.onDivLabelClick }, hAsync("slot", { key: '
|
|
10066
|
+
}, part: "label", id: this.inputLabelId, onClick: this.onDivLabelClick }, hAsync("slot", { key: '23ff66138f8c3a2f56f39113fc842d54b2f7952a' }), this.renderHintText()), hAsync("div", { key: 'ab914d9623c19fc46821d5e62db92f1192ebbe7e', class: "native-wrapper" }, hAsync("svg", { key: '66e3f4f5dcaa9756fb0e9452299954f9ed3dcb7b', class: "checkbox-icon", viewBox: "0 0 24 24", part: "container", "aria-hidden": "true" }, path)))));
|
|
9854
10067
|
}
|
|
9855
10068
|
getSVGPath(mode, indeterminate) {
|
|
9856
10069
|
let path = indeterminate ? (hAsync("path", { d: "M6 12L18 12", part: "mark" })) : (hAsync("path", { d: "M5.9,12.5l3.8,3.8l8.8-8.8", part: "mark" }));
|
|
@@ -9880,6 +10093,8 @@ class Checkbox {
|
|
|
9880
10093
|
"justify": [1],
|
|
9881
10094
|
"alignment": [1],
|
|
9882
10095
|
"required": [4],
|
|
10096
|
+
"isInvalid": [32],
|
|
10097
|
+
"hintTextId": [32],
|
|
9883
10098
|
"setFocus": [64]
|
|
9884
10099
|
},
|
|
9885
10100
|
"$listeners$": undefined,
|
|
@@ -13024,6 +13239,28 @@ class Datetime {
|
|
|
13024
13239
|
destroyKeyboardMO();
|
|
13025
13240
|
}
|
|
13026
13241
|
};
|
|
13242
|
+
/**
|
|
13243
|
+
* TODO(FW-6931): Remove this fallback upon solving the root cause
|
|
13244
|
+
* Fallback to ensure the datetime becomes ready even if
|
|
13245
|
+
* IntersectionObserver never reports it as intersecting.
|
|
13246
|
+
*
|
|
13247
|
+
* This is primarily used in environments where the observer
|
|
13248
|
+
* might not fire as expected, such as when running under
|
|
13249
|
+
* synthetic tests that stub IntersectionObserver.
|
|
13250
|
+
*/
|
|
13251
|
+
this.ensureReadyIfVisible = () => {
|
|
13252
|
+
if (this.el.classList.contains('datetime-ready')) {
|
|
13253
|
+
return;
|
|
13254
|
+
}
|
|
13255
|
+
const rect = this.el.getBoundingClientRect();
|
|
13256
|
+
if (rect.width === 0 || rect.height === 0) {
|
|
13257
|
+
return;
|
|
13258
|
+
}
|
|
13259
|
+
this.initializeListeners();
|
|
13260
|
+
writeTask(() => {
|
|
13261
|
+
this.el.classList.add('datetime-ready');
|
|
13262
|
+
});
|
|
13263
|
+
};
|
|
13027
13264
|
this.processValue = (value) => {
|
|
13028
13265
|
const hasValue = value !== null && value !== undefined && value !== '' && (!Array.isArray(value) || value.length > 0);
|
|
13029
13266
|
const valueToProcess = hasValue ? parseDate(value) : this.defaultParts;
|
|
@@ -13341,6 +13578,17 @@ class Datetime {
|
|
|
13341
13578
|
* triggering the `hiddenIO` observer below.
|
|
13342
13579
|
*/
|
|
13343
13580
|
raf(() => visibleIO === null || visibleIO === void 0 ? void 0 : visibleIO.observe(intersectionTrackerRef));
|
|
13581
|
+
/**
|
|
13582
|
+
* TODO(FW-6931): Remove this fallback upon solving the root cause
|
|
13583
|
+
* Fallback: If IntersectionObserver never reports that the
|
|
13584
|
+
* datetime is visible but the host clearly has layout, ensure
|
|
13585
|
+
* we still initialize listeners and mark the component as ready.
|
|
13586
|
+
*
|
|
13587
|
+
* We schedule this after everything has had a chance to run.
|
|
13588
|
+
*/
|
|
13589
|
+
setTimeout(() => {
|
|
13590
|
+
this.ensureReadyIfVisible();
|
|
13591
|
+
}, 100);
|
|
13344
13592
|
/**
|
|
13345
13593
|
* We need to clean up listeners when the datetime is hidden
|
|
13346
13594
|
* in a popover/modal so that we can properly scroll containers
|
|
@@ -14096,7 +14344,7 @@ class Datetime {
|
|
|
14096
14344
|
const hasDatePresentation = presentation === 'date' || presentation === 'date-time' || presentation === 'time-date';
|
|
14097
14345
|
const hasWheelVariant = hasDatePresentation && preferWheel;
|
|
14098
14346
|
renderHiddenInput(true, el, name, formatValue(value), disabled);
|
|
14099
|
-
return (hAsync(Host, { key: '
|
|
14347
|
+
return (hAsync(Host, { key: 'efdbc0922670a841bc667ceac392cdc1dedffd01', "aria-disabled": disabled ? 'true' : null, onFocus: this.onFocus, onBlur: this.onBlur, class: Object.assign({}, createColorClasses$1(color, {
|
|
14100
14348
|
[mode]: true,
|
|
14101
14349
|
['datetime-readonly']: readonly,
|
|
14102
14350
|
['datetime-disabled']: disabled,
|
|
@@ -14106,7 +14354,7 @@ class Datetime {
|
|
|
14106
14354
|
[`datetime-size-${size}`]: true,
|
|
14107
14355
|
[`datetime-prefer-wheel`]: hasWheelVariant,
|
|
14108
14356
|
[`datetime-grid`]: isGridStyle,
|
|
14109
|
-
})) }, hAsync("div", { key: '
|
|
14357
|
+
})) }, hAsync("div", { key: '3f8bb75fcb0baff55182ef3aa1b535eacc58d81f', class: "intersection-tracker", ref: (el) => (this.intersectionTrackerRef = el) }), this.renderDatetime(mode)));
|
|
14110
14358
|
}
|
|
14111
14359
|
get el() { return getElement(this); }
|
|
14112
14360
|
static get watchers() { return {
|
|
@@ -16314,202 +16562,6 @@ class InfiniteScrollContent {
|
|
|
16314
16562
|
}; }
|
|
16315
16563
|
}
|
|
16316
16564
|
|
|
16317
|
-
/**
|
|
16318
|
-
* A utility to calculate the size of an outline notch
|
|
16319
|
-
* width relative to the content passed. This is used in
|
|
16320
|
-
* components such as `ion-select` with `fill="outline"`
|
|
16321
|
-
* where we need to pass slotted HTML content. This is not
|
|
16322
|
-
* needed when rendering plaintext content because we can
|
|
16323
|
-
* render the plaintext again hidden with `opacity: 0` inside
|
|
16324
|
-
* of the notch. As a result we can rely on the intrinsic size
|
|
16325
|
-
* of the element to correctly compute the notch width. We
|
|
16326
|
-
* cannot do this with slotted content because we cannot project
|
|
16327
|
-
* it into 2 places at once.
|
|
16328
|
-
*
|
|
16329
|
-
* @internal
|
|
16330
|
-
* @param el: The host element
|
|
16331
|
-
* @param getNotchSpacerEl: A function that returns a reference to the notch spacer element inside of the component template.
|
|
16332
|
-
* @param getLabelSlot: A function that returns a reference to the slotted content.
|
|
16333
|
-
*/
|
|
16334
|
-
const createNotchController = (el, getNotchSpacerEl, getLabelSlot) => {
|
|
16335
|
-
let notchVisibilityIO;
|
|
16336
|
-
const needsExplicitNotchWidth = () => {
|
|
16337
|
-
const notchSpacerEl = getNotchSpacerEl();
|
|
16338
|
-
if (
|
|
16339
|
-
/**
|
|
16340
|
-
* If the notch is not being used
|
|
16341
|
-
* then we do not need to set the notch width.
|
|
16342
|
-
*/
|
|
16343
|
-
notchSpacerEl === undefined ||
|
|
16344
|
-
/**
|
|
16345
|
-
* If either the label property is being
|
|
16346
|
-
* used or the label slot is not defined,
|
|
16347
|
-
* then we do not need to estimate the notch width.
|
|
16348
|
-
*/
|
|
16349
|
-
el.label !== undefined ||
|
|
16350
|
-
getLabelSlot() === null) {
|
|
16351
|
-
return false;
|
|
16352
|
-
}
|
|
16353
|
-
return true;
|
|
16354
|
-
};
|
|
16355
|
-
const calculateNotchWidth = () => {
|
|
16356
|
-
if (needsExplicitNotchWidth()) {
|
|
16357
|
-
/**
|
|
16358
|
-
* Run this the frame after
|
|
16359
|
-
* the browser has re-painted the host element.
|
|
16360
|
-
* Otherwise, the label element may have a width
|
|
16361
|
-
* of 0 and the IntersectionObserver will be used.
|
|
16362
|
-
*/
|
|
16363
|
-
raf(() => {
|
|
16364
|
-
setNotchWidth();
|
|
16365
|
-
});
|
|
16366
|
-
}
|
|
16367
|
-
};
|
|
16368
|
-
/**
|
|
16369
|
-
* When using a label prop we can render
|
|
16370
|
-
* the label value inside of the notch and
|
|
16371
|
-
* let the browser calculate the size of the notch.
|
|
16372
|
-
* However, we cannot render the label slot in multiple
|
|
16373
|
-
* places so we need to manually calculate the notch dimension
|
|
16374
|
-
* based on the size of the slotted content.
|
|
16375
|
-
*
|
|
16376
|
-
* This function should only be used to set the notch width
|
|
16377
|
-
* on slotted label content. The notch width for label prop
|
|
16378
|
-
* content is automatically calculated based on the
|
|
16379
|
-
* intrinsic size of the label text.
|
|
16380
|
-
*/
|
|
16381
|
-
const setNotchWidth = () => {
|
|
16382
|
-
const notchSpacerEl = getNotchSpacerEl();
|
|
16383
|
-
if (notchSpacerEl === undefined) {
|
|
16384
|
-
return;
|
|
16385
|
-
}
|
|
16386
|
-
if (!needsExplicitNotchWidth()) {
|
|
16387
|
-
notchSpacerEl.style.removeProperty('width');
|
|
16388
|
-
return;
|
|
16389
|
-
}
|
|
16390
|
-
const width = getLabelSlot().scrollWidth;
|
|
16391
|
-
if (
|
|
16392
|
-
/**
|
|
16393
|
-
* If the computed width of the label is 0
|
|
16394
|
-
* and notchSpacerEl's offsetParent is null
|
|
16395
|
-
* then that means the element is hidden.
|
|
16396
|
-
* As a result, we need to wait for the element
|
|
16397
|
-
* to become visible before setting the notch width.
|
|
16398
|
-
*
|
|
16399
|
-
* We do not check el.offsetParent because
|
|
16400
|
-
* that can be null if the host element has
|
|
16401
|
-
* position: fixed applied to it.
|
|
16402
|
-
* notchSpacerEl does not have position: fixed.
|
|
16403
|
-
*/
|
|
16404
|
-
width === 0 &&
|
|
16405
|
-
notchSpacerEl.offsetParent === null &&
|
|
16406
|
-
win$1 !== undefined &&
|
|
16407
|
-
'IntersectionObserver' in win$1) {
|
|
16408
|
-
/**
|
|
16409
|
-
* If there is an IO already attached
|
|
16410
|
-
* then that will update the notch
|
|
16411
|
-
* once the element becomes visible.
|
|
16412
|
-
* As a result, there is no need to create
|
|
16413
|
-
* another one.
|
|
16414
|
-
*/
|
|
16415
|
-
if (notchVisibilityIO !== undefined) {
|
|
16416
|
-
return;
|
|
16417
|
-
}
|
|
16418
|
-
const io = (notchVisibilityIO = new IntersectionObserver((ev) => {
|
|
16419
|
-
/**
|
|
16420
|
-
* If the element is visible then we
|
|
16421
|
-
* can try setting the notch width again.
|
|
16422
|
-
*/
|
|
16423
|
-
if (ev[0].intersectionRatio === 1) {
|
|
16424
|
-
setNotchWidth();
|
|
16425
|
-
io.disconnect();
|
|
16426
|
-
notchVisibilityIO = undefined;
|
|
16427
|
-
}
|
|
16428
|
-
},
|
|
16429
|
-
/**
|
|
16430
|
-
* Set the root to be the host element
|
|
16431
|
-
* This causes the IO callback
|
|
16432
|
-
* to be fired in WebKit as soon as the element
|
|
16433
|
-
* is visible. If we used the default root value
|
|
16434
|
-
* then WebKit would only fire the IO callback
|
|
16435
|
-
* after any animations (such as a modal transition)
|
|
16436
|
-
* finished, and there would potentially be a flicker.
|
|
16437
|
-
*/
|
|
16438
|
-
{ threshold: 0.01, root: el }));
|
|
16439
|
-
io.observe(notchSpacerEl);
|
|
16440
|
-
return;
|
|
16441
|
-
}
|
|
16442
|
-
/**
|
|
16443
|
-
* If the element is visible then we can set the notch width.
|
|
16444
|
-
* The notch is only visible when the label is scaled,
|
|
16445
|
-
* which is why we multiply the width by 0.75 as this is
|
|
16446
|
-
* the same amount the label element is scaled by in the host CSS.
|
|
16447
|
-
* (See $form-control-label-stacked-scale in ionic.globals.scss).
|
|
16448
|
-
*/
|
|
16449
|
-
notchSpacerEl.style.setProperty('width', `${width * 0.75}px`);
|
|
16450
|
-
};
|
|
16451
|
-
const destroy = () => {
|
|
16452
|
-
if (notchVisibilityIO) {
|
|
16453
|
-
notchVisibilityIO.disconnect();
|
|
16454
|
-
notchVisibilityIO = undefined;
|
|
16455
|
-
}
|
|
16456
|
-
};
|
|
16457
|
-
return {
|
|
16458
|
-
calculateNotchWidth,
|
|
16459
|
-
destroy,
|
|
16460
|
-
};
|
|
16461
|
-
};
|
|
16462
|
-
|
|
16463
|
-
/**
|
|
16464
|
-
* Uses the compareWith param to compare two values to determine if they are equal.
|
|
16465
|
-
*
|
|
16466
|
-
* @param currentValue The current value of the control.
|
|
16467
|
-
* @param compareValue The value to compare against.
|
|
16468
|
-
* @param compareWith The function or property name to use to compare values.
|
|
16469
|
-
*/
|
|
16470
|
-
const compareOptions = (currentValue, compareValue, compareWith) => {
|
|
16471
|
-
if (typeof compareWith === 'function') {
|
|
16472
|
-
return compareWith(currentValue, compareValue);
|
|
16473
|
-
}
|
|
16474
|
-
else if (typeof compareWith === 'string') {
|
|
16475
|
-
return currentValue[compareWith] === compareValue[compareWith];
|
|
16476
|
-
}
|
|
16477
|
-
else {
|
|
16478
|
-
return Array.isArray(compareValue) ? compareValue.includes(currentValue) : currentValue === compareValue;
|
|
16479
|
-
}
|
|
16480
|
-
};
|
|
16481
|
-
/**
|
|
16482
|
-
* Compares a value against the current value(s) to determine if it is selected.
|
|
16483
|
-
*
|
|
16484
|
-
* @param currentValue The current value of the control.
|
|
16485
|
-
* @param compareValue The value to compare against.
|
|
16486
|
-
* @param compareWith The function or property name to use to compare values.
|
|
16487
|
-
*/
|
|
16488
|
-
const isOptionSelected = (currentValue, compareValue, compareWith) => {
|
|
16489
|
-
if (currentValue === undefined) {
|
|
16490
|
-
return false;
|
|
16491
|
-
}
|
|
16492
|
-
if (Array.isArray(currentValue)) {
|
|
16493
|
-
return currentValue.some((val) => compareOptions(val, compareValue, compareWith));
|
|
16494
|
-
}
|
|
16495
|
-
else {
|
|
16496
|
-
return compareOptions(currentValue, compareValue, compareWith);
|
|
16497
|
-
}
|
|
16498
|
-
};
|
|
16499
|
-
|
|
16500
|
-
/**
|
|
16501
|
-
* Checks if the form element is in an invalid state based on
|
|
16502
|
-
* Ionic validation classes.
|
|
16503
|
-
*
|
|
16504
|
-
* @param el The form element to check.
|
|
16505
|
-
* @returns `true` if the element is invalid, `false` otherwise.
|
|
16506
|
-
*/
|
|
16507
|
-
const checkInvalidState = (el) => {
|
|
16508
|
-
const hasIonTouched = el.classList.contains('ion-touched');
|
|
16509
|
-
const hasIonInvalid = el.classList.contains('ion-invalid');
|
|
16510
|
-
return hasIonTouched && hasIonInvalid;
|
|
16511
|
-
};
|
|
16512
|
-
|
|
16513
16565
|
/**
|
|
16514
16566
|
* Used to update a scoped component that uses emulated slots. This fires when
|
|
16515
16567
|
* content is passed into the slot or when the content inside of a slot changes.
|
|
@@ -28053,6 +28105,10 @@ class RadioGroup {
|
|
|
28053
28105
|
this.helperTextId = `${this.inputId}-helper-text`;
|
|
28054
28106
|
this.errorTextId = `${this.inputId}-error-text`;
|
|
28055
28107
|
this.labelId = `${this.inputId}-lbl`;
|
|
28108
|
+
/**
|
|
28109
|
+
* Track validation state for proper aria-live announcements.
|
|
28110
|
+
*/
|
|
28111
|
+
this.isInvalid = false;
|
|
28056
28112
|
/**
|
|
28057
28113
|
* If `true`, the radios can be deselected.
|
|
28058
28114
|
*/
|
|
@@ -28134,6 +28190,18 @@ class RadioGroup {
|
|
|
28134
28190
|
this.labelId = label.id = this.name + '-lbl';
|
|
28135
28191
|
}
|
|
28136
28192
|
}
|
|
28193
|
+
// Always set initial state
|
|
28194
|
+
this.isInvalid = checkInvalidState(this.el);
|
|
28195
|
+
}
|
|
28196
|
+
componentWillLoad() {
|
|
28197
|
+
this.hintTextId = this.getHintTextId();
|
|
28198
|
+
}
|
|
28199
|
+
disconnectedCallback() {
|
|
28200
|
+
// Clean up validation observer to prevent memory leaks.
|
|
28201
|
+
if (this.validationObserver) {
|
|
28202
|
+
this.validationObserver.disconnect();
|
|
28203
|
+
this.validationObserver = undefined;
|
|
28204
|
+
}
|
|
28137
28205
|
}
|
|
28138
28206
|
getRadios() {
|
|
28139
28207
|
return Array.from(this.el.querySelectorAll('ion-radio'));
|
|
@@ -28209,16 +28277,16 @@ class RadioGroup {
|
|
|
28209
28277
|
* Renders the helper text or error text values
|
|
28210
28278
|
*/
|
|
28211
28279
|
renderHintText() {
|
|
28212
|
-
const { helperText, errorText, helperTextId, errorTextId } = this;
|
|
28280
|
+
const { helperText, errorText, helperTextId, errorTextId, isInvalid } = this;
|
|
28213
28281
|
const hasHintText = !!helperText || !!errorText;
|
|
28214
28282
|
if (!hasHintText) {
|
|
28215
28283
|
return;
|
|
28216
28284
|
}
|
|
28217
|
-
return (hAsync("div", { class: "radio-group-top" }, hAsync("div", { id: helperTextId, class: "helper-text" }, helperText), hAsync("div", { id: errorTextId, class: "error-text" }, errorText)));
|
|
28285
|
+
return (hAsync("div", { class: "radio-group-top" }, hAsync("div", { id: helperTextId, class: "helper-text", "aria-live": "polite" }, !isInvalid ? helperText : null), hAsync("div", { id: errorTextId, class: "error-text", role: "alert" }, isInvalid ? errorText : null)));
|
|
28218
28286
|
}
|
|
28219
|
-
|
|
28220
|
-
const {
|
|
28221
|
-
if (
|
|
28287
|
+
getHintTextId() {
|
|
28288
|
+
const { helperText, errorText, helperTextId, errorTextId, isInvalid } = this;
|
|
28289
|
+
if (isInvalid && errorText) {
|
|
28222
28290
|
return errorTextId;
|
|
28223
28291
|
}
|
|
28224
28292
|
if (helperText) {
|
|
@@ -28230,7 +28298,7 @@ class RadioGroup {
|
|
|
28230
28298
|
const { label, labelId, el, name, value } = this;
|
|
28231
28299
|
const mode = getIonMode$1(this);
|
|
28232
28300
|
renderHiddenInput(true, el, name, value, false);
|
|
28233
|
-
return (hAsync(Host, { key: '
|
|
28301
|
+
return (hAsync(Host, { key: 'db593b3ed511e9395e3c7bfd91b787328692cd6d', role: "radiogroup", "aria-labelledby": label ? labelId : null, "aria-describedby": this.hintTextId, "aria-invalid": this.isInvalid ? 'true' : undefined, onClick: this.onClick, class: mode }, this.renderHintText(), hAsync("div", { key: '85045b45a0100a45f3b9a35d1c5a25ec63d525c4', class: "radio-group-wrapper" }, hAsync("slot", { key: '53dacb87ce62398e78771fb2efaf839ab922d946' }))));
|
|
28234
28302
|
}
|
|
28235
28303
|
get el() { return getElement(this); }
|
|
28236
28304
|
static get watchers() { return {
|
|
@@ -28250,6 +28318,8 @@ class RadioGroup {
|
|
|
28250
28318
|
"value": [1032],
|
|
28251
28319
|
"helperText": [1, "helper-text"],
|
|
28252
28320
|
"errorText": [1, "error-text"],
|
|
28321
|
+
"isInvalid": [32],
|
|
28322
|
+
"hintTextId": [32],
|
|
28253
28323
|
"setFocus": [64]
|
|
28254
28324
|
},
|
|
28255
28325
|
"$listeners$": [[4, "keydown", "onKeydown"]],
|
|
@@ -33378,7 +33448,7 @@ class Select {
|
|
|
33378
33448
|
}
|
|
33379
33449
|
componentWillLoad() {
|
|
33380
33450
|
this.inheritedAttributes = inheritAttributes$1(this.el, ['aria-label']);
|
|
33381
|
-
this.
|
|
33451
|
+
this.hintTextId = this.getHintTextId();
|
|
33382
33452
|
}
|
|
33383
33453
|
componentDidLoad() {
|
|
33384
33454
|
/**
|
|
@@ -33877,9 +33947,9 @@ class Select {
|
|
|
33877
33947
|
}
|
|
33878
33948
|
renderListbox() {
|
|
33879
33949
|
const { disabled, inputId, isExpanded, required } = this;
|
|
33880
|
-
return (hAsync("button", { disabled: disabled, id: inputId, "aria-label": this.ariaLabel, "aria-haspopup": "dialog", "aria-expanded": `${isExpanded}`, "aria-describedby": this.
|
|
33950
|
+
return (hAsync("button", { disabled: disabled, id: inputId, "aria-label": this.ariaLabel, "aria-haspopup": "dialog", "aria-expanded": `${isExpanded}`, "aria-describedby": this.hintTextId, "aria-invalid": this.isInvalid ? 'true' : undefined, "aria-required": `${required}`, onFocus: this.onFocus, onBlur: this.onBlur, ref: (focusEl) => (this.focusEl = focusEl) }));
|
|
33881
33951
|
}
|
|
33882
|
-
|
|
33952
|
+
getHintTextId() {
|
|
33883
33953
|
const { helperText, errorText, helperTextId, errorTextId, isInvalid } = this;
|
|
33884
33954
|
if (isInvalid && errorText) {
|
|
33885
33955
|
return errorTextId;
|
|
@@ -34004,7 +34074,7 @@ class Select {
|
|
|
34004
34074
|
"isExpanded": [32],
|
|
34005
34075
|
"hasFocus": [32],
|
|
34006
34076
|
"isInvalid": [32],
|
|
34007
|
-
"
|
|
34077
|
+
"hintTextId": [32],
|
|
34008
34078
|
"open": [64]
|
|
34009
34079
|
},
|
|
34010
34080
|
"$listeners$": undefined,
|
|
@@ -36475,6 +36545,10 @@ class Toggle {
|
|
|
36475
36545
|
this.inheritedAttributes = {};
|
|
36476
36546
|
this.didLoad = false;
|
|
36477
36547
|
this.activated = false;
|
|
36548
|
+
/**
|
|
36549
|
+
* Track validation state for proper aria-live announcements.
|
|
36550
|
+
*/
|
|
36551
|
+
this.isInvalid = false;
|
|
36478
36552
|
/**
|
|
36479
36553
|
* The name of the control, which is submitted with the form data.
|
|
36480
36554
|
*/
|
|
@@ -36588,15 +36662,18 @@ class Toggle {
|
|
|
36588
36662
|
});
|
|
36589
36663
|
}
|
|
36590
36664
|
async connectedCallback() {
|
|
36665
|
+
const { didLoad, el } = this;
|
|
36591
36666
|
/**
|
|
36592
36667
|
* If we have not yet rendered
|
|
36593
36668
|
* ion-toggle, then toggleTrack is not defined.
|
|
36594
36669
|
* But if we are moving ion-toggle via appendChild,
|
|
36595
36670
|
* then toggleTrack will be defined.
|
|
36596
36671
|
*/
|
|
36597
|
-
if (
|
|
36672
|
+
if (didLoad) {
|
|
36598
36673
|
this.setupGesture();
|
|
36599
36674
|
}
|
|
36675
|
+
// Always set initial state
|
|
36676
|
+
this.isInvalid = checkInvalidState(el);
|
|
36600
36677
|
}
|
|
36601
36678
|
componentDidLoad() {
|
|
36602
36679
|
this.setupGesture();
|
|
@@ -36607,9 +36684,15 @@ class Toggle {
|
|
|
36607
36684
|
this.gesture.destroy();
|
|
36608
36685
|
this.gesture = undefined;
|
|
36609
36686
|
}
|
|
36687
|
+
// Clean up validation observer to prevent memory leaks.
|
|
36688
|
+
if (this.validationObserver) {
|
|
36689
|
+
this.validationObserver.disconnect();
|
|
36690
|
+
this.validationObserver = undefined;
|
|
36691
|
+
}
|
|
36610
36692
|
}
|
|
36611
36693
|
componentWillLoad() {
|
|
36612
36694
|
this.inheritedAttributes = Object.assign({}, inheritAriaAttributes(this.el));
|
|
36695
|
+
this.hintTextId = this.getHintTextId();
|
|
36613
36696
|
}
|
|
36614
36697
|
onStart() {
|
|
36615
36698
|
this.activated = true;
|
|
@@ -36650,9 +36733,9 @@ class Toggle {
|
|
|
36650
36733
|
get hasLabel() {
|
|
36651
36734
|
return this.el.textContent !== '';
|
|
36652
36735
|
}
|
|
36653
|
-
|
|
36654
|
-
const {
|
|
36655
|
-
if (
|
|
36736
|
+
getHintTextId() {
|
|
36737
|
+
const { helperText, errorText, helperTextId, errorTextId, isInvalid } = this;
|
|
36738
|
+
if (isInvalid && errorText) {
|
|
36656
36739
|
return errorTextId;
|
|
36657
36740
|
}
|
|
36658
36741
|
if (helperText) {
|
|
@@ -36665,7 +36748,7 @@ class Toggle {
|
|
|
36665
36748
|
* This element should only be rendered if hint text is set.
|
|
36666
36749
|
*/
|
|
36667
36750
|
renderHintText() {
|
|
36668
|
-
const { helperText, errorText, helperTextId, errorTextId } = this;
|
|
36751
|
+
const { helperText, errorText, helperTextId, errorTextId, isInvalid } = this;
|
|
36669
36752
|
/**
|
|
36670
36753
|
* undefined and empty string values should
|
|
36671
36754
|
* be treated as not having helper/error text.
|
|
@@ -36674,15 +36757,15 @@ class Toggle {
|
|
|
36674
36757
|
if (!hasHintText) {
|
|
36675
36758
|
return;
|
|
36676
36759
|
}
|
|
36677
|
-
return (hAsync("div", { class: "toggle-bottom" }, hAsync("div", { id: helperTextId, class: "helper-text", part: "supporting-text helper-text" }, helperText), hAsync("div", { id: errorTextId, class: "error-text", part: "supporting-text error-text" }, errorText)));
|
|
36760
|
+
return (hAsync("div", { class: "toggle-bottom" }, hAsync("div", { id: helperTextId, class: "helper-text", part: "supporting-text helper-text", "aria-live": "polite" }, !isInvalid ? helperText : null), hAsync("div", { id: errorTextId, class: "error-text", part: "supporting-text error-text", role: "alert" }, isInvalid ? errorText : null)));
|
|
36678
36761
|
}
|
|
36679
36762
|
render() {
|
|
36680
|
-
const { activated, alignment, checked, color, disabled, el,
|
|
36763
|
+
const { activated, alignment, checked, color, disabled, el, hasLabel, inheritedAttributes, inputId, inputLabelId, justify, labelPlacement, name, required, } = this;
|
|
36681
36764
|
const mode = getIonMode$1(this);
|
|
36682
36765
|
const value = this.getValue();
|
|
36683
36766
|
const rtl = isRTL$1(el) ? 'rtl' : 'ltr';
|
|
36684
36767
|
renderHiddenInput(true, el, name, checked ? value : '', disabled);
|
|
36685
|
-
return (hAsync(Host, { key: '
|
|
36768
|
+
return (hAsync(Host, { key: 'f569148edd89ee041a4719ffc4733c16b05229bd', role: "switch", "aria-checked": `${checked}`, "aria-describedby": this.hintTextId, "aria-invalid": this.isInvalid ? 'true' : undefined, onClick: this.onClick, "aria-labelledby": hasLabel ? inputLabelId : null, "aria-label": inheritedAttributes['aria-label'] || null, "aria-disabled": disabled ? 'true' : null, "aria-required": required ? 'true' : undefined, tabindex: disabled ? undefined : 0, onKeyDown: this.onKeyDown, onFocus: this.onFocus, onBlur: this.onBlur, class: createColorClasses$1(color, {
|
|
36686
36769
|
[mode]: true,
|
|
36687
36770
|
'in-item': hostContext('ion-item', el),
|
|
36688
36771
|
'toggle-activated': activated,
|
|
@@ -36692,10 +36775,10 @@ class Toggle {
|
|
|
36692
36775
|
[`toggle-alignment-${alignment}`]: alignment !== undefined,
|
|
36693
36776
|
[`toggle-label-placement-${labelPlacement}`]: true,
|
|
36694
36777
|
[`toggle-${rtl}`]: true,
|
|
36695
|
-
}) }, hAsync("label", { key: '
|
|
36778
|
+
}) }, hAsync("label", { key: '3027f2ac4be6de422a14486d847fbee77f615db1', class: "toggle-wrapper", htmlFor: inputId }, hAsync("input", Object.assign({ key: '4b0304c9e879e432b80184b4e5de37d55c11b436', type: "checkbox", role: "switch", "aria-checked": `${checked}`, checked: checked, disabled: disabled, id: inputId, required: required }, inheritedAttributes)), hAsync("div", { key: '8ef265ec942e7f01ff31cbb202ed146c6bf94e02', class: {
|
|
36696
36779
|
'label-text-wrapper': true,
|
|
36697
36780
|
'label-text-wrapper-hidden': !hasLabel,
|
|
36698
|
-
}, part: "label", id: inputLabelId, onClick: this.onDivLabelClick }, hAsync("slot", { key: '
|
|
36781
|
+
}, part: "label", id: inputLabelId, onClick: this.onDivLabelClick }, hAsync("slot", { key: '7b162b7dd27199cca2a4c995276a18b9f8e44aaf' }), this.renderHintText()), hAsync("div", { key: 'd13c34bd42fca01cc73ddb4ea7e471b33a282a3e', class: "native-wrapper" }, this.renderToggleControl()))));
|
|
36699
36782
|
}
|
|
36700
36783
|
get el() { return getElement(this); }
|
|
36701
36784
|
static get watchers() { return {
|
|
@@ -36721,7 +36804,9 @@ class Toggle {
|
|
|
36721
36804
|
"justify": [1],
|
|
36722
36805
|
"alignment": [1],
|
|
36723
36806
|
"required": [4],
|
|
36724
|
-
"activated": [32]
|
|
36807
|
+
"activated": [32],
|
|
36808
|
+
"isInvalid": [32],
|
|
36809
|
+
"hintTextId": [32]
|
|
36725
36810
|
},
|
|
36726
36811
|
"$listeners$": undefined,
|
|
36727
36812
|
"$lazyBundleId$": "-",
|