ion-range.cjs.entry.js 46 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721
  1. /*!
  2. * (C) Ionic http://ionicframework.com - MIT License
  3. */
  4. 'use strict';
  5. Object.defineProperty(exports, '__esModule', { value: true });
  6. const index = require('./index-2e236a04.js');
  7. const index$2 = require('./index-31b07b9c.js');
  8. const helpers = require('./helpers-8a48fdea.js');
  9. const index$1 = require('./index-cc858e97.js');
  10. const dir = require('./dir-94c21456.js');
  11. const theme = require('./theme-d1c573d2.js');
  12. const ionicGlobal = require('./ionic-global-6dea5a96.js');
  13. function getDecimalPlaces(n) {
  14. if (!helpers.isSafeNumber(n))
  15. return 0;
  16. if (n % 1 === 0)
  17. return 0;
  18. return n.toString().split('.')[1].length;
  19. }
  20. /**
  21. * Fixes floating point rounding errors in a result by rounding
  22. * to the same specificity, or number of decimal places (*not*
  23. * significant figures) as provided reference numbers. If multiple
  24. * references are provided, the highest number of decimal places
  25. * between them will be used.
  26. *
  27. * The main use case is when numbers x and y are added to produce n,
  28. * but x and y are floats, so n may have rounding errors (such as
  29. * 3.1000000004 instead of 3.1). As long as only addition/subtraction
  30. * occurs between x and y, the specificity of the result will never
  31. * increase, so x and y should be passed in as the references.
  32. *
  33. * If multiplication, division, or other operations were used to
  34. * calculate n, the rounded result may have less specificity than
  35. * desired. For example, 1 / 3 = 0.33333(...), but
  36. * roundToMaxDecimalPlaces((1 / 3), 1, 3) will return 0, since both
  37. * 1 and 3 are whole numbers.
  38. *
  39. * Note that extremely precise reference numbers may lead to rounding
  40. * errors not being trimmed, due to the error result having the same or
  41. * fewer decimal places as the reference(s). This is acceptable as we
  42. * would not be able to tell the difference between a rounding error
  43. * and correct value in this case, but it does mean there is an implicit
  44. * precision limit. If precision that high is needed, it is recommended
  45. * to use a third party data type designed to handle floating point
  46. * errors instead.
  47. *
  48. * @param n The number to round.
  49. * @param references Number(s) used to calculate n, or that should otherwise
  50. * be used as a reference for the desired specificity.
  51. */
  52. function roundToMaxDecimalPlaces(n, ...references) {
  53. if (!helpers.isSafeNumber(n))
  54. return 0;
  55. const maxPlaces = Math.max(...references.map((r) => getDecimalPlaces(r)));
  56. return Number(n.toFixed(maxPlaces));
  57. }
  58. const rangeIosCss = ":host{--knob-handle-size:calc(var(--knob-size) * 2);display:-ms-flexbox;display:flex;position:relative;-ms-flex:3;flex:3;-ms-flex-align:center;align-items:center;font-family:var(--ion-font-family, inherit);-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;z-index:2}:host(.range-disabled){pointer-events:none}::slotted(ion-label){-ms-flex:initial;flex:initial}::slotted(ion-icon[slot]){font-size:24px}.range-slider{position:relative;-ms-flex:1;flex:1;width:100%;height:var(--height);contain:size layout style;cursor:-webkit-grab;cursor:grab;-ms-touch-action:pan-y;touch-action:pan-y}:host(.range-pressed) .range-slider{cursor:-webkit-grabbing;cursor:grabbing}.range-pin{position:absolute;background:var(--ion-color-base);color:var(--ion-color-contrast);text-align:center;-webkit-box-sizing:border-box;box-sizing:border-box}.range-knob-handle{top:calc((var(--height) - var(--knob-handle-size)) / 2);-webkit-margin-start:calc(0px - var(--knob-handle-size) / 2);margin-inline-start:calc(0px - var(--knob-handle-size) / 2);display:-ms-flexbox;display:flex;position:absolute;-ms-flex-pack:center;justify-content:center;width:var(--knob-handle-size);height:var(--knob-handle-size);text-align:center}.range-knob-handle{inset-inline-start:0}:host-context([dir=rtl]) .range-knob-handle{left:unset}[dir=rtl] .range-knob-handle{left:unset}@supports selector(:dir(rtl)){.range-knob-handle:dir(rtl){left:unset}}.range-knob-handle:active,.range-knob-handle:focus{outline:none}.range-bar-container{border-radius:var(--bar-border-radius);top:calc((var(--height) - var(--bar-height)) / 2);position:absolute;width:100%;height:var(--bar-height)}.range-bar-container{inset-inline-start:0}:host-context([dir=rtl]) .range-bar-container{left:unset}[dir=rtl] .range-bar-container{left:unset}@supports selector(:dir(rtl)){.range-bar-container:dir(rtl){left:unset}}.range-bar{border-radius:var(--bar-border-radius);position:absolute;width:100%;height:var(--bar-height);background:var(--bar-background);pointer-events:none}.range-knob{border-radius:var(--knob-border-radius);top:calc(50% - var(--knob-size) / 2);position:absolute;width:var(--knob-size);height:var(--knob-size);background:var(--knob-background);-webkit-box-shadow:var(--knob-box-shadow);box-shadow:var(--knob-box-shadow);z-index:2;pointer-events:none}.range-knob{inset-inline-start:calc(50% - var(--knob-size) / 2)}:host-context([dir=rtl]) .range-knob{left:unset}[dir=rtl] .range-knob{left:unset}@supports selector(:dir(rtl)){.range-knob:dir(rtl){left:unset}}:host(.range-pressed) .range-bar-active{will-change:left, right}:host(.in-item){width:100%}:host([slot=start]),:host([slot=end]){width:auto}:host(.in-item) ::slotted(ion-label){-ms-flex-item-align:center;align-self:center}.range-wrapper{display:-ms-flexbox;display:flex;position:relative;-ms-flex-positive:1;flex-grow:1;-ms-flex-align:center;align-items:center;height:inherit}::slotted([slot=label]){max-width:200px;text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.label-text-wrapper-hidden{display:none}.native-wrapper{display:-ms-flexbox;display:flex;-ms-flex-positive:1;flex-grow:1;-ms-flex-align:center;align-items:center}:host(.range-label-placement-start) .range-wrapper{-ms-flex-direction:row;flex-direction:row}:host(.range-label-placement-start) .label-text-wrapper{-webkit-margin-start:0;margin-inline-start:0;-webkit-margin-end:16px;margin-inline-end:16px;margin-top:0;margin-bottom:0}:host(.range-label-placement-end) .range-wrapper{-ms-flex-direction:row-reverse;flex-direction:row-reverse}:host(.range-label-placement-end) .label-text-wrapper{-webkit-margin-start:16px;margin-inline-start:16px;-webkit-margin-end:0;margin-inline-end:0;margin-top:0;margin-bottom:0}:host(.range-label-placement-fixed) .label-text-wrapper{-webkit-margin-start:0;margin-inline-start:0;-webkit-margin-end:16px;margin-inline-end:16px;margin-top:0;margin-bottom:0}:host(.range-label-placement-fixed) .label-text-wrapper{-ms-flex:0 0 100px;flex:0 0 100px;width:100px;min-width:100px;max-width:200px}:host(.range-label-placement-stacked) .range-wrapper{-ms-flex-direction:column;flex-direction:column;-ms-flex-align:stretch;align-items:stretch}:host(.range-label-placement-stacked) .label-text-wrapper{-webkit-transform-origin:left top;transform-origin:left top;-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-context([dir=rtl]):host(.range-label-placement-stacked) .label-text-wrapper,:host-context([dir=rtl]).range-label-placement-stacked .label-text-wrapper{-webkit-transform-origin:right top;transform-origin:right top}@supports selector(:dir(rtl)){:host(.range-label-placement-stacked:dir(rtl)) .label-text-wrapper{-webkit-transform-origin:right top;transform-origin:right top}}:host(.in-item.range-label-placement-stacked) .label-text-wrapper{margin-top:10px;margin-bottom:16px}:host(.in-item.range-label-placement-stacked) .native-wrapper{margin-bottom:0px}:host{--knob-border-radius:50%;--knob-background:#ffffff;--knob-box-shadow:0px 0.5px 4px rgba(0, 0, 0, 0.12), 0px 6px 13px rgba(0, 0, 0, 0.12);--knob-size:26px;--bar-height:4px;--bar-background:var(--ion-color-step-900, var(--ion-background-color-step-900, #e6e6e6));--bar-background-active:var(--ion-color-primary, #0054e9);--bar-border-radius:2px;--height:42px}:host(.range-item-start-adjustment){-webkit-padding-start:24px;padding-inline-start:24px}:host(.range-item-end-adjustment){-webkit-padding-end:24px;padding-inline-end:24px}:host(.ion-color) .range-bar-active,:host(.ion-color) .range-tick-active{background:var(--ion-color-base)}::slotted([slot=start]){-webkit-margin-start:0;margin-inline-start:0;-webkit-margin-end:16px;margin-inline-end:16px;margin-top:0;margin-bottom:0}::slotted([slot=end]){-webkit-margin-start:16px;margin-inline-start:16px;-webkit-margin-end:0;margin-inline-end:0;margin-top:0;margin-bottom:0}:host(.range-has-pin:not(.range-label-placement-stacked)){padding-top:calc(8px + 0.75rem)}:host(.range-has-pin.range-label-placement-stacked) .label-text-wrapper{margin-bottom:calc(8px + 0.75rem)}.range-bar-active{bottom:0;width:auto;background:var(--bar-background-active)}.range-bar-active.has-ticks{border-radius:0;-webkit-margin-start:-2px;margin-inline-start:-2px;-webkit-margin-end:-2px;margin-inline-end:-2px}.range-tick{-webkit-margin-start:-2px;margin-inline-start:-2px;border-radius:0;position:absolute;top:17px;width:4px;height:8px;background:var(--ion-color-step-900, var(--ion-background-color-step-900, #e6e6e6));pointer-events:none}.range-tick-active{background:var(--bar-background-active)}.range-pin{-webkit-transform:translate3d(0, 100%, 0) scale(0.01);transform:translate3d(0, 100%, 0) scale(0.01);-webkit-padding-start:8px;padding-inline-start:8px;-webkit-padding-end:8px;padding-inline-end:8px;padding-top:8px;padding-bottom:8px;min-width:28px;-webkit-transition:-webkit-transform 120ms ease;transition:-webkit-transform 120ms ease;transition:transform 120ms ease;transition:transform 120ms ease, -webkit-transform 120ms ease;background:transparent;color:var(--ion-text-color, #000);font-size:0.75rem;text-align:center}.range-knob-pressed .range-pin,.range-knob-handle.ion-focused .range-pin{-webkit-transform:translate3d(0, calc(-100% + 11px), 0) scale(1);transform:translate3d(0, calc(-100% + 11px), 0) scale(1)}:host(.range-disabled){opacity:0.3}";
  59. const IonRangeIosStyle0 = rangeIosCss;
  60. const rangeMdCss = ":host{--knob-handle-size:calc(var(--knob-size) * 2);display:-ms-flexbox;display:flex;position:relative;-ms-flex:3;flex:3;-ms-flex-align:center;align-items:center;font-family:var(--ion-font-family, inherit);-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;z-index:2}:host(.range-disabled){pointer-events:none}::slotted(ion-label){-ms-flex:initial;flex:initial}::slotted(ion-icon[slot]){font-size:24px}.range-slider{position:relative;-ms-flex:1;flex:1;width:100%;height:var(--height);contain:size layout style;cursor:-webkit-grab;cursor:grab;-ms-touch-action:pan-y;touch-action:pan-y}:host(.range-pressed) .range-slider{cursor:-webkit-grabbing;cursor:grabbing}.range-pin{position:absolute;background:var(--ion-color-base);color:var(--ion-color-contrast);text-align:center;-webkit-box-sizing:border-box;box-sizing:border-box}.range-knob-handle{top:calc((var(--height) - var(--knob-handle-size)) / 2);-webkit-margin-start:calc(0px - var(--knob-handle-size) / 2);margin-inline-start:calc(0px - var(--knob-handle-size) / 2);display:-ms-flexbox;display:flex;position:absolute;-ms-flex-pack:center;justify-content:center;width:var(--knob-handle-size);height:var(--knob-handle-size);text-align:center}.range-knob-handle{inset-inline-start:0}:host-context([dir=rtl]) .range-knob-handle{left:unset}[dir=rtl] .range-knob-handle{left:unset}@supports selector(:dir(rtl)){.range-knob-handle:dir(rtl){left:unset}}.range-knob-handle:active,.range-knob-handle:focus{outline:none}.range-bar-container{border-radius:var(--bar-border-radius);top:calc((var(--height) - var(--bar-height)) / 2);position:absolute;width:100%;height:var(--bar-height)}.range-bar-container{inset-inline-start:0}:host-context([dir=rtl]) .range-bar-container{left:unset}[dir=rtl] .range-bar-container{left:unset}@supports selector(:dir(rtl)){.range-bar-container:dir(rtl){left:unset}}.range-bar{border-radius:var(--bar-border-radius);position:absolute;width:100%;height:var(--bar-height);background:var(--bar-background);pointer-events:none}.range-knob{border-radius:var(--knob-border-radius);top:calc(50% - var(--knob-size) / 2);position:absolute;width:var(--knob-size);height:var(--knob-size);background:var(--knob-background);-webkit-box-shadow:var(--knob-box-shadow);box-shadow:var(--knob-box-shadow);z-index:2;pointer-events:none}.range-knob{inset-inline-start:calc(50% - var(--knob-size) / 2)}:host-context([dir=rtl]) .range-knob{left:unset}[dir=rtl] .range-knob{left:unset}@supports selector(:dir(rtl)){.range-knob:dir(rtl){left:unset}}:host(.range-pressed) .range-bar-active{will-change:left, right}:host(.in-item){width:100%}:host([slot=start]),:host([slot=end]){width:auto}:host(.in-item) ::slotted(ion-label){-ms-flex-item-align:center;align-self:center}.range-wrapper{display:-ms-flexbox;display:flex;position:relative;-ms-flex-positive:1;flex-grow:1;-ms-flex-align:center;align-items:center;height:inherit}::slotted([slot=label]){max-width:200px;text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.label-text-wrapper-hidden{display:none}.native-wrapper{display:-ms-flexbox;display:flex;-ms-flex-positive:1;flex-grow:1;-ms-flex-align:center;align-items:center}:host(.range-label-placement-start) .range-wrapper{-ms-flex-direction:row;flex-direction:row}:host(.range-label-placement-start) .label-text-wrapper{-webkit-margin-start:0;margin-inline-start:0;-webkit-margin-end:16px;margin-inline-end:16px;margin-top:0;margin-bottom:0}:host(.range-label-placement-end) .range-wrapper{-ms-flex-direction:row-reverse;flex-direction:row-reverse}:host(.range-label-placement-end) .label-text-wrapper{-webkit-margin-start:16px;margin-inline-start:16px;-webkit-margin-end:0;margin-inline-end:0;margin-top:0;margin-bottom:0}:host(.range-label-placement-fixed) .label-text-wrapper{-webkit-margin-start:0;margin-inline-start:0;-webkit-margin-end:16px;margin-inline-end:16px;margin-top:0;margin-bottom:0}:host(.range-label-placement-fixed) .label-text-wrapper{-ms-flex:0 0 100px;flex:0 0 100px;width:100px;min-width:100px;max-width:200px}:host(.range-label-placement-stacked) .range-wrapper{-ms-flex-direction:column;flex-direction:column;-ms-flex-align:stretch;align-items:stretch}:host(.range-label-placement-stacked) .label-text-wrapper{-webkit-transform-origin:left top;transform-origin:left top;-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-context([dir=rtl]):host(.range-label-placement-stacked) .label-text-wrapper,:host-context([dir=rtl]).range-label-placement-stacked .label-text-wrapper{-webkit-transform-origin:right top;transform-origin:right top}@supports selector(:dir(rtl)){:host(.range-label-placement-stacked:dir(rtl)) .label-text-wrapper{-webkit-transform-origin:right top;transform-origin:right top}}:host(.in-item.range-label-placement-stacked) .label-text-wrapper{margin-top:10px;margin-bottom:16px}:host(.in-item.range-label-placement-stacked) .native-wrapper{margin-bottom:0px}:host{--knob-border-radius:50%;--knob-background:var(--bar-background-active);--knob-box-shadow:none;--knob-size:18px;--bar-height:2px;--bar-background:rgba(var(--ion-color-primary-rgb, 0, 84, 233), 0.26);--bar-background-active:var(--ion-color-primary, #0054e9);--bar-border-radius:0;--height:42px;--pin-background:var(--ion-color-primary, #0054e9);--pin-color:var(--ion-color-primary-contrast, #fff)}::slotted(:not(ion-icon)[slot=start]),::slotted(:not(ion-icon)[slot=end]),.native-wrapper{font-size:0.75rem}:host(.range-item-start-adjustment){-webkit-padding-start:18px;padding-inline-start:18px}:host(.range-item-end-adjustment){-webkit-padding-end:18px;padding-inline-end:18px}:host(.ion-color) .range-bar{background:rgba(var(--ion-color-base-rgb), 0.26)}:host(.ion-color) .range-bar-active,:host(.ion-color) .range-knob,:host(.ion-color) .range-knob::before,:host(.ion-color) .range-pin,:host(.ion-color) .range-pin::before,:host(.ion-color) .range-tick{background:var(--ion-color-base);color:var(--ion-color-contrast)}::slotted([slot=start]){-webkit-margin-start:0;margin-inline-start:0;-webkit-margin-end:14px;margin-inline-end:14px;margin-top:0;margin-bottom:0}::slotted([slot=end]){-webkit-margin-start:14px;margin-inline-start:14px;-webkit-margin-end:0;margin-inline-end:0;margin-top:0;margin-bottom:0}:host(.range-has-pin:not(.range-label-placement-stacked)){padding-top:1.75rem}:host(.range-has-pin.range-label-placement-stacked) .label-text-wrapper{margin-bottom:1.75rem}.range-bar-active{bottom:0;width:auto;background:var(--bar-background-active)}.range-knob{-webkit-transform:scale(0.67);transform:scale(0.67);-webkit-transition-duration:120ms;transition-duration:120ms;-webkit-transition-property:background-color, border, -webkit-transform;transition-property:background-color, border, -webkit-transform;transition-property:transform, background-color, border;transition-property:transform, background-color, border, -webkit-transform;-webkit-transition-timing-function:ease;transition-timing-function:ease;z-index:2}.range-knob::before{border-radius:50%;position:absolute;width:var(--knob-size);height:var(--knob-size);-webkit-transform:scale(1);transform:scale(1);-webkit-transition:0.267s cubic-bezier(0, 0, 0.58, 1);transition:0.267s cubic-bezier(0, 0, 0.58, 1);background:var(--knob-background);content:\"\";opacity:0.13;pointer-events:none}.range-knob::before{inset-inline-start:0}.range-tick{position:absolute;top:calc((var(--height) - var(--bar-height)) / 2);width:var(--bar-height);height:var(--bar-height);background:var(--bar-background-active);z-index:1;pointer-events:none}.range-tick-active{background:transparent}.range-pin{padding-left:0;padding-right:0;padding-top:8px;padding-bottom:8px;border-radius:50%;-webkit-transform:translate3d(0, 0, 0) scale(0.01);transform:translate3d(0, 0, 0) scale(0.01);display:-ms-flexbox;display:flex;-ms-flex-align:center;align-items:center;-ms-flex-pack:center;justify-content:center;width:1.75rem;height:1.75rem;-webkit-transition:background 120ms ease, -webkit-transform 120ms ease;transition:background 120ms ease, -webkit-transform 120ms ease;transition:transform 120ms ease, background 120ms ease;transition:transform 120ms ease, background 120ms ease, -webkit-transform 120ms ease;background:var(--pin-background);color:var(--pin-color)}.range-pin::before{bottom:-1px;-webkit-margin-start:-13px;margin-inline-start:-13px;border-radius:50% 50% 50% 0;position:absolute;width:26px;height:26px;-webkit-transform:rotate(-45deg);transform:rotate(-45deg);-webkit-transition:background 120ms ease;transition:background 120ms ease;background:var(--pin-background);content:\"\";z-index:-1}.range-pin::before{inset-inline-start:50%}:host-context([dir=rtl]) .range-pin::before{left:unset}[dir=rtl] .range-pin::before{left:unset}@supports selector(:dir(rtl)){.range-pin::before:dir(rtl){left:unset}}.range-knob-pressed .range-pin,.range-knob-handle.ion-focused .range-pin{-webkit-transform:translate3d(0, calc(-100% + 4px), 0) scale(1);transform:translate3d(0, calc(-100% + 4px), 0) scale(1)}@media (any-hover: hover){.range-knob-handle:hover .range-knob:before{-webkit-transform:scale(2);transform:scale(2);opacity:0.13}}.range-knob-handle.ion-activated .range-knob:before,.range-knob-handle.ion-focused .range-knob:before,.range-knob-handle.range-knob-pressed .range-knob:before{-webkit-transform:scale(2);transform:scale(2)}.range-knob-handle.ion-focused .range-knob::before{opacity:0.13}.range-knob-handle.ion-activated .range-knob::before,.range-knob-handle.range-knob-pressed .range-knob::before{opacity:0.25}:host(:not(.range-has-pin)) .range-knob-pressed .range-knob,:host(:not(.range-has-pin)) .range-knob-handle.ion-focused .range-knob{-webkit-transform:scale(1);transform:scale(1)}:host(.range-disabled) .range-bar-active,:host(.range-disabled) .range-bar,:host(.range-disabled) .range-tick{background-color:var(--ion-color-step-250, var(--ion-background-color-step-250, #bfbfbf))}:host(.range-disabled) .range-knob{-webkit-transform:scale(0.55);transform:scale(0.55);outline:5px solid #fff;background-color:var(--ion-color-step-250, var(--ion-background-color-step-250, #bfbfbf))}:host(.range-disabled) .label-text-wrapper,:host(.range-disabled) ::slotted([slot=start]),:host(.range-disabled) ::slotted([slot=end]){opacity:0.38}";
  61. const IonRangeMdStyle0 = rangeMdCss;
  62. const Range = class {
  63. constructor(hostRef) {
  64. index.registerInstance(this, hostRef);
  65. this.ionChange = index.createEvent(this, "ionChange", 7);
  66. this.ionInput = index.createEvent(this, "ionInput", 7);
  67. this.ionFocus = index.createEvent(this, "ionFocus", 7);
  68. this.ionBlur = index.createEvent(this, "ionBlur", 7);
  69. this.ionKnobMoveStart = index.createEvent(this, "ionKnobMoveStart", 7);
  70. this.ionKnobMoveEnd = index.createEvent(this, "ionKnobMoveEnd", 7);
  71. this.rangeId = `ion-r-${rangeIds++}`;
  72. this.didLoad = false;
  73. this.noUpdate = false;
  74. this.hasFocus = false;
  75. this.inheritedAttributes = {};
  76. this.contentEl = null;
  77. this.initialContentScrollY = true;
  78. /**
  79. * Compares two RangeValue inputs to determine if they are different.
  80. *
  81. * @param newVal - The new value.
  82. * @param oldVal - The old value.
  83. * @returns `true` if the values are different, `false` otherwise.
  84. */
  85. this.compareValues = (newVal, oldVal) => {
  86. if (typeof newVal === 'object' && typeof oldVal === 'object') {
  87. return newVal.lower !== oldVal.lower || newVal.upper !== oldVal.upper;
  88. }
  89. return newVal !== oldVal;
  90. };
  91. this.clampBounds = (value) => {
  92. return helpers.clamp(this.min, value, this.max);
  93. };
  94. this.ensureValueInBounds = (value) => {
  95. if (this.dualKnobs) {
  96. return {
  97. lower: this.clampBounds(value.lower),
  98. upper: this.clampBounds(value.upper),
  99. };
  100. }
  101. else {
  102. return this.clampBounds(value);
  103. }
  104. };
  105. this.setupGesture = async () => {
  106. const rangeSlider = this.rangeSlider;
  107. if (rangeSlider) {
  108. this.gesture = (await Promise.resolve().then(function () { return require('./index-ee07ed59.js'); })).createGesture({
  109. el: rangeSlider,
  110. gestureName: 'range',
  111. gesturePriority: 100,
  112. /**
  113. * Provide a threshold since the drag movement
  114. * might be a user scrolling the view.
  115. * If this is true, then the range
  116. * should not move.
  117. */
  118. threshold: 10,
  119. onStart: () => this.onStart(),
  120. onMove: (ev) => this.onMove(ev),
  121. onEnd: (ev) => this.onEnd(ev),
  122. });
  123. this.gesture.enable(!this.disabled);
  124. }
  125. };
  126. this.handleKeyboard = (knob, isIncrease) => {
  127. const { ensureValueInBounds } = this;
  128. let step = this.step;
  129. step = step > 0 ? step : 1;
  130. step = step / (this.max - this.min);
  131. if (!isIncrease) {
  132. step *= -1;
  133. }
  134. if (knob === 'A') {
  135. this.ratioA = helpers.clamp(0, this.ratioA + step, 1);
  136. }
  137. else {
  138. this.ratioB = helpers.clamp(0, this.ratioB + step, 1);
  139. }
  140. this.ionKnobMoveStart.emit({ value: ensureValueInBounds(this.value) });
  141. this.updateValue();
  142. this.emitValueChange();
  143. this.ionKnobMoveEnd.emit({ value: ensureValueInBounds(this.value) });
  144. };
  145. this.onBlur = () => {
  146. if (this.hasFocus) {
  147. this.hasFocus = false;
  148. this.ionBlur.emit();
  149. }
  150. };
  151. this.onFocus = () => {
  152. if (!this.hasFocus) {
  153. this.hasFocus = true;
  154. this.ionFocus.emit();
  155. }
  156. };
  157. this.ratioA = 0;
  158. this.ratioB = 0;
  159. this.pressedKnob = undefined;
  160. this.color = undefined;
  161. this.debounce = undefined;
  162. this.name = this.rangeId;
  163. this.label = undefined;
  164. this.dualKnobs = false;
  165. this.min = 0;
  166. this.max = 100;
  167. this.pin = false;
  168. this.pinFormatter = (value) => Math.round(value);
  169. this.snaps = false;
  170. this.step = 1;
  171. this.ticks = true;
  172. this.activeBarStart = undefined;
  173. this.disabled = false;
  174. this.value = 0;
  175. this.labelPlacement = 'start';
  176. }
  177. debounceChanged() {
  178. const { ionInput, debounce, originalIonInput } = this;
  179. /**
  180. * If debounce is undefined, we have to manually revert the ionInput emitter in case
  181. * debounce used to be set to a number. Otherwise, the event would stay debounced.
  182. */
  183. this.ionInput = debounce === undefined ? originalIonInput !== null && originalIonInput !== void 0 ? originalIonInput : ionInput : helpers.debounceEvent(ionInput, debounce);
  184. }
  185. minChanged(newValue) {
  186. if (!helpers.isSafeNumber(newValue)) {
  187. this.min = 0;
  188. }
  189. if (!this.noUpdate) {
  190. this.updateRatio();
  191. }
  192. }
  193. maxChanged(newValue) {
  194. if (!helpers.isSafeNumber(newValue)) {
  195. this.max = 100;
  196. }
  197. if (!this.noUpdate) {
  198. this.updateRatio();
  199. }
  200. }
  201. stepChanged(newValue) {
  202. if (!helpers.isSafeNumber(newValue)) {
  203. this.step = 1;
  204. }
  205. }
  206. activeBarStartChanged() {
  207. const { activeBarStart } = this;
  208. if (activeBarStart !== undefined) {
  209. if (activeBarStart > this.max) {
  210. index$1.printIonWarning(`[ion-range] - The value of activeBarStart (${activeBarStart}) is greater than the max (${this.max}). Valid values are greater than or equal to the min value and less than or equal to the max value.`, this.el);
  211. this.activeBarStart = this.max;
  212. }
  213. else if (activeBarStart < this.min) {
  214. index$1.printIonWarning(`[ion-range] - The value of activeBarStart (${activeBarStart}) is less than the min (${this.min}). Valid values are greater than or equal to the min value and less than or equal to the max value.`, this.el);
  215. this.activeBarStart = this.min;
  216. }
  217. }
  218. }
  219. disabledChanged() {
  220. if (this.gesture) {
  221. this.gesture.enable(!this.disabled);
  222. }
  223. }
  224. valueChanged(newValue, oldValue) {
  225. const valuesChanged = this.compareValues(newValue, oldValue);
  226. if (valuesChanged) {
  227. this.ionInput.emit({ value: this.value });
  228. }
  229. if (!this.noUpdate) {
  230. this.updateRatio();
  231. }
  232. }
  233. componentWillLoad() {
  234. /**
  235. * If user has custom ID set then we should
  236. * not assign the default incrementing ID.
  237. */
  238. if (this.el.hasAttribute('id')) {
  239. this.rangeId = this.el.getAttribute('id');
  240. }
  241. this.inheritedAttributes = helpers.inheritAriaAttributes(this.el);
  242. // If min, max, or step are not safe, set them to 0, 100, and 1, respectively.
  243. // Each watch does this, but not before the initial load.
  244. this.min = helpers.isSafeNumber(this.min) ? this.min : 0;
  245. this.max = helpers.isSafeNumber(this.max) ? this.max : 100;
  246. this.step = helpers.isSafeNumber(this.step) ? this.step : 1;
  247. }
  248. componentDidLoad() {
  249. this.originalIonInput = this.ionInput;
  250. this.setupGesture();
  251. this.updateRatio();
  252. this.didLoad = true;
  253. }
  254. connectedCallback() {
  255. var _a;
  256. this.updateRatio();
  257. this.debounceChanged();
  258. this.disabledChanged();
  259. this.activeBarStartChanged();
  260. /**
  261. * If we have not yet rendered
  262. * ion-range, then rangeSlider is not defined.
  263. * But if we are moving ion-range via appendChild,
  264. * then rangeSlider will be defined.
  265. */
  266. if (this.didLoad) {
  267. this.setupGesture();
  268. }
  269. const ionContent = index$2.findClosestIonContent(this.el);
  270. this.contentEl = (_a = ionContent === null || ionContent === void 0 ? void 0 : ionContent.querySelector('.ion-content-scroll-host')) !== null && _a !== void 0 ? _a : ionContent;
  271. }
  272. disconnectedCallback() {
  273. if (this.gesture) {
  274. this.gesture.destroy();
  275. this.gesture = undefined;
  276. }
  277. }
  278. getValue() {
  279. var _a;
  280. const value = (_a = this.value) !== null && _a !== void 0 ? _a : 0;
  281. if (this.dualKnobs) {
  282. if (typeof value === 'object') {
  283. return value;
  284. }
  285. return {
  286. lower: 0,
  287. upper: value,
  288. };
  289. }
  290. else {
  291. if (typeof value === 'object') {
  292. return value.upper;
  293. }
  294. return value;
  295. }
  296. }
  297. /**
  298. * Emits an `ionChange` event.
  299. *
  300. * This API should be called for user committed changes.
  301. * This API should not be used for external value changes.
  302. */
  303. emitValueChange() {
  304. this.value = this.ensureValueInBounds(this.value);
  305. this.ionChange.emit({ value: this.value });
  306. }
  307. /**
  308. * The value should be updated on touch end or
  309. * when the component is being dragged.
  310. * This follows the native behavior of mobile devices.
  311. *
  312. * For example: When the user lifts their finger from the
  313. * screen after tapping the bar or dragging the bar or knob.
  314. */
  315. onStart() {
  316. this.ionKnobMoveStart.emit({ value: this.ensureValueInBounds(this.value) });
  317. }
  318. /**
  319. * The value should be updated while dragging the
  320. * bar or knob.
  321. *
  322. * While the user is dragging, the view
  323. * should not scroll. This is to prevent the user from
  324. * feeling disoriented while dragging.
  325. *
  326. * The user can scroll on the view if the knob or
  327. * bar is not being dragged.
  328. *
  329. * @param detail The details of the gesture event.
  330. */
  331. onMove(detail) {
  332. const { contentEl, pressedKnob } = this;
  333. const currentX = detail.currentX;
  334. /**
  335. * Since the user is dragging on the bar or knob, the view should not scroll.
  336. *
  337. * This only needs to be done once.
  338. */
  339. if (contentEl && this.pressedKnob === undefined) {
  340. this.initialContentScrollY = index$2.disableContentScrollY(contentEl);
  341. }
  342. /**
  343. * The `pressedKnob` can be undefined if the user just
  344. * started dragging the knob.
  345. *
  346. * This is necessary to determine which knob the user is dragging,
  347. * especially when it's a dual knob.
  348. * Plus, it determines when to apply certain styles.
  349. *
  350. * This only needs to be done once since the knob won't change
  351. * while the user is dragging.
  352. */
  353. if (pressedKnob === undefined) {
  354. this.setPressedKnob(currentX);
  355. }
  356. this.update(currentX);
  357. }
  358. /**
  359. * The value should be updated on touch end:
  360. * - When the user lifts their finger from the screen after
  361. * tapping the bar.
  362. *
  363. * @param detail The details of the gesture or mouse event.
  364. */
  365. onEnd(detail) {
  366. var _a;
  367. const { contentEl, initialContentScrollY } = this;
  368. const currentX = (_a = detail.currentX) !== null && _a !== void 0 ? _a : detail.clientX;
  369. /**
  370. * The `pressedKnob` can be undefined if the user never
  371. * dragged the knob. They just tapped on the bar.
  372. *
  373. * This is necessary to determine which knob the user is changing,
  374. * especially when it's a dual knob.
  375. * Plus, it determines when to apply certain styles.
  376. */
  377. if (this.pressedKnob === undefined) {
  378. this.setPressedKnob(currentX);
  379. }
  380. /**
  381. * The user is no longer dragging the bar or
  382. * knob (if they were dragging it).
  383. *
  384. * The user can now scroll on the view in the next gesture event.
  385. */
  386. if (contentEl && this.pressedKnob !== undefined) {
  387. index$2.resetContentScrollY(contentEl, initialContentScrollY);
  388. }
  389. // update the active knob's position
  390. this.update(currentX);
  391. /**
  392. * Reset the pressed knob to undefined since the user
  393. * may start dragging a different knob in the next gesture event.
  394. */
  395. this.pressedKnob = undefined;
  396. this.emitValueChange();
  397. this.ionKnobMoveEnd.emit({ value: this.ensureValueInBounds(this.value) });
  398. }
  399. update(currentX) {
  400. // figure out where the pointer is currently at
  401. // update the knob being interacted with
  402. const rect = this.rect;
  403. let ratio = helpers.clamp(0, (currentX - rect.left) / rect.width, 1);
  404. if (dir.isRTL(this.el)) {
  405. ratio = 1 - ratio;
  406. }
  407. if (this.snaps) {
  408. // snaps the ratio to the current value
  409. ratio = valueToRatio(ratioToValue(ratio, this.min, this.max, this.step), this.min, this.max);
  410. }
  411. // update which knob is pressed
  412. if (this.pressedKnob === 'A') {
  413. this.ratioA = ratio;
  414. }
  415. else {
  416. this.ratioB = ratio;
  417. }
  418. // Update input value
  419. this.updateValue();
  420. }
  421. setPressedKnob(currentX) {
  422. const rect = (this.rect = this.rangeSlider.getBoundingClientRect());
  423. // figure out which knob they started closer to
  424. let ratio = helpers.clamp(0, (currentX - rect.left) / rect.width, 1);
  425. if (dir.isRTL(this.el)) {
  426. ratio = 1 - ratio;
  427. }
  428. this.pressedKnob = !this.dualKnobs || Math.abs(this.ratioA - ratio) < Math.abs(this.ratioB - ratio) ? 'A' : 'B';
  429. this.setFocus(this.pressedKnob);
  430. }
  431. get valA() {
  432. return ratioToValue(this.ratioA, this.min, this.max, this.step);
  433. }
  434. get valB() {
  435. return ratioToValue(this.ratioB, this.min, this.max, this.step);
  436. }
  437. get ratioLower() {
  438. if (this.dualKnobs) {
  439. return Math.min(this.ratioA, this.ratioB);
  440. }
  441. const { activeBarStart } = this;
  442. if (activeBarStart == null) {
  443. return 0;
  444. }
  445. return valueToRatio(activeBarStart, this.min, this.max);
  446. }
  447. get ratioUpper() {
  448. if (this.dualKnobs) {
  449. return Math.max(this.ratioA, this.ratioB);
  450. }
  451. return this.ratioA;
  452. }
  453. updateRatio() {
  454. const value = this.getValue();
  455. const { min, max } = this;
  456. if (this.dualKnobs) {
  457. this.ratioA = valueToRatio(value.lower, min, max);
  458. this.ratioB = valueToRatio(value.upper, min, max);
  459. }
  460. else {
  461. this.ratioA = valueToRatio(value, min, max);
  462. }
  463. }
  464. updateValue() {
  465. this.noUpdate = true;
  466. const { valA, valB } = this;
  467. this.value = !this.dualKnobs
  468. ? valA
  469. : {
  470. lower: Math.min(valA, valB),
  471. upper: Math.max(valA, valB),
  472. };
  473. this.noUpdate = false;
  474. }
  475. setFocus(knob) {
  476. if (this.el.shadowRoot) {
  477. const knobEl = this.el.shadowRoot.querySelector(knob === 'A' ? '.range-knob-a' : '.range-knob-b');
  478. if (knobEl) {
  479. knobEl.focus();
  480. }
  481. }
  482. }
  483. /**
  484. * Returns true if content was passed to the "start" slot
  485. */
  486. get hasStartSlotContent() {
  487. return this.el.querySelector('[slot="start"]') !== null;
  488. }
  489. /**
  490. * Returns true if content was passed to the "end" slot
  491. */
  492. get hasEndSlotContent() {
  493. return this.el.querySelector('[slot="end"]') !== null;
  494. }
  495. get hasLabel() {
  496. return this.label !== undefined || this.el.querySelector('[slot="label"]') !== null;
  497. }
  498. renderRangeSlider() {
  499. var _a;
  500. const { min, max, step, handleKeyboard, pressedKnob, disabled, pin, ratioLower, ratioUpper, pinFormatter, inheritedAttributes, } = this;
  501. let barStart = `${ratioLower * 100}%`;
  502. let barEnd = `${100 - ratioUpper * 100}%`;
  503. const rtl = dir.isRTL(this.el);
  504. const start = rtl ? 'right' : 'left';
  505. const end = rtl ? 'left' : 'right';
  506. const tickStyle = (tick) => {
  507. return {
  508. [start]: tick[start],
  509. };
  510. };
  511. if (this.dualKnobs === false) {
  512. /**
  513. * When the value is less than the activeBarStart or the min value,
  514. * the knob will display at the start of the active bar.
  515. */
  516. if (this.valA < ((_a = this.activeBarStart) !== null && _a !== void 0 ? _a : this.min)) {
  517. /**
  518. * Sets the bar positions relative to the upper and lower limits.
  519. * Converts the ratio values into percentages, used as offsets for left/right styles.
  520. *
  521. * The ratioUpper refers to the knob position on the bar.
  522. * The ratioLower refers to the end position of the active bar (the value).
  523. */
  524. barStart = `${ratioUpper * 100}%`;
  525. barEnd = `${100 - ratioLower * 100}%`;
  526. }
  527. else {
  528. /**
  529. * Otherwise, the knob will display at the end of the active bar.
  530. *
  531. * The ratioLower refers to the start position of the active bar (the value).
  532. * The ratioUpper refers to the knob position on the bar.
  533. */
  534. barStart = `${ratioLower * 100}%`;
  535. barEnd = `${100 - ratioUpper * 100}%`;
  536. }
  537. }
  538. const barStyle = {
  539. [start]: barStart,
  540. [end]: barEnd,
  541. };
  542. const ticks = [];
  543. if (this.snaps && this.ticks) {
  544. for (let value = min; value <= max; value += step) {
  545. const ratio = valueToRatio(value, min, max);
  546. const ratioMin = Math.min(ratioLower, ratioUpper);
  547. const ratioMax = Math.max(ratioLower, ratioUpper);
  548. const tick = {
  549. ratio,
  550. /**
  551. * Sets the tick mark as active when the tick is between the min bounds and the knob.
  552. * When using activeBarStart, the tick mark will be active between the knob and activeBarStart.
  553. */
  554. active: ratio >= ratioMin && ratio <= ratioMax,
  555. };
  556. tick[start] = `${ratio * 100}%`;
  557. ticks.push(tick);
  558. }
  559. }
  560. return (index.h("div", { class: "range-slider", ref: (rangeEl) => (this.rangeSlider = rangeEl),
  561. /**
  562. * Since the gesture has a threshold, the value
  563. * won't change until the user has dragged past
  564. * the threshold. This is to prevent the range
  565. * from moving when the user is scrolling.
  566. *
  567. * This results in the value not being updated
  568. * and the event emitters not being triggered
  569. * if the user taps on the range. This is why
  570. * we need to listen for the "pointerUp" event.
  571. */
  572. onPointerUp: (ev) => {
  573. /**
  574. * If the user drags the knob on the web
  575. * version (does not occur on mobile),
  576. * the "pointerUp" event will be triggered
  577. * along with the gesture's events.
  578. * This leads to duplicate events.
  579. *
  580. * By checking if the pressedKnob is undefined,
  581. * we can determine if the "pointerUp" event was
  582. * triggered by a tap or a drag. If it was
  583. * dragged, the pressedKnob will be defined.
  584. */
  585. if (this.pressedKnob === undefined) {
  586. this.onStart();
  587. this.onEnd(ev);
  588. }
  589. } }, ticks.map((tick) => (index.h("div", { style: tickStyle(tick), role: "presentation", class: {
  590. 'range-tick': true,
  591. 'range-tick-active': tick.active,
  592. }, part: tick.active ? 'tick-active' : 'tick' }))), index.h("div", { class: "range-bar-container" }, index.h("div", { class: "range-bar", role: "presentation", part: "bar" }), index.h("div", { class: {
  593. 'range-bar': true,
  594. 'range-bar-active': true,
  595. 'has-ticks': ticks.length > 0,
  596. }, role: "presentation", style: barStyle, part: "bar-active" })), renderKnob(rtl, {
  597. knob: 'A',
  598. pressed: pressedKnob === 'A',
  599. value: this.valA,
  600. ratio: this.ratioA,
  601. pin,
  602. pinFormatter,
  603. disabled,
  604. handleKeyboard,
  605. min,
  606. max,
  607. inheritedAttributes,
  608. }), this.dualKnobs &&
  609. renderKnob(rtl, {
  610. knob: 'B',
  611. pressed: pressedKnob === 'B',
  612. value: this.valB,
  613. ratio: this.ratioB,
  614. pin,
  615. pinFormatter,
  616. disabled,
  617. handleKeyboard,
  618. min,
  619. max,
  620. inheritedAttributes,
  621. })));
  622. }
  623. render() {
  624. const { disabled, el, hasLabel, rangeId, pin, pressedKnob, labelPlacement, label } = this;
  625. const inItem = theme.hostContext('ion-item', el);
  626. /**
  627. * If there is no start content then the knob at
  628. * the min value will be cut off by the item margin.
  629. */
  630. const hasStartContent = (hasLabel && (labelPlacement === 'start' || labelPlacement === 'fixed')) || this.hasStartSlotContent;
  631. const needsStartAdjustment = inItem && !hasStartContent;
  632. /**
  633. * If there is no end content then the knob at
  634. * the max value will be cut off by the item margin.
  635. */
  636. const hasEndContent = (hasLabel && labelPlacement === 'end') || this.hasEndSlotContent;
  637. const needsEndAdjustment = inItem && !hasEndContent;
  638. const mode = ionicGlobal.getIonMode(this);
  639. helpers.renderHiddenInput(true, el, this.name, JSON.stringify(this.getValue()), disabled);
  640. return (index.h(index.Host, { key: '3e065039ee048f1f70d97dba5dae98fa1315d867', onFocusin: this.onFocus, onFocusout: this.onBlur, id: rangeId, class: theme.createColorClasses(this.color, {
  641. [mode]: true,
  642. 'in-item': inItem,
  643. 'range-disabled': disabled,
  644. 'range-pressed': pressedKnob !== undefined,
  645. 'range-has-pin': pin,
  646. [`range-label-placement-${labelPlacement}`]: true,
  647. 'range-item-start-adjustment': needsStartAdjustment,
  648. 'range-item-end-adjustment': needsEndAdjustment,
  649. }) }, index.h("label", { key: '27ff22842c9ea79a1b9495302b926f70c9080a95', class: "range-wrapper", id: "range-label" }, index.h("div", { key: 'da1f9784be02dfe87d2fef34931d8b7f2148189e', class: {
  650. 'label-text-wrapper': true,
  651. 'label-text-wrapper-hidden': !hasLabel,
  652. }, part: "label" }, label !== undefined ? index.h("div", { class: "label-text" }, label) : index.h("slot", { name: "label" })), index.h("div", { key: '4389bf30b08214f5b5917fc30976b38f7bcdd29b', class: "native-wrapper" }, index.h("slot", { key: 'ad1b2745f8b061ee189617bb5c567e4f1d02250c', name: "start" }), this.renderRangeSlider(), index.h("slot", { key: 'c6dec9e843e232af2a5f16a0f8ee56439c545d7a', name: "end" })))));
  653. }
  654. get el() { return index.getElement(this); }
  655. static get watchers() { return {
  656. "debounce": ["debounceChanged"],
  657. "min": ["minChanged"],
  658. "max": ["maxChanged"],
  659. "step": ["stepChanged"],
  660. "activeBarStart": ["activeBarStartChanged"],
  661. "disabled": ["disabledChanged"],
  662. "value": ["valueChanged"]
  663. }; }
  664. };
  665. const renderKnob = (rtl, { knob, value, ratio, min, max, disabled, pressed, pin, handleKeyboard, pinFormatter, inheritedAttributes }) => {
  666. const start = rtl ? 'right' : 'left';
  667. const knobStyle = () => {
  668. const style = {};
  669. style[start] = `${ratio * 100}%`;
  670. return style;
  671. };
  672. // The aria label should be preferred over visible text if both are specified
  673. const ariaLabel = inheritedAttributes['aria-label'];
  674. return (index.h("div", { onKeyDown: (ev) => {
  675. const key = ev.key;
  676. if (key === 'ArrowLeft' || key === 'ArrowDown') {
  677. handleKeyboard(knob, false);
  678. ev.preventDefault();
  679. ev.stopPropagation();
  680. }
  681. else if (key === 'ArrowRight' || key === 'ArrowUp') {
  682. handleKeyboard(knob, true);
  683. ev.preventDefault();
  684. ev.stopPropagation();
  685. }
  686. }, class: {
  687. 'range-knob-handle': true,
  688. 'range-knob-a': knob === 'A',
  689. 'range-knob-b': knob === 'B',
  690. 'range-knob-pressed': pressed,
  691. 'range-knob-min': value === min,
  692. 'range-knob-max': value === max,
  693. 'ion-activatable': true,
  694. 'ion-focusable': true,
  695. }, style: knobStyle(), role: "slider", tabindex: disabled ? -1 : 0, "aria-label": ariaLabel !== undefined ? ariaLabel : null, "aria-labelledby": ariaLabel === undefined ? 'range-label' : null, "aria-valuemin": min, "aria-valuemax": max, "aria-disabled": disabled ? 'true' : null, "aria-valuenow": value }, pin && (index.h("div", { class: "range-pin", role: "presentation", part: "pin" }, pinFormatter(value))), index.h("div", { class: "range-knob", role: "presentation", part: "knob" })));
  696. };
  697. const ratioToValue = (ratio, min, max, step) => {
  698. let value = (max - min) * ratio;
  699. if (step > 0) {
  700. // round to nearest multiple of step, then add min
  701. value = Math.round(value / step) * step + min;
  702. }
  703. const clampedValue = helpers.clamp(min, value, max);
  704. return roundToMaxDecimalPlaces(clampedValue, min, max, step);
  705. };
  706. const valueToRatio = (value, min, max) => {
  707. return helpers.clamp(0, (value - min) / (max - min), 1);
  708. };
  709. let rangeIds = 0;
  710. Range.style = {
  711. ios: IonRangeIosStyle0,
  712. md: IonRangeMdStyle0
  713. };
  714. exports.ion_range = Range;