@rowsncolumns/spreadsheet-state 29.1.4 → 29.1.6

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 (221) hide show
  1. package/dist/cjs/api/circular-reference.d.ts +31 -0
  2. package/dist/cjs/api/circular-reference.d.ts.map +1 -0
  3. package/dist/cjs/api/circular-reference.js +85 -0
  4. package/dist/cjs/api/copy-paste.d.ts +6 -0
  5. package/dist/cjs/api/copy-paste.d.ts.map +1 -1
  6. package/dist/cjs/api/copy-paste.js +24 -15
  7. package/dist/cjs/api/datatype.d.ts +2 -0
  8. package/dist/cjs/api/datatype.d.ts.map +1 -1
  9. package/dist/cjs/api/datatype.js +50 -27
  10. package/dist/cjs/api/decimals.d.ts +10 -0
  11. package/dist/cjs/api/decimals.d.ts.map +1 -1
  12. package/dist/cjs/api/decimals.js +34 -11
  13. package/dist/cjs/api/dependency.d.ts +19 -1
  14. package/dist/cjs/api/dependency.d.ts.map +1 -1
  15. package/dist/cjs/api/dependency.js +30 -14
  16. package/dist/cjs/api/filter-condition.d.ts +58 -0
  17. package/dist/cjs/api/filter-condition.d.ts.map +1 -0
  18. package/dist/cjs/api/filter-condition.js +157 -0
  19. package/dist/cjs/api/formula.d.ts.map +1 -1
  20. package/dist/cjs/api/formula.js +9 -7
  21. package/dist/cjs/api/image-embed.d.ts +41 -0
  22. package/dist/cjs/api/image-embed.d.ts.map +1 -0
  23. package/dist/cjs/api/image-embed.js +55 -0
  24. package/dist/cjs/api/immer-utils.d.ts.map +1 -1
  25. package/dist/cjs/api/immer-utils.js +43 -15
  26. package/dist/cjs/api/named-range-structural.d.ts +29 -3
  27. package/dist/cjs/api/named-range-structural.d.ts.map +1 -1
  28. package/dist/cjs/api/named-range-structural.js +36 -11
  29. package/dist/cjs/api/parse-html.d.ts.map +1 -1
  30. package/dist/cjs/api/parse-html.js +11 -5
  31. package/dist/cjs/api/structural-formula-update.d.ts +20 -1
  32. package/dist/cjs/api/structural-formula-update.d.ts.map +1 -1
  33. package/dist/cjs/api/structural-formula-update.js +264 -90
  34. package/dist/cjs/api/structural-guards.d.ts +11 -0
  35. package/dist/cjs/api/structural-guards.d.ts.map +1 -1
  36. package/dist/cjs/api/structural-guards.js +45 -1
  37. package/dist/cjs/api/structural-table-refs.d.ts +15 -2
  38. package/dist/cjs/api/structural-table-refs.d.ts.map +1 -1
  39. package/dist/cjs/api/structural-table-refs.js +79 -35
  40. package/dist/cjs/commands.d.ts +17 -3
  41. package/dist/cjs/commands.d.ts.map +1 -1
  42. package/dist/cjs/components/editors/conditional-format-rule-editor.d.ts.map +1 -1
  43. package/dist/cjs/components/editors/conditional-format-rule-editor.js +19 -7
  44. package/dist/cjs/constants.d.ts +4 -1
  45. package/dist/cjs/constants.d.ts.map +1 -1
  46. package/dist/cjs/constants.js +4 -0
  47. package/dist/cjs/helpers/sheet-title.d.ts +2 -1
  48. package/dist/cjs/helpers/sheet-title.d.ts.map +1 -1
  49. package/dist/cjs/helpers/sheet-title.js +3 -1
  50. package/dist/cjs/hooks/use-can-edit-cellrange.d.ts +1 -1
  51. package/dist/cjs/hooks/use-can-edit-cellrange.d.ts.map +1 -1
  52. package/dist/cjs/hooks/use-can-edit-cellrange.js +1 -1
  53. package/dist/cjs/hooks/use-on-calculation-success.d.ts +5 -1
  54. package/dist/cjs/hooks/use-on-calculation-success.d.ts.map +1 -1
  55. package/dist/cjs/hooks/use-on-calculation-success.js +20 -3
  56. package/dist/cjs/hooks/use-on-copy.d.ts.map +1 -1
  57. package/dist/cjs/hooks/use-on-copy.js +23 -25
  58. package/dist/cjs/hooks/use-on-create-sheet.d.ts.map +1 -1
  59. package/dist/cjs/hooks/use-on-create-sheet.js +11 -1
  60. package/dist/cjs/hooks/use-on-delete.d.ts.map +1 -1
  61. package/dist/cjs/hooks/use-on-delete.js +15 -3
  62. package/dist/cjs/hooks/use-on-drag-n-drop.d.ts +5 -0
  63. package/dist/cjs/hooks/use-on-drag-n-drop.d.ts.map +1 -1
  64. package/dist/cjs/hooks/use-on-drag-n-drop.js +6 -5
  65. package/dist/cjs/hooks/use-on-filter-table.d.ts.map +1 -1
  66. package/dist/cjs/hooks/use-on-filter-table.js +6 -1
  67. package/dist/cjs/hooks/use-on-find-replace.d.ts.map +1 -1
  68. package/dist/cjs/hooks/use-on-find-replace.js +111 -23
  69. package/dist/cjs/hooks/use-on-insert-image.d.ts.map +1 -1
  70. package/dist/cjs/hooks/use-on-insert-image.js +20 -33
  71. package/dist/cjs/hooks/use-on-paste.d.ts +2 -1
  72. package/dist/cjs/hooks/use-on-paste.d.ts.map +1 -1
  73. package/dist/cjs/hooks/use-on-paste.js +53 -24
  74. package/dist/cjs/hooks/use-on-rename-sheet.d.ts +3 -1
  75. package/dist/cjs/hooks/use-on-rename-sheet.d.ts.map +1 -1
  76. package/dist/cjs/hooks/use-on-rename-sheet.js +19 -9
  77. package/dist/cjs/hooks/use-on-sort-column.d.ts +7 -1
  78. package/dist/cjs/hooks/use-on-sort-column.d.ts.map +1 -1
  79. package/dist/cjs/hooks/use-on-sort-column.js +25 -8
  80. package/dist/cjs/hooks/use-on-sort-range.d.ts +16 -2
  81. package/dist/cjs/hooks/use-on-sort-range.d.ts.map +1 -1
  82. package/dist/cjs/hooks/use-on-sort-range.js +72 -40
  83. package/dist/cjs/hooks/use-on-sort-table.d.ts +7 -2
  84. package/dist/cjs/hooks/use-on-sort-table.d.ts.map +1 -1
  85. package/dist/cjs/hooks/use-on-sort-table.js +25 -4
  86. package/dist/cjs/hooks/use-spreadsheet-state.d.ts +5 -3
  87. package/dist/cjs/hooks/use-spreadsheet-state.d.ts.map +1 -1
  88. package/dist/cjs/hooks/use-spreadsheet-state.js +7 -0
  89. package/dist/cjs/hooks/utils/sort-rows.d.ts +15 -0
  90. package/dist/cjs/hooks/utils/sort-rows.d.ts.map +1 -1
  91. package/dist/cjs/hooks/utils/sort-rows.js +16 -0
  92. package/dist/cjs/index.d.ts +3 -0
  93. package/dist/cjs/index.d.ts.map +1 -1
  94. package/dist/cjs/index.js +3 -0
  95. package/dist/cjs/interface/delete-column.d.ts.map +1 -1
  96. package/dist/cjs/interface/delete-column.js +254 -101
  97. package/dist/cjs/interface/delete-row.d.ts.map +1 -1
  98. package/dist/cjs/interface/delete-row.js +233 -81
  99. package/dist/cjs/interface/duplicate-sheet.d.ts.map +1 -1
  100. package/dist/cjs/interface/duplicate-sheet.js +4 -9
  101. package/dist/cjs/interface/insert-column.d.ts.map +1 -1
  102. package/dist/cjs/interface/insert-column.js +1 -1
  103. package/dist/cjs/interface/insert-row.d.ts.map +1 -1
  104. package/dist/cjs/interface/insert-row.js +1 -1
  105. package/dist/cjs/interface/new-sheet.d.ts.map +1 -1
  106. package/dist/cjs/interface/new-sheet.js +6 -13
  107. package/dist/cjs/sheet-cell.d.ts +9 -0
  108. package/dist/cjs/sheet-cell.d.ts.map +1 -1
  109. package/dist/cjs/sheet-cell.js +46 -9
  110. package/dist/cjs/tsconfig.cjs.tsbuildinfo +1 -1
  111. package/dist/esm/api/circular-reference.d.ts +31 -0
  112. package/dist/esm/api/circular-reference.d.ts.map +1 -0
  113. package/dist/esm/api/circular-reference.js +55 -0
  114. package/dist/esm/api/copy-paste.d.ts +6 -0
  115. package/dist/esm/api/copy-paste.d.ts.map +1 -1
  116. package/dist/esm/api/copy-paste.js +26 -14
  117. package/dist/esm/api/datatype.d.ts +2 -0
  118. package/dist/esm/api/datatype.d.ts.map +1 -1
  119. package/dist/esm/api/datatype.js +50 -27
  120. package/dist/esm/api/decimals.d.ts +10 -0
  121. package/dist/esm/api/decimals.d.ts.map +1 -1
  122. package/dist/esm/api/decimals.js +31 -10
  123. package/dist/esm/api/dependency.d.ts +19 -1
  124. package/dist/esm/api/dependency.d.ts.map +1 -1
  125. package/dist/esm/api/dependency.js +15 -10
  126. package/dist/esm/api/filter-condition.d.ts +58 -0
  127. package/dist/esm/api/filter-condition.d.ts.map +1 -0
  128. package/dist/esm/api/filter-condition.js +146 -0
  129. package/dist/esm/api/formula.d.ts.map +1 -1
  130. package/dist/esm/api/formula.js +9 -7
  131. package/dist/esm/api/image-embed.d.ts +41 -0
  132. package/dist/esm/api/image-embed.d.ts.map +1 -0
  133. package/dist/esm/api/image-embed.js +52 -0
  134. package/dist/esm/api/immer-utils.d.ts.map +1 -1
  135. package/dist/esm/api/immer-utils.js +43 -14
  136. package/dist/esm/api/named-range-structural.d.ts +29 -3
  137. package/dist/esm/api/named-range-structural.d.ts.map +1 -1
  138. package/dist/esm/api/named-range-structural.js +35 -11
  139. package/dist/esm/api/parse-html.d.ts.map +1 -1
  140. package/dist/esm/api/parse-html.js +14 -5
  141. package/dist/esm/api/structural-formula-update.d.ts +20 -1
  142. package/dist/esm/api/structural-formula-update.d.ts.map +1 -1
  143. package/dist/esm/api/structural-formula-update.js +151 -55
  144. package/dist/esm/api/structural-guards.d.ts +11 -0
  145. package/dist/esm/api/structural-guards.d.ts.map +1 -1
  146. package/dist/esm/api/structural-guards.js +31 -0
  147. package/dist/esm/api/structural-table-refs.d.ts +15 -2
  148. package/dist/esm/api/structural-table-refs.d.ts.map +1 -1
  149. package/dist/esm/api/structural-table-refs.js +49 -18
  150. package/dist/esm/commands.d.ts +17 -3
  151. package/dist/esm/commands.d.ts.map +1 -1
  152. package/dist/esm/components/editors/conditional-format-rule-editor.d.ts.map +1 -1
  153. package/dist/esm/components/editors/conditional-format-rule-editor.js +18 -7
  154. package/dist/esm/constants.d.ts +4 -1
  155. package/dist/esm/constants.d.ts.map +1 -1
  156. package/dist/esm/constants.js +4 -0
  157. package/dist/esm/helpers/sheet-title.d.ts +2 -1
  158. package/dist/esm/helpers/sheet-title.d.ts.map +1 -1
  159. package/dist/esm/helpers/sheet-title.js +3 -1
  160. package/dist/esm/hooks/use-can-edit-cellrange.d.ts +1 -1
  161. package/dist/esm/hooks/use-can-edit-cellrange.d.ts.map +1 -1
  162. package/dist/esm/hooks/use-can-edit-cellrange.js +1 -1
  163. package/dist/esm/hooks/use-on-calculation-success.d.ts +5 -1
  164. package/dist/esm/hooks/use-on-calculation-success.d.ts.map +1 -1
  165. package/dist/esm/hooks/use-on-calculation-success.js +19 -3
  166. package/dist/esm/hooks/use-on-copy.d.ts.map +1 -1
  167. package/dist/esm/hooks/use-on-copy.js +17 -17
  168. package/dist/esm/hooks/use-on-create-sheet.d.ts.map +1 -1
  169. package/dist/esm/hooks/use-on-create-sheet.js +11 -1
  170. package/dist/esm/hooks/use-on-delete.d.ts.map +1 -1
  171. package/dist/esm/hooks/use-on-delete.js +15 -3
  172. package/dist/esm/hooks/use-on-drag-n-drop.d.ts +5 -0
  173. package/dist/esm/hooks/use-on-drag-n-drop.d.ts.map +1 -1
  174. package/dist/esm/hooks/use-on-drag-n-drop.js +7 -4
  175. package/dist/esm/hooks/use-on-filter-table.d.ts.map +1 -1
  176. package/dist/esm/hooks/use-on-filter-table.js +13 -2
  177. package/dist/esm/hooks/use-on-find-replace.d.ts.map +1 -1
  178. package/dist/esm/hooks/use-on-find-replace.js +111 -23
  179. package/dist/esm/hooks/use-on-insert-image.d.ts.map +1 -1
  180. package/dist/esm/hooks/use-on-insert-image.js +15 -25
  181. package/dist/esm/hooks/use-on-paste.d.ts +2 -1
  182. package/dist/esm/hooks/use-on-paste.d.ts.map +1 -1
  183. package/dist/esm/hooks/use-on-paste.js +46 -15
  184. package/dist/esm/hooks/use-on-rename-sheet.d.ts +3 -1
  185. package/dist/esm/hooks/use-on-rename-sheet.d.ts.map +1 -1
  186. package/dist/esm/hooks/use-on-rename-sheet.js +19 -9
  187. package/dist/esm/hooks/use-on-sort-column.d.ts +7 -1
  188. package/dist/esm/hooks/use-on-sort-column.d.ts.map +1 -1
  189. package/dist/esm/hooks/use-on-sort-column.js +18 -1
  190. package/dist/esm/hooks/use-on-sort-range.d.ts +16 -2
  191. package/dist/esm/hooks/use-on-sort-range.d.ts.map +1 -1
  192. package/dist/esm/hooks/use-on-sort-range.js +30 -3
  193. package/dist/esm/hooks/use-on-sort-table.d.ts +7 -2
  194. package/dist/esm/hooks/use-on-sort-table.d.ts.map +1 -1
  195. package/dist/esm/hooks/use-on-sort-table.js +25 -4
  196. package/dist/esm/hooks/use-spreadsheet-state.d.ts +5 -3
  197. package/dist/esm/hooks/use-spreadsheet-state.d.ts.map +1 -1
  198. package/dist/esm/hooks/use-spreadsheet-state.js +7 -0
  199. package/dist/esm/hooks/utils/sort-rows.d.ts +15 -0
  200. package/dist/esm/hooks/utils/sort-rows.d.ts.map +1 -1
  201. package/dist/esm/hooks/utils/sort-rows.js +15 -0
  202. package/dist/esm/index.d.ts +3 -0
  203. package/dist/esm/index.d.ts.map +1 -1
  204. package/dist/esm/index.js +3 -0
  205. package/dist/esm/interface/delete-column.d.ts.map +1 -1
  206. package/dist/esm/interface/delete-column.js +111 -80
  207. package/dist/esm/interface/delete-row.d.ts.map +1 -1
  208. package/dist/esm/interface/delete-row.js +91 -59
  209. package/dist/esm/interface/duplicate-sheet.d.ts.map +1 -1
  210. package/dist/esm/interface/duplicate-sheet.js +4 -9
  211. package/dist/esm/interface/insert-column.d.ts.map +1 -1
  212. package/dist/esm/interface/insert-column.js +1 -1
  213. package/dist/esm/interface/insert-row.d.ts.map +1 -1
  214. package/dist/esm/interface/insert-row.js +1 -1
  215. package/dist/esm/interface/new-sheet.d.ts.map +1 -1
  216. package/dist/esm/interface/new-sheet.js +6 -13
  217. package/dist/esm/sheet-cell.d.ts +9 -0
  218. package/dist/esm/sheet-cell.d.ts.map +1 -1
  219. package/dist/esm/sheet-cell.js +46 -7
  220. package/dist/esm/tsconfig.esm.tsbuildinfo +1 -1
  221. package/package.json +9 -9
