@rowsncolumns/spreadsheet-state 28.0.72 → 28.0.74

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 (185) hide show
  1. package/dist/cjs/api/advanced-filter.d.ts +72 -0
  2. package/dist/cjs/api/advanced-filter.d.ts.map +1 -0
  3. package/dist/cjs/api/advanced-filter.js +0 -0
  4. package/dist/cjs/api/goal-seek.d.ts +29 -0
  5. package/dist/cjs/api/goal-seek.d.ts.map +1 -0
  6. package/dist/cjs/api/goal-seek.js +131 -0
  7. package/dist/cjs/api/immer-utils.d.ts.map +1 -1
  8. package/dist/cjs/api/immer-utils.js +2 -0
  9. package/dist/cjs/api/paint-format.d.ts +41 -0
  10. package/dist/cjs/api/paint-format.d.ts.map +1 -0
  11. package/dist/cjs/api/paint-format.js +115 -0
  12. package/dist/cjs/api/paste-special.d.ts +48 -0
  13. package/dist/cjs/api/paste-special.d.ts.map +1 -0
  14. package/dist/cjs/api/paste-special.js +229 -0
  15. package/dist/cjs/api/split-text.d.ts +12 -0
  16. package/dist/cjs/api/split-text.d.ts.map +1 -1
  17. package/dist/cjs/api/split-text.js +41 -0
  18. package/dist/cjs/api/subtotal.d.ts +85 -0
  19. package/dist/cjs/api/subtotal.d.ts.map +1 -0
  20. package/dist/cjs/api/subtotal.js +250 -0
  21. package/dist/cjs/commands.d.ts +13 -0
  22. package/dist/cjs/commands.d.ts.map +1 -1
  23. package/dist/cjs/components/editors/data-validation-rule-editor.d.ts.map +1 -1
  24. package/dist/cjs/components/editors/data-validation-rule-editor.js +83 -16
  25. package/dist/cjs/components/editors/table-editor.js +7 -2
  26. package/dist/cjs/hooks/use-calculation-worker.d.ts.map +1 -1
  27. package/dist/cjs/hooks/use-calculation-worker.js +39 -8
  28. package/dist/cjs/hooks/use-calculation.d.ts +12 -2
  29. package/dist/cjs/hooks/use-calculation.d.ts.map +1 -1
  30. package/dist/cjs/hooks/use-calculation.js +71 -35
  31. package/dist/cjs/hooks/use-on-advanced-filter.d.ts +21 -0
  32. package/dist/cjs/hooks/use-on-advanced-filter.d.ts.map +1 -0
  33. package/dist/cjs/hooks/use-on-advanced-filter.js +42 -0
  34. package/dist/cjs/hooks/use-on-goal-seek.d.ts +30 -0
  35. package/dist/cjs/hooks/use-on-goal-seek.d.ts.map +1 -0
  36. package/dist/cjs/hooks/use-on-goal-seek.js +140 -0
  37. package/dist/cjs/hooks/use-on-import-excel.d.ts +10 -1
  38. package/dist/cjs/hooks/use-on-import-excel.d.ts.map +1 -1
  39. package/dist/cjs/hooks/use-on-import-excel.js +8 -4
  40. package/dist/cjs/hooks/use-on-merge-unmerge-cells.d.ts.map +1 -1
  41. package/dist/cjs/hooks/use-on-merge-unmerge-cells.js +53 -34
  42. package/dist/cjs/hooks/use-on-paste.d.ts.map +1 -1
  43. package/dist/cjs/hooks/use-on-paste.js +82 -52
  44. package/dist/cjs/hooks/use-on-remove-duplicates.d.ts +2 -1
  45. package/dist/cjs/hooks/use-on-remove-duplicates.d.ts.map +1 -1
  46. package/dist/cjs/hooks/use-on-remove-duplicates.js +5 -3
  47. package/dist/cjs/hooks/use-on-show-column.d.ts.map +1 -1
  48. package/dist/cjs/hooks/use-on-show-column.js +2 -0
  49. package/dist/cjs/hooks/use-on-show-row.d.ts.map +1 -1
  50. package/dist/cjs/hooks/use-on-show-row.js +2 -0
  51. package/dist/cjs/hooks/use-on-subtotal.d.ts +26 -0
  52. package/dist/cjs/hooks/use-on-subtotal.d.ts.map +1 -0
  53. package/dist/cjs/hooks/use-on-subtotal.js +53 -0
  54. package/dist/cjs/hooks/use-paint-format.d.ts +19 -3
  55. package/dist/cjs/hooks/use-paint-format.d.ts.map +1 -1
  56. package/dist/cjs/hooks/use-paint-format.js +85 -31
  57. package/dist/cjs/hooks/use-sheet-properties.d.ts +3 -0
  58. package/dist/cjs/hooks/use-sheet-properties.d.ts.map +1 -1
  59. package/dist/cjs/hooks/use-sheet-properties.js +8 -0
  60. package/dist/cjs/hooks/use-split-text-to-columns.d.ts +2 -1
  61. package/dist/cjs/hooks/use-split-text-to-columns.d.ts.map +1 -1
  62. package/dist/cjs/hooks/use-split-text-to-columns.js +3 -2
  63. package/dist/cjs/hooks/use-spreadsheet-state.d.ts +50 -36
  64. package/dist/cjs/hooks/use-spreadsheet-state.d.ts.map +1 -1
  65. package/dist/cjs/hooks/use-spreadsheet-state.js +98 -18
  66. package/dist/cjs/index.d.ts +9 -0
  67. package/dist/cjs/index.d.ts.map +1 -1
  68. package/dist/cjs/index.js +9 -0
  69. package/dist/cjs/interface/calculation-interface.d.ts.map +1 -1
  70. package/dist/cjs/interface/calculation-interface.js +5 -0
  71. package/dist/cjs/interface/change-batch-stream.d.ts.map +1 -1
  72. package/dist/cjs/interface/change-batch-stream.js +12 -6
  73. package/dist/cjs/interface/change-batch.d.ts.map +1 -1
  74. package/dist/cjs/interface/change-batch.js +17 -9
  75. package/dist/cjs/interface/change-formatting.d.ts.map +1 -1
  76. package/dist/cjs/interface/change-formatting.js +30 -11
  77. package/dist/cjs/interface/hide-column.d.ts.map +1 -1
  78. package/dist/cjs/interface/hide-column.js +4 -0
  79. package/dist/cjs/interface/hide-row.d.ts.map +1 -1
  80. package/dist/cjs/interface/hide-row.js +4 -0
  81. package/dist/cjs/interface/remove-duplicates.d.ts +3 -2
  82. package/dist/cjs/interface/remove-duplicates.d.ts.map +1 -1
  83. package/dist/cjs/interface/remove-duplicates.js +41 -7
  84. package/dist/cjs/interface/split-text.d.ts +2 -1
  85. package/dist/cjs/interface/split-text.d.ts.map +1 -1
  86. package/dist/cjs/interface/split-text.js +7 -3
  87. package/dist/cjs/interface/spreadsheet-interface.d.ts +2 -1
  88. package/dist/cjs/interface/spreadsheet-interface.d.ts.map +1 -1
  89. package/dist/cjs/interface/spreadsheet-interface.js +5 -5
  90. package/dist/cjs/sheet-cell.d.ts.map +1 -1
  91. package/dist/cjs/sheet-cell.js +7 -0
  92. package/dist/cjs/tsconfig.cjs.tsbuildinfo +1 -1
  93. package/dist/esm/api/advanced-filter.d.ts +72 -0
  94. package/dist/esm/api/advanced-filter.d.ts.map +1 -0
  95. package/dist/esm/api/advanced-filter.js +0 -0
  96. package/dist/esm/api/goal-seek.d.ts +29 -0
  97. package/dist/esm/api/goal-seek.d.ts.map +1 -0
  98. package/dist/esm/api/goal-seek.js +108 -0
  99. package/dist/esm/api/immer-utils.d.ts.map +1 -1
  100. package/dist/esm/api/immer-utils.js +2 -0
  101. package/dist/esm/api/paint-format.d.ts +41 -0
  102. package/dist/esm/api/paint-format.d.ts.map +1 -0
  103. package/dist/esm/api/paint-format.js +77 -0
  104. package/dist/esm/api/paste-special.d.ts +48 -0
  105. package/dist/esm/api/paste-special.d.ts.map +1 -0
  106. package/dist/esm/api/paste-special.js +220 -0
  107. package/dist/esm/api/split-text.d.ts +12 -0
  108. package/dist/esm/api/split-text.d.ts.map +1 -1
  109. package/dist/esm/api/split-text.js +28 -0
  110. package/dist/esm/api/subtotal.d.ts +85 -0
  111. package/dist/esm/api/subtotal.d.ts.map +1 -0
  112. package/dist/esm/api/subtotal.js +181 -0
  113. package/dist/esm/commands.d.ts +13 -0
  114. package/dist/esm/commands.d.ts.map +1 -1
  115. package/dist/esm/components/editors/data-validation-rule-editor.d.ts.map +1 -1
  116. package/dist/esm/components/editors/data-validation-rule-editor.js +52 -4
  117. package/dist/esm/components/editors/table-editor.js +7 -4
  118. package/dist/esm/hooks/use-calculation-worker.d.ts.map +1 -1
  119. package/dist/esm/hooks/use-calculation-worker.js +20 -2
  120. package/dist/esm/hooks/use-calculation.d.ts +12 -2
  121. package/dist/esm/hooks/use-calculation.d.ts.map +1 -1
  122. package/dist/esm/hooks/use-calculation.js +38 -7
  123. package/dist/esm/hooks/use-on-advanced-filter.d.ts +21 -0
  124. package/dist/esm/hooks/use-on-advanced-filter.d.ts.map +1 -0
  125. package/dist/esm/hooks/use-on-advanced-filter.js +41 -0
  126. package/dist/esm/hooks/use-on-goal-seek.d.ts +30 -0
  127. package/dist/esm/hooks/use-on-goal-seek.d.ts.map +1 -0
  128. package/dist/esm/hooks/use-on-goal-seek.js +82 -0
  129. package/dist/esm/hooks/use-on-import-excel.d.ts +10 -1
  130. package/dist/esm/hooks/use-on-import-excel.d.ts.map +1 -1
  131. package/dist/esm/hooks/use-on-import-excel.js +8 -4
  132. package/dist/esm/hooks/use-on-merge-unmerge-cells.d.ts.map +1 -1
  133. package/dist/esm/hooks/use-on-merge-unmerge-cells.js +13 -13
  134. package/dist/esm/hooks/use-on-paste.d.ts.map +1 -1
  135. package/dist/esm/hooks/use-on-paste.js +49 -14
  136. package/dist/esm/hooks/use-on-remove-duplicates.d.ts +2 -1
  137. package/dist/esm/hooks/use-on-remove-duplicates.d.ts.map +1 -1
  138. package/dist/esm/hooks/use-on-remove-duplicates.js +5 -3
  139. package/dist/esm/hooks/use-on-show-column.d.ts.map +1 -1
  140. package/dist/esm/hooks/use-on-show-column.js +2 -0
  141. package/dist/esm/hooks/use-on-show-row.d.ts.map +1 -1
  142. package/dist/esm/hooks/use-on-show-row.js +2 -0
  143. package/dist/esm/hooks/use-on-subtotal.d.ts +26 -0
  144. package/dist/esm/hooks/use-on-subtotal.d.ts.map +1 -0
  145. package/dist/esm/hooks/use-on-subtotal.js +48 -0
  146. package/dist/esm/hooks/use-paint-format.d.ts +19 -3
  147. package/dist/esm/hooks/use-paint-format.d.ts.map +1 -1
  148. package/dist/esm/hooks/use-paint-format.js +71 -29
  149. package/dist/esm/hooks/use-sheet-properties.d.ts +3 -0
  150. package/dist/esm/hooks/use-sheet-properties.d.ts.map +1 -1
  151. package/dist/esm/hooks/use-sheet-properties.js +8 -0
  152. package/dist/esm/hooks/use-split-text-to-columns.d.ts +2 -1
  153. package/dist/esm/hooks/use-split-text-to-columns.d.ts.map +1 -1
  154. package/dist/esm/hooks/use-split-text-to-columns.js +3 -2
  155. package/dist/esm/hooks/use-spreadsheet-state.d.ts +50 -36
  156. package/dist/esm/hooks/use-spreadsheet-state.d.ts.map +1 -1
  157. package/dist/esm/hooks/use-spreadsheet-state.js +89 -16
  158. package/dist/esm/index.d.ts +9 -0
  159. package/dist/esm/index.d.ts.map +1 -1
  160. package/dist/esm/index.js +9 -0
  161. package/dist/esm/interface/calculation-interface.d.ts.map +1 -1
  162. package/dist/esm/interface/calculation-interface.js +3 -0
  163. package/dist/esm/interface/change-batch-stream.d.ts.map +1 -1
  164. package/dist/esm/interface/change-batch-stream.js +12 -6
  165. package/dist/esm/interface/change-batch.d.ts.map +1 -1
  166. package/dist/esm/interface/change-batch.js +15 -9
  167. package/dist/esm/interface/change-formatting.d.ts.map +1 -1
  168. package/dist/esm/interface/change-formatting.js +28 -11
  169. package/dist/esm/interface/hide-column.d.ts.map +1 -1
  170. package/dist/esm/interface/hide-column.js +4 -0
  171. package/dist/esm/interface/hide-row.d.ts.map +1 -1
  172. package/dist/esm/interface/hide-row.js +4 -0
  173. package/dist/esm/interface/remove-duplicates.d.ts +3 -2
  174. package/dist/esm/interface/remove-duplicates.d.ts.map +1 -1
  175. package/dist/esm/interface/remove-duplicates.js +37 -6
  176. package/dist/esm/interface/split-text.d.ts +2 -1
  177. package/dist/esm/interface/split-text.d.ts.map +1 -1
  178. package/dist/esm/interface/split-text.js +6 -3
  179. package/dist/esm/interface/spreadsheet-interface.d.ts +2 -1
  180. package/dist/esm/interface/spreadsheet-interface.d.ts.map +1 -1
  181. package/dist/esm/interface/spreadsheet-interface.js +5 -5
  182. package/dist/esm/sheet-cell.d.ts.map +1 -1
  183. package/dist/esm/sheet-cell.js +7 -0
  184. package/dist/esm/tsconfig.esm.tsbuildinfo +1 -1
  185. package/package.json +18 -18
