15839014aca5f32d659d07134c1891163a86bcb01eaf1c2239613fa85f6c0f4d0fa7ef9f0bcbb8e54ddedc4bc6b1ec79d5f0d3974d0d6b32196c5c53fa7c27 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151
  1. import { castArray } from 'lodash-unified';
  2. import { isFirefox } from '../../../utils/browser.mjs';
  3. const filterOption = (pattern, option) => {
  4. const lowerCase = pattern.toLowerCase();
  5. const label = option.label || option.value || "";
  6. return label.toLowerCase().includes(lowerCase);
  7. };
  8. const getMentionCtx = (inputEl, prefix, split) => {
  9. const { selectionEnd } = inputEl;
  10. if (selectionEnd === null)
  11. return;
  12. const inputValue = inputEl.value;
  13. const prefixArray = castArray(prefix);
  14. let splitIndex = -1;
  15. let mentionCtx;
  16. for (let i = selectionEnd - 1; i >= 0; --i) {
  17. const char = inputValue[i];
  18. if (char === split || char === "\n" || char === "\r") {
  19. splitIndex = i;
  20. continue;
  21. }
  22. if (prefixArray.includes(char)) {
  23. const end = splitIndex === -1 ? selectionEnd : splitIndex;
  24. const pattern = inputValue.slice(i + 1, end);
  25. mentionCtx = {
  26. pattern,
  27. start: i + 1,
  28. end,
  29. prefix: char,
  30. prefixIndex: i,
  31. splitIndex,
  32. selectionEnd
  33. };
  34. break;
  35. }
  36. }
  37. return mentionCtx;
  38. };
  39. const getCursorPosition = (element, options = {
  40. debug: false,
  41. useSelectionEnd: false
  42. }) => {
  43. const selectionStart = element.selectionStart !== null ? element.selectionStart : 0;
  44. const selectionEnd = element.selectionEnd !== null ? element.selectionEnd : 0;
  45. const position = options.useSelectionEnd ? selectionEnd : selectionStart;
  46. const properties = [
  47. "direction",
  48. "boxSizing",
  49. "width",
  50. "height",
  51. "overflowX",
  52. "overflowY",
  53. "borderTopWidth",
  54. "borderRightWidth",
  55. "borderBottomWidth",
  56. "borderLeftWidth",
  57. "borderStyle",
  58. "paddingTop",
  59. "paddingRight",
  60. "paddingBottom",
  61. "paddingLeft",
  62. "fontStyle",
  63. "fontVariant",
  64. "fontWeight",
  65. "fontStretch",
  66. "fontSize",
  67. "fontSizeAdjust",
  68. "lineHeight",
  69. "fontFamily",
  70. "textAlign",
  71. "textTransform",
  72. "textIndent",
  73. "textDecoration",
  74. "letterSpacing",
  75. "wordSpacing",
  76. "tabSize",
  77. "MozTabSize"
  78. ];
  79. if (options.debug) {
  80. const el = document.querySelector("#input-textarea-caret-position-mirror-div");
  81. if (el == null ? void 0 : el.parentNode)
  82. el.parentNode.removeChild(el);
  83. }
  84. const div = document.createElement("div");
  85. div.id = "input-textarea-caret-position-mirror-div";
  86. document.body.appendChild(div);
  87. const style = div.style;
  88. const computed = window.getComputedStyle(element);
  89. const isInput = element.nodeName === "INPUT";
  90. style.whiteSpace = isInput ? "nowrap" : "pre-wrap";
  91. if (!isInput)
  92. style.wordWrap = "break-word";
  93. style.position = "absolute";
  94. if (!options.debug)
  95. style.visibility = "hidden";
  96. properties.forEach((prop) => {
  97. if (isInput && prop === "lineHeight") {
  98. if (computed.boxSizing === "border-box") {
  99. const height = Number.parseInt(computed.height);
  100. const outerHeight = Number.parseInt(computed.paddingTop) + Number.parseInt(computed.paddingBottom) + Number.parseInt(computed.borderTopWidth) + Number.parseInt(computed.borderBottomWidth);
  101. const targetHeight = outerHeight + Number.parseInt(computed.lineHeight);
  102. if (height > targetHeight) {
  103. style.lineHeight = `${height - outerHeight}px`;
  104. } else if (height === targetHeight) {
  105. style.lineHeight = computed.lineHeight;
  106. } else {
  107. style.lineHeight = "0";
  108. }
  109. } else {
  110. style.lineHeight = computed.height;
  111. }
  112. } else {
  113. style[prop] = computed[prop];
  114. }
  115. });
  116. if (isFirefox()) {
  117. if (element.scrollHeight > Number.parseInt(computed.height)) {
  118. style.overflowY = "scroll";
  119. }
  120. } else {
  121. style.overflow = "hidden";
  122. }
  123. div.textContent = element.value.slice(0, Math.max(0, position));
  124. if (isInput && div.textContent) {
  125. div.textContent = div.textContent.replace(/\s/g, "\xA0");
  126. }
  127. const span = document.createElement("span");
  128. span.textContent = element.value.slice(Math.max(0, position)) || ".";
  129. span.style.position = "relative";
  130. span.style.left = `${-element.scrollLeft}px`;
  131. span.style.top = `${-element.scrollTop}px`;
  132. div.appendChild(span);
  133. const relativePosition = {
  134. top: span.offsetTop + Number.parseInt(computed.borderTopWidth),
  135. left: span.offsetLeft + Number.parseInt(computed.borderLeftWidth),
  136. height: Number.parseInt(computed.fontSize) * 1.5
  137. };
  138. if (options.debug) {
  139. span.style.backgroundColor = "#aaa";
  140. } else {
  141. document.body.removeChild(div);
  142. }
  143. if (relativePosition.left >= element.clientWidth) {
  144. relativePosition.left = element.clientWidth;
  145. }
  146. return relativePosition;
  147. };
  148. export { filterOption, getCursorPosition, getMentionCtx };
  149. //# sourceMappingURL=helper.mjs.map