@@ -1,10 +1,25 @@
1
- import { isNil, iterateCellsInRange } from "@rowsncolumns/utils";
1
+ import { getCellEffectiveValue, getCellUserEnteredValue, getExtendedValueBool, getExtendedValueFormula, getExtendedValueNumber, getExtendedValueString, isNil, iterateCellsInRange, } from "@rowsncolumns/utils";
2
2
  import { produceWithPatches } from "immer";
3
+ import isEqual from "lodash/isEqual";
3
4
  import { useCallback } from "react";
4
5
  import { createSheetCellIdentifier } from "../api/formula";
5
6
  import { createSheetDraft } from "../api/immer-utils";
6
- import { SheetCell } from "../sheet-cell";
7
+ import { SheetCell, hasExcelTextPrefix, stripExcelTextPrefix, } from "../sheet-cell";
7
8
  import { buildSearchRegex } from "./use-search";
9
+ /**
10
+ * The text `text` becomes after replacing every match of `regex` with
11
+ * `replaceWith`, or `undefined` when nothing matches / nothing changes (the
12
+ * cell is then left untouched). `regex` is the `g`-flagged matcher from
13
+ * `buildSearchRegex`, so `lastIndex` is reset before each use.
14
+ */
15
+ const replaceIn = (regex, text, replaceWith) => {
16
+ regex.lastIndex = 0;
17
+ if (!regex.test(text))
18
+ return undefined;
19
+ regex.lastIndex = 0;
20
+ const next = text.replace(regex, replaceWith ?? "");
21
+ return next === text ? undefined : next;
22
+ };
8
23
  export const useOnFindReplace = ({ locale, createHistory, onChangeSheetData, enqueueCalculation, enqueueStructureChange, sharedStringRegistry, onCommand, }) => {
9
24
  return useCallback((lookupRanges, searchStr, replaceWith, options) => {
10
25
  // Build the matcher once with the same helper `useSearch` uses, so
@@ -55,28 +70,101 @@ export const useOnFindReplace = ({ locale, createHistory, onChangeSheetData, enq
55
70
  const currentSheet = createSheetDraft(draft, range.sheetId, rowIndex);
56
71
  const cellData = draft[range.sheetId]?.[rowIndex]?.values?.[columnIndex];
57
72
  sheetCell.assign(range.sheetId, { rowIndex, columnIndex }, cellData, { locale });
58
- // Match AND replace against the formatted value — what
59
- // the user sees and what `useSearch` matched. The
60
- // user-entered value can be a number / formula whose
61
- // display form ("$100.00") doesn't contain the literal
62
- // search string ("100"), so trying to replace in `sv`
63
- // alone misses those cells. Writing the replaced
64
- // formatted text back as the new user-entered value
65
- // mirrors Excel / Google Sheets — a cell that was
66
- // numeric with a currency format becomes the plain
67
- // string the user typed in the Replace box.
68
- const formattedValue = sheetCell.formattedValue;
69
- if (isNil(formattedValue))
70
- continue;
71
- // `g` flag is set by `buildSearchRegex`; reset lastIndex
72
- // before .test so a stateful regex doesn't skip the
73
- // first character on a re-run.
74
- regex.lastIndex = 0;
75
- if (!regex.test(formattedValue))
73
+ // Excel's Replace edits the cell's STORED content (it runs in
74
+ // "Look in: Formulas" only), so the match text and the write
75
+ // depend on what the cell holds — never on the display alone:
76
+ // - a formula cell is matched on and rewritten in its SOURCE
77
+ // text (`=SUM(A1:A2)` → `=SUM(B1:A2)`); its computed result
78
+ // is not a hit, so the formula is never flattened to a
79
+ // literal;
80
+ // - a text cell is matched on its display (what `useSearch`
81
+ // highlighted) but the replacement runs over the stored
82
+ // string and is written back AS TEXT — `'0123` keeps its
83
+ // quote prefix (`'0124`), a Text-formatted `0123` stays
84
+ // `0124`, and a text whose new content looks numeric is not
85
+ // re-inferred;
86
+ // - a number / boolean / date is matched on its display
87
+ // ("$1,234.50"), the replacement runs over that display and
88
+ // the result is re-entered under the cell's own number
89
+ // format — `$1,235.50` stays the number 1235.5 in currency,
90
+ // `1/15/2025` stays a date serial — and the format itself
91
+ // is left exactly as it was.
92
+ const ue = getCellUserEnteredValue(cellData);
93
+ const ev = getCellEffectiveValue(cellData);
94
+ const formula = getExtendedValueFormula(ue);
95
+ // The legacy model keeps a number's ENTERED string in `ue.sv`
96
+ // ("$1,234.50") and its value in `ev.nv`, so `ue.sv` alone does
97
+ // not make a cell text: a literal is text when it evaluates to
98
+ // a string, carries Excel's `'` prefix, or sits in a Text
99
+ // format. Anything else with a stored string is a typed
100
+ // number / boolean / date.
101
+ const storedText = isNil(formula)
102
+ ? getExtendedValueString(ue)
103
+ : undefined;
104
+ const isNumericLiteral = !isNil(getExtendedValueNumber(ev)) ||
105
+ !isNil(getExtendedValueBool(ev));
106
+ const isTextLiteral = !isNil(storedText) &&
107
+ !isNumericLiteral &&
108
+ (!isNil(getExtendedValueString(ev)) ||
109
+ hasExcelTextPrefix(storedText) ||
110
+ sheetCell.isText(sheetCell.getNumberFormat()));
111
+ let next;
112
+ let writeAsText = false;
113
+ let textPrefix = "";
114
+ if (!isNil(formula)) {
115
+ next = replaceIn(regex, formula, replaceWith);
116
+ }
117
+ else {
118
+ const formattedValue = sheetCell.formattedValue;
119
+ if (isNil(formattedValue))
120
+ continue;
121
+ // `g` flag is set by `buildSearchRegex`; reset lastIndex
122
+ // before .test so a stateful regex doesn't skip the
123
+ // first character on a re-run.
124
+ regex.lastIndex = 0;
125
+ if (!regex.test(formattedValue))
126
+ continue;
127
+ if (isTextLiteral) {
128
+ if (hasExcelTextPrefix(storedText)) {
129
+ textPrefix = "'";
130
+ }
131
+ const base = textPrefix
132
+ ? stripExcelTextPrefix(storedText)
133
+ : storedText;
134
+ // A needle that appears only in an `@`-pattern's
135
+ // decoration (`"Note: "@`) is not cell content.
136
+ next = replaceIn(regex, base, replaceWith);
137
+ writeAsText = true;
138
+ }
139
+ else {
140
+ next = replaceIn(regex, formattedValue, replaceWith);
141
+ }
142
+ }
143
+ if (isNil(next))
76
144
  continue;
77
- regex.lastIndex = 0;
78
- const next = formattedValue.replace(regex, replaceWith ?? "");
79
- sheetCell.setUserEnteredValue(next);
145
+ if (next === "") {
146
+ sheetCell.setUserEnteredValue("");
147
+ }
148
+ else if (writeAsText) {
149
+ if (textPrefix) {
150
+ // The normal entry path keeps a `'`-prefixed entry as text
151
+ // and preserves the prefix in `ue.sv` for the formula bar.
152
+ sheetCell.setUserEnteredValue(`${textPrefix}${next}`);
153
+ }
154
+ else {
155
+ sheetCell.setUserEnteredValue(next, undefined, {
156
+ disableTypeInference: true,
157
+ });
158
+ }
159
+ }
160
+ else {
161
+ const numberFormat = sheetCell.getNumberFormat();
162
+ sheetCell.setUserEnteredValue(next);
163
+ if (!isNil(numberFormat) &&
164
+ !isEqual(sheetCell.getNumberFormat(), numberFormat)) {
165
+ sheetCell.setUserEnteredFormat("numberFormat", numberFormat);
166
+ }
167
+ }
80
168
  sharedStringRegistry?.registerCell(sheetCell);
81
169
  currentSheet[rowIndex].values[columnIndex] =
82
170
  sheetCell.getCellData();
@@ -1 +1 @@
1
- {"version":3,"file":"use-on-insert-image.d.ts","sourceRoot":"","sources":["../../../hooks/use-on-insert-image.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,4BAA4B,CAAC;AAChE,OAAO,KAAK,EACV,QAAQ,EAER,KAAK,EACN,MAAM,2BAA2B,CAAC;AAYnC,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAG7C,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,mBAAmB,CAAC;AAC9D,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;AAC9D,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,yBAAyB,CAAC;AACnE,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AAExD,KAAK,qBAAqB,CAAC,CAAC,SAAS,QAAQ,EAAE,CAAC,SAAS,KAAK,IAAI;IAChE,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB;;OAEG;IACH,kBAAkB,CAAC,EAAE,mBAAmB,CAAC,oBAAoB,CAAC,CAAC;IAC/D,kBAAkB,CAAC,SAAS,EAAE,oBAAoB,GAAG,IAAI,CAAC;IAC1D,aAAa,EAAE,MAAM,CAAC,OAAO,EAAE,gBAAgB,KAAK,IAAI,CAAC;IACzD,iBAAiB,EAAE,mBAAmB,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,mBAAmB,CAAC,CAAC;IAClE,cAAc,EAAE,mBAAmB,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,gBAAgB,CAAC,CAAC;IAC5D,SAAS,CAAC,EAAE,SAAS,CAAC;CACvB,CAAC;AAEF,eAAO,MAAM,gBAAgB,GAAI,CAAC,SAAS,QAAQ,EAAE,CAAC,SAAS,KAAK,EAAE,kHAQnE,qBAAqB,CAAC,CAAC,EAAE,CAAC,CAAC,iBAIb,IAAI,GAAG,MAAM,WACf,MAAM,cACH,aAAa,YACf,iBAAiB,GAAG;IAAE,OAAO,CAAC,EAAE,MAAM,GAAG,MAAM,CAAA;CAAE,kBAoJhE,CAAC"}
1
+ {"version":3,"file":"use-on-insert-image.d.ts","sourceRoot":"","sources":["../../../hooks/use-on-insert-image.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,4BAA4B,CAAC;AAChE,OAAO,KAAK,EACV,QAAQ,EAER,KAAK,EACN,MAAM,2BAA2B,CAAC;AAanC,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAG7C,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,mBAAmB,CAAC;AAC9D,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;AAC9D,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,yBAAyB,CAAC;AACnE,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AAExD,KAAK,qBAAqB,CAAC,CAAC,SAAS,QAAQ,EAAE,CAAC,SAAS,KAAK,IAAI;IAChE,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB;;OAEG;IACH,kBAAkB,CAAC,EAAE,mBAAmB,CAAC,oBAAoB,CAAC,CAAC;IAC/D,kBAAkB,CAAC,SAAS,EAAE,oBAAoB,GAAG,IAAI,CAAC;IAC1D,aAAa,EAAE,MAAM,CAAC,OAAO,EAAE,gBAAgB,KAAK,IAAI,CAAC;IACzD,iBAAiB,EAAE,mBAAmB,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,mBAAmB,CAAC,CAAC;IAClE,cAAc,EAAE,mBAAmB,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,gBAAgB,CAAC,CAAC;IAC5D,SAAS,CAAC,EAAE,SAAS,CAAC;CACvB,CAAC;AAEF,eAAO,MAAM,gBAAgB,GAAI,CAAC,SAAS,QAAQ,EAAE,CAAC,SAAS,KAAK,EAAE,kHAQnE,qBAAqB,CAAC,CAAC,EAAE,CAAC,CAAC,iBAIb,IAAI,GAAG,MAAM,WACf,MAAM,cACH,aAAa,YACf,iBAAiB,GAAG;IAAE,OAAO,CAAC,EAAE,MAAM,GAAG,MAAM,CAAA;CAAE,kBA0IhE,CAAC"}
@@ -1,26 +1,25 @@
1
1
  import { useGetSheetDimensions } from "@rowsncolumns/spreadsheet";
2
2
  import { getImageDimensionsFromUrl, readImageFileAsDataUri, } from "@rowsncolumns/toolkit";
3
- import { log, uuid } from "@rowsncolumns/utils";
3
+ import { log } from "@rowsncolumns/utils";
4
4
  import { produceWithPatches } from "immer";
5
5
  import { useCallback } from "react";
6
6
  import { createSheetCellIdentifier } from "../api/formula";
7
+ import { createImageEmbed, fitImageToViewport } from "../api/image-embed";
7
8
  import { createSheetDraft } from "../api/immer-utils";
8
9
  import { SheetCell } from "../sheet-cell";
9
10
  export const useOnInsertImage = ({ locale, idCreationStrategy, enqueueCalculation, createHistory, onChangeEmbeds, onChangeSheetData, onCommand, }) => {
10
11
  const getSheetDimensions = useGetSheetDimensions();
11
12
  return useCallback(async (fileOrUrl, sheetId, activeCell, options) => {
12
13
  const { insertOverCells, embedId } = options ?? {};
13
- const maxDimension = 800;
14
14
  const [imageUrl, width, height] = fileOrUrl instanceof File
15
15
  ? await readImageFileAsDataUri(fileOrUrl)
16
16
  : [
17
17
  fileOrUrl,
18
18
  ...(await getImageDimensionsFromUrl(fileOrUrl)),
19
19
  ];
20
- const ratio = width / height;
21
- const [sheetWidth = maxDimension] = getSheetDimensions?.() ?? [];
22
- const finalWidth = Math.min(width, Math.min(sheetWidth, maxDimension));
23
- const finalHeight = finalWidth / ratio;
20
+ // Excel's default picture size: natural pixels, scaled down to fit the visible grid.
21
+ const viewport = getSheetDimensions?.();
22
+ const { widthPixels: finalWidth, heightPixels: finalHeight } = fitImageToViewport(width, height, viewport);
24
23
  // Recalc cells
25
24
  const recalcCells = new Map();
26
25
  const saveHistory = createHistory();
@@ -33,25 +32,16 @@ export const useOnInsertImage = ({ locale, idCreationStrategy, enqueueCalculatio
33
32
  if (!draft) {
34
33
  draft = [];
35
34
  }
36
- const embed = {
37
- embedId: idCreationStrategy?.("embed") ?? uuid(),
38
- position: {
39
- sheetId,
40
- overlayPosition: {
41
- anchorCell: activeCell,
42
- widthPixels: finalWidth,
43
- heightPixels: finalHeight,
44
- offsetXPixels: 0,
45
- offsetYPixels: 0,
46
- },
47
- },
48
- borderColor: "transparent",
49
- lockAspectRatio: true,
50
- spec: {
51
- type: "image",
52
- imageUrl,
53
- },
54
- };
35
+ // The same floating picture the clipboard paste / file drop create.
36
+ const embed = createImageEmbed({
37
+ sheetId,
38
+ anchorCell: activeCell,
39
+ imageUrl,
40
+ width,
41
+ height,
42
+ viewport,
43
+ idCreationStrategy,
44
+ });
55
45
  if (embedId) {
56
46
  const idx = draft.findIndex((cur) => cur.embedId === embedId);
57
47
  if (idx !== -1) {
@@ -95,7 +95,8 @@ type UseOnPasteProps<T extends CellData, S extends Sheet> = {
95
95
  */
96
96
  onChangeCitations?: UseSpreadsheetProps<T, S>["onChangeCitations"];
97
97
  /**
98
- * Optional HTML sanitizer for clipboard paste operations
98
+ * Optional additional HTML sanitizer for clipboard paste operations. The
99
+ * built-in sanitizer always runs afterwards; this can only tighten it.
99
100
  */
100
101
  sanitizeHtml?: (html: string) => string;
101
102
  /**
@@ -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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"}
@@ -1,7 +1,7 @@
1
1
  import { isStaticNode } from "@rowsncolumns/dag";
2
2
  import { areaInsideArea, areaIntersects, isAreasEqual } from "@rowsncolumns/grid";
3
3
  import { selectionFromActiveCell } from "@rowsncolumns/grid";
4
- import { DEFAULT_COLUMN_COUNT, DEFAULT_ROW_COUNT, findActiveTableWithinCell, loadWebFont, MAX_COLUMN_COUNT, MAX_ROW_COUNT, useFocusEmbedOrChart, useGetFinalRowHeight, useRedrawGrid, } from "@rowsncolumns/spreadsheet";
4
+ import { DEFAULT_COLUMN_COUNT, DEFAULT_ROW_COUNT, findActiveTableWithinCell, loadWebFont, MAX_COLUMN_COUNT, MAX_ROW_COUNT, useFocusEmbedOrChart, useGetFinalRowHeight, useGetSheetDimensions, useRedrawGrid, } from "@rowsncolumns/spreadsheet";
5
5
  import { isSelectionACell, useGetEffectiveValuesFromRange, } from "@rowsncolumns/spreadsheet";
6
6
  import { error, getCellFormattedValue, getCellUserEnteredFormat, getCellUserEnteredValue, getExtendedValueBool, getExtendedValueFormula, getExtendedValueNumber, getExtendedValueString, isNil, iterateCellsInRange, uuidString, } from "@rowsncolumns/utils";
7
7
  import { produceWithPatches } from "immer";
@@ -73,6 +73,7 @@ export const useOnPaste = ({ rowCount, columnCount, locale, sheetData, tables: c
73
73
  });
74
74
  const redrawGrid = useRedrawGrid();
75
75
  const getFinalRowHeight = useGetFinalRowHeight();
76
+ const getSheetDimensions = useGetSheetDimensions();
76
77
  const { enqueue, processQueue } = useCalculationQueue({ enqueueCalculation });
77
78
  return useCallback(async (e, sourceSheetId, destinationSheetId, copiedSelections, activeCell, selections, finalSelections, isCutOperation) => {
78
79
  // Paste Special request (values / formats / formulas, operation, skip
@@ -109,7 +110,7 @@ export const useOnPaste = ({ rowCount, columnCount, locale, sheetData, tables: c
109
110
  }
110
111
  }
111
112
  else {
112
- const pasteResults = await generateDataFromClipboard(e, activeCell, destinationSheetId, activeSheetName, preserveFormatting, locale, idCreationStrategy, forcePlainText, sanitizeHtml);
113
+ const pasteResults = await generateDataFromClipboard(e, activeCell, destinationSheetId, activeSheetName, preserveFormatting, locale, idCreationStrategy, forcePlainText, sanitizeHtml, { imageViewport: getSheetDimensions?.() });
113
114
  selectedRowValues = pasteResults?.results ?? [];
114
115
  merges = pasteResults?.merges;
115
116
  embeds = pasteResults?.embeds;
@@ -121,6 +122,34 @@ export const useOnPaste = ({ rowCount, columnCount, locale, sheetData, tables: c
121
122
  if (isNil(selectedRowValues)) {
122
123
  return;
123
124
  }
125
+ // Floating objects the clipboard carried (the pasted picture(s) of an image paste) — one
126
+ // undo entry, the first one selected, like a freshly inserted chart.
127
+ const insertEmbeds = (saveHistory, pastedEmbeds) => {
128
+ const firstEmbedId = pastedEmbeds[0].embedId;
129
+ onChangeEmbeds?.((prevEmbeds) => {
130
+ const [nextState, patches, inversePatches] = produceWithPatches(prevEmbeds, (draft) => {
131
+ draft.push(...pastedEmbeds);
132
+ });
133
+ saveHistory({
134
+ embeds: { patches, inversePatches },
135
+ selectedEmbedOrChart: { redo: firstEmbedId, undo: undefined },
136
+ });
137
+ return nextState;
138
+ });
139
+ // Selected first embed
140
+ focusEmbedOrChart(firstEmbedId);
141
+ };
142
+ // An image paste writes NO cells: the picture floats over the grid anchored at the active
143
+ // cell (Excel / Google Sheets Ctrl+V of a picture), so it skips the cell-paste pipeline.
144
+ if (!selectedRowValues.length && embeds?.length) {
145
+ const anchorRange = selectionFromActiveCell(activeCell)[0].range;
146
+ if (!canEditCellRange(destinationSheetId, anchorRange)) {
147
+ console.debug("Protected range, You cannot paste on to protected cells.");
148
+ return;
149
+ }
150
+ insertEmbeds(createHistory(), embeds);
151
+ return;
152
+ }
124
153
  if (pasteSpecial.transpose && selectedRowValues.length) {
125
154
  selectedRowValues = transpose(selectedRowValues);
126
155
  }
@@ -668,6 +697,13 @@ export const useOnPaste = ({ rowCount, columnCount, locale, sheetData, tables: c
668
697
  }
669
698
  }
670
699
  }
700
+ // The landed block replaces the merge geometry it covers (Excel: pasting a
701
+ // block over a merged cell unmerges it so every pasted value is visible; a
702
+ // cut block's merges travel with it, and a partial cover was refused above).
703
+ // A single copied cell pasted onto a merged cell keeps the merge and fills it.
704
+ if (sheet.merges?.length && rowSpan * colSpan > 1) {
705
+ sheet.merges = sheet.merges.filter((merge) => !areaIntersects(merge, to.range));
706
+ }
671
707
  // Update merges
672
708
  if (mergesToAdd) {
673
709
  sheet.merges = sheet.merges ?? [];
@@ -717,6 +753,12 @@ export const useOnPaste = ({ rowCount, columnCount, locale, sheetData, tables: c
717
753
  // Clipboard-provided row heights win.
718
754
  if (clipboardSizedRows.has(rowIndex))
719
755
  continue;
756
+ // Excel keeps a custom (user-dragged) height: only auto-height
757
+ // rows refit to pasted wrapped / multi-line text. The grid's
758
+ // measurer also skips pinned rows — the guard here keeps the
759
+ // rule at the write site so no measurer can clobber the pin.
760
+ if (sheet.rowMetadata?.[rowIndex]?.resizedByUser)
761
+ continue;
720
762
  const rowData = selectedRowValues[dataRowIndex];
721
763
  if (!rowData)
722
764
  continue;
@@ -918,19 +960,7 @@ export const useOnPaste = ({ rowCount, columnCount, locale, sheetData, tables: c
918
960
  }
919
961
  // Embeds
920
962
  if (embeds?.length) {
921
- const firstEmbedId = embeds[0].embedId;
922
- onChangeEmbeds?.((prevEmbeds) => {
923
- const [nextState, patches, inversePatches] = produceWithPatches(prevEmbeds, (draft) => {
924
- draft.push(...embeds);
925
- });
926
- saveHistory({
927
- embeds: { patches, inversePatches },
928
- selectedEmbedOrChart: { redo: firstEmbedId, undo: undefined },
929
- });
930
- return nextState;
931
- });
932
- // Selected first embed
933
- focusEmbedOrChart(embeds[0].embedId);
963
+ insertEmbeds(saveHistory, embeds);
934
964
  }
935
965
  // Tables
936
966
  if (tables?.length) {
@@ -1091,6 +1121,7 @@ export const useOnPaste = ({ rowCount, columnCount, locale, sheetData, tables: c
1091
1121
  getUserEnteredValue,
1092
1122
  focusEmbedOrChart,
1093
1123
  redrawGrid,
1124
+ getSheetDimensions,
1094
1125
  processQueue,
1095
1126
  enqueue,
1096
1127
  isHiddenByFilterRow,
@@ -7,6 +7,8 @@ import type { UseSpreadsheetProps } from "./use-spreadsheet-state";
7
7
  import type { SpreadsheetPatch } from "./use-undo-redo";
8
8
  type UseOnRenameSheetProps<T extends CellData, S extends Sheet> = {
9
9
  locale?: string;
10
+ /** The workbook's sheets — a rename to a title another sheet holds (case-insensitively) is refused. */
11
+ sheets: S[];
10
12
  onChangeSheetData: UseSpreadsheetProps<T, S>["onChangeSheetData"];
11
13
  onChangeSheets: UseSpreadsheetProps<T, S>["onChangeSheets"];
12
14
  onChangeActiveCell(sheetId: number, cell: CellInterface): void;
@@ -16,6 +18,6 @@ type UseOnRenameSheetProps<T extends CellData, S extends Sheet> = {
16
18
  createHistory(): (patches: SpreadsheetPatch) => void;
17
19
  onCommand?: OnCommand;
18
20
  };
19
- export declare const useOnRenameSheet: <T extends CellData, S extends Sheet>({ locale, onChangeSheetData, onChangeSheets, onChangeActiveCell, getActiveCell, getGraphNodes, getPrecedents, createHistory, onCommand, }: UseOnRenameSheetProps<T, S>) => (sheetId: number, name: string, oldName: string) => void;
21
+ export declare const useOnRenameSheet: <T extends CellData, S extends Sheet>({ locale, sheets, onChangeSheetData, onChangeSheets, onChangeActiveCell, getActiveCell, getGraphNodes, getPrecedents, createHistory, onCommand, }: UseOnRenameSheetProps<T, S>) => (sheetId: number, name: string, oldName: string) => void;
20
22
  export {};
21
23
  //# sourceMappingURL=use-on-rename-sheet.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"use-on-rename-sheet.d.ts","sourceRoot":"","sources":["../../../hooks/use-on-rename-sheet.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,4BAA4B,CAAC;AAChE,OAAO,KAAK,EACV,cAAc,EACd,QAAQ,EACR,aAAa,EACd,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAC/C,OAAO,EAAE,KAAK,QAAQ,EAAE,KAAK,KAAK,EAAE,MAAM,2BAA2B,CAAC;AAKtE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAG7C,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,yBAAyB,CAAC;AACnE,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AAExD,KAAK,qBAAqB,CAAC,CAAC,SAAS,QAAQ,EAAE,CAAC,SAAS,KAAK,IAAI;IAChE,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,iBAAiB,EAAE,mBAAmB,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,mBAAmB,CAAC,CAAC;IAClE,cAAc,EAAE,mBAAmB,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,gBAAgB,CAAC,CAAC;IAC5D,kBAAkB,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,aAAa,GAAG,IAAI,CAAC;IAC/D,aAAa,IAAI,aAAa,CAAC;IAC/B,aAAa,IAAI,GAAG,CAAC,MAAM,EAAE,QAAQ,GAAG,aAAa,GAAG,UAAU,CAAC,CAAC;IACpE,aAAa,CACX,MAAM,EAAE,cAAc,GACrB,CAAC,QAAQ,GAAG,aAAa,GAAG,UAAU,CAAC,EAAE,CAAC;IAC7C,aAAa,IAAI,CAAC,OAAO,EAAE,gBAAgB,KAAK,IAAI,CAAC;IACrD,SAAS,CAAC,EAAE,SAAS,CAAC;CACvB,CAAC;AAEF,eAAO,MAAM,gBAAgB,GAAI,CAAC,SAAS,QAAQ,EAAE,CAAC,SAAS,KAAK,EAAE,2IAUnE,qBAAqB,CAAC,CAAC,EAAE,CAAC,CAAC,eAIhB,MAAM,QAAQ,MAAM,WAAW,MAAM,SAyFlD,CAAC"}
1
+ {"version":3,"file":"use-on-rename-sheet.d.ts","sourceRoot":"","sources":["../../../hooks/use-on-rename-sheet.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,4BAA4B,CAAC;AAChE,OAAO,KAAK,EACV,cAAc,EACd,QAAQ,EACR,aAAa,EACd,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAC/C,OAAO,EAAE,KAAK,QAAQ,EAAE,KAAK,KAAK,EAAE,MAAM,2BAA2B,CAAC;AAOtE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAE7C,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,yBAAyB,CAAC;AACnE,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AAExD,KAAK,qBAAqB,CAAC,CAAC,SAAS,QAAQ,EAAE,CAAC,SAAS,KAAK,IAAI;IAChE,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,uGAAuG;IACvG,MAAM,EAAE,CAAC,EAAE,CAAC;IACZ,iBAAiB,EAAE,mBAAmB,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,mBAAmB,CAAC,CAAC;IAClE,cAAc,EAAE,mBAAmB,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,gBAAgB,CAAC,CAAC;IAC5D,kBAAkB,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,aAAa,GAAG,IAAI,CAAC;IAC/D,aAAa,IAAI,aAAa,CAAC;IAC/B,aAAa,IAAI,GAAG,CAAC,MAAM,EAAE,QAAQ,GAAG,aAAa,GAAG,UAAU,CAAC,CAAC;IACpE,aAAa,CACX,MAAM,EAAE,cAAc,GACrB,CAAC,QAAQ,GAAG,aAAa,GAAG,UAAU,CAAC,EAAE,CAAC;IAC7C,aAAa,IAAI,CAAC,OAAO,EAAE,gBAAgB,KAAK,IAAI,CAAC;IACrD,SAAS,CAAC,EAAE,SAAS,CAAC;CACvB,CAAC;AAEF,eAAO,MAAM,gBAAgB,GAAI,CAAC,SAAS,QAAQ,EAAE,CAAC,SAAS,KAAK,EAAE,mJAWnE,qBAAqB,CAAC,CAAC,EAAE,CAAC,CAAC,eAKhB,MAAM,QAAQ,MAAM,WAAW,MAAM,SAiGlD,CAAC"}
@@ -1,18 +1,26 @@
1
+ import { validateSheetName } from "@rowsncolumns/utils";
1
2
  import { produceWithPatches } from "immer";
2
3
  import { useCallback } from "react";
3
4
  import { updateFormulaSheetReferences } from "../api/rename-sheet";
4
- import { isValidSheetTitle, truncateSheetTitle } from "../helpers/sheet-title";
5
+ import { useShowError } from "../atoms/error-state.atom";
5
6
  import { useCanEditSheet, useCanEditWorkbook } from "./use-can-edit-cellrange";
6
- export const useOnRenameSheet = ({ locale, onChangeSheetData, onChangeSheets, onChangeActiveCell, getActiveCell, getGraphNodes, getPrecedents, createHistory, onCommand, }) => {
7
+ export const useOnRenameSheet = ({ locale, sheets, onChangeSheetData, onChangeSheets, onChangeActiveCell, getActiveCell, getGraphNodes, getPrecedents, createHistory, onCommand, }) => {
7
8
  const canEditSheet = useCanEditSheet();
8
9
  const canEditWorkbook = useCanEditWorkbook();
10
+ const showError = useShowError();
9
11
  return useCallback((sheetId, name, oldName) => {
10
- // Worksheet names cannot be empty or whitespace-only
11
- if (!isValidSheetTitle(name)) {
12
- console.debug("Sheet name cannot be empty.");
12
+ // Excel's worksheet-name rules (rowsncolumns/spreadsheet#939 U-01): at most 31 characters,
13
+ // none of `\ / ? * [ ] :`, no leading / trailing apostrophe, not `History`, and unique
14
+ // case-insensitively (the calc engine's sheet registry folds case too: `SHEET1` beside
15
+ // `Sheet1` would alias one engine sheet). Every refusal shows Excel's dialog text; a blank
16
+ // name is a silent no-op (the tab editor's "nothing typed").
17
+ const validation = validateSheetName(name, sheets, sheetId);
18
+ if (!validation.ok) {
19
+ if (validation.reason !== "blank") {
20
+ showError({ title: "Error", message: validation.message });
21
+ }
13
22
  return;
14
23
  }
15
- const truncatedName = truncateSheetTitle(name);
16
24
  if (!canEditWorkbook()) {
17
25
  console.debug("Workbook is structurally protected, cannot rename a sheet.");
18
26
  return;
@@ -27,7 +35,7 @@ export const useOnRenameSheet = ({ locale, onChangeSheetData, onChangeSheets, on
27
35
  const [nextState, patches, inversePatches] = produceWithPatches(prevSheets, (draft) => {
28
36
  const sheet = draft.find((sheet) => sheet.sheetId === sheetId);
29
37
  if (sheet) {
30
- sheet.title = truncatedName;
38
+ sheet.title = name;
31
39
  }
32
40
  });
33
41
  // Save sheets history
@@ -42,7 +50,7 @@ export const useOnRenameSheet = ({ locale, onChangeSheetData, onChangeSheets, on
42
50
  updateFormulaSheetReferences(draft, {
43
51
  sheetId,
44
52
  oldName,
45
- newName: truncatedName,
53
+ newName: name,
46
54
  locale,
47
55
  getGraphNodes,
48
56
  getPrecedents,
@@ -59,11 +67,12 @@ export const useOnRenameSheet = ({ locale, onChangeSheetData, onChangeSheets, on
59
67
  onCommand?.({
60
68
  command: "rename-sheet",
61
69
  sheetId,
62
- name: truncatedName,
70
+ name,
63
71
  oldName,
64
72
  });
65
73
  }, [
66
74
  locale,
75
+ sheets,
67
76
  onChangeActiveCell,
68
77
  onChangeSheetData,
69
78
  onChangeSheets,
@@ -73,6 +82,7 @@ export const useOnRenameSheet = ({ locale, onChangeSheetData, onChangeSheets, on
73
82
  createHistory,
74
83
  canEditSheet,
75
84
  canEditWorkbook,
85
+ showError,
76
86
  onCommand,
77
87
  ]);
78
88
  };
@@ -1,3 +1,4 @@
1
+ import type { GridRange } from "@rowsncolumns/common-types";
1
2
  import { type CellData, type Sheet, type SortOrder, type SpreadsheetTheme } from "@rowsncolumns/spreadsheet";
2
3
  import type { OnCommand } from "../commands";
3
4
  import type { useCalculation } from "./use-calculation";
@@ -41,6 +42,11 @@ export type UseOnSortColumnProps<T extends CellData, S extends Sheet = Sheet> =
41
42
  getCellData(sheetId: number, rowIndex: number, columnIndex: number): T | null | undefined;
42
43
  /** Length of the sheet's committed data array — the last row a sort touches. */
43
44
  getDataRowCount(sheetId: number): number | undefined;
45
+ /**
46
+ * The sheet's merged regions. Excel refuses a sort over merged cells that
47
+ * are not laid out identically on every row of the sorted block.
48
+ */
49
+ getMerges?(sheetId: number): GridRange[] | null | undefined;
44
50
  /**
45
51
  * Any hidden row (by the user, a filter, or a collapsed group). Used as
46
52
  * the pin predicate only when `isManuallyHiddenRow` is not supplied.
@@ -74,5 +80,5 @@ export type UseOnSortColumnProps<T extends CellData, S extends Sheet = Sheet> =
74
80
  * @param param0
75
81
  * @returns
76
82
  */
77
- export declare const useOnSortColumn: <T extends CellData, S extends Sheet = Sheet>({ rowCount, columnCount, locale, sharedStringRegistry, createHistory, enqueueCalculation, enqueueStructureChange, enqueueGraphOperation, onChangeSheetData, onChangeSheets, getCellData, getDataRowCount, isHiddenRow, isManuallyHiddenRow, getDependents, getFrozenRowCount, getSheetName, getEffectiveFormat, theme, enableSortTimingLogs, onCommand, }: UseOnSortColumnProps<T, S>) => (sheetId: number, sortedColumnIndex: number, sortOrder: SortOrder, options?: SortColumnOptions, additionalLevels?: SortColumnLevel[]) => void;
83
+ export declare const useOnSortColumn: <T extends CellData, S extends Sheet = Sheet>({ rowCount, columnCount, locale, sharedStringRegistry, createHistory, enqueueCalculation, enqueueStructureChange, enqueueGraphOperation, onChangeSheetData, onChangeSheets, getCellData, getDataRowCount, getMerges, isHiddenRow, isManuallyHiddenRow, getDependents, getFrozenRowCount, getSheetName, getEffectiveFormat, theme, enableSortTimingLogs, onCommand, }: UseOnSortColumnProps<T, S>) => (sheetId: number, sortedColumnIndex: number, sortOrder: SortOrder, options?: SortColumnOptions, additionalLevels?: SortColumnLevel[]) => void;
78
84
  //# sourceMappingURL=use-on-sort-column.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"use-on-sort-column.d.ts","sourceRoot":"","sources":["../../../hooks/use-on-sort-column.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"use-on-sort-column.d.ts","sourceRoot":"","sources":["../../../hooks/use-on-sort-column.ts"],"names":[],"mappings":"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"}
@@ -4,6 +4,7 @@ import { produceWithPatches } from "immer";
4
4
  import { useCallback } from "react";
5
5
  import { createSheetCellIdentifier } from "../api/formula";
6
6
  import { getCellSortValue } from "../api/sort";
7
+ import { getSortMergeRefusal } from "../api/structural-guards";
7
8
  import { createSheetDraft } from "../api/immer-utils";
8
9
  import { SheetCell } from "../sheet-cell";
9
10
  import { useShowError } from "../atoms/error-state.atom";
@@ -33,7 +34,7 @@ const buildSortValue = (options, fallbackValue, getEffectiveFormat, theme, sheet
33
34
  * @param param0
34
35
  * @returns
35
36
  */
36
- export const useOnSortColumn = ({ rowCount, columnCount, locale, sharedStringRegistry, createHistory, enqueueCalculation, enqueueStructureChange, enqueueGraphOperation, onChangeSheetData, onChangeSheets, getCellData, getDataRowCount, isHiddenRow, isManuallyHiddenRow, getDependents, getFrozenRowCount, getSheetName, getEffectiveFormat, theme, enableSortTimingLogs, onCommand, }) => {
37
+ export const useOnSortColumn = ({ rowCount, columnCount, locale, sharedStringRegistry, createHistory, enqueueCalculation, enqueueStructureChange, enqueueGraphOperation, onChangeSheetData, onChangeSheets, getCellData, getDataRowCount, getMerges, isHiddenRow, isManuallyHiddenRow, getDependents, getFrozenRowCount, getSheetName, getEffectiveFormat, theme, enableSortTimingLogs, onCommand, }) => {
37
38
  const canEditSheet = useCanEditSheet();
38
39
  const canPerformSheetAction = useCanPerformSheetAction();
39
40
  const showError = useShowError();
@@ -60,6 +61,21 @@ export const useOnSortColumn = ({ rowCount, columnCount, locale, sharedStringReg
60
61
  ? performance.now.bind(performance)
61
62
  : Date.now;
62
63
  const activeSheetName = getSheetName(sheetId);
64
+ // Excel refuses to sort a block whose merged cells differ in layout between rows — the
65
+ // anchor values would move while the merge outlines stayed behind.
66
+ const mergeRefusal = getSortMergeRefusal({
67
+ range: {
68
+ startRowIndex: 1,
69
+ endRowIndex: getDataRowCount(sheetId) ?? 0,
70
+ startColumnIndex: 1,
71
+ endColumnIndex: columnCount,
72
+ },
73
+ merges: getMerges?.(sheetId),
74
+ });
75
+ if (mergeRefusal) {
76
+ showError(mergeRefusal);
77
+ return;
78
+ }
63
79
  // We need to track this for history. Precedent cells
64
80
  const recalcCells = new Map();
65
81
  // History
@@ -290,6 +306,7 @@ export const useOnSortColumn = ({ rowCount, columnCount, locale, sharedStringReg
290
306
  onChangeSheets,
291
307
  getCellData,
292
308
  getDataRowCount,
309
+ getMerges,
293
310
  isHiddenRow,
294
311
  isManuallyHiddenRow,
295
312
  getDependents,
@@ -1,4 +1,5 @@
1
- import type { SelectionArea } from "@rowsncolumns/common-types";
1
+ import type { GridRange, SelectionArea } from "@rowsncolumns/common-types";
2
+ import { type CellInterface } from "@rowsncolumns/grid";
2
3
  import { type CellData, type Sheet, type SelectionAttributes, type SortOrder, type SpreadsheetTheme } from "@rowsncolumns/spreadsheet";
3
4
  import type { OnCommand } from "../commands";
4
5
  import type { useCalculation } from "./use-calculation";
@@ -42,6 +43,12 @@ export type UseOnSortRangeProps<T extends CellData, S extends Sheet = Sheet> = {
42
43
  getDependents: ReturnType<typeof useCalculation>["getDependents"];
43
44
  getFrozenRowCount(sheetId: number): number;
44
45
  getSheetName(sheetId: number): string;
46
+ /**
47
+ * The sheet's merged regions. A range whose merges are not laid out
48
+ * identically on every row is refused (Excel), because the sort would move
49
+ * the anchor values without their merge outlines.
50
+ */
51
+ getMerges?(sheetId: number): GridRange[] | null | undefined;
45
52
  /**
46
53
  * Optional — needed when callers pass per-column specs using
47
54
  * `sortBy: "cellColor" | "fontColor" | "icon"`. Without it those sort
@@ -54,6 +61,13 @@ export type UseOnSortRangeProps<T extends CellData, S extends Sheet = Sheet> = {
54
61
  */
55
62
  theme: SpreadsheetTheme;
56
63
  onCommand?: OnCommand;
64
+ /**
65
+ * The cursor at sort time. When it stands inside the sorted range (and no
66
+ * per-column `specs` are given) its column is the sort key — Excel / Sheets
67
+ * "Sort A to Z" sorts the range by the column the user is in, not by its
68
+ * leftmost column. Without it the legacy leftmost-column-first order applies.
69
+ */
70
+ getActiveCell?: () => CellInterface | null | undefined;
57
71
  };
58
72
  /**
59
73
  * Sorts a column range.
@@ -61,5 +75,5 @@ export type UseOnSortRangeProps<T extends CellData, S extends Sheet = Sheet> = {
61
75
  * @param param0
62
76
  * @returns
63
77
  */
64
- export declare const useOnSortRange: <T extends CellData, S extends Sheet = Sheet>({ locale, sharedStringRegistry, createHistory, enqueueStructureChange, enqueueGraphOperation, enqueueCalculation, onChangeSheetData, onChangeSheets, getCellData, getDependents, isHiddenRow, isManuallyHiddenRow, getFrozenRowCount, getSheetName, getEffectiveFormat, theme, onCommand, }: UseOnSortRangeProps<T, S>) => (sheetId: number, selections: SelectionArea<SelectionAttributes>[], sortOrder: SortOrder, specs?: DimensionSortSpec[]) => void;
78
+ export declare const useOnSortRange: <T extends CellData, S extends Sheet = Sheet>({ locale, sharedStringRegistry, createHistory, enqueueStructureChange, enqueueGraphOperation, enqueueCalculation, onChangeSheetData, onChangeSheets, getCellData, getDependents, isHiddenRow, isManuallyHiddenRow, getFrozenRowCount, getSheetName, getMerges, getEffectiveFormat, theme, onCommand, getActiveCell, }: UseOnSortRangeProps<T, S>) => (sheetId: number, selections: SelectionArea<SelectionAttributes>[], sortOrder: SortOrder, specs?: DimensionSortSpec[]) => void;
65
79
  //# sourceMappingURL=use-on-sort-range.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"use-on-sort-range.d.ts","sourceRoot":"","sources":["../../../hooks/use-on-sort-range.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,4BAA4B,CAAC;AAGhE,OAAO,EACL,KAAK,QAAQ,EACb,KAAK,KAAK,EAIV,KAAK,mBAAmB,EACxB,KAAK,SAAS,EACd,KAAK,gBAAgB,EACtB,MAAM,2BAA2B,CAAC;AAQnC,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAS7C,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,oBAAoB,EAAE,MAAM,mBAAmB,CAAC;AAC9D,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AACxD,OAAO,EACL,KAAK,iBAAiB,EAEvB,MAAM,mBAAmB,CAAC;AAE3B,MAAM,MAAM,mBAAmB,CAC7B,CAAC,SAAS,QAAQ,EAClB,CAAC,SAAS,KAAK,GAAG,KAAK,IACrB;IACF,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,oBAAoB,CAAC,EAAE,oBAAoB,CAAC;IAC5C,aAAa,IAAI,CAAC,OAAO,EAAE,gBAAgB,KAAK,IAAI,CAAC;IACrD,sBAAsB,CAAC,EAAE,UAAU,CACjC,OAAO,cAAc,CACtB,CAAC,wBAAwB,CAAC,CAAC;IAC5B,qBAAqB,EAAE,UAAU,CAC/B,OAAO,cAAc,CACtB,CAAC,uBAAuB,CAAC,CAAC;IAC3B,kBAAkB,EAAE,UAAU,CAAC,OAAO,cAAc,CAAC,CAAC,oBAAoB,CAAC,CAAC;IAC5E,iBAAiB,EAAE,mBAAmB,CAAC,CAAC,CAAC,CAAC,mBAAmB,CAAC,CAAC;IAC/D;;;;OAIG;IACH,cAAc,CAAC,EAAE,mBAAmB,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,gBAAgB,CAAC,CAAC;IAC7D;;;;OAIG;IACH,WAAW,CACT,OAAO,EAAE,MAAM,EACf,QAAQ,EAAE,MAAM,EAChB,WAAW,EAAE,MAAM,GAClB,CAAC,GAAG,IAAI,GAAG,SAAS,CAAC;IACxB;;;OAGG;IACH,WAAW,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC;IACxD;;;;;OAKG;IACH,mBAAmB,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC;IACjE,aAAa,EAAE,UAAU,CAAC,OAAO,cAAc,CAAC,CAAC,eAAe,CAAC,CAAC;IAClE,iBAAiB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAAC;IAC3C,YAAY,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAAC;IACtC;;;;OAIG;IACH,kBAAkB,CAAC,EAAE,UAAU,CAC7B,OAAO,kBAAkB,CAC1B,CAAC,oBAAoB,CAAC,CAAC;IACxB;;;OAGG;IACH,KAAK,EAAE,gBAAgB,CAAC;IACxB,SAAS,CAAC,EAAE,SAAS,CAAC;CACvB,CAAC;AAEF;;;;;GAKG;AACH,eAAO,MAAM,cAAc,GAAI,CAAC,SAAS,QAAQ,EAAE,CAAC,SAAS,KAAK,GAAG,KAAK,EAAE,6RAkBzE,mBAAmB,CAAC,CAAC,EAAE,CAAC,CAAC,eAMb,MAAM,cACH,aAAa,CAAC,mBAAmB,CAAC,EAAE,aACrC,SAAS,UAQZ,iBAAiB,EAAE,SA2UhC,CAAC"}
1
+ {"version":3,"file":"use-on-sort-range.d.ts","sourceRoot":"","sources":["../../../hooks/use-on-sort-range.ts"],"names":[],"mappings":"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"}