@visactor/vtable-sheet 1.20.0-alpha.0

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.
Files changed (231) hide show
  1. package/cjs/components/vtable-sheet.d.ts +78 -0
  2. package/cjs/components/vtable-sheet.js +474 -0
  3. package/cjs/components/vtable-sheet.js.map +1 -0
  4. package/cjs/core/WorkSheet.d.ts +69 -0
  5. package/cjs/core/WorkSheet.js +298 -0
  6. package/cjs/core/WorkSheet.js.map +1 -0
  7. package/cjs/core/table-plugins.d.ts +3 -0
  8. package/cjs/core/table-plugins.js +171 -0
  9. package/cjs/core/table-plugins.js.map +1 -0
  10. package/cjs/event/event-manager.d.ts +29 -0
  11. package/cjs/event/event-manager.js +71 -0
  12. package/cjs/event/event-manager.js.map +1 -0
  13. package/cjs/event/event-target.d.ts +12 -0
  14. package/cjs/event/event-target.js +50 -0
  15. package/cjs/event/event-target.js.map +1 -0
  16. package/cjs/formula/cell-highlight-manager.d.ts +29 -0
  17. package/cjs/formula/cell-highlight-manager.js +141 -0
  18. package/cjs/formula/cell-highlight-manager.js.map +1 -0
  19. package/cjs/formula/formula-autocomplete.d.ts +39 -0
  20. package/cjs/formula/formula-autocomplete.js +239 -0
  21. package/cjs/formula/formula-autocomplete.js.map +1 -0
  22. package/cjs/formula/formula-editor.d.ts +21 -0
  23. package/cjs/formula/formula-editor.js +162 -0
  24. package/cjs/formula/formula-editor.js.map +1 -0
  25. package/cjs/formula/formula-helper.d.ts +8 -0
  26. package/cjs/formula/formula-helper.js +66 -0
  27. package/cjs/formula/formula-helper.js.map +1 -0
  28. package/cjs/formula/formula-range-selector.d.ts +19 -0
  29. package/cjs/formula/formula-range-selector.js +201 -0
  30. package/cjs/formula/formula-range-selector.js.map +1 -0
  31. package/cjs/formula/formula-throttle.d.ts +10 -0
  32. package/cjs/formula/formula-throttle.js +39 -0
  33. package/cjs/formula/formula-throttle.js.map +1 -0
  34. package/cjs/formula/formula-ui-manager.d.ts +19 -0
  35. package/cjs/formula/formula-ui-manager.js +226 -0
  36. package/cjs/formula/formula-ui-manager.js.map +1 -0
  37. package/cjs/formula/index.d.ts +5 -0
  38. package/cjs/formula/index.js +23 -0
  39. package/cjs/formula/index.js.map +1 -0
  40. package/cjs/index.d.ts +6 -0
  41. package/cjs/index.js +50 -0
  42. package/cjs/index.js.map +1 -0
  43. package/cjs/managers/formula-manager.d.ts +82 -0
  44. package/cjs/managers/formula-manager.js +445 -0
  45. package/cjs/managers/formula-manager.js.map +1 -0
  46. package/cjs/managers/menu-manager.d.ts +12 -0
  47. package/cjs/managers/menu-manager.js +89 -0
  48. package/cjs/managers/menu-manager.js.map +1 -0
  49. package/cjs/managers/sheet-manager.d.ts +21 -0
  50. package/cjs/managers/sheet-manager.js +74 -0
  51. package/cjs/managers/sheet-manager.js.map +1 -0
  52. package/cjs/managers/tab-drag-manager.d.ts +24 -0
  53. package/cjs/managers/tab-drag-manager.js +121 -0
  54. package/cjs/managers/tab-drag-manager.js.map +1 -0
  55. package/cjs/sheet-helper.d.ts +16 -0
  56. package/cjs/sheet-helper.js +64 -0
  57. package/cjs/sheet-helper.js.map +1 -0
  58. package/cjs/styles/common.d.ts +1 -0
  59. package/cjs/styles/common.js +17 -0
  60. package/cjs/styles/common.js.map +1 -0
  61. package/cjs/styles/formula-autocomplete.d.ts +1 -0
  62. package/cjs/styles/formula-autocomplete.js +17 -0
  63. package/cjs/styles/formula-autocomplete.js.map +1 -0
  64. package/cjs/styles/formula-bar.d.ts +1 -0
  65. package/cjs/styles/formula-bar.js +17 -0
  66. package/cjs/styles/formula-bar.js.map +1 -0
  67. package/cjs/styles/menu.d.ts +1 -0
  68. package/cjs/styles/menu.js +17 -0
  69. package/cjs/styles/menu.js.map +1 -0
  70. package/cjs/styles/sheet-tab.d.ts +1 -0
  71. package/cjs/styles/sheet-tab.js +17 -0
  72. package/cjs/styles/sheet-tab.js.map +1 -0
  73. package/cjs/styles/sheet.d.ts +1 -0
  74. package/cjs/styles/sheet.js +17 -0
  75. package/cjs/styles/sheet.js.map +1 -0
  76. package/cjs/styles/style-manager.d.ts +1 -0
  77. package/cjs/styles/style-manager.js +15 -0
  78. package/cjs/styles/style-manager.js.map +1 -0
  79. package/cjs/test/formula-complete.test.d.ts +1 -0
  80. package/cjs/test/formula-complete.test.js +42 -0
  81. package/cjs/test/formula-complete.test.js.map +1 -0
  82. package/cjs/tools/env.d.ts +20 -0
  83. package/cjs/tools/env.js +59 -0
  84. package/cjs/tools/env.js.map +1 -0
  85. package/cjs/tools/index.d.ts +3 -0
  86. package/cjs/tools/index.js +16 -0
  87. package/cjs/tools/index.js.map +1 -0
  88. package/cjs/tools/ui/snackbar.d.ts +1 -0
  89. package/cjs/tools/ui/snackbar.js +20 -0
  90. package/cjs/tools/ui/snackbar.js.map +1 -0
  91. package/cjs/ts-types/base.d.ts +44 -0
  92. package/cjs/ts-types/base.js +14 -0
  93. package/cjs/ts-types/base.js.map +1 -0
  94. package/cjs/ts-types/event.d.ts +79 -0
  95. package/cjs/ts-types/event.js +6 -0
  96. package/cjs/ts-types/event.js.map +1 -0
  97. package/cjs/ts-types/events.d.ts +1 -0
  98. package/cjs/ts-types/events.js +3 -0
  99. package/cjs/ts-types/events.js.map +1 -0
  100. package/cjs/ts-types/filter.d.ts +58 -0
  101. package/cjs/ts-types/filter.js +16 -0
  102. package/cjs/ts-types/filter.js.map +1 -0
  103. package/cjs/ts-types/formula.d.ts +51 -0
  104. package/cjs/ts-types/formula.js +6 -0
  105. package/cjs/ts-types/formula.js.map +1 -0
  106. package/cjs/ts-types/index.d.ts +67 -0
  107. package/cjs/ts-types/index.js +37 -0
  108. package/cjs/ts-types/index.js.map +1 -0
  109. package/cjs/ts-types/sheet.d.ts +45 -0
  110. package/cjs/ts-types/sheet.js +6 -0
  111. package/cjs/ts-types/sheet.js.map +1 -0
  112. package/cjs/vtable.d.ts +1 -0
  113. package/cjs/vtable.js +35 -0
  114. package/cjs/vtable.js.map +1 -0
  115. package/dist/vtable-sheet.js +114494 -0
  116. package/dist/vtable-sheet.min.js +853 -0
  117. package/es/components/vtable-sheet.d.ts +78 -0
  118. package/es/components/vtable-sheet.js +462 -0
  119. package/es/components/vtable-sheet.js.map +1 -0
  120. package/es/core/WorkSheet.d.ts +69 -0
  121. package/es/core/WorkSheet.js +298 -0
  122. package/es/core/WorkSheet.js.map +1 -0
  123. package/es/core/table-plugins.d.ts +3 -0
  124. package/es/core/table-plugins.js +164 -0
  125. package/es/core/table-plugins.js.map +1 -0
  126. package/es/event/event-manager.d.ts +29 -0
  127. package/es/event/event-manager.js +63 -0
  128. package/es/event/event-manager.js.map +1 -0
  129. package/es/event/event-target.d.ts +12 -0
  130. package/es/event/event-target.js +42 -0
  131. package/es/event/event-target.js.map +1 -0
  132. package/es/formula/cell-highlight-manager.d.ts +29 -0
  133. package/es/formula/cell-highlight-manager.js +133 -0
  134. package/es/formula/cell-highlight-manager.js.map +1 -0
  135. package/es/formula/formula-autocomplete.d.ts +39 -0
  136. package/es/formula/formula-autocomplete.js +231 -0
  137. package/es/formula/formula-autocomplete.js.map +1 -0
  138. package/es/formula/formula-editor.d.ts +21 -0
  139. package/es/formula/formula-editor.js +135 -0
  140. package/es/formula/formula-editor.js.map +1 -0
  141. package/es/formula/formula-helper.d.ts +8 -0
  142. package/es/formula/formula-helper.js +60 -0
  143. package/es/formula/formula-helper.js.map +1 -0
  144. package/es/formula/formula-range-selector.d.ts +19 -0
  145. package/es/formula/formula-range-selector.js +195 -0
  146. package/es/formula/formula-range-selector.js.map +1 -0
  147. package/es/formula/formula-throttle.d.ts +10 -0
  148. package/es/formula/formula-throttle.js +31 -0
  149. package/es/formula/formula-throttle.js.map +1 -0
  150. package/es/formula/formula-ui-manager.d.ts +19 -0
  151. package/es/formula/formula-ui-manager.js +218 -0
  152. package/es/formula/formula-ui-manager.js.map +1 -0
  153. package/es/formula/index.d.ts +5 -0
  154. package/es/formula/index.js +10 -0
  155. package/es/formula/index.js.map +1 -0
  156. package/es/index.d.ts +6 -0
  157. package/es/index.js +13 -0
  158. package/es/index.js.map +1 -0
  159. package/es/managers/formula-manager.d.ts +82 -0
  160. package/es/managers/formula-manager.js +441 -0
  161. package/es/managers/formula-manager.js.map +1 -0
  162. package/es/managers/menu-manager.d.ts +12 -0
  163. package/es/managers/menu-manager.js +81 -0
  164. package/es/managers/menu-manager.js.map +1 -0
  165. package/es/managers/sheet-manager.d.ts +21 -0
  166. package/es/managers/sheet-manager.js +66 -0
  167. package/es/managers/sheet-manager.js.map +1 -0
  168. package/es/managers/tab-drag-manager.d.ts +24 -0
  169. package/es/managers/tab-drag-manager.js +113 -0
  170. package/es/managers/tab-drag-manager.js.map +1 -0
  171. package/es/sheet-helper.d.ts +16 -0
  172. package/es/sheet-helper.js +54 -0
  173. package/es/sheet-helper.js.map +1 -0
  174. package/es/styles/common.d.ts +1 -0
  175. package/es/styles/common.js +9 -0
  176. package/es/styles/common.js.map +1 -0
  177. package/es/styles/formula-autocomplete.d.ts +1 -0
  178. package/es/styles/formula-autocomplete.js +9 -0
  179. package/es/styles/formula-autocomplete.js.map +1 -0
  180. package/es/styles/formula-bar.d.ts +1 -0
  181. package/es/styles/formula-bar.js +9 -0
  182. package/es/styles/formula-bar.js.map +1 -0
  183. package/es/styles/menu.d.ts +1 -0
  184. package/es/styles/menu.js +9 -0
  185. package/es/styles/menu.js.map +1 -0
  186. package/es/styles/sheet-tab.d.ts +1 -0
  187. package/es/styles/sheet-tab.js +9 -0
  188. package/es/styles/sheet-tab.js.map +1 -0
  189. package/es/styles/sheet.d.ts +1 -0
  190. package/es/styles/sheet.js +9 -0
  191. package/es/styles/sheet.js.map +1 -0
  192. package/es/styles/style-manager.d.ts +1 -0
  193. package/es/styles/style-manager.js +17 -0
  194. package/es/styles/style-manager.js.map +1 -0
  195. package/es/test/formula-complete.test.d.ts +1 -0
  196. package/es/test/formula-complete.test.js +36 -0
  197. package/es/test/formula-complete.test.js.map +1 -0
  198. package/es/tools/env.d.ts +20 -0
  199. package/es/tools/env.js +53 -0
  200. package/es/tools/env.js.map +1 -0
  201. package/es/tools/index.d.ts +3 -0
  202. package/es/tools/index.js +9 -0
  203. package/es/tools/index.js.map +1 -0
  204. package/es/tools/ui/snackbar.d.ts +1 -0
  205. package/es/tools/ui/snackbar.js +14 -0
  206. package/es/tools/ui/snackbar.js.map +1 -0
  207. package/es/ts-types/base.d.ts +44 -0
  208. package/es/ts-types/base.js +14 -0
  209. package/es/ts-types/base.js.map +1 -0
  210. package/es/ts-types/event.d.ts +79 -0
  211. package/es/ts-types/event.js +2 -0
  212. package/es/ts-types/event.js.map +1 -0
  213. package/es/ts-types/events.d.ts +1 -0
  214. package/es/ts-types/events.js +3 -0
  215. package/es/ts-types/events.js.map +1 -0
  216. package/es/ts-types/filter.d.ts +58 -0
  217. package/es/ts-types/filter.js +16 -0
  218. package/es/ts-types/filter.js.map +1 -0
  219. package/es/ts-types/formula.d.ts +51 -0
  220. package/es/ts-types/formula.js +2 -0
  221. package/es/ts-types/formula.js.map +1 -0
  222. package/es/ts-types/index.d.ts +67 -0
  223. package/es/ts-types/index.js +14 -0
  224. package/es/ts-types/index.js.map +1 -0
  225. package/es/ts-types/sheet.d.ts +45 -0
  226. package/es/ts-types/sheet.js +2 -0
  227. package/es/ts-types/sheet.js.map +1 -0
  228. package/es/vtable.d.ts +1 -0
  229. package/es/vtable.js +2 -0
  230. package/es/vtable.js.map +1 -0
  231. package/package.json +120 -0
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/formula/formula-helper.ts"],"names":[],"mappings":";;;AAAa,QAAA,kBAAkB,GAAG;IAChC,KAAK;IACL,SAAS;IACT,KAAK;IACL,KAAK;IACL,OAAO;IACP,QAAQ;IACR,IAAI;IACJ,KAAK;IACL,IAAI;IACJ,KAAK;IACL,OAAO;IACP,OAAO;IACP,SAAS;IACT,KAAK;IACL,MAAM;IACN,OAAO;IACP,KAAK;IACL,KAAK;IACL,MAAM;IACN,OAAO;IACP,KAAK;IACL,MAAM;IACN,OAAO;IACP,KAAK;IACL,MAAM;IACN,QAAQ;IACR,QAAQ;CACT,CAAC;AAQF,SAAS,sBAAsB,CAAC,OAAe,EAAE,cAAsB;IACrE,IAAI,KAAK,GAAG,CAAC,CAAC;IAEd,KAAK,IAAI,CAAC,GAAG,cAAc,GAAG,CAAC,EAAE,CAAC,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE;QACxD,IAAI,OAAO,CAAC,CAAC,CAAC,KAAK,GAAG,EAAE;YACtB,KAAK,EAAE,CAAC;SACT;aAAM,IAAI,OAAO,CAAC,CAAC,CAAC,KAAK,GAAG,EAAE;YAC7B,KAAK,EAAE,CAAC;YACR,IAAI,KAAK,KAAK,CAAC,EAAE;gBACf,OAAO,CAAC,CAAC;aACV;SACF;KACF;IAED,OAAO,CAAC,CAAC,CAAC;AACZ,CAAC;AAQD,SAAgB,+BAA+B,CAC7C,OAAe,EACf,cAAsB;IAStB,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE;QAC5B,OAAO;YACL,WAAW,EAAE,KAAK;YAClB,qBAAqB,EAAE,IAAI;SAC5B,CAAC;KACH;IAID,MAAM,aAAa,GAAG,mBAAmB,CAAC;IAC1C,IAAI,KAAK,CAAC;IACV,IAAI,oBAAoB,GAAG,CAAC,CAAC,CAAC;IAG9B,OAAO,CAAC,KAAK,GAAG,aAAa,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,KAAK,IAAI,EAAE;QACrD,MAAM,YAAY,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC;QAC5C,MAAM,aAAa,GAAG,KAAK,CAAC,KAAK,CAAC;QAClC,MAAM,cAAc,GAAG,OAAO,CAAC,OAAO,CAAC,GAAG,EAAE,aAAa,CAAC,CAAC;QAG3D,IAAI,cAAc,GAAG,cAAc,IAAI,cAAc,GAAG,oBAAoB,EAAE;YAE5E,MAAM,eAAe,GAAG,sBAAsB,CAAC,OAAO,EAAE,cAAc,CAAC,CAAC;YAGxE,IAAI,cAAc,GAAG,cAAc,IAAI,CAAC,eAAe,KAAK,CAAC,CAAC,IAAI,cAAc,IAAI,eAAe,CAAC,EAAE;gBACpG,OAAO;oBACL,WAAW,EAAE,IAAI;oBACjB,qBAAqB,EAAE;wBACrB,KAAK,EAAE,cAAc,GAAG,CAAC;wBACzB,GAAG,EAAE,cAAc;qBACpB;iBACF,CAAC;aACH;YAGD,IAAI,cAAc,KAAK,cAAc,GAAG,CAAC,EAAE;gBACzC,OAAO;oBACL,WAAW,EAAE,IAAI;oBACjB,qBAAqB,EAAE;wBACrB,KAAK,EAAE,cAAc,GAAG,CAAC;wBACzB,GAAG,EAAE,cAAc;qBACpB;iBACF,CAAC;aACH;YAGD,oBAAoB,GAAG,cAAc,CAAC;SACvC;KACF;IAGD,IAAI,cAAc,GAAG,CAAC,IAAI,cAAc,IAAI,OAAO,CAAC,MAAM,EAAE;QAC1D,MAAM,QAAQ,GAAG,OAAO,CAAC,cAAc,GAAG,CAAC,CAAC,CAAC;QAC7C,IAAI,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,CAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE;YACnF,OAAO;gBACL,WAAW,EAAE,IAAI;gBACjB,qBAAqB,EAAE;oBACrB,KAAK,EAAE,cAAc;oBACrB,GAAG,EAAE,cAAc;iBACpB;aACF,CAAC;SACH;KACF;IAGD,IAAI,cAAc,KAAK,CAAC,IAAI,OAAO,CAAC,CAAC,CAAC,KAAK,GAAG,EAAE;QAC9C,OAAO;YACL,WAAW,EAAE,IAAI;YACjB,qBAAqB,EAAE;gBACrB,KAAK,EAAE,cAAc;gBACrB,GAAG,EAAE,cAAc;aACpB;SACF,CAAC;KACH;IAGD,OAAO;QACL,WAAW,EAAE,KAAK;QAClB,qBAAqB,EAAE,IAAI;KAC5B,CAAC;AACJ,CAAC;AA5FD,0EA4FC","file":"formula-helper.js","sourcesContent":["export const supportedFunctions = [\n 'SUM',\n 'AVERAGE',\n 'MAX',\n 'MIN',\n 'COUNT',\n 'COUNTA',\n 'IF',\n 'AND',\n 'OR',\n 'NOT',\n 'ROUND',\n 'FLOOR',\n 'CEILING',\n 'ABS',\n 'SQRT',\n 'POWER',\n 'MOD',\n 'INT',\n 'RAND',\n 'TODAY',\n 'NOW',\n 'YEAR',\n 'MONTH',\n 'DAY',\n 'HOUR',\n 'MINUTE',\n 'SECOND'\n];\n\n/**\n * 查找匹配的右括号\n * @param formula 公式内容\n * @param openParenIndex 左括号的位置\n * @returns 匹配的右括号位置,若未找到则返回-1\n */\nfunction findMatchingCloseParen(formula: string, openParenIndex: number): number {\n let depth = 1; // 括号深度计数\n\n for (let i = openParenIndex + 1; i < formula.length; i++) {\n if (formula[i] === '(') {\n depth++;\n } else if (formula[i] === ')') {\n depth--;\n if (depth === 0) {\n return i; // 找到匹配的右括号\n }\n }\n }\n\n return -1; // 未找到匹配的右括号\n}\n\n/**\n * 检测函数参数位置\n * @param formula 公式内容\n * @param cursorPosition 光标位置\n * @returns 是否在函数参数位置\n */\nexport function detectFunctionParameterPosition(\n formula: string,\n cursorPosition: number\n): {\n inParamMode: boolean;\n functionParamPosition: {\n start: number;\n end: number;\n } | null;\n} {\n // 基本检查\n if (!formula.startsWith('=')) {\n return {\n inParamMode: false,\n functionParamPosition: null\n };\n }\n\n // 1. 先检查是否在函数参数位置\n // 匹配所有函数调用模式:FUNCTION_NAME(\n const functionRegex = /([A-Za-z]+)\\s*\\(/g;\n let match;\n let positionBeforeCursor = -1;\n\n // 查找距离光标最近的左括号\n while ((match = functionRegex.exec(formula)) !== null) {\n const functionName = match[1].toUpperCase();\n const functionStart = match.index;\n const openParenIndex = formula.indexOf('(', functionStart);\n\n // 如果光标在函数名之后,且这个函数比之前找到的更接近光标\n if (openParenIndex < cursorPosition && openParenIndex > positionBeforeCursor) {\n // 查找对应的右括号位置\n const closeParenIndex = findMatchingCloseParen(formula, openParenIndex);\n\n // 检查光标是否在函数参数位置(在左括号之后且在右括号之前或没有找到右括号)\n if (cursorPosition > openParenIndex && (closeParenIndex === -1 || cursorPosition <= closeParenIndex)) {\n return {\n inParamMode: true,\n functionParamPosition: {\n start: openParenIndex + 1,\n end: cursorPosition\n }\n };\n }\n\n // 如果光标正好在括号后面,也认为是参数位置\n if (cursorPosition === openParenIndex + 1) {\n return {\n inParamMode: true,\n functionParamPosition: {\n start: openParenIndex + 1,\n end: cursorPosition\n }\n };\n }\n\n // 记录这个左括号位置,用于比较\n positionBeforeCursor = openParenIndex;\n }\n }\n\n // 2. 检查是否在操作符后面 - 也将此视为函数参数模式\n if (cursorPosition > 1 && cursorPosition <= formula.length) {\n const prevChar = formula[cursorPosition - 1];\n if (['+', '-', '*', '/', '=', '>', '<', '&', '|', '^', '(', ','].includes(prevChar)) {\n return {\n inParamMode: true,\n functionParamPosition: {\n start: cursorPosition,\n end: cursorPosition\n }\n };\n }\n }\n\n // 3. 检查是否在公式开始位置 - 公式开始后也视为可能需要函数输入\n if (cursorPosition === 1 && formula[0] === '=') {\n return {\n inParamMode: true,\n functionParamPosition: {\n start: cursorPosition,\n end: cursorPosition\n }\n };\n }\n\n // 默认情况,不在任何特殊位置\n return {\n inParamMode: false,\n functionParamPosition: null\n };\n}\n"]}
@@ -0,0 +1,19 @@
1
+ import type { FormulaManager } from '../managers/formula-manager';
2
+ import type { CellRange, CellValueChangedEvent } from '../ts-types';
3
+ export interface FunctionParamPosition {
4
+ start: number;
5
+ end: number;
6
+ }
7
+ export declare class FormulaRangeSelector {
8
+ private formulaManager;
9
+ constructor(formulaManager: FormulaManager);
10
+ selectionsToA1Notation(selections: any[], addressFromCoord: (row: number, col: number) => string): string;
11
+ insertA1ReferenceInFunction(formulaInput: HTMLInputElement, a1Notation: string, isCtrlAddSelection: boolean): void;
12
+ private findCurrentArgumentPosition;
13
+ handleSelectionChanged(selections: CellRange[], formulaInput: HTMLInputElement, isCtrlAddSelection: boolean, addressFromCoord: (row: number, col: number) => string): void;
14
+ handleCellValueChanged(event: CellValueChangedEvent): void;
15
+ handleSelectionChangedForRangeMode(event: any): void;
16
+ private hasFormulaDependents;
17
+ private ensureCursorVisible;
18
+ release(): void;
19
+ }
@@ -0,0 +1,201 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: !0
5
+ }), exports.FormulaRangeSelector = void 0;
6
+
7
+ const formula_throttle_1 = require("./formula-throttle"), formula_helper_1 = require("./formula-helper");
8
+
9
+ class FormulaRangeSelector {
10
+ constructor(formulaManager) {
11
+ this.formulaManager = formulaManager;
12
+ }
13
+ selectionsToA1Notation(selections, addressFromCoord) {
14
+ if (!selections || 0 === selections.length) return "";
15
+ const ranges = [];
16
+ for (const range of selections) {
17
+ const startAddr = addressFromCoord(range.startRow, range.startCol), endAddr = addressFromCoord(range.endRow, range.endCol);
18
+ range.startRow === range.endRow && range.startCol === range.endCol ? ranges.push(startAddr) : ranges.push(`${startAddr}:${endAddr}`);
19
+ }
20
+ return ranges.join(",");
21
+ }
22
+ insertA1ReferenceInFunction(formulaInput, a1Notation, isCtrlAddSelection) {
23
+ if (!this.formulaManager.inputIsParamMode.inParamMode) return;
24
+ const currentValue = formulaInput.value, cursorPos = this.formulaManager.lastKnownCursorPosInFormulaInput, argPosition = this.findCurrentArgumentPosition(currentValue, cursorPos);
25
+ let newValue;
26
+ if (argPosition) if (isCtrlAddSelection) {
27
+ newValue = currentValue.substring(argPosition.start, argPosition.end).trim() ? currentValue.slice(0, argPosition.end) + ("," === currentValue[argPosition.end - 1] ? " " : ", ") + a1Notation + currentValue.slice(argPosition.end) : currentValue.slice(0, argPosition.start) + a1Notation + currentValue.slice(argPosition.end);
28
+ } else newValue = currentValue.slice(0, argPosition.start) + a1Notation + currentValue.slice(argPosition.end); else newValue = currentValue;
29
+ formulaInput.value = newValue, this.formulaManager.setCellContent({
30
+ sheet: this.formulaManager.sheet.getActiveSheet().getKey(),
31
+ row: this.formulaManager.sheet.getActiveSheet().editingCell.row,
32
+ col: this.formulaManager.sheet.getActiveSheet().editingCell.col
33
+ }, newValue);
34
+ const newCursorPos = isCtrlAddSelection ? this.formulaManager.lastKnownCursorPosInFormulaInput + (newValue.length - currentValue.length) : argPosition ? argPosition.start + a1Notation.length : cursorPos;
35
+ formulaInput.setSelectionRange(newCursorPos, newCursorPos), setTimeout((() => {
36
+ this.ensureCursorVisible(formulaInput, newCursorPos);
37
+ })), this.formulaManager.inputIsParamMode.functionParamPosition = {
38
+ start: newCursorPos,
39
+ end: newCursorPos
40
+ };
41
+ const inputEvent = new Event("input", {
42
+ bubbles: !0
43
+ });
44
+ Object.defineProperty(inputEvent, "isFormulaInsertion", {
45
+ value: !0
46
+ }), formulaInput.dispatchEvent(inputEvent);
47
+ }
48
+ findCurrentArgumentPosition(formula, cursorPos) {
49
+ if (cursorPos > 1 && cursorPos <= formula.length) {
50
+ const prevChar = formula[cursorPos - 1];
51
+ if ([ "+", "-", "*", "/", "=", ">", "<", "&", "|", "^" ].includes(prevChar)) return {
52
+ start: cursorPos,
53
+ end: cursorPos
54
+ };
55
+ }
56
+ if (!formula.includes("(")) return null;
57
+ let lastOpenParenBeforeCursor = -1, nestLevel = 0, inQuote = !1;
58
+ for (let i = 0; i < cursorPos; i++) {
59
+ const char = formula[i];
60
+ '"' !== char || 0 !== i && "\\" === formula[i - 1] ? inQuote || ("(" === char ? (nestLevel++,
61
+ lastOpenParenBeforeCursor = i) : ")" === char && nestLevel--) : inQuote = !inQuote;
62
+ }
63
+ if (-1 === lastOpenParenBeforeCursor || nestLevel <= 0) return formula.startsWith("=") && 1 === cursorPos ? {
64
+ start: cursorPos,
65
+ end: cursorPos
66
+ } : null;
67
+ if (cursorPos === lastOpenParenBeforeCursor + 1) return {
68
+ start: cursorPos,
69
+ end: cursorPos
70
+ };
71
+ if (cursorPos > 0 && "," === formula[cursorPos - 1]) return {
72
+ start: cursorPos,
73
+ end: cursorPos
74
+ };
75
+ let argumentStart = lastOpenParenBeforeCursor + 1, argumentEnd = cursorPos;
76
+ nestLevel = 1, inQuote = !1;
77
+ for (let i = argumentStart; i < cursorPos; i++) {
78
+ const char = formula[i];
79
+ if ('"' !== char || 0 !== i && "\\" === formula[i - 1]) {
80
+ if (!inQuote) if ("(" === char) nestLevel++; else if (")" === char) {
81
+ if (nestLevel--, 0 === nestLevel) break;
82
+ } else "," === char && 1 === nestLevel && (argumentStart = i + 1);
83
+ } else inQuote = !inQuote;
84
+ }
85
+ nestLevel = 0, inQuote = !1;
86
+ for (let i = 0; i < cursorPos; i++) '"' !== formula[i] || 0 !== i && "\\" === formula[i - 1] ? inQuote || ("(" === formula[i] && nestLevel++,
87
+ ")" === formula[i] && nestLevel--) : inQuote = !inQuote;
88
+ argumentEnd = formula.length;
89
+ for (let i = cursorPos; i < formula.length; i++) {
90
+ const char = formula[i];
91
+ if ('"' !== char || 0 !== i && "\\" === formula[i - 1]) {
92
+ if (!inQuote) if ("(" === char) nestLevel++; else if (")" === char) {
93
+ if (nestLevel--, 0 === nestLevel) {
94
+ argumentEnd = i;
95
+ break;
96
+ }
97
+ } else if ("," === char && 1 === nestLevel) {
98
+ argumentEnd = i;
99
+ break;
100
+ }
101
+ } else inQuote = !inQuote;
102
+ }
103
+ const paramContentBefore = formula.substring(argumentStart, cursorPos).trim(), paramContentAfter = formula.substring(cursorPos, argumentEnd).trim();
104
+ return "" === paramContentBefore && cursorPos === argumentStart ? {
105
+ start: argumentStart,
106
+ end: argumentStart
107
+ } : ("" === paramContentAfter && cursorPos < argumentEnd && (argumentEnd = cursorPos),
108
+ {
109
+ start: argumentStart,
110
+ end: argumentEnd
111
+ });
112
+ }
113
+ handleSelectionChanged(selections, formulaInput, isCtrlAddSelection, addressFromCoord) {
114
+ if (!this.formulaManager.inputIsParamMode.inParamMode || !selections || 0 === selections.length) return;
115
+ const a1Notation = this.selectionsToA1Notation(selections, addressFromCoord);
116
+ a1Notation && this.insertA1ReferenceInFunction(formulaInput, a1Notation, isCtrlAddSelection);
117
+ }
118
+ handleCellValueChanged(event) {
119
+ var _a, _b, _c;
120
+ const activeWorkSheet = this.formulaManager.sheet.getActiveSheet(), formulaManager = this.formulaManager.sheet.formulaManager;
121
+ if (activeWorkSheet && !this.formulaManager.formulaWorkingOnCell) try {
122
+ const newValue = event.newValue;
123
+ if ("string" == typeof newValue && newValue.startsWith("=") && newValue.length > 1) try {
124
+ const currentCellAddress = activeWorkSheet.addressFromCoord(event.row, event.col);
125
+ if (new RegExp(`(^|[^A-Za-z0-9])${currentCellAddress}([^A-Za-z0-9]|$)`).test(newValue)) return null === (_a = activeWorkSheet.tableInstance) || void 0 === _a || _a.changeCellValue(event.col, event.row, "#CYCLE!", !0, !1),
126
+ void (this.formulaManager.formulaWorkingOnCell = null);
127
+ formulaManager.setCellContent({
128
+ sheet: activeWorkSheet.getKey(),
129
+ row: event.row,
130
+ col: event.col
131
+ }, newValue);
132
+ const result = formulaManager.getCellValue({
133
+ sheet: activeWorkSheet.getKey(),
134
+ row: event.row,
135
+ col: event.col
136
+ });
137
+ null === (_b = activeWorkSheet.tableInstance) || void 0 === _b || _b.changeCellValue(event.col, event.row, result.value, !0, !1),
138
+ this.formulaManager.formulaWorkingOnCell = null;
139
+ } catch (error) {
140
+ null === (_c = activeWorkSheet.tableInstance) || void 0 === _c || _c.changeCellValue(event.col, event.row, "#ERROR!", !0, !1),
141
+ this.formulaManager.formulaWorkingOnCell = null;
142
+ } else formulaManager.setCellContent({
143
+ sheet: activeWorkSheet.getKey(),
144
+ row: event.row,
145
+ col: event.col
146
+ }, newValue);
147
+ const formulaThrottle = formula_throttle_1.FormulaThrottle.getInstance();
148
+ if (this.hasFormulaDependents({
149
+ sheet: activeWorkSheet.getKey(),
150
+ row: event.row,
151
+ col: event.col
152
+ })) {
153
+ formulaManager.getCellDependents({
154
+ sheet: activeWorkSheet.getKey(),
155
+ row: event.row,
156
+ col: event.col
157
+ }).forEach((dependent => {
158
+ const result = formulaManager.getCellValue(dependent);
159
+ activeWorkSheet && activeWorkSheet.setCellValue(dependent.row, dependent.col, result.value);
160
+ })), formulaThrottle.immediateRebuildAndRecalculate(formulaManager);
161
+ } else formulaThrottle.throttledRebuildAndRecalculate(formulaManager);
162
+ } catch (error) {}
163
+ }
164
+ handleSelectionChangedForRangeMode(event) {
165
+ var _a;
166
+ const activeWorkSheet = this.formulaManager.sheet.getActiveSheet(), formulaWorkingOnCell = this.formulaManager.formulaWorkingOnCell, formulaManager = this.formulaManager.sheet.formulaManager;
167
+ if (!activeWorkSheet || !formulaWorkingOnCell) return;
168
+ const formulaInput = this.formulaManager.inputingElement;
169
+ if (!formulaInput) return;
170
+ if (this.formulaManager.inputIsParamMode = (0, formula_helper_1.detectFunctionParameterPosition)(formulaInput.value, this.formulaManager.lastKnownCursorPosInFormulaInput),
171
+ !this.formulaManager.inputIsParamMode.inParamMode) return;
172
+ document.activeElement !== formulaInput && formulaInput.focus();
173
+ const selections = activeWorkSheet.getMultipleSelections(), todoSelection = selections[selections.length - 1];
174
+ let isCtrlAddSelection = !1;
175
+ if ((null == selections ? void 0 : selections.length) > (null === (_a = formulaManager.lastSelectionRangesOfHandling) || void 0 === _a ? void 0 : _a.length) && (isCtrlAddSelection = !0),
176
+ formulaManager.lastSelectionRangesOfHandling = selections, !selections || 0 === selections.length) return;
177
+ const editCell = formulaManager.formulaWorkingOnCell, safeSelections = this.formulaManager.sheet.excludeEditCellFromSelection(todoSelection, (null == editCell ? void 0 : editCell.row) || 0, (null == editCell ? void 0 : editCell.col) || 0);
178
+ this.handleSelectionChanged([ safeSelections ], formulaInput, isCtrlAddSelection, ((row, col) => activeWorkSheet.addressFromCoord(row, col)));
179
+ }
180
+ hasFormulaDependents(cell) {
181
+ try {
182
+ return this.formulaManager.getCellDependents(cell).length > 0;
183
+ } catch (error) {
184
+ return !1;
185
+ }
186
+ }
187
+ ensureCursorVisible(input, cursorPos) {
188
+ const tempSpan = document.createElement("span"), inputStyle = window.getComputedStyle(input);
189
+ tempSpan.style.font = inputStyle.font, tempSpan.style.letterSpacing = inputStyle.letterSpacing,
190
+ tempSpan.style.position = "absolute", tempSpan.style.visibility = "hidden", tempSpan.style.whiteSpace = "pre",
191
+ tempSpan.textContent = input.value.substring(0, cursorPos), document.body.appendChild(tempSpan);
192
+ const cursorOffset = tempSpan.offsetWidth;
193
+ document.body.removeChild(tempSpan);
194
+ const inputScrollLeft = input.scrollLeft, inputWidth = input.clientWidth, paddingLeft = parseFloat(inputStyle.paddingLeft), paddingRight = parseFloat(inputStyle.paddingRight), visibleWidth = inputWidth - paddingLeft - paddingRight;
195
+ cursorOffset < inputScrollLeft + paddingLeft ? input.scrollLeft = Math.max(0, cursorOffset - paddingLeft) : cursorOffset > inputScrollLeft + visibleWidth && (input.scrollLeft = cursorOffset - visibleWidth + paddingRight);
196
+ }
197
+ release() {}
198
+ }
199
+
200
+ exports.FormulaRangeSelector = FormulaRangeSelector;
201
+ //# sourceMappingURL=formula-range-selector.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/formula/formula-range-selector.ts"],"names":[],"mappings":"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","file":"formula-range-selector.js","sourcesContent":["/**\n * 公式范围选择器\n * 实现Excel风格的公式输入体验:用户输入\"=sum(\"后,选择单元格范围自动插入A1引用\n */\n\nimport { FormulaThrottle } from './formula-throttle';\nimport type { FormulaManager } from '../managers/formula-manager';\nimport type { CellRange, CellValueChangedEvent, FormulaCell } from '../ts-types';\nimport { detectFunctionParameterPosition } from './formula-helper';\n\nexport interface FunctionParamPosition {\n start: number;\n end: number;\n}\n\nexport class FormulaRangeSelector {\n private formulaManager: FormulaManager;\n constructor(formulaManager: FormulaManager) {\n this.formulaManager = formulaManager;\n }\n\n /**\n * 将选择范围转换为A1格式\n * @param selections 选择范围数组\n * @param addressFromCoord 坐标转地址函数\n * @returns A1格式字符串\n */\n selectionsToA1Notation(selections: any[], addressFromCoord: (row: number, col: number) => string): string {\n if (!selections || selections.length === 0) {\n return '';\n }\n\n const ranges: string[] = [];\n\n for (const range of selections) {\n const startAddr = addressFromCoord(range.startRow, range.startCol);\n const endAddr = addressFromCoord(range.endRow, range.endCol);\n\n // 如果是单个单元格(start和end相同)\n if (range.startRow === range.endRow && range.startCol === range.endCol) {\n ranges.push(startAddr);\n } else {\n // 如果是范围,使用冒号分隔\n ranges.push(`${startAddr}:${endAddr}`);\n }\n }\n\n return ranges.join(',');\n }\n\n insertA1ReferenceInFunction(formulaInput: HTMLInputElement, a1Notation: string, isCtrlAddSelection: boolean): void {\n if (!this.formulaManager.inputIsParamMode.inParamMode) {\n return;\n }\n\n const currentValue = formulaInput.value;\n const cursorPos = this.formulaManager.lastKnownCursorPosInFormulaInput;\n\n // 找到当前光标所处的参数位置\n const argPosition = this.findCurrentArgumentPosition(currentValue, cursorPos);\n\n // 在函数参数位置插入或替换A1引用\n let newValue;\n\n if (argPosition) {\n if (isCtrlAddSelection) {\n // Ctrl模式:追加而非替换\n const currentArg = currentValue.substring(argPosition.start, argPosition.end).trim();\n\n if (currentArg) {\n // 如果当前参数不为空,追加逗号和新引用\n newValue =\n currentValue.slice(0, argPosition.end) +\n (currentValue[argPosition.end - 1] === ',' ? ' ' : ', ') +\n a1Notation +\n currentValue.slice(argPosition.end);\n } else {\n // 如果当前参数为空,直接插入新引用\n newValue = currentValue.slice(0, argPosition.start) + a1Notation + currentValue.slice(argPosition.end);\n }\n } else {\n // 替换模式:完全替换当前参数\n newValue = currentValue.slice(0, argPosition.start) + a1Notation + currentValue.slice(argPosition.end);\n }\n } else {\n // 防止newValue未定义\n newValue = currentValue;\n }\n\n formulaInput.value = newValue;\n // 首先设置公式内容\n this.formulaManager.setCellContent(\n {\n sheet: this.formulaManager.sheet.getActiveSheet().getKey(),\n row: this.formulaManager.sheet.getActiveSheet().editingCell.row,\n col: this.formulaManager.sheet.getActiveSheet().editingCell.col\n },\n newValue\n );\n // 设置光标位置到插入内容之后\n const newCursorPos = isCtrlAddSelection\n ? this.formulaManager.lastKnownCursorPosInFormulaInput + (newValue.length - currentValue.length)\n : argPosition\n ? argPosition.start + a1Notation.length\n : cursorPos;\n\n formulaInput.setSelectionRange(newCursorPos, newCursorPos);\n setTimeout(() => {\n // 确保光标位置在可视区域内\n this.ensureCursorVisible(formulaInput, newCursorPos);\n });\n // 更新函数参数位置\n this.formulaManager.inputIsParamMode.functionParamPosition = {\n start: newCursorPos,\n end: newCursorPos\n };\n\n // 触发输入事件以更新高亮\n const inputEvent = new Event('input', { bubbles: true });\n Object.defineProperty(inputEvent, 'isFormulaInsertion', { value: true });\n formulaInput.dispatchEvent(inputEvent);\n }\n /**\n * 找到光标所在的参数位置\n * @param formula 公式文本\n * @param cursorPos 光标位置\n * @returns 参数的起始和结束位置\n */\n private findCurrentArgumentPosition(formula: string, cursorPos: number): { start: number; end: number } | null {\n // 首先检查光标是否在操作符后面\n if (cursorPos > 1 && cursorPos <= formula.length) {\n const prevChar = formula[cursorPos - 1];\n if (['+', '-', '*', '/', '=', '>', '<', '&', '|', '^'].includes(prevChar)) {\n // 光标在操作符后面,将光标位置视为参数的起始和结束位置\n return {\n start: cursorPos,\n end: cursorPos\n };\n }\n }\n\n // 检查公式是否包含括号\n if (!formula.includes('(')) {\n return null;\n }\n\n // 从后向前查找最接近光标的左括号\n let lastOpenParenBeforeCursor = -1;\n let nestLevel = 0;\n let inQuote = false;\n\n // 第一阶段:找到光标所在的函数调用\n for (let i = 0; i < cursorPos; i++) {\n const char = formula[i];\n\n // 处理引号内的内容\n if (char === '\"' && (i === 0 || formula[i - 1] !== '\\\\')) {\n inQuote = !inQuote;\n continue;\n }\n\n // 如果在引号内,忽略所有特殊字符\n if (inQuote) {\n continue;\n }\n\n if (char === '(') {\n nestLevel++;\n lastOpenParenBeforeCursor = i;\n } else if (char === ')') {\n nestLevel--;\n }\n }\n\n // 如果没有找到左括号或者光标不在任何括号内\n if (lastOpenParenBeforeCursor === -1 || nestLevel <= 0) {\n // 检查是否在公式开始位置\n if (formula.startsWith('=') && cursorPos === 1) {\n return {\n start: cursorPos,\n end: cursorPos\n };\n }\n\n return null;\n }\n\n // 特殊处理:光标恰好在左括号后面\n if (cursorPos === lastOpenParenBeforeCursor + 1) {\n return {\n start: cursorPos,\n end: cursorPos\n };\n }\n\n // 特殊处理:光标在逗号后面\n if (cursorPos > 0 && formula[cursorPos - 1] === ',') {\n return {\n start: cursorPos,\n end: cursorPos\n };\n }\n\n // 找到当前参数的起始位置\n let argumentStart = lastOpenParenBeforeCursor + 1;\n let argumentEnd = cursorPos;\n\n // 重置状态\n nestLevel = 1; // 从左括号开始,嵌套级别为1\n inQuote = false;\n\n // 从找到的左括号位置向光标方向扫描,找到当前参数的起始位置\n for (let i = argumentStart; i < cursorPos; i++) {\n const char = formula[i];\n\n if (char === '\"' && (i === 0 || formula[i - 1] !== '\\\\')) {\n inQuote = !inQuote;\n continue;\n }\n if (inQuote) {\n continue;\n }\n\n if (char === '(') {\n nestLevel++;\n } else if (char === ')') {\n nestLevel--;\n if (nestLevel === 0) {\n // 如果回到了函数最外层,则这个右括号后面的内容不再是当前函数的参数\n break;\n }\n } else if (char === ',' && nestLevel === 1) {\n // 如果是当前函数层级的参数分隔符,更新参数开始位置\n argumentStart = i + 1;\n }\n }\n\n // 重置状态,准备从光标位置向后扫描\n nestLevel = 0;\n inQuote = false;\n\n // 重新计算光标位置的嵌套级别\n for (let i = 0; i < cursorPos; i++) {\n if (formula[i] === '\"' && (i === 0 || formula[i - 1] !== '\\\\')) {\n inQuote = !inQuote;\n continue;\n }\n if (inQuote) {\n continue;\n }\n\n if (formula[i] === '(') {\n nestLevel++;\n }\n if (formula[i] === ')') {\n nestLevel--;\n }\n }\n\n // 从光标位置向后查找参数结束位置\n argumentEnd = formula.length;\n for (let i = cursorPos; i < formula.length; i++) {\n const char = formula[i];\n\n if (char === '\"' && (i === 0 || formula[i - 1] !== '\\\\')) {\n inQuote = !inQuote;\n continue;\n }\n if (inQuote) {\n continue;\n }\n\n if (char === '(') {\n nestLevel++;\n } else if (char === ')') {\n nestLevel--;\n // 如果回到了当前函数的右括号\n if (nestLevel === 0) {\n argumentEnd = i;\n break;\n }\n } else if (char === ',' && nestLevel === 1) {\n // 找到下一个同级参数的分隔符\n argumentEnd = i;\n break;\n }\n }\n\n // 处理空参数的情况\n const paramContentBefore = formula.substring(argumentStart, cursorPos).trim();\n const paramContentAfter = formula.substring(cursorPos, argumentEnd).trim();\n\n if (paramContentBefore === '' && cursorPos === argumentStart) {\n // 光标在参数起始位置,且参数为空\n return {\n start: argumentStart,\n end: argumentStart\n };\n }\n\n if (paramContentAfter === '' && cursorPos < argumentEnd) {\n // 光标后面到结束位置都是空白\n argumentEnd = cursorPos;\n }\n\n return {\n start: argumentStart,\n end: argumentEnd\n };\n }\n /**\n * 处理单元格选择变化\n * @param selections 当前选择范围\n * @param formulaInput 公式输入框\n * @param addressFromCoord 坐标转地址函数\n */\n handleSelectionChanged(\n selections: CellRange[],\n formulaInput: HTMLInputElement,\n isCtrlAddSelection: boolean,\n addressFromCoord: (row: number, col: number) => string\n ): void {\n if (!this.formulaManager.inputIsParamMode.inParamMode || !selections || selections.length === 0) {\n return;\n }\n\n const a1Notation = this.selectionsToA1Notation(selections, addressFromCoord);\n if (a1Notation) {\n this.insertA1ReferenceInFunction(formulaInput, a1Notation, isCtrlAddSelection);\n }\n }\n\n /**\n * 处理单元格值变更事件\n * @param event 事件\n */\n handleCellValueChanged(event: CellValueChangedEvent): void {\n console.log('handleCellValueChanged', event);\n const activeWorkSheet = this.formulaManager.sheet.getActiveSheet();\n const formulaManager = this.formulaManager.sheet.formulaManager;\n\n if (!activeWorkSheet || this.formulaManager.formulaWorkingOnCell) {\n return;\n }\n\n try {\n // 检查新输入的值是否为公式\n const newValue = event.newValue;\n if (typeof newValue === 'string' && newValue.startsWith('=') && newValue.length > 1) {\n try {\n // 检查是否包含循环引用\n const currentCellAddress = activeWorkSheet.addressFromCoord(event.row, event.col);\n // 使用正则表达式来精确匹配单元格引用\n const cellRegex = new RegExp(`(^|[^A-Za-z0-9])${currentCellAddress}([^A-Za-z0-9]|$)`);\n if (cellRegex.test(newValue)) {\n console.warn('Circular reference detected:', newValue, 'contains', currentCellAddress);\n activeWorkSheet.tableInstance?.changeCellValue(event.col, event.row, '#CYCLE!', true, false);\n this.formulaManager.formulaWorkingOnCell = null;\n return;\n }\n\n // 首先设置公式内容\n formulaManager.setCellContent(\n {\n sheet: activeWorkSheet.getKey(),\n row: event.row,\n col: event.col\n },\n newValue\n );\n\n // 获取计算结果\n const result = formulaManager.getCellValue({\n sheet: activeWorkSheet.getKey(),\n row: event.row,\n col: event.col\n });\n // // 检查当前单元格是否正在编辑(是否在公式栏中编辑)\n // const formulaInput = this.formulaManager.inputingElement;\n // const isEditing = document.activeElement === formulaInput;\n\n // 更新单元格显示 - 如果正在编辑则显示公式,否则显示计算结果\n // activeWorkSheet.tableInstance?.changeCellValue(event.col, event.row, isEditing ? newValue : result.value);\n activeWorkSheet.tableInstance?.changeCellValue(event.col, event.row, result.value, true, false);\n this.formulaManager.formulaWorkingOnCell = null;\n } catch (error) {\n console.warn('Formula processing error:', error);\n // 显示错误状态\n activeWorkSheet.tableInstance?.changeCellValue(event.col, event.row, '#ERROR!', true, false);\n this.formulaManager.formulaWorkingOnCell = null;\n }\n } else {\n // 非公式值,同步到HyperFormula\n formulaManager.setCellContent(\n {\n sheet: activeWorkSheet.getKey(),\n row: event.row,\n col: event.col\n },\n newValue\n );\n }\n\n // 使用FormulaThrottle来优化公式重新计算\n const formulaThrottle = FormulaThrottle.getInstance();\n // 判断是否需要立即更新\n const needImmediateUpdate = this.hasFormulaDependents({\n sheet: activeWorkSheet.getKey(),\n row: event.row,\n col: event.col\n });\n if (needImmediateUpdate) {\n // 更新依赖的公式\n const dependents = formulaManager.getCellDependents({\n sheet: activeWorkSheet.getKey(),\n row: event.row,\n col: event.col\n });\n\n // 重新计算依赖该单元格的所有公式\n dependents.forEach(dependent => {\n const result = formulaManager.getCellValue(dependent);\n if (activeWorkSheet) {\n activeWorkSheet.setCellValue(dependent.row, dependent.col, result.value);\n }\n });\n // 立即执行完整重新计算\n formulaThrottle.immediateRebuildAndRecalculate(formulaManager);\n } else {\n // 使用节流方式进行公式计算\n formulaThrottle.throttledRebuildAndRecalculate(formulaManager);\n }\n\n // // 如果当前编辑的单元格就是选中的单元格,更新 fx 输入框\n // const selection = this.activeWorkSheet.getSelection();\n // if (selection && selection.startRow === event.row && selection.startCol === event.col) {\n // this.updateFormulaBar();\n // }\n } catch (error) {\n console.error('Error in handleCellValueChanged:', error);\n }\n }\n\n /**\n * 处理范围选择模式下的单元格选中事件\n */\n handleSelectionChangedForRangeMode(event: any): void {\n console.log('handleSelectionChangedForRangeMode', event);\n const activeWorkSheet = this.formulaManager.sheet.getActiveSheet();\n const formulaWorkingOnCell = this.formulaManager.formulaWorkingOnCell;\n const formulaManager = this.formulaManager.sheet.formulaManager;\n if (!activeWorkSheet || !formulaWorkingOnCell) {\n return;\n }\n\n // const formulaInput = this.formulaInput;\n const formulaInput = this.formulaManager.inputingElement;\n // if (!formulaInput || this.formulaManager.isUpdatingFromFormula) {\n // return;\n // }\n // TODO 尝试全部去掉isUpdatingFromFormula的判断和赋值\n if (!formulaInput) {\n return;\n }\n\n // 不依赖 event.type 字符串,selection-end 已在上层绑定,这里直接处理\n\n this.formulaManager.inputIsParamMode = detectFunctionParameterPosition(\n formulaInput.value,\n this.formulaManager.lastKnownCursorPosInFormulaInput\n );\n if (!this.formulaManager.inputIsParamMode.inParamMode) {\n return;\n }\n\n if (document.activeElement !== formulaInput) {\n formulaInput.focus();\n }\n\n // 获取所有选择范围(支持Ctrl/Cmd多选)\n const selections = activeWorkSheet.getMultipleSelections();\n const todoSelection = selections[selections.length - 1];\n let isCtrlAddSelection = false;\n if (selections?.length > formulaManager.lastSelectionRangesOfHandling?.length) {\n isCtrlAddSelection = true;\n }\n formulaManager.lastSelectionRangesOfHandling = selections;\n if (!selections || selections.length === 0) {\n return;\n }\n\n // 排除当前编辑单元格,避免形成自引用导致 #CYCLE!\n const editCell = formulaManager.formulaWorkingOnCell;\n // const safeSelections = selections\n // .map(selection => this.excludeEditCellFromSelection(selection, editCell?.row || 0, editCell?.col || 0))\n // .filter(selection => selection.startRow >= 0 && selection.startCol >= 0); // 过滤掉无效选择\n const safeSelections = this.formulaManager.sheet.excludeEditCellFromSelection(\n todoSelection,\n editCell?.row || 0,\n editCell?.col || 0\n );\n\n this.handleSelectionChanged([safeSelections], formulaInput, isCtrlAddSelection, (row: number, col: number) =>\n activeWorkSheet!.addressFromCoord(row, col)\n );\n\n // 写入后不再刷新公式栏,以免覆盖刚插入的引用\n }\n\n /**\n * 检查单元格是否有公式依赖\n * @param cell 单元格\n * @returns 是否有公式依赖\n */\n private hasFormulaDependents(cell: FormulaCell): boolean {\n try {\n const dependents = this.formulaManager.getCellDependents(cell);\n return dependents.length > 0;\n } catch (error) {\n console.warn('Error checking formula dependents:', error);\n return false;\n }\n }\n\n /**\n * 确保光标位置在输入框的可视区域内\n * @param input 输入框元素\n * @param cursorPos 光标位置\n */\n private ensureCursorVisible(input: HTMLInputElement, cursorPos: number): void {\n // 创建一个临时元素来计算光标位置\n const tempSpan = document.createElement('span');\n const inputStyle = window.getComputedStyle(input);\n\n // 复制输入框的样式到临时元素\n tempSpan.style.font = inputStyle.font;\n tempSpan.style.letterSpacing = inputStyle.letterSpacing;\n tempSpan.style.position = 'absolute';\n tempSpan.style.visibility = 'hidden';\n tempSpan.style.whiteSpace = 'pre';\n\n // 设置文本内容为光标位置前的文本\n tempSpan.textContent = input.value.substring(0, cursorPos);\n document.body.appendChild(tempSpan);\n\n // 计算光标位置\n const cursorOffset = tempSpan.offsetWidth;\n document.body.removeChild(tempSpan);\n\n // 计算可视区域\n const inputScrollLeft = input.scrollLeft;\n const inputWidth = input.clientWidth;\n const paddingLeft = parseFloat(inputStyle.paddingLeft);\n const paddingRight = parseFloat(inputStyle.paddingRight);\n const visibleWidth = inputWidth - paddingLeft - paddingRight;\n\n // 调整滚动位置确保光标可见\n if (cursorOffset < inputScrollLeft + paddingLeft) {\n // 光标在可视区域左侧\n input.scrollLeft = Math.max(0, cursorOffset - paddingLeft);\n } else if (cursorOffset > inputScrollLeft + visibleWidth) {\n // 光标在可视区域右侧\n input.scrollLeft = cursorOffset - visibleWidth + paddingRight;\n }\n }\n\n release(): void {\n //do nothing\n }\n}\n"]}
@@ -0,0 +1,10 @@
1
+ import type { FormulaManager } from '../managers/formula-manager';
2
+ export declare class FormulaThrottle {
3
+ private static instance;
4
+ private recalcTimer;
5
+ private pendingRecalc;
6
+ private throttleDelay;
7
+ static getInstance(): FormulaThrottle;
8
+ throttledRebuildAndRecalculate(formulaManager: FormulaManager): void;
9
+ immediateRebuildAndRecalculate(formulaManager: FormulaManager): void;
10
+ }
@@ -0,0 +1,39 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: !0
5
+ }), exports.FormulaThrottle = void 0;
6
+
7
+ class FormulaThrottle {
8
+ constructor() {
9
+ this.recalcTimer = null, this.pendingRecalc = !1, this.throttleDelay = 150;
10
+ }
11
+ static getInstance() {
12
+ return FormulaThrottle.instance || (FormulaThrottle.instance = new FormulaThrottle),
13
+ FormulaThrottle.instance;
14
+ }
15
+ throttledRebuildAndRecalculate(formulaManager) {
16
+ if (formulaManager) if (null === this.recalcTimer) {
17
+ if (!this.pendingRecalc) try {
18
+ formulaManager.rebuildAndRecalculate();
19
+ } catch (e) {}
20
+ this.pendingRecalc = !1, this.recalcTimer = window.setTimeout((() => {
21
+ if (this.recalcTimer = null, this.pendingRecalc) try {
22
+ formulaManager.rebuildAndRecalculate(), this.pendingRecalc = !1;
23
+ } catch (e) {}
24
+ }), this.throttleDelay);
25
+ } else this.pendingRecalc = !0;
26
+ }
27
+ immediateRebuildAndRecalculate(formulaManager) {
28
+ if (formulaManager) {
29
+ null !== this.recalcTimer && (window.clearTimeout(this.recalcTimer), this.recalcTimer = null),
30
+ this.pendingRecalc = !1;
31
+ try {
32
+ formulaManager.rebuildAndRecalculate();
33
+ } catch (e) {}
34
+ }
35
+ }
36
+ }
37
+
38
+ exports.FormulaThrottle = FormulaThrottle;
39
+ //# sourceMappingURL=formula-throttle.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/formula/formula-throttle.ts"],"names":[],"mappings":";;;AAEA,MAAa,eAAe;IAA5B;QAEU,gBAAW,GAAkB,IAAI,CAAC;QAClC,kBAAa,GAAG,KAAK,CAAC;QACtB,kBAAa,GAAG,GAAG,CAAC;IAsE9B,CAAC;IApEC,MAAM,CAAC,WAAW;QAChB,IAAI,CAAC,eAAe,CAAC,QAAQ,EAAE;YAC7B,eAAe,CAAC,QAAQ,GAAG,IAAI,eAAe,EAAE,CAAC;SAClD;QACD,OAAO,eAAe,CAAC,QAAQ,CAAC;IAClC,CAAC;IAMD,8BAA8B,CAAC,cAA8B;QAC3D,IAAI,CAAC,cAAc,EAAE;YACnB,OAAO;SACR;QAGD,IAAI,IAAI,CAAC,WAAW,KAAK,IAAI,EAAE;YAC7B,IAAI,CAAC,aAAa,GAAG,IAAI,CAAC;YAC1B,OAAO;SACR;QAGD,IAAI,CAAC,IAAI,CAAC,aAAa,EAAE;YACvB,IAAI;gBACF,cAAc,CAAC,qBAAqB,EAAE,CAAC;aACxC;YAAC,OAAO,CAAC,EAAE;gBACV,OAAO,CAAC,IAAI,CAAC,+CAA+C,EAAE,CAAC,CAAC,CAAC;aAClE;SACF;QAED,IAAI,CAAC,aAAa,GAAG,KAAK,CAAC;QAC3B,IAAI,CAAC,WAAW,GAAG,MAAM,CAAC,UAAU,CAAC,GAAG,EAAE;YACxC,IAAI,CAAC,WAAW,GAAG,IAAI,CAAC;YACxB,IAAI,IAAI,CAAC,aAAa,EAAE;gBACtB,IAAI;oBACF,cAAc,CAAC,qBAAqB,EAAE,CAAC;oBACvC,IAAI,CAAC,aAAa,GAAG,KAAK,CAAC;iBAC5B;gBAAC,OAAO,CAAC,EAAE;oBACV,OAAO,CAAC,IAAI,CAAC,wDAAwD,EAAE,CAAC,CAAC,CAAC;iBAC3E;aACF;QACH,CAAC,EAAE,IAAI,CAAC,aAAa,CAAC,CAAC;IACzB,CAAC;IAMD,8BAA8B,CAAC,cAA8B;QAC3D,IAAI,CAAC,cAAc,EAAE;YACnB,OAAO;SACR;QAGD,IAAI,IAAI,CAAC,WAAW,KAAK,IAAI,EAAE;YAC7B,MAAM,CAAC,YAAY,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;YACtC,IAAI,CAAC,WAAW,GAAG,IAAI,CAAC;SACzB;QAED,IAAI,CAAC,aAAa,GAAG,KAAK,CAAC;QAE3B,IAAI;YACF,cAAc,CAAC,qBAAqB,EAAE,CAAC;SACxC;QAAC,OAAO,CAAC,EAAE;YACV,OAAO,CAAC,IAAI,CAAC,yDAAyD,EAAE,CAAC,CAAC,CAAC;SAC5E;IACH,CAAC;CACF;AA1ED,0CA0EC","file":"formula-throttle.js","sourcesContent":["import type { FormulaManager } from '../managers/formula-manager';\n\nexport class FormulaThrottle {\n private static instance: FormulaThrottle;\n private recalcTimer: number | null = null;\n private pendingRecalc = false;\n private throttleDelay = 150; // ms\n\n static getInstance(): FormulaThrottle {\n if (!FormulaThrottle.instance) {\n FormulaThrottle.instance = new FormulaThrottle();\n }\n return FormulaThrottle.instance;\n }\n\n /**\n * 节流方式调用公式重建和重新计算\n * @param formulaManager 公式管理器实例\n */\n throttledRebuildAndRecalculate(formulaManager: FormulaManager): void {\n if (!formulaManager) {\n return;\n }\n\n // 如果有定时器正在等待,直接返回\n if (this.recalcTimer !== null) {\n this.pendingRecalc = true;\n return;\n }\n\n // 如果没有待处理的重新计算,执行一次,然后设置定时器\n if (!this.pendingRecalc) {\n try {\n formulaManager.rebuildAndRecalculate();\n } catch (e) {\n console.warn('Error during formula rebuild and recalculate:', e);\n }\n }\n\n this.pendingRecalc = false;\n this.recalcTimer = window.setTimeout(() => {\n this.recalcTimer = null;\n if (this.pendingRecalc) {\n try {\n formulaManager.rebuildAndRecalculate();\n this.pendingRecalc = false;\n } catch (e) {\n console.warn('Error during formula rebuild and recalculate in timer:', e);\n }\n }\n }, this.throttleDelay);\n }\n\n /**\n * 立即执行一次计算,并取消任何待处理的计算\n * @param formulaManager 公式管理器实例\n */\n immediateRebuildAndRecalculate(formulaManager: FormulaManager): void {\n if (!formulaManager) {\n return;\n }\n\n // 清除任何待处理的计时器\n if (this.recalcTimer !== null) {\n window.clearTimeout(this.recalcTimer);\n this.recalcTimer = null;\n }\n\n this.pendingRecalc = false;\n\n try {\n formulaManager.rebuildAndRecalculate();\n } catch (e) {\n console.warn('Error during immediate formula rebuild and recalculate:', e);\n }\n }\n}\n"]}
@@ -0,0 +1,19 @@
1
+ import type VTableSheet from '../components/vtable-sheet';
2
+ export declare class FormulaUIManager {
3
+ private sheet;
4
+ private formulaBarElement;
5
+ formulaInput: HTMLInputElement | null;
6
+ isFormulaBarShowingResult: boolean;
7
+ private isEnterKeyPressed;
8
+ constructor(sheet: VTableSheet);
9
+ createFormulaBar(): HTMLElement;
10
+ activateFormulaBar(): void;
11
+ deactivateFormulaBar(): void;
12
+ cancelFormulaEdit(): void;
13
+ confirmFormulaEdit(): void;
14
+ updateFormulaBar(): void;
15
+ private handleFormulaInput;
16
+ private handleFormulaKeydown;
17
+ clearFormula(): void;
18
+ release(): void;
19
+ }
@@ -0,0 +1,226 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: !0
5
+ }), exports.FormulaUIManager = void 0;
6
+
7
+ const formula_helper_1 = require("./formula-helper");
8
+
9
+ class FormulaUIManager {
10
+ constructor(sheet) {
11
+ this.formulaBarElement = null, this.formulaInput = null, this.isFormulaBarShowingResult = !1,
12
+ this.isEnterKeyPressed = !1, this.sheet = sheet;
13
+ }
14
+ createFormulaBar() {
15
+ const formulaBar = document.createElement("div");
16
+ formulaBar.className = "vtable-sheet-formula-bar";
17
+ const cellAddressBox = document.createElement("div");
18
+ cellAddressBox.className = "vtable-sheet-cell-address", cellAddressBox.textContent = "",
19
+ formulaBar.appendChild(cellAddressBox);
20
+ const formulaIcon = document.createElement("div");
21
+ formulaIcon.className = "vtable-sheet-formula-icon", formulaIcon.textContent = "fx",
22
+ formulaIcon.title = "插入函数", formulaBar.appendChild(formulaIcon);
23
+ const formulaInput = document.createElement("input");
24
+ this.formulaInput = formulaInput, formulaInput.className = "vtable-sheet-formula-input",
25
+ formulaInput.placeholder = "输入公式...";
26
+ [ "click", "mouseup", "keyup", "select", "input", "focus" ].forEach((eventType => {
27
+ formulaInput.addEventListener(eventType, (e => {
28
+ const cursorPos = formulaInput.selectionStart;
29
+ null != cursorPos && (this.sheet.formulaManager.lastKnownCursorPosInFormulaInput = cursorPos,
30
+ this.sheet.formulaManager.inputingElement = formulaInput);
31
+ }));
32
+ })), formulaInput.addEventListener("input", (e => this.handleFormulaInput(e))),
33
+ formulaInput.addEventListener("keydown", (e => this.handleFormulaKeydown(e))), formulaInput.addEventListener("focus", (() => {
34
+ this.activateFormulaBar();
35
+ const activeWorkSheet = this.sheet.getActiveSheet();
36
+ if (activeWorkSheet) {
37
+ const editingCell = activeWorkSheet.editingCell;
38
+ if (editingCell && !this.sheet.formulaManager.formulaWorkingOnCell) {
39
+ const formula = this.sheet.formulaManager.getCellFormula({
40
+ sheet: editingCell.sheet,
41
+ row: editingCell.row,
42
+ col: editingCell.col
43
+ });
44
+ if (formula) {
45
+ this.sheet.formulaManager.formulaWorkingOnCell = editingCell;
46
+ const displayFormula = formula.startsWith("=") ? formula : `=${formula}`;
47
+ formulaInput.value = displayFormula, this.sheet.formulaManager.cellHighlightManager.highlightFormulaCells(displayFormula),
48
+ this.sheet.formulaManager.inputIsParamMode = (0, formula_helper_1.detectFunctionParameterPosition)(formulaInput.value, this.sheet.formulaManager.lastKnownCursorPosInFormulaInput);
49
+ }
50
+ }
51
+ }
52
+ })), formulaInput.addEventListener("blur", (() => {
53
+ var _a;
54
+ if (this.sheet.formulaManager.formulaWorkingOnCell) return;
55
+ this.deactivateFormulaBar(), this.sheet.formulaManager.cellHighlightManager.clearHighlights();
56
+ const activeWorkSheet = this.sheet.getActiveSheet();
57
+ if (activeWorkSheet) {
58
+ const selection = activeWorkSheet.getSelection();
59
+ if (selection) {
60
+ const result = this.sheet.formulaManager.getCellValue({
61
+ sheet: activeWorkSheet.getKey(),
62
+ row: selection.startRow,
63
+ col: selection.startCol
64
+ });
65
+ null === (_a = activeWorkSheet.tableInstance) || void 0 === _a || _a.changeCellValue(selection.startCol, selection.startRow, result.error ? "#ERROR!" : result.value);
66
+ }
67
+ }
68
+ })), formulaBar.appendChild(formulaInput);
69
+ const formulaActions = document.createElement("div");
70
+ formulaActions.className = "vtable-sheet-formula-actions";
71
+ const cancelButton = document.createElement("button");
72
+ cancelButton.className = "vtable-sheet-formula-button vtable-sheet-formula-cancel",
73
+ cancelButton.innerHTML = '<svg viewBox="0 0 24 24" width="16" height="16"><path fill="currentColor" d="M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z"/></svg>',
74
+ cancelButton.title = "取消", cancelButton.addEventListener("click", (() => this.cancelFormulaEdit())),
75
+ formulaActions.appendChild(cancelButton);
76
+ const confirmButton = document.createElement("button");
77
+ return confirmButton.className = "vtable-sheet-formula-button vtable-sheet-formula-confirm",
78
+ confirmButton.innerHTML = '<svg viewBox="0 0 24 24" width="16" height="16"><path fill="currentColor" d="M9 16.17L4.83 12l-1.42 1.41L9 19 21 7l-1.41-1.41z"/></svg>',
79
+ confirmButton.title = "确认", confirmButton.addEventListener("click", (() => this.confirmFormulaEdit())),
80
+ formulaActions.appendChild(confirmButton), formulaBar.appendChild(formulaActions),
81
+ this.formulaBarElement = formulaBar, formulaBar;
82
+ }
83
+ activateFormulaBar() {
84
+ const formulaBar = this.formulaBarElement;
85
+ formulaBar && formulaBar.classList.add("active");
86
+ }
87
+ deactivateFormulaBar() {
88
+ const formulaBar = this.formulaBarElement;
89
+ formulaBar && formulaBar.classList.remove("active"), this.sheet.formulaManager.cellHighlightManager.clearHighlights();
90
+ }
91
+ cancelFormulaEdit() {
92
+ this.formulaInput && this.updateFormulaBar();
93
+ }
94
+ confirmFormulaEdit() {
95
+ var _a;
96
+ const formulaInput = this.formulaInput, activeWorkSheet = this.sheet.getActiveSheet();
97
+ if (formulaInput && activeWorkSheet) {
98
+ const selection = activeWorkSheet.editingCell;
99
+ if (!selection) return;
100
+ const value = formulaInput.value;
101
+ if (value.startsWith("=") && value.length > 1) try {
102
+ const currentCellAddress = activeWorkSheet.addressFromCoord(selection.row, selection.col);
103
+ if (new RegExp(`(^|[^A-Za-z0-9])${currentCellAddress}([^A-Za-z0-9]|$)`).test(value)) return activeWorkSheet.setCellValue(selection.row, selection.col, "#CYCLE!"),
104
+ null === (_a = activeWorkSheet.tableInstance) || void 0 === _a || _a.changeCellValue(selection.col, selection.row, "#CYCLE!"),
105
+ formulaInput.value = "", void formulaInput.blur();
106
+ this.sheet.formulaManager.setCellContent({
107
+ sheet: activeWorkSheet.getKey(),
108
+ row: selection.row,
109
+ col: selection.col
110
+ }, value);
111
+ const result = this.sheet.formulaManager.getCellValue({
112
+ sheet: activeWorkSheet.getKey(),
113
+ row: selection.row,
114
+ col: selection.col
115
+ });
116
+ activeWorkSheet.setCellValue(selection.row, selection.col, result.value);
117
+ } catch (error) {
118
+ activeWorkSheet.setCellValue(selection.row, selection.col, "#ERROR!");
119
+ } else activeWorkSheet.setCellValue(selection.row, selection.col, value);
120
+ }
121
+ }
122
+ updateFormulaBar() {
123
+ if (!this.formulaBarElement) return;
124
+ const activeWorkSheet = this.sheet.getActiveSheet();
125
+ if (!activeWorkSheet) return void this.clearFormula();
126
+ const selection = activeWorkSheet.getSelection();
127
+ if (selection) try {
128
+ const rowCount = activeWorkSheet.getRowCount(), colCount = activeWorkSheet.getColumnCount();
129
+ if (selection.startRow < 0 || selection.startRow >= rowCount || selection.startCol < 0 || selection.startCol >= colCount) return void this.clearFormula();
130
+ const cellAddressBox = this.formulaBarElement.querySelector(".vtable-sheet-cell-address");
131
+ cellAddressBox && (cellAddressBox.textContent = activeWorkSheet.addressFromCoord(selection.startRow, selection.startCol));
132
+ const formulaInput = this.formulaInput;
133
+ if (formulaInput) {
134
+ if (this.sheet.formulaManager.inputIsParamMode = (0, formula_helper_1.detectFunctionParameterPosition)(formulaInput.value, this.sheet.formulaManager.lastKnownCursorPosInFormulaInput),
135
+ this.sheet.formulaManager.inputIsParamMode.inParamMode) return;
136
+ if (this.isFormulaBarShowingResult) return;
137
+ try {
138
+ const formula = this.sheet.formulaManager.getCellFormula({
139
+ sheet: activeWorkSheet.getKey(),
140
+ row: selection.startRow,
141
+ col: selection.startCol
142
+ });
143
+ if (formula) {
144
+ const displayFormula = formula.startsWith("=") ? formula : "=" + formula;
145
+ formulaInput.value = displayFormula;
146
+ } else {
147
+ const cellValue = activeWorkSheet.getCellValue(selection.startRow, selection.startCol);
148
+ formulaInput.value = null != cellValue ? String(cellValue) : "";
149
+ }
150
+ } catch (e) {
151
+ formulaInput.value = "";
152
+ }
153
+ }
154
+ } catch (e) {
155
+ this.clearFormula();
156
+ } else this.clearFormula();
157
+ }
158
+ handleFormulaInput(event) {
159
+ var _a;
160
+ const activeWorkSheet = this.sheet.getActiveSheet();
161
+ if (!activeWorkSheet) return;
162
+ const editingCell = activeWorkSheet.editingCell;
163
+ if (!editingCell) return;
164
+ const input = event.target, value = input.value;
165
+ this.sheet.getActiveSheet().tableInstance.editorManager.editingEditor || this.sheet.getActiveSheet().tableInstance.startEditCell(editingCell.col, editingCell.row, value),
166
+ (null === (_a = this.sheet.getActiveSheet().tableInstance.editorManager.editingEditor) || void 0 === _a ? void 0 : _a.getInputElement) && (this.sheet.getActiveSheet().tableInstance.editorManager.editingEditor.getInputElement().value = value,
167
+ input.focus()), value.startsWith("=") && this.sheet.formulaManager.cellHighlightManager.highlightFormulaCells(value),
168
+ event.isFormulaInsertion || (this.sheet.formulaManager.inputIsParamMode = (0, formula_helper_1.detectFunctionParameterPosition)(value, this.sheet.formulaManager.lastKnownCursorPosInFormulaInput),
169
+ value.startsWith("=") ? (this.sheet.formulaManager.cellHighlightManager.highlightFormulaCells(value),
170
+ this.isFormulaBarShowingResult = !1, this.sheet.formulaManager.setCellContent({
171
+ sheet: activeWorkSheet.getKey(),
172
+ row: editingCell.row,
173
+ col: editingCell.col
174
+ }, value)) : this.sheet.formulaManager.cellHighlightManager.clearHighlights(), this.sheet.formulaManager.formulaWorkingOnCell = activeWorkSheet.editingCell);
175
+ }
176
+ handleFormulaKeydown(event) {
177
+ var _a, _b, _c, _d;
178
+ const activeWorkSheet = this.sheet.getActiveSheet();
179
+ if (!activeWorkSheet) return;
180
+ const input = event.target;
181
+ if ("Enter" === event.key) {
182
+ const editingCell = activeWorkSheet.editingCell;
183
+ if (!editingCell) return;
184
+ const value = input.value;
185
+ if (value.startsWith("=") && value.length > 1) try {
186
+ const currentCellAddress = activeWorkSheet.addressFromCoord(editingCell.row, editingCell.col);
187
+ if (new RegExp(`(^|[^A-Za-z0-9])${currentCellAddress}([^A-Za-z0-9]|$)`).test(value)) return activeWorkSheet.setCellValue(editingCell.row, editingCell.col, "#CYCLE!"),
188
+ null === (_a = activeWorkSheet.tableInstance) || void 0 === _a || _a.changeCellValue(editingCell.col, editingCell.row, "#CYCLE!"),
189
+ this.sheet.formulaManager.formulaWorkingOnCell = null, input.value = "", void input.blur();
190
+ this.sheet.formulaManager.setCellContent({
191
+ sheet: activeWorkSheet.getKey(),
192
+ row: editingCell.row,
193
+ col: editingCell.col
194
+ }, value);
195
+ const result = this.sheet.formulaManager.getCellValue({
196
+ sheet: activeWorkSheet.getKey(),
197
+ row: editingCell.row,
198
+ col: editingCell.col
199
+ });
200
+ null === (_b = activeWorkSheet.tableInstance) || void 0 === _b || _b.changeCellValue(editingCell.col, editingCell.row, result.error ? "#ERROR!" : result.value),
201
+ this.isFormulaBarShowingResult = !0, input.blur(), setTimeout((() => {
202
+ this.sheet.formulaManager.formulaWorkingOnCell = null, activeWorkSheet.tableInstance.clearSelected(),
203
+ this.sheet.formulaManager.cellHighlightManager.clearHighlights(), activeWorkSheet.tableInstance.selectCell(editingCell.col, editingCell.row);
204
+ }), 0);
205
+ } catch (error) {
206
+ activeWorkSheet.setCellValue(editingCell.row, editingCell.col, "#ERROR!"), null === (_c = activeWorkSheet.tableInstance) || void 0 === _c || _c.changeCellValue(editingCell.col, editingCell.row, "#ERROR!"),
207
+ this.sheet.formulaManager.formulaWorkingOnCell = null;
208
+ } else activeWorkSheet.setCellValue(editingCell.row, editingCell.col, value), null === (_d = activeWorkSheet.tableInstance) || void 0 === _d || _d.changeCellValue(editingCell.col, editingCell.row, value),
209
+ this.sheet.formulaManager.formulaWorkingOnCell = null;
210
+ this.isEnterKeyPressed = !0, event.preventDefault(), event.stopPropagation();
211
+ }
212
+ }
213
+ clearFormula() {
214
+ var _a;
215
+ const cellAddressBox = null === (_a = this.formulaBarElement) || void 0 === _a ? void 0 : _a.querySelector(".vtable-sheet-cell-address");
216
+ cellAddressBox && (cellAddressBox.textContent = "");
217
+ const formulaInput = this.formulaInput;
218
+ formulaInput && (formulaInput.value = "");
219
+ }
220
+ release() {
221
+ this.formulaBarElement = null, this.formulaInput = null;
222
+ }
223
+ }
224
+
225
+ exports.FormulaUIManager = FormulaUIManager;
226
+ //# sourceMappingURL=formula-ui-manager.js.map