@@ -284,7 +284,7 @@ const isHeavyArrayFormula = (formula) => {
284
284
  hasLargeExplicitRange(formula));
285
285
  };
286
286
  const cellPromises = new Map();
287
- export const useCalculation = ({ locale, functions, iterativeCalculation, onDemandFormulaPattern, activeSheetId, onSuccess, onChangeDependencyGraph, getSheetId, getSheetName, getSheetIndex, getSheetCount, getActiveSheetId, getEffectiveValue, getUserEnteredValue, getConditionalFormatFormula, getDataValidationFormula, getSheetProperties, getCellData, onStructuredReference, onNamedRange, namedRanges, onChangeStaticReference, onBeginCalculation, getEffectiveStructuredValue, isRowHidden, isRowHiddenByFilter, enableLazyCalculation = true, enabled = true, }) => {
287
+ export const useCalculation = ({ locale, functions, iterativeCalculation, onDemandFormulaPattern, activeSheetId, onSuccess, onChangeDependencyGraph, getSheetId, getSheetName, getSheetIndex, getSheetNames, getSheetCount, getActiveSheetId, getEffectiveValue, getUserEnteredValue, getConditionalFormatFormula, getDataValidationFormula, getSheetProperties, getCellData, onStructuredReference, onNamedRange, namedRanges, onChangeStaticReference, onBeginCalculation, getEffectiveStructuredValue, isRowHidden, isRowHiddenByFilter, enableLazyCalculation = true, enabled = true, }) => {
288
288
  // Convert string pattern to RegExp if provided
289
289
  const onDemandPattern = useMemo(() => {
290
290
  if (!onDemandFormulaPattern)
@@ -299,6 +299,9 @@ export const useCalculation = ({ locale, functions, iterativeCalculation, onDema
299
299
  const graphOperationQueue = useRef([]);
300
300
  // Results queue
301
301
  const resultsQueueRef = useRef(new Map());
302
+ // Circular-reference members awaiting the next `onSuccess` flush (see
303
+ // `CalculationSuccessContext.circularReferences`).
304
+ const circularReferencesQueueRef = useRef(new Map());
302
305
  const resultsFlushPendingRef = useRef(false);
303
306
  const isFullRecalcRef = useRef(false);
304
307
  const staticNodeArrayRef = useRef([]);
@@ -306,6 +309,7 @@ export const useCalculation = ({ locale, functions, iterativeCalculation, onDema
306
309
  const getSheetNameStable = useCallbackRef(getSheetName);
307
310
  const getSheetIdStable = useCallbackRef(getSheetId);
308
311
  const getSheetIndexStable = useCallbackRef(getSheetIndex);
312
+ const getSheetNamesStable = useCallbackRef(getSheetNames);
309
313
  const getSheetCountStable = useCallbackRef(getSheetCount);
310
314
  const getCellDataStable = useCallbackRef(getCellData);
311
315
  const onStructuredReferenceStable = useCallbackRef(onStructuredReference);
@@ -595,6 +599,7 @@ export const useCalculation = ({ locale, functions, iterativeCalculation, onDema
595
599
  locale,
596
600
  getSheetId: getSheetIdStable,
597
601
  getSheetIndex: getSheetIndexStable,
602
+ getSheetNames: getSheetNames ? getSheetNamesStable : undefined,
598
603
  getSheetCount: getSheetCountStable,
599
604
  getSheetProperties: (sheetId = getActiveSheetId()) => getSheetProperties(sheetId),
600
605
  getSheetName: getSheetNameStable,
@@ -602,6 +607,17 @@ export const useCalculation = ({ locale, functions, iterativeCalculation, onDema
602
607
  isRowHiddenByFilter: isRowHiddenByFilter
603
608
  ? isRowHiddenByFilterStable
604
609
  : undefined,
610
+ getCellFormula(sheetId, rowIndex, columnIndex) {
611
+ const userEnteredValue = getFinalUserEnteredValue({
612
+ sheetId,
613
+ rowIndex,
614
+ columnIndex,
615
+ });
616
+ return typeof userEnteredValue === "string" &&
617
+ isAFormula(userEnteredValue)
618
+ ? userEnteredValue
619
+ : undefined;
620
+ },
605
621
  getCellValue(sheetId, rowIndex, columnIndex, property) {
606
622
  const key = makeKey({
607
623
  sheetId,
@@ -884,16 +900,22 @@ export const useCalculation = ({ locale, functions, iterativeCalculation, onDema
884
900
  if (!iterativeCalculationRef.current?.enabled) {
885
901
  const circularKeys = findCircularKeys(cellNodes);
886
902
  if (circularKeys.size) {
903
+ // Excel with iterative calculation off: a circular cell displays
904
+ // 0 — never an error value — so its dependents compute with 0
905
+ // (`=A1+1` → 1, `ISERROR(A1)` → FALSE) and nothing Excel doesn't
906
+ // recognise reaches an export. The warning Excel raises travels
907
+ // on `CalculationSuccessContext.circularReferences`.
887
908
  const results = new Map();
909
+ const circularPositions = [];
888
910
  for (const node of cellNodes) {
889
911
  if (!circularKeys.has(node.key)) {
890
912
  continue;
891
913
  }
892
- const error = new FormulaError("#REF!", "Circular dependency detected.");
893
- getComputationCache().set(node.key, error);
894
- results.set(node.key, [node.position, error]);
914
+ getComputationCache().set(node.key, 0);
915
+ results.set(node.key, [node.position, 0]);
916
+ circularPositions.push(node.position);
895
917
  }
896
- publishResults(results.values());
918
+ publishResults(results.values(), circularPositions);
897
919
  cellNodes = cellNodes.filter((node) => !circularKeys.has(node.key));
898
920
  }
899
921
  }
@@ -1501,11 +1523,14 @@ export const useCalculation = ({ locale, functions, iterativeCalculation, onDema
1501
1523
  /**
1502
1524
  * Publish results back to the
1503
1525
  */
1504
- const publishResults = useCallback((item) => {
1526
+ const publishResults = useCallback((item, circularReferences) => {
1505
1527
  for (const entry of item) {
1506
1528
  const [key] = entry;
1507
1529
  resultsQueueRef.current.set(makeKey(key), entry);
1508
1530
  }
1531
+ for (const position of circularReferences ?? []) {
1532
+ circularReferencesQueueRef.current.set(makeKey(position), position);
1533
+ }
1509
1534
  if (resultsQueueRef.current.size === 0) {
1510
1535
  return;
1511
1536
  }
@@ -1523,14 +1548,20 @@ export const useCalculation = ({ locale, functions, iterativeCalculation, onDema
1523
1548
  if (!resultsQueueRef.current.size) {
1524
1549
  return;
1525
1550
  }
1551
+ const context = circularReferencesQueueRef.current.size > 0
1552
+ ? {
1553
+ circularReferences: Array.from(circularReferencesQueueRef.current.values()),
1554
+ }
1555
+ : {};
1526
1556
  try {
1527
- onSuccess?.(resultsQueueRef.current.values(), isFullRecalc, {});
1557
+ onSuccess?.(resultsQueueRef.current.values(), isFullRecalc, context);
1528
1558
  }
1529
1559
  catch (err) {
1530
1560
  console.error("[spreadsheet-state] recalculation pass aborted:", err);
1531
1561
  }
1532
1562
  finally {
1533
1563
  resultsQueueRef.current.clear();
1564
+ circularReferencesQueueRef.current.clear();
1534
1565
  isFullRecalcRef.current = false;
1535
1566
  }
1536
1567
  });
@@ -0,0 +1,21 @@
1
+ import type { GridRange } from "@rowsncolumns/common-types";
2
+ import { type AdvancedFilterOptions, type AdvancedFilterPlan, type AdvancedFilterPlanExecutor } from "../api/advanced-filter";
3
+ import type { useSheetProperties } from "./use-sheet-properties";
4
+ export type { AdvancedFilterOptions, AdvancedFilterPlan };
5
+ export type UseOnAdvancedFilterProps = {
6
+ getEffectiveValue: ReturnType<typeof useSheetProperties>["getEffectiveValue"];
7
+ getFormattedValue: ReturnType<typeof useSheetProperties>["getFormattedValue"];
8
+ onHideRow: AdvancedFilterPlanExecutor["onHideRow"];
9
+ onShowRow: AdvancedFilterPlanExecutor["onShowRow"];
10
+ onChangeBatch: (sheetId: number, ranges: GridRange, values: (string | number | boolean | null)[][]) => void;
11
+ };
12
+ /**
13
+ * Excel's Data → Sort & Filter → Advanced, composed over the existing
14
+ * hide/show-row and batch-write callbacks so both engines execute it through
15
+ * the same streamed commands. Records are compared by their effective value
16
+ * (numbers stay numeric) and fall back to the displayed text. Returns the
17
+ * applied plan, or `undefined` when the list has no records, the copy
18
+ * destination is missing / protected, or the sheet cannot be edited.
19
+ */
20
+ export declare const useOnAdvancedFilter: ({ getEffectiveValue, getFormattedValue, onHideRow, onShowRow, onChangeBatch, }: UseOnAdvancedFilterProps) => (sheetId: number, options: AdvancedFilterOptions) => AdvancedFilterPlan | undefined;
21
+ //# sourceMappingURL=use-on-advanced-filter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"use-on-advanced-filter.d.ts","sourceRoot":"","sources":["../../../hooks/use-on-advanced-filter.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,4BAA4B,CAAC;AAG5D,OAAO,EACL,KAAK,qBAAqB,EAC1B,KAAK,kBAAkB,EACvB,KAAK,0BAA0B,EAGhC,MAAM,wBAAwB,CAAC;AAEhC,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,wBAAwB,CAAC;AAEjE,YAAY,EAAE,qBAAqB,EAAE,kBAAkB,EAAE,CAAC;AAE1D,MAAM,MAAM,wBAAwB,GAAG;IACrC,iBAAiB,EAAE,UAAU,CAAC,OAAO,kBAAkB,CAAC,CAAC,mBAAmB,CAAC,CAAC;IAC9E,iBAAiB,EAAE,UAAU,CAAC,OAAO,kBAAkB,CAAC,CAAC,mBAAmB,CAAC,CAAC;IAC9E,SAAS,EAAE,0BAA0B,CAAC,WAAW,CAAC,CAAC;IACnD,SAAS,EAAE,0BAA0B,CAAC,WAAW,CAAC,CAAC;IACnD,aAAa,EAAE,CACb,OAAO,EAAE,MAAM,EACf,MAAM,EAAE,SAAS,EACjB,MAAM,EAAE,CAAC,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,IAAI,CAAC,EAAE,EAAE,KAC3C,IAAI,CAAC;CACX,CAAC;AAEF;;;;;;;GAOG;AACH,eAAO,MAAM,mBAAmB,GAAI,gFAMjC,wBAAwB,eAKb,MAAM,WAAW,qBAAqB,KAAG,kBAAkB,GAAG,SA2B3E,CAAC"}
@@ -0,0 +1,41 @@
1
+ import { useCallback } from "react";
2
+ import { applyAdvancedFilterPlan, planAdvancedFilter, } from "../api/advanced-filter";
3
+ import { useCanEditCellRange, useCanEditSheet } from "./use-can-edit-cellrange";
4
+ /**
5
+ * Excel's Data → Sort & Filter → Advanced, composed over the existing
6
+ * hide/show-row and batch-write callbacks so both engines execute it through
7
+ * the same streamed commands. Records are compared by their effective value
8
+ * (numbers stay numeric) and fall back to the displayed text. Returns the
9
+ * applied plan, or `undefined` when the list has no records, the copy
10
+ * destination is missing / protected, or the sheet cannot be edited.
11
+ */
12
+ export const useOnAdvancedFilter = ({ getEffectiveValue, getFormattedValue, onHideRow, onShowRow, onChangeBatch, }) => {
13
+ const canEditCellRange = useCanEditCellRange();
14
+ const canEditSheet = useCanEditSheet();
15
+ return useCallback((sheetId, options) => {
16
+ if (!canEditSheet(sheetId)) {
17
+ console.debug("This sheet is protected, users cannot filter it.");
18
+ return undefined;
19
+ }
20
+ const plan = planAdvancedFilter(options, (rowIndex, columnIndex) => {
21
+ const value = getEffectiveValue(sheetId, rowIndex, columnIndex);
22
+ return value ?? getFormattedValue(sheetId, rowIndex, columnIndex);
23
+ });
24
+ if (!plan)
25
+ return undefined;
26
+ if (plan.copy && !canEditCellRange(sheetId, plan.copy.range)) {
27
+ console.debug("This range is protected, users cannot edit this cell range.");
28
+ return undefined;
29
+ }
30
+ applyAdvancedFilterPlan(sheetId, plan, { onHideRow, onShowRow, onChangeBatch });
31
+ return plan;
32
+ }, [
33
+ canEditSheet,
34
+ canEditCellRange,
35
+ getEffectiveValue,
36
+ getFormattedValue,
37
+ onHideRow,
38
+ onShowRow,
39
+ onChangeBatch,
40
+ ]);
41
+ };
@@ -0,0 +1,30 @@
1
+ import type { CellInterface } from "@rowsncolumns/common-types";
2
+ import { type GoalSeekResult } from "../api/goal-seek";
3
+ import type { useCalculation } from "./use-calculation";
4
+ import type { useOnChange } from "./use-on-change";
5
+ import type { useSheetProperties } from "./use-sheet-properties";
6
+ export type { GoalSeekResult };
7
+ export type UseOnGoalSeekProps = {
8
+ getFormulaValue: ReturnType<typeof useSheetProperties>["getFormulaValue"];
9
+ getEffectiveValue: ReturnType<typeof useSheetProperties>["getEffectiveValue"];
10
+ /** The calculator's scratch evaluation (UNFORMATTED results). */
11
+ onRequestCalculate: ReturnType<typeof useCalculation>["onRequestCalculate"];
12
+ getDependents: ReturnType<typeof useCalculation>["getDependents"];
13
+ onChange: ReturnType<typeof useOnChange>;
14
+ };
15
+ /**
16
+ * Excel's Goal Seek (Data → What-If Analysis): find the value of
17
+ * `changingCell` that makes the formula in `setCell` evaluate to
18
+ * `targetValue`. Every trial is a scratch evaluation — the changing cell is
19
+ * pinned through the calculator's override map and the formula cells between
20
+ * it and the set cell (its transitive dependents, in dependency order) are
21
+ * re-evaluated into the same map, so nothing is written until the search
22
+ * ends. The final value is committed through `onChange` (one undo step,
23
+ * streamed to any engine consumer like a typed edit).
24
+ *
25
+ * Resolves to `undefined` when the set cell holds no formula or the changing
26
+ * cell is protected; otherwise the {@link GoalSeekResult} — Excel reports
27
+ * "found a solution" / "may not have found a solution" from `status`.
28
+ */
29
+ export declare const useOnGoalSeek: ({ getFormulaValue, getEffectiveValue, onRequestCalculate, getDependents, onChange, }: UseOnGoalSeekProps) => (sheetId: number, setCell: CellInterface, targetValue: number, changingCell: CellInterface) => Promise<GoalSeekResult | undefined>;
30
+ //# sourceMappingURL=use-on-goal-seek.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"use-on-goal-seek.d.ts","sourceRoot":"","sources":["../../../hooks/use-on-goal-seek.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,4BAA4B,CAAC;AAIhE,OAAO,EAAY,KAAK,cAAc,EAAE,MAAM,kBAAkB,CAAC;AACjE,OAAO,KAAK,EAGV,cAAc,EACf,MAAM,mBAAmB,CAAC;AAE3B,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AACnD,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,wBAAwB,CAAC;AAEjE,YAAY,EAAE,cAAc,EAAE,CAAC;AAE/B,MAAM,MAAM,kBAAkB,GAAG;IAC/B,eAAe,EAAE,UAAU,CAAC,OAAO,kBAAkB,CAAC,CAAC,iBAAiB,CAAC,CAAC;IAC1E,iBAAiB,EAAE,UAAU,CAAC,OAAO,kBAAkB,CAAC,CAAC,mBAAmB,CAAC,CAAC;IAC9E,iEAAiE;IACjE,kBAAkB,EAAE,UAAU,CAAC,OAAO,cAAc,CAAC,CAAC,oBAAoB,CAAC,CAAC;IAC5E,aAAa,EAAE,UAAU,CAAC,OAAO,cAAc,CAAC,CAAC,eAAe,CAAC,CAAC;IAClE,QAAQ,EAAE,UAAU,CAAC,OAAO,WAAW,CAAC,CAAC;CAC1C,CAAC;AAUF;;;;;;;;;;;;;GAaG;AACH,eAAO,MAAM,aAAa,GAAI,sFAM3B,kBAAkB,eAKN,MAAM,WACN,aAAa,eACT,MAAM,gBACL,aAAa,KAC1B,OAAO,CAAC,cAAc,GAAG,SAAS,CA+DxC,CAAC"}
@@ -0,0 +1,82 @@
1
+ import { isCellNode, makeKey } from "@rowsncolumns/dag";
2
+ import { useCallback } from "react";
3
+ import { goalSeek } from "../api/goal-seek";
4
+ import { useCanEditCellRange } from "./use-can-edit-cellrange";
5
+ /** Cap on the formula chain re-evaluated per trial (a runaway dependency fan-out). */
6
+ const MAX_AFFECTED_CELLS = 2000;
7
+ const sameCell = (a, sheetId, b) => (a.sheetId ?? sheetId) === sheetId &&
8
+ a.rowIndex === b.rowIndex &&
9
+ a.columnIndex === b.columnIndex;
10
+ /**
11
+ * Excel's Goal Seek (Data → What-If Analysis): find the value of
12
+ * `changingCell` that makes the formula in `setCell` evaluate to
13
+ * `targetValue`. Every trial is a scratch evaluation — the changing cell is
14
+ * pinned through the calculator's override map and the formula cells between
15
+ * it and the set cell (its transitive dependents, in dependency order) are
16
+ * re-evaluated into the same map, so nothing is written until the search
17
+ * ends. The final value is committed through `onChange` (one undo step,
18
+ * streamed to any engine consumer like a typed edit).
19
+ *
20
+ * Resolves to `undefined` when the set cell holds no formula or the changing
21
+ * cell is protected; otherwise the {@link GoalSeekResult} — Excel reports
22
+ * "found a solution" / "may not have found a solution" from `status`.
23
+ */
24
+ export const useOnGoalSeek = ({ getFormulaValue, getEffectiveValue, onRequestCalculate, getDependents, onChange, }) => {
25
+ const canEditCellRange = useCanEditCellRange();
26
+ return useCallback(async (sheetId, setCell, targetValue, changingCell) => {
27
+ if (!Number.isFinite(targetValue))
28
+ return undefined;
29
+ if (!canEditCellRange(sheetId, changingCell)) {
30
+ console.debug("This range is protected, users cannot edit this cell range.");
31
+ return undefined;
32
+ }
33
+ const formula = getFormulaValue(sheetId, setCell.rowIndex, setCell.columnIndex);
34
+ if (!formula)
35
+ return undefined;
36
+ if (sameCell(setCell, sheetId, changingCell))
37
+ return undefined;
38
+ const changingPosition = { sheetId, ...changingCell };
39
+ // Formula cells downstream of the changing cell, in dependency order,
40
+ // minus the set cell itself (evaluated last, from the trial map).
41
+ const affected = [];
42
+ for (const node of getDependents(changingPosition)) {
43
+ if (!isCellNode(node))
44
+ continue;
45
+ const { position } = node;
46
+ if (sameCell(position, sheetId, setCell) && position.sheetId === sheetId)
47
+ continue;
48
+ if (position.conditionalFormatId != null || position.dataValidationId != null)
49
+ continue;
50
+ affected.push(position);
51
+ if (affected.length >= MAX_AFFECTED_CELLS)
52
+ break;
53
+ }
54
+ const evaluate = async (trial) => {
55
+ const overrides = new Map([[makeKey(changingPosition), trial]]);
56
+ const scratch = async (text, position) => onRequestCalculate(text, position.sheetId, position.rowIndex, position.columnIndex, {
57
+ overrides,
58
+ disablePreview: true,
59
+ });
60
+ for (const position of affected) {
61
+ const cellFormula = getFormulaValue(position.sheetId, position.rowIndex, position.columnIndex);
62
+ if (!cellFormula)
63
+ continue;
64
+ const value = await scratch(cellFormula, position);
65
+ // An errored intermediate reads as an error in the set cell too,
66
+ // which the solver treats as an unusable trial.
67
+ overrides.set(makeKey(position), value instanceof Error ? undefined : value);
68
+ }
69
+ const result = await scratch(formula, { sheetId, ...setCell });
70
+ return typeof result === "number" && Number.isFinite(result) ? result : undefined;
71
+ };
72
+ const current = getEffectiveValue(sheetId, changingCell.rowIndex, changingCell.columnIndex);
73
+ const initialValue = typeof current === "number"
74
+ ? current
75
+ : typeof current === "string" && current.trim() !== "" && Number.isFinite(Number(current))
76
+ ? Number(current)
77
+ : 0;
78
+ const result = await goalSeek({ evaluate, targetValue, initialValue });
79
+ onChange(sheetId, changingCell, String(result.value), undefined);
80
+ return result;
81
+ }, [canEditCellRange, getFormulaValue, getEffectiveValue, onRequestCalculate, getDependents, onChange]);
82
+ };
@@ -19,6 +19,7 @@ export type UseOnImportExcelFileProps<T extends CellData, S extends Sheet> = {
19
19
  onChangeCellXfs?: UseSpreadsheetProps<T, S>["onChangeCellXfs"];
20
20
  onRequestFonts: UseSpreadsheetProps<T, S>["onRequestFonts"];
21
21
  onChangeTheme: UseSpreadsheetProps<T, S>["onChangeTheme"];
22
+ onChangeNamedCellStyles?: UseSpreadsheetProps<T, S>["onChangeNamedCellStyles"];
22
23
  onChangeSlicers: UseSpreadsheetProps<T, S>["onChangeSlicers"];
23
24
  /**
24
25
  * Phase D1 — pivot table import. Worker emits
@@ -39,7 +40,15 @@ export type UseOnImportExcelFileProps<T extends CellData, S extends Sheet> = {
39
40
  export type ExcelImportResponse = {
40
41
  requiresRecalc?: boolean;
41
42
  iterativeCalculationOptions?: IterativeCalculationOptions;
43
+ /**
44
+ * Date system of the imported cell data — always the 1900 system: a
45
+ * `date1904` workbook is converted on import (date-formatted serials
46
+ * shifted by 1462 days), so this can be wired straight to
47
+ * `SheetCell.setUse1904` / `createExcelFile({ use1904 })`.
48
+ */
42
49
  use1904?: boolean;
50
+ /** The source workbook declared the 1904 date system (informational). */
51
+ sourceUse1904?: boolean;
43
52
  success: boolean;
44
53
  isPasswordProtected?: boolean;
45
54
  };
@@ -59,7 +68,7 @@ export type ExcelImportOptions = {
59
68
  */
60
69
  prompt?: UseSpreadsheetProps["onPrompt"];
61
70
  };
62
- export declare const useOnImportExcelFile: <T extends CellData, S extends Sheet>({ enableExcelImportHistory, onChangeSheetData, onChangeSheets, onChangeTables, onChangeEmbeds, onChangeNamedRanges, onChangeSharedStrings, onChangeConditionalFormats, onChangeDataValidations, onChangeCellXfs, onChangeCharts, onRequestFonts, onChangeTheme, onCreateDataValidationRule, onClearHistory, onChangeHistory, onChangeSlicers, onChangePivotTables, evaluateConditionalFormatting, evaluateDataValidations, clearRangeCache, onConfirm, onPrompt, }: UseOnImportExcelFileProps<T, S>) => {
71
+ export declare const useOnImportExcelFile: <T extends CellData, S extends Sheet>({ enableExcelImportHistory, onChangeSheetData, onChangeSheets, onChangeTables, onChangeEmbeds, onChangeNamedRanges, onChangeSharedStrings, onChangeConditionalFormats, onChangeDataValidations, onChangeCellXfs, onChangeCharts, onRequestFonts, onChangeTheme, onChangeNamedCellStyles, onCreateDataValidationRule, onClearHistory, onChangeHistory, onChangeSlicers, onChangePivotTables, evaluateConditionalFormatting, evaluateDataValidations, clearRangeCache, onConfirm, onPrompt, }: UseOnImportExcelFileProps<T, S>) => {
63
72
  importExcelFile: (file: File | ArrayBuffer, options?: ExcelImportOptions) => Promise<ExcelImportResponse>;
64
73
  isImportingExcelfile: boolean;
65
74
  generateStatePatches: () => Promise<SpreadsheetPatch>;
@@ -1 +1 @@
1
- {"version":3,"file":"use-on-import-excel.d.ts","sourceRoot":"","sources":["../../../hooks/use-on-import-excel.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"use-on-import-excel.d.ts","sourceRoot":"","sources":["../../../hooks/use-on-import-excel.ts"],"names":[],"mappings":"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"}
@@ -5,7 +5,7 @@ import { produce, produceWithPatches } from "immer";
5
5
  import { useCallback, useState } from "react";
6
6
  import { SheetCell } from "../sheet-cell";
7
7
  const TIMEOUT_FONT_LOAD = 5000;
8
- export const useOnImportExcelFile = ({ enableExcelImportHistory = false, onChangeSheetData, onChangeSheets, onChangeTables, onChangeEmbeds, onChangeNamedRanges, onChangeSharedStrings, onChangeConditionalFormats, onChangeDataValidations, onChangeCellXfs, onChangeCharts, onRequestFonts, onChangeTheme, onCreateDataValidationRule, onClearHistory, onChangeHistory, onChangeSlicers, onChangePivotTables, evaluateConditionalFormatting, evaluateDataValidations, clearRangeCache, onConfirm, onPrompt, }) => {
8
+ export const useOnImportExcelFile = ({ enableExcelImportHistory = false, onChangeSheetData, onChangeSheets, onChangeTables, onChangeEmbeds, onChangeNamedRanges, onChangeSharedStrings, onChangeConditionalFormats, onChangeDataValidations, onChangeCellXfs, onChangeCharts, onRequestFonts, onChangeTheme, onChangeNamedCellStyles, onCreateDataValidationRule, onClearHistory, onChangeHistory, onChangeSlicers, onChangePivotTables, evaluateConditionalFormatting, evaluateDataValidations, clearRangeCache, onConfirm, onPrompt, }) => {
9
9
  const [isImportingExcelfile, setIsImporting] = useState(false);
10
10
  const [showLoader, hideLoader] = useLoadingIndicator();
11
11
  const getViewPort = useGetViewPort();
@@ -229,7 +229,7 @@ export const useOnImportExcelFile = ({ enableExcelImportHistory = false, onChang
229
229
  const { observable, sendMessage } = createExcelImportWorker(file, minRowCount, minColumnCount);
230
230
  let requiresRecalc = false;
231
231
  let iterativeCalculationOptions;
232
- let use1904 = false;
232
+ let sourceUse1904 = false;
233
233
  let isPromptingForPassword = false;
234
234
  let isPasswordProtected = false;
235
235
  // Set import
@@ -345,7 +345,7 @@ export const useOnImportExcelFile = ({ enableExcelImportHistory = false, onChang
345
345
  requiresRecalc = response.requiresRecalc ?? false;
346
346
  iterativeCalculationOptions =
347
347
  response.iterativeCalculationOptions ?? undefined;
348
- use1904 = response.use1904 ?? false;
348
+ sourceUse1904 = response.use1904 ?? false;
349
349
  }
350
350
  if (response.responseType === ResponseType.GET_SHEETS_SUCCESS) {
351
351
  onChangeSheets(response.sheets);
@@ -357,6 +357,9 @@ export const useOnImportExcelFile = ({ enableExcelImportHistory = false, onChang
357
357
  if (response.theme) {
358
358
  onChangeTheme?.(response.theme);
359
359
  }
360
+ if (response.namedCellStyles) {
361
+ onChangeNamedCellStyles?.(response.namedCellStyles);
362
+ }
360
363
  }
361
364
  if (response.responseType === ResponseType.GET_CONDITIONAL_FORMATTING) {
362
365
  showLoader("Loading conditional formatting");
@@ -555,7 +558,8 @@ export const useOnImportExcelFile = ({ enableExcelImportHistory = false, onChang
555
558
  resolve({
556
559
  requiresRecalc,
557
560
  iterativeCalculationOptions,
558
- use1904,
561
+ use1904: false,
562
+ sourceUse1904,
559
563
  success: true,
560
564
  isPasswordProtected,
561
565
  });
@@ -1 +1 @@
1
- {"version":3,"file":"use-on-merge-unmerge-cells.d.ts","sourceRoot":"","sources":["../../../hooks/use-on-merge-unmerge-cells.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,aAAa,EACb,SAAS,EACT,aAAa,EACd,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAGL,SAAS,EAGV,MAAM,oBAAoB,CAAC;AAC5B,OAAO,KAAK,EACV,QAAQ,EACR,mBAAmB,EACnB,KAAK,EACN,MAAM,2BAA2B,CAAC;AAOnC,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAG7C,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,mBAAmB,CAAC;AAO9D,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AACvD,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,yBAAyB,CAAC;AACnE,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AACxD,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AACzD,OAAO,EAAE,oBAAoB,EAAE,MAAM,mBAAmB,CAAC;AAEzD,KAAK,2BAA2B,CAAC,CAAC,SAAS,QAAQ,EAAE,CAAC,SAAS,KAAK,IAAI;IACtE,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,SAAS,EAAE,GAAG,IAAI,CAAC;IAC5B,eAAe,CAAC,EAAE,eAAe,CAAC;IAClC,oBAAoB,CAAC,EAAE,oBAAoB,CAAC;IAC5C,aAAa,EAAE,MAAM,CAAC,OAAO,EAAE,gBAAgB,KAAK,IAAI,CAAC;IACzD,iBAAiB,EAAE,mBAAmB,CAAC,CAAC,CAAC,CAAC,mBAAmB,CAAC,CAAC;IAC/D,cAAc,EAAE,mBAAmB,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,gBAAgB,CAAC,CAAC;IAC5D,kBAAkB,EAAE,UAAU,CAAC,OAAO,aAAa,CAAC,CAAC,oBAAoB,CAAC,CAAC;IAC3E,kBAAkB,EAAE,CAAC,SAAS,EAAE,oBAAoB,KAAK,IAAI,CAAC;IAC9D,SAAS,CAAC,EAAE,SAAS,CAAC;CACvB,CAAC;AAEF,eAAO,MAAM,sBAAsB,GAAI,CAAC,SAAS,QAAQ,EAAE,CAAC,SAAS,KAAK,EAAE,iKAWzE,2BAA2B,CAAC,CAAC,EAAE,CAAC,CAAC;4BASrB,MAAM,cACH,aAAa,cACb,aAAa,CAAC,mBAAmB,CAAC,EAAE,cACpC,SAAS;8BAiSZ,MAAM,cACH,aAAa,qBACN,aAAa,CAAC,mBAAmB,CAAC,EAAE;CA4I5D,CAAC"}
1
+ {"version":3,"file":"use-on-merge-unmerge-cells.d.ts","sourceRoot":"","sources":["../../../hooks/use-on-merge-unmerge-cells.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,aAAa,EACb,SAAS,EACT,aAAa,EACd,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAGL,SAAS,EAGV,MAAM,oBAAoB,CAAC;AAC5B,OAAO,KAAK,EACV,QAAQ,EACR,mBAAmB,EACnB,KAAK,EACN,MAAM,2BAA2B,CAAC;AAOnC,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAG7C,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,mBAAmB,CAAC;AAO9D,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AACvD,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,yBAAyB,CAAC;AACnE,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AACxD,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AACzD,OAAO,EAAE,oBAAoB,EAAE,MAAM,mBAAmB,CAAC;AAEzD,KAAK,2BAA2B,CAAC,CAAC,SAAS,QAAQ,EAAE,CAAC,SAAS,KAAK,IAAI;IACtE,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,SAAS,EAAE,GAAG,IAAI,CAAC;IAC5B,eAAe,CAAC,EAAE,eAAe,CAAC;IAClC,oBAAoB,CAAC,EAAE,oBAAoB,CAAC;IAC5C,aAAa,EAAE,MAAM,CAAC,OAAO,EAAE,gBAAgB,KAAK,IAAI,CAAC;IACzD,iBAAiB,EAAE,mBAAmB,CAAC,CAAC,CAAC,CAAC,mBAAmB,CAAC,CAAC;IAC/D,cAAc,EAAE,mBAAmB,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,gBAAgB,CAAC,CAAC;IAC5D,kBAAkB,EAAE,UAAU,CAAC,OAAO,aAAa,CAAC,CAAC,oBAAoB,CAAC,CAAC;IAC3E,kBAAkB,EAAE,CAAC,SAAS,EAAE,oBAAoB,KAAK,IAAI,CAAC;IAC9D,SAAS,CAAC,EAAE,SAAS,CAAC;CACvB,CAAC;AAEF,eAAO,MAAM,sBAAsB,GAAI,CAAC,SAAS,QAAQ,EAAE,CAAC,SAAS,KAAK,EAAE,iKAWzE,2BAA2B,CAAC,CAAC,EAAE,CAAC,CAAC;4BASrB,MAAM,cACH,aAAa,cACb,aAAa,CAAC,mBAAmB,CAAC,EAAE,cACpC,SAAS;8BAqRZ,MAAM,cACH,aAAa,qBACN,aAAa,CAAC,mBAAmB,CAAC,EAAE;CA4I5D,CAAC"}
@@ -51,6 +51,13 @@ export const useOnMergeUnMergeCells = ({ locale, merges, cellXfsRegistry, shared
51
51
  });
52
52
  }
53
53
  }
54
+ else if (selections.length > 1) {
55
+ // A multi-area selection merges each area on its own (Excel's Merge & Center on a
56
+ // Ctrl-selection). The format painter tiles a source block's merges through this path.
57
+ for (const sel of selections) {
58
+ newMerges.push(sel.range);
59
+ }
60
+ }
54
61
  else {
55
62
  newMerges.push(range);
56
63
  }
@@ -136,22 +143,15 @@ export const useOnMergeUnMergeCells = ({ locale, merges, cellXfsRegistry, shared
136
143
  // Keep track of master cells
137
144
  // Merging cells only keeps the upper-left value and discards other values.
138
145
  const masterCells = new Set();
139
- if (direction === Direction.Right) {
140
- for (let rowIndex = range.startRowIndex; rowIndex <= range.endRowIndex; rowIndex++) {
141
- masterCells.add(cellIdentifier(rowIndex, range.startColumnIndex));
142
- }
143
- }
144
- else if (direction === Direction.Down) {
145
- for (let columnIndex = range.startColumnIndex; columnIndex <= range.endColumnIndex; columnIndex++) {
146
- masterCells.add(cellIdentifier(range.startRowIndex, columnIndex));
147
- }
148
- }
149
- else {
150
- masterCells.add(cellIdentifier(range.startRowIndex, range.startColumnIndex));
146
+ for (const merge of newMerges) {
147
+ masterCells.add(cellIdentifier(merge.startRowIndex, merge.startColumnIndex));
151
148
  }
152
149
  // Create a cell
153
150
  const sheetCell = new SheetCell();
154
- for (const [rowIndex, columnIndex] of iterateCellsInRange(range)) {
151
+ const mergedCells = newMerges.flatMap((merge) => [
152
+ ...iterateCellsInRange(merge),
153
+ ]);
154
+ for (const [rowIndex, columnIndex] of mergedCells) {
155
155
  const cellId = cellIdentifier(rowIndex, columnIndex);
156
156
  if (masterCells.has(cellId)) {
157
157
  continue;
@@ -1 +1 @@
1
- {"version":3,"file":"use-on-paste.d.ts","sourceRoot":"","sources":["../../../hooks/use-on-paste.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"use-on-paste.d.ts","sourceRoot":"","sources":["../../../hooks/use-on-paste.ts"],"names":[],"mappings":"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"}
@@ -9,6 +9,7 @@ import { useCallback } from "react";
9
9
  import { processSideEffectDependentCells } from "../api/dependency";
10
10
  import { createSheetCellIdentifier } from "../api/formula";
11
11
  import { createSheetDraft } from "../api/immer-utils";
12
+ import { applyPasteOperation, isBlankClipboardCell, resolvePasteSpecialOptions, } from "../api/paste-special";
12
13
  import { findAdjacentTable, findTableColumnIndex } from "../api/table";
13
14
  import { addCalculatedColumnsForRowExpansion } from "../interface/change-table-column";
14
15
  import { collectDataValidationTarget, extendDataValidationRanges, } from "../interface/data-validation-utils";
@@ -62,7 +63,11 @@ export const useOnPaste = ({ rowCount, columnCount, locale, sheetData, tables: c
62
63
  const getFinalRowHeight = useGetFinalRowHeight();
63
64
  const { enqueue, processQueue } = useCalculationQueue({ enqueueCalculation });
64
65
  return useCallback(async (e, sourceSheetId, destinationSheetId, copiedSelections, activeCell, selections, finalSelections, isCutOperation) => {
65
- const pasteSpecialType = e?.clipboardData?.getData("pasteSpecialType");
66
+ // Paste Special request (values / formats / formulas, operation, skip
67
+ // blanks, transpose) stashed on the event by the grid's `paste()`.
68
+ const pasteSpecial = resolvePasteSpecialOptions(e?.clipboardData);
69
+ const pasteMode = pasteSpecial.paste;
70
+ const pasteOperation = pasteSpecial.operation;
66
71
  const pasteEvent = e;
67
72
  const forcePlainText = Boolean(pasteEvent?.__forcePlainText ||
68
73
  (pasteEvent?.shiftKey &&
@@ -104,16 +109,16 @@ export const useOnPaste = ({ rowCount, columnCount, locale, sheetData, tables: c
104
109
  if (isNil(selectedRowValues)) {
105
110
  return;
106
111
  }
107
- if (pasteSpecialType === "Transposed") {
112
+ if (pasteSpecial.transpose && selectedRowValues.length) {
108
113
  selectedRowValues = transpose(selectedRowValues);
109
114
  }
110
- else if (pasteSpecialType === "Formatting") {
115
+ if (pasteMode === "formats") {
111
116
  selectedRowValues = pickFormatting(selectedRowValues);
112
117
  }
113
- else if (pasteSpecialType === "Formula") {
118
+ else if (pasteMode === "formulas") {
114
119
  selectedRowValues = pickFormula(selectedRowValues, destinationSheetId, locale);
115
120
  }
116
- else if (pasteSpecialType === "Value") {
121
+ else if (pasteMode === "values") {
117
122
  selectedRowValues = pickValue(selectedRowValues, destinationSheetId, locale);
118
123
  }
119
124
  const saveHistory = createHistory();
@@ -362,19 +367,50 @@ export const useOnPaste = ({ rowCount, columnCount, locale, sheetData, tables: c
362
367
  for (let columnIndex = to.range.startColumnIndex; columnIndex <= to.range.endColumnIndex; columnIndex++, columnCursor++) {
363
368
  const dataColumnIndex = colSpan > 0 ? columnCursor % colSpan : 0;
364
369
  let cellValue = selectedRowValues[dataRowIndex]?.[dataColumnIndex];
365
- if (pasteSpecialType === "Formatting") {
370
+ // Skip blanks: an empty clipboard cell leaves the
371
+ // destination (value and format) untouched.
372
+ if (pasteSpecial.skipBlanks &&
373
+ isBlankClipboardCell(cellValue)) {
374
+ continue;
375
+ }
376
+ // Operation: combine the pasted cell with the cell it
377
+ // lands on. The clipboard is anchored at the FIRST tile,
378
+ // so a source formula is relocated to the tile it lands
379
+ // on first (the same `moveFormula` shift the plain paste
380
+ // applies below); the composed `=(dest)op(source)` is
381
+ // then anchored at the destination and must not be moved
382
+ // again (that would shift the destination fragment too).
383
+ if (pasteOperation) {
384
+ const sourceFormula = getExtendedValueFormula(getCellUserEnteredValue(cellValue));
385
+ if (!isNil(sourceFormula) &&
386
+ dataRowIndex === 0 &&
387
+ dataColumnIndex === 0 &&
388
+ (rowIndex !== sourceCell.rowIndex ||
389
+ columnIndex !== sourceCell.columnIndex)) {
390
+ const tileCell = new SheetCell();
391
+ tileCell.setLocale(locale);
392
+ tileCell.assign(destinationSheetId, sourceCell, cellValue);
393
+ tileCell.moveFormula(sourceCell, { rowIndex, columnIndex }, activeSheetName, { preserveAbsolutes: true });
394
+ cellValue = {
395
+ ...cellValue,
396
+ ue: { ...cellValue?.ue, fv: tileCell.formula },
397
+ };
398
+ }
399
+ cellValue = applyPasteOperation(cellValue, prevSheetData[destinationSheetId]?.[rowIndex]?.values?.[columnIndex], pasteOperation, destinationSheetId, locale);
400
+ }
401
+ if (pasteMode === "formats") {
366
402
  const existingCellData = prevSheetData[destinationSheetId]?.[rowIndex]?.values?.[columnIndex];
367
403
  cellValue = { ...existingCellData, ...cellValue };
368
404
  sheetCell.extendCellData(cellValue);
369
405
  }
370
- if (pasteSpecialType === "Value" || forcePlainText) {
406
+ if (pasteMode === "values" || forcePlainText) {
371
407
  const existingCellData = prevSheetData[destinationSheetId]?.[rowIndex]?.values?.[columnIndex];
372
408
  // Remove ss from existingCellData since we're replacing the value
373
409
  const { ss: _ss, ...existingWithoutSs } = existingCellData ?? {};
374
410
  cellValue = { ...existingWithoutSs, ...cellValue };
375
411
  sheetCell.extendCellData(cellValue);
376
412
  }
377
- if (pasteSpecialType === "Transposed") {
413
+ if (pasteSpecial.transpose && pasteMode === "all") {
378
414
  sheetCell.assign(destinationSheetId, { rowIndex, columnIndex }, prevSheetData[destinationSheetId]?.[rowIndex]?.values?.[columnIndex], {
379
415
  locale,
380
416
  cellXfsRegistry,
@@ -396,11 +432,13 @@ export const useOnPaste = ({ rowCount, columnCount, locale, sheetData, tables: c
396
432
  sharedStringRegistry,
397
433
  });
398
434
  }
399
- if (pasteSpecialType === "Formatting") {
435
+ if (pasteMode === "formats") {
400
436
  sheetCell.refreshFormattedValue();
401
437
  }
402
438
  if (sheetCell.isFormula()) {
403
- if (dataRowIndex === 0 && dataColumnIndex === 0) {
439
+ if (dataRowIndex === 0 &&
440
+ dataColumnIndex === 0 &&
441
+ !pasteOperation) {
404
442
  sheetCell.moveFormula(sourceCell, {
405
443
  rowIndex,
406
444
  columnIndex,
@@ -544,10 +582,7 @@ export const useOnPaste = ({ rowCount, columnCount, locale, sheetData, tables: c
544
582
  // Skipped for paste-special variants since the destination
545
583
  // cell ends up as a merge of existing + pasted data, not
546
584
  // the raw pasted value we can read from selectedRowValues.
547
- const skipAutoResize = pasteSpecialType === "Formatting" ||
548
- pasteSpecialType === "Value" ||
549
- pasteSpecialType === "Formula" ||
550
- pasteSpecialType === "Transposed";
585
+ const skipAutoResize = pasteSpecial.isSpecial;
551
586
  if (!skipAutoResize &&
552
587
  getFinalRowHeight &&
553
588
  selectedRowValues.length &&
@@ -1,5 +1,6 @@
1
1
  import type { CellInterface, SelectionArea } from "@rowsncolumns/common-types";
2
2
  import type { CellData, SelectionAttributes, Sheet } from "@rowsncolumns/spreadsheet";
3
+ import { type RemoveDuplicatesOptions } from "../interface/remove-duplicates";
3
4
  import type { useCalculation } from "./use-calculation";
4
5
  import type { useSheetProperties } from "./use-sheet-properties";
5
6
  import type { UseSpreadsheetProps } from "./use-spreadsheet-state";
@@ -17,5 +18,5 @@ export type UseOnRemoveDuplicatesProps<T extends CellData> = {
17
18
  onChangeSheetData: UseSpreadsheetProps<T, Sheet>["onChangeSheetData"];
18
19
  onCommand?: OnCommand;
19
20
  };
20
- export declare const useOnRemoveDuplicates: <T extends CellData>({ locale, cellXfsRegistry, sharedStringRegistry, getFormattedValue, onChangeSheetData, enqueueCalculation, createHistory, onCommand, }: UseOnRemoveDuplicatesProps<T>) => (sheetId: number, activeCell: CellInterface, selections?: SelectionArea<SelectionAttributes>[]) => import("../interface/remove-duplicates").RemoveDuplicatesResult | undefined;
21
+ export declare const useOnRemoveDuplicates: <T extends CellData>({ locale, cellXfsRegistry, sharedStringRegistry, getFormattedValue, onChangeSheetData, enqueueCalculation, createHistory, onCommand, }: UseOnRemoveDuplicatesProps<T>) => (sheetId: number, activeCell: CellInterface, selections?: SelectionArea<SelectionAttributes>[], options?: RemoveDuplicatesOptions) => import("../interface/remove-duplicates").RemoveDuplicatesResult | undefined;
21
22
  //# sourceMappingURL=use-on-remove-duplicates.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"use-on-remove-duplicates.d.ts","sourceRoot":"","sources":["../../../hooks/use-on-remove-duplicates.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,4BAA4B,CAAC;AAC/E,OAAO,KAAK,EACV,QAAQ,EACR,mBAAmB,EACnB,KAAK,EACN,MAAM,2BAA2B,CAAC;AAKnC,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AACxD,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,wBAAwB,CAAC;AACjE,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,yBAAyB,CAAC;AACnE,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AACxD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAC7C,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AACzD,OAAO,EAAE,oBAAoB,EAAE,MAAM,mBAAmB,CAAC;AAEzD,MAAM,MAAM,0BAA0B,CAAC,CAAC,SAAS,QAAQ,IAAI;IAC3D,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,eAAe,CAAC,EAAE,eAAe,CAAC;IAClC,oBAAoB,CAAC,EAAE,oBAAoB,CAAC;IAC5C,iBAAiB,EAAE,UAAU,CAAC,OAAO,kBAAkB,CAAC,CAAC,mBAAmB,CAAC,CAAC;IAC9E,kBAAkB,EAAE,UAAU,CAAC,OAAO,cAAc,CAAC,CAAC,oBAAoB,CAAC,CAAC;IAC5E,aAAa,EAAE,MAAM,CAAC,OAAO,EAAE,gBAAgB,KAAK,IAAI,CAAC;IACzD,iBAAiB,EAAE,mBAAmB,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,mBAAmB,CAAC,CAAC;IACtE,SAAS,CAAC,EAAE,SAAS,CAAC;CACvB,CAAC;AAEF,eAAO,MAAM,qBAAqB,GAAI,CAAC,SAAS,QAAQ,EAAE,wIASvD,0BAA0B,CAAC,CAAC,CAAC,eAKjB,MAAM,cACH,aAAa,eACZ,aAAa,CAAC,mBAAmB,CAAC,EAAE,gFAyCtD,CAAC"}
1
+ {"version":3,"file":"use-on-remove-duplicates.d.ts","sourceRoot":"","sources":["../../../hooks/use-on-remove-duplicates.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,4BAA4B,CAAC;AAC/E,OAAO,KAAK,EACV,QAAQ,EACR,mBAAmB,EACnB,KAAK,EACN,MAAM,2BAA2B,CAAC;AAGnC,OAAO,EAEL,KAAK,uBAAuB,EAC7B,MAAM,gCAAgC,CAAC;AAExC,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AACxD,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,wBAAwB,CAAC;AACjE,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,yBAAyB,CAAC;AACnE,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AACxD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAC7C,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AACzD,OAAO,EAAE,oBAAoB,EAAE,MAAM,mBAAmB,CAAC;AAEzD,MAAM,MAAM,0BAA0B,CAAC,CAAC,SAAS,QAAQ,IAAI;IAC3D,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,eAAe,CAAC,EAAE,eAAe,CAAC;IAClC,oBAAoB,CAAC,EAAE,oBAAoB,CAAC;IAC5C,iBAAiB,EAAE,UAAU,CAAC,OAAO,kBAAkB,CAAC,CAAC,mBAAmB,CAAC,CAAC;IAC9E,kBAAkB,EAAE,UAAU,CAAC,OAAO,cAAc,CAAC,CAAC,oBAAoB,CAAC,CAAC;IAC5E,aAAa,EAAE,MAAM,CAAC,OAAO,EAAE,gBAAgB,KAAK,IAAI,CAAC;IACzD,iBAAiB,EAAE,mBAAmB,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,mBAAmB,CAAC,CAAC;IACtE,SAAS,CAAC,EAAE,SAAS,CAAC;CACvB,CAAC;AAEF,eAAO,MAAM,qBAAqB,GAAI,CAAC,SAAS,QAAQ,EAAE,wIASvD,0BAA0B,CAAC,CAAC,CAAC,eAKjB,MAAM,cACH,aAAa,eACZ,aAAa,CAAC,mBAAmB,CAAC,EAAE,YACvC,uBAAuB,gFA2CtC,CAAC"}