input.utils-a7957fd6.js 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150
  1. /*!
  2. * (C) Ionic http://ionicframework.com - MIT License
  3. */
  4. 'use strict';
  5. const index = require('./index-c8d52405.js');
  6. const helpers = require('./helpers-8a48fdea.js');
  7. const index$1 = require('./index-cc858e97.js');
  8. /**
  9. * Used to update a scoped component that uses emulated slots. This fires when
  10. * content is passed into the slot or when the content inside of a slot changes.
  11. * This is not needed for components using native slots in the Shadow DOM.
  12. * @internal
  13. * @param el The host element to observe
  14. * @param slotName mutationCallback will fire when nodes on these slot(s) change
  15. * @param mutationCallback The callback to fire whenever the slotted content changes
  16. */
  17. const createSlotMutationController = (el, slotName, mutationCallback) => {
  18. let hostMutationObserver;
  19. let slottedContentMutationObserver;
  20. if (index.win !== undefined && 'MutationObserver' in index.win) {
  21. const slots = Array.isArray(slotName) ? slotName : [slotName];
  22. hostMutationObserver = new MutationObserver((entries) => {
  23. for (const entry of entries) {
  24. for (const node of entry.addedNodes) {
  25. /**
  26. * Check to see if the added node
  27. * is our slotted content.
  28. */
  29. if (node.nodeType === Node.ELEMENT_NODE && slots.includes(node.slot)) {
  30. /**
  31. * If so, we want to watch the slotted
  32. * content itself for changes. This lets us
  33. * detect when content inside of the slot changes.
  34. */
  35. mutationCallback();
  36. /**
  37. * Adding the listener in an raf
  38. * waits until Stencil moves the slotted element
  39. * into the correct place in the event that
  40. * slotted content is being added.
  41. */
  42. helpers.raf(() => watchForSlotChange(node));
  43. return;
  44. }
  45. }
  46. }
  47. });
  48. hostMutationObserver.observe(el, {
  49. childList: true,
  50. /**
  51. * This fixes an issue with the `ion-input` and
  52. * `ion-textarea` not re-rendering in some cases
  53. * when using the label slot functionality.
  54. *
  55. * HTML element patches in Stencil that are enabled
  56. * by the `experimentalSlotFixes` flag in Stencil v4
  57. * result in DOM manipulations that won't trigger
  58. * the current mutation observer configuration and
  59. * callback.
  60. */
  61. subtree: true,
  62. });
  63. }
  64. /**
  65. * Listen for changes inside of the slotted content.
  66. * We can listen for subtree changes here to be
  67. * informed of text within the slotted content
  68. * changing. Doing this on the host is possible
  69. * but it is much more expensive to do because
  70. * it also listens for changes to the internals
  71. * of the component.
  72. */
  73. const watchForSlotChange = (slottedEl) => {
  74. var _a;
  75. if (slottedContentMutationObserver) {
  76. slottedContentMutationObserver.disconnect();
  77. slottedContentMutationObserver = undefined;
  78. }
  79. slottedContentMutationObserver = new MutationObserver((entries) => {
  80. mutationCallback();
  81. for (const entry of entries) {
  82. for (const node of entry.removedNodes) {
  83. /**
  84. * If the element was removed then we
  85. * need to destroy the MutationObserver
  86. * so the element can be garbage collected.
  87. */
  88. if (node.nodeType === Node.ELEMENT_NODE && node.slot === slotName) {
  89. destroySlottedContentObserver();
  90. }
  91. }
  92. }
  93. });
  94. /**
  95. * Listen for changes inside of the element
  96. * as well as anything deep in the tree.
  97. * We listen on the parentElement so that we can
  98. * detect when slotted element itself is removed.
  99. */
  100. slottedContentMutationObserver.observe((_a = slottedEl.parentElement) !== null && _a !== void 0 ? _a : slottedEl, { subtree: true, childList: true });
  101. };
  102. const destroy = () => {
  103. if (hostMutationObserver) {
  104. hostMutationObserver.disconnect();
  105. hostMutationObserver = undefined;
  106. }
  107. destroySlottedContentObserver();
  108. };
  109. const destroySlottedContentObserver = () => {
  110. if (slottedContentMutationObserver) {
  111. slottedContentMutationObserver.disconnect();
  112. slottedContentMutationObserver = undefined;
  113. }
  114. };
  115. return {
  116. destroy,
  117. };
  118. };
  119. const getCounterText = (value, maxLength, counterFormatter) => {
  120. const valueLength = value == null ? 0 : value.toString().length;
  121. const defaultCounterText = defaultCounterFormatter(valueLength, maxLength);
  122. /**
  123. * If developers did not pass a custom formatter,
  124. * use the default one.
  125. */
  126. if (counterFormatter === undefined) {
  127. return defaultCounterText;
  128. }
  129. /**
  130. * Otherwise, try to use the custom formatter
  131. * and fallback to the default formatter if
  132. * there was an error.
  133. */
  134. try {
  135. return counterFormatter(valueLength, maxLength);
  136. }
  137. catch (e) {
  138. index$1.printIonError('[ion-input] - Exception in provided `counterFormatter`:', e);
  139. return defaultCounterText;
  140. }
  141. };
  142. const defaultCounterFormatter = (length, maxlength) => {
  143. return `${length} / ${maxlength}`;
  144. };
  145. exports.createSlotMutationController = createSlotMutationController;
  146. exports.getCounterText = getCounterText;