@rowsncolumns/spreadsheet-state 28.0.74 → 28.0.76

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 (253) hide show
  1. package/dist/cjs/api/anchored-objects.d.ts +66 -0
  2. package/dist/cjs/api/anchored-objects.d.ts.map +1 -0
  3. package/dist/cjs/api/anchored-objects.js +259 -0
  4. package/dist/cjs/api/datatype.d.ts.map +1 -1
  5. package/dist/cjs/api/datatype.js +8 -1
  6. package/dist/cjs/api/dependency.d.ts +13 -2
  7. package/dist/cjs/api/dependency.d.ts.map +1 -1
  8. package/dist/cjs/api/dependency.js +11 -5
  9. package/dist/cjs/api/fill-series-spec.d.ts +35 -0
  10. package/dist/cjs/api/fill-series-spec.d.ts.map +1 -0
  11. package/dist/cjs/api/fill-series-spec.js +164 -0
  12. package/dist/cjs/api/fill.d.ts +95 -3
  13. package/dist/cjs/api/fill.d.ts.map +1 -1
  14. package/dist/cjs/api/fill.js +1186 -418
  15. package/dist/cjs/api/formula.d.ts +61 -4
  16. package/dist/cjs/api/formula.d.ts.map +1 -1
  17. package/dist/cjs/api/formula.js +250 -61
  18. package/dist/cjs/api/immer-utils.d.ts.map +1 -1
  19. package/dist/cjs/api/immer-utils.js +20 -15
  20. package/dist/cjs/api/intl.d.ts.map +1 -1
  21. package/dist/cjs/api/merges.d.ts +8 -0
  22. package/dist/cjs/api/merges.d.ts.map +1 -1
  23. package/dist/cjs/api/merges.js +64 -1
  24. package/dist/cjs/api/named-range-structural.d.ts +62 -0
  25. package/dist/cjs/api/named-range-structural.d.ts.map +1 -0
  26. package/dist/cjs/api/named-range-structural.js +197 -0
  27. package/dist/cjs/api/paint-format.d.ts +15 -1
  28. package/dist/cjs/api/paint-format.d.ts.map +1 -1
  29. package/dist/cjs/api/paint-format.js +69 -10
  30. package/dist/cjs/api/range-rule-helpers.d.ts +45 -1
  31. package/dist/cjs/api/range-rule-helpers.d.ts.map +1 -1
  32. package/dist/cjs/api/range-rule-helpers.js +159 -6
  33. package/dist/cjs/api/structural-formula-update.d.ts.map +1 -1
  34. package/dist/cjs/api/structural-formula-update.js +24 -6
  35. package/dist/cjs/api/structural-guards.d.ts +78 -0
  36. package/dist/cjs/api/structural-guards.d.ts.map +1 -0
  37. package/dist/cjs/api/structural-guards.js +202 -0
  38. package/dist/cjs/api/structural-table-refs.d.ts +94 -0
  39. package/dist/cjs/api/structural-table-refs.d.ts.map +1 -0
  40. package/dist/cjs/api/structural-table-refs.js +313 -0
  41. package/dist/cjs/commands.d.ts +11 -1
  42. package/dist/cjs/commands.d.ts.map +1 -1
  43. package/dist/cjs/constants.d.ts +25 -0
  44. package/dist/cjs/constants.d.ts.map +1 -0
  45. package/dist/cjs/constants.js +26 -0
  46. package/dist/cjs/hooks/use-calculation-worker.d.ts.map +1 -1
  47. package/dist/cjs/hooks/use-calculation-worker.js +64 -6
  48. package/dist/cjs/hooks/use-calculation.d.ts +8 -1
  49. package/dist/cjs/hooks/use-calculation.d.ts.map +1 -1
  50. package/dist/cjs/hooks/use-calculation.js +15 -0
  51. package/dist/cjs/hooks/use-on-calculation-success.d.ts +7 -0
  52. package/dist/cjs/hooks/use-on-calculation-success.d.ts.map +1 -1
  53. package/dist/cjs/hooks/use-on-calculation-success.js +7 -1
  54. package/dist/cjs/hooks/use-on-delete-cells-shift-left.d.ts +13 -3
  55. package/dist/cjs/hooks/use-on-delete-cells-shift-left.d.ts.map +1 -1
  56. package/dist/cjs/hooks/use-on-delete-cells-shift-left.js +27 -2
  57. package/dist/cjs/hooks/use-on-delete-cells-shift-up.d.ts +13 -3
  58. package/dist/cjs/hooks/use-on-delete-cells-shift-up.d.ts.map +1 -1
  59. package/dist/cjs/hooks/use-on-delete-cells-shift-up.js +27 -2
  60. package/dist/cjs/hooks/use-on-delete-column.d.ts +13 -4
  61. package/dist/cjs/hooks/use-on-delete-column.d.ts.map +1 -1
  62. package/dist/cjs/hooks/use-on-delete-column.js +14 -2
  63. package/dist/cjs/hooks/use-on-delete-row.d.ts +13 -4
  64. package/dist/cjs/hooks/use-on-delete-row.d.ts.map +1 -1
  65. package/dist/cjs/hooks/use-on-delete-row.js +14 -2
  66. package/dist/cjs/hooks/use-on-fill.d.ts +13 -4
  67. package/dist/cjs/hooks/use-on-fill.d.ts.map +1 -1
  68. package/dist/cjs/hooks/use-on-fill.js +28 -7
  69. package/dist/cjs/hooks/use-on-insert-cells-shift-down.d.ts +13 -3
  70. package/dist/cjs/hooks/use-on-insert-cells-shift-down.d.ts.map +1 -1
  71. package/dist/cjs/hooks/use-on-insert-cells-shift-down.js +27 -2
  72. package/dist/cjs/hooks/use-on-insert-cells-shift-right.d.ts +13 -3
  73. package/dist/cjs/hooks/use-on-insert-cells-shift-right.d.ts.map +1 -1
  74. package/dist/cjs/hooks/use-on-insert-cells-shift-right.js +27 -2
  75. package/dist/cjs/hooks/use-on-insert-column.d.ts +10 -3
  76. package/dist/cjs/hooks/use-on-insert-column.d.ts.map +1 -1
  77. package/dist/cjs/hooks/use-on-insert-column.js +33 -7
  78. package/dist/cjs/hooks/use-on-insert-row.d.ts +10 -3
  79. package/dist/cjs/hooks/use-on-insert-row.d.ts.map +1 -1
  80. package/dist/cjs/hooks/use-on-insert-row.js +32 -7
  81. package/dist/cjs/hooks/use-paint-format.d.ts.map +1 -1
  82. package/dist/cjs/hooks/use-paint-format.js +10 -7
  83. package/dist/cjs/hooks/use-spreadsheet-state.d.ts +3 -3
  84. package/dist/cjs/hooks/use-spreadsheet-state.d.ts.map +1 -1
  85. package/dist/cjs/hooks/use-spreadsheet-state.js +73 -16
  86. package/dist/cjs/hooks/use-structured-reference.d.ts.map +1 -1
  87. package/dist/cjs/hooks/use-structured-reference.js +10 -6
  88. package/dist/cjs/index.d.ts +3 -0
  89. package/dist/cjs/index.d.ts.map +1 -1
  90. package/dist/cjs/index.js +3 -0
  91. package/dist/cjs/interface/apply-fill.d.ts +3 -3
  92. package/dist/cjs/interface/apply-fill.d.ts.map +1 -1
  93. package/dist/cjs/interface/apply-fill.js +100 -53
  94. package/dist/cjs/interface/calculation-interface.d.ts +9 -0
  95. package/dist/cjs/interface/calculation-interface.d.ts.map +1 -1
  96. package/dist/cjs/interface/calculation-interface.js +31 -2
  97. package/dist/cjs/interface/delete-cells-shift-left.d.ts +8 -1
  98. package/dist/cjs/interface/delete-cells-shift-left.d.ts.map +1 -1
  99. package/dist/cjs/interface/delete-cells-shift-left.js +158 -80
  100. package/dist/cjs/interface/delete-cells-shift-up.d.ts +9 -1
  101. package/dist/cjs/interface/delete-cells-shift-up.d.ts.map +1 -1
  102. package/dist/cjs/interface/delete-cells-shift-up.js +155 -73
  103. package/dist/cjs/interface/delete-column.d.ts +1 -1
  104. package/dist/cjs/interface/delete-column.d.ts.map +1 -1
  105. package/dist/cjs/interface/delete-column.js +90 -31
  106. package/dist/cjs/interface/delete-row.d.ts +1 -1
  107. package/dist/cjs/interface/delete-row.d.ts.map +1 -1
  108. package/dist/cjs/interface/delete-row.js +85 -26
  109. package/dist/cjs/interface/insert-cells-shift-down.d.ts +10 -1
  110. package/dist/cjs/interface/insert-cells-shift-down.d.ts.map +1 -1
  111. package/dist/cjs/interface/insert-cells-shift-down.js +147 -52
  112. package/dist/cjs/interface/insert-cells-shift-right.d.ts +10 -1
  113. package/dist/cjs/interface/insert-cells-shift-right.d.ts.map +1 -1
  114. package/dist/cjs/interface/insert-cells-shift-right.js +154 -58
  115. package/dist/cjs/interface/insert-column.d.ts +1 -1
  116. package/dist/cjs/interface/insert-column.d.ts.map +1 -1
  117. package/dist/cjs/interface/insert-column.js +46 -8
  118. package/dist/cjs/interface/insert-row.d.ts +1 -1
  119. package/dist/cjs/interface/insert-row.d.ts.map +1 -1
  120. package/dist/cjs/interface/insert-row.js +47 -10
  121. package/dist/cjs/interface/spreadsheet-interface.d.ts +1 -1
  122. package/dist/cjs/interface/spreadsheet-interface.d.ts.map +1 -1
  123. package/dist/cjs/interface/spreadsheet-interface.js +33 -0
  124. package/dist/cjs/sheet-cell.d.ts.map +1 -1
  125. package/dist/cjs/sheet-cell.js +30 -6
  126. package/dist/cjs/tsconfig.cjs.tsbuildinfo +1 -1
  127. package/dist/esm/api/anchored-objects.d.ts +66 -0
  128. package/dist/esm/api/anchored-objects.d.ts.map +1 -0
  129. package/dist/esm/api/anchored-objects.js +212 -0
  130. package/dist/esm/api/datatype.d.ts.map +1 -1
  131. package/dist/esm/api/datatype.js +8 -1
  132. package/dist/esm/api/dependency.d.ts +13 -2
  133. package/dist/esm/api/dependency.d.ts.map +1 -1
  134. package/dist/esm/api/dependency.js +10 -4
  135. package/dist/esm/api/fill-series-spec.d.ts +35 -0
  136. package/dist/esm/api/fill-series-spec.d.ts.map +1 -0
  137. package/dist/esm/api/fill-series-spec.js +160 -0
  138. package/dist/esm/api/fill.d.ts +95 -3
  139. package/dist/esm/api/fill.d.ts.map +1 -1
  140. package/dist/esm/api/fill.js +1158 -418
  141. package/dist/esm/api/formula.d.ts +61 -4
  142. package/dist/esm/api/formula.d.ts.map +1 -1
  143. package/dist/esm/api/formula.js +238 -60
  144. package/dist/esm/api/immer-utils.d.ts.map +1 -1
  145. package/dist/esm/api/immer-utils.js +20 -15
  146. package/dist/esm/api/intl.d.ts.map +1 -1
  147. package/dist/esm/api/merges.d.ts +8 -0
  148. package/dist/esm/api/merges.d.ts.map +1 -1
  149. package/dist/esm/api/merges.js +51 -0
  150. package/dist/esm/api/named-range-structural.d.ts +62 -0
  151. package/dist/esm/api/named-range-structural.d.ts.map +1 -0
  152. package/dist/esm/api/named-range-structural.js +176 -0
  153. package/dist/esm/api/paint-format.d.ts +15 -1
  154. package/dist/esm/api/paint-format.d.ts.map +1 -1
  155. package/dist/esm/api/paint-format.js +46 -1
  156. package/dist/esm/api/range-rule-helpers.d.ts +45 -1
  157. package/dist/esm/api/range-rule-helpers.d.ts.map +1 -1
  158. package/dist/esm/api/range-rule-helpers.js +153 -1
  159. package/dist/esm/api/structural-formula-update.d.ts.map +1 -1
  160. package/dist/esm/api/structural-formula-update.js +24 -6
  161. package/dist/esm/api/structural-guards.d.ts +78 -0
  162. package/dist/esm/api/structural-guards.d.ts.map +1 -0
  163. package/dist/esm/api/structural-guards.js +186 -0
  164. package/dist/esm/api/structural-table-refs.d.ts +94 -0
  165. package/dist/esm/api/structural-table-refs.d.ts.map +1 -0
  166. package/dist/esm/api/structural-table-refs.js +219 -0
  167. package/dist/esm/commands.d.ts +11 -1
  168. package/dist/esm/commands.d.ts.map +1 -1
  169. package/dist/esm/constants.d.ts +25 -0
  170. package/dist/esm/constants.d.ts.map +1 -0
  171. package/dist/esm/constants.js +26 -0
  172. package/dist/esm/hooks/use-calculation-worker.d.ts.map +1 -1
  173. package/dist/esm/hooks/use-calculation-worker.js +45 -0
  174. package/dist/esm/hooks/use-calculation.d.ts +8 -1
  175. package/dist/esm/hooks/use-calculation.d.ts.map +1 -1
  176. package/dist/esm/hooks/use-calculation.js +15 -0
  177. package/dist/esm/hooks/use-on-calculation-success.d.ts +7 -0
  178. package/dist/esm/hooks/use-on-calculation-success.d.ts.map +1 -1
  179. package/dist/esm/hooks/use-on-calculation-success.js +7 -1
  180. package/dist/esm/hooks/use-on-delete-cells-shift-left.d.ts +13 -3
  181. package/dist/esm/hooks/use-on-delete-cells-shift-left.d.ts.map +1 -1
  182. package/dist/esm/hooks/use-on-delete-cells-shift-left.js +26 -2
  183. package/dist/esm/hooks/use-on-delete-cells-shift-up.d.ts +13 -3
  184. package/dist/esm/hooks/use-on-delete-cells-shift-up.d.ts.map +1 -1
  185. package/dist/esm/hooks/use-on-delete-cells-shift-up.js +26 -2
  186. package/dist/esm/hooks/use-on-delete-column.d.ts +13 -4
  187. package/dist/esm/hooks/use-on-delete-column.d.ts.map +1 -1
  188. package/dist/esm/hooks/use-on-delete-column.js +14 -2
  189. package/dist/esm/hooks/use-on-delete-row.d.ts +13 -4
  190. package/dist/esm/hooks/use-on-delete-row.d.ts.map +1 -1
  191. package/dist/esm/hooks/use-on-delete-row.js +14 -2
  192. package/dist/esm/hooks/use-on-fill.d.ts +13 -4
  193. package/dist/esm/hooks/use-on-fill.d.ts.map +1 -1
  194. package/dist/esm/hooks/use-on-fill.js +24 -4
  195. package/dist/esm/hooks/use-on-insert-cells-shift-down.d.ts +13 -3
  196. package/dist/esm/hooks/use-on-insert-cells-shift-down.d.ts.map +1 -1
  197. package/dist/esm/hooks/use-on-insert-cells-shift-down.js +26 -2
  198. package/dist/esm/hooks/use-on-insert-cells-shift-right.d.ts +13 -3
  199. package/dist/esm/hooks/use-on-insert-cells-shift-right.d.ts.map +1 -1
  200. package/dist/esm/hooks/use-on-insert-cells-shift-right.js +26 -2
  201. package/dist/esm/hooks/use-on-insert-column.d.ts +10 -3
  202. package/dist/esm/hooks/use-on-insert-column.d.ts.map +1 -1
  203. package/dist/esm/hooks/use-on-insert-column.js +33 -7
  204. package/dist/esm/hooks/use-on-insert-row.d.ts +10 -3
  205. package/dist/esm/hooks/use-on-insert-row.d.ts.map +1 -1
  206. package/dist/esm/hooks/use-on-insert-row.js +32 -7
  207. package/dist/esm/hooks/use-paint-format.d.ts.map +1 -1
  208. package/dist/esm/hooks/use-paint-format.js +10 -7
  209. package/dist/esm/hooks/use-spreadsheet-state.d.ts +3 -3
  210. package/dist/esm/hooks/use-spreadsheet-state.d.ts.map +1 -1
  211. package/dist/esm/hooks/use-spreadsheet-state.js +73 -16
  212. package/dist/esm/hooks/use-structured-reference.d.ts.map +1 -1
  213. package/dist/esm/hooks/use-structured-reference.js +10 -6
  214. package/dist/esm/index.d.ts +3 -0
  215. package/dist/esm/index.d.ts.map +1 -1
  216. package/dist/esm/index.js +3 -0
  217. package/dist/esm/interface/apply-fill.d.ts +3 -3
  218. package/dist/esm/interface/apply-fill.d.ts.map +1 -1
  219. package/dist/esm/interface/apply-fill.js +93 -48
  220. package/dist/esm/interface/calculation-interface.d.ts +9 -0
  221. package/dist/esm/interface/calculation-interface.d.ts.map +1 -1
  222. package/dist/esm/interface/calculation-interface.js +33 -2
  223. package/dist/esm/interface/delete-cells-shift-left.d.ts +8 -1
  224. package/dist/esm/interface/delete-cells-shift-left.d.ts.map +1 -1
  225. package/dist/esm/interface/delete-cells-shift-left.js +135 -59
  226. package/dist/esm/interface/delete-cells-shift-up.d.ts +9 -1
  227. package/dist/esm/interface/delete-cells-shift-up.d.ts.map +1 -1
  228. package/dist/esm/interface/delete-cells-shift-up.js +133 -53
  229. package/dist/esm/interface/delete-column.d.ts +1 -1
  230. package/dist/esm/interface/delete-column.d.ts.map +1 -1
  231. package/dist/esm/interface/delete-column.js +80 -11
  232. package/dist/esm/interface/delete-row.d.ts +1 -1
  233. package/dist/esm/interface/delete-row.d.ts.map +1 -1
  234. package/dist/esm/interface/delete-row.js +81 -11
  235. package/dist/esm/interface/insert-cells-shift-down.d.ts +10 -1
  236. package/dist/esm/interface/insert-cells-shift-down.d.ts.map +1 -1
  237. package/dist/esm/interface/insert-cells-shift-down.js +116 -47
  238. package/dist/esm/interface/insert-cells-shift-right.d.ts +10 -1
  239. package/dist/esm/interface/insert-cells-shift-right.d.ts.map +1 -1
  240. package/dist/esm/interface/insert-cells-shift-right.js +120 -51
  241. package/dist/esm/interface/insert-column.d.ts +1 -1
  242. package/dist/esm/interface/insert-column.d.ts.map +1 -1
  243. package/dist/esm/interface/insert-column.js +46 -8
  244. package/dist/esm/interface/insert-row.d.ts +1 -1
  245. package/dist/esm/interface/insert-row.d.ts.map +1 -1
  246. package/dist/esm/interface/insert-row.js +47 -10
  247. package/dist/esm/interface/spreadsheet-interface.d.ts +1 -1
  248. package/dist/esm/interface/spreadsheet-interface.d.ts.map +1 -1
  249. package/dist/esm/interface/spreadsheet-interface.js +29 -0
  250. package/dist/esm/sheet-cell.d.ts.map +1 -1
  251. package/dist/esm/sheet-cell.js +30 -6
  252. package/dist/esm/tsconfig.esm.tsbuildinfo +1 -1
  253. package/package.json +17 -17
@@ -0,0 +1,66 @@
1
+ import type { CellInterface, GridRange } from "@rowsncolumns/common-types";
2
+ import type { EmbeddedChart, EmbeddedObject, ProtectedRange } from "@rowsncolumns/spreadsheet";
3
+ import type { Draft } from "immer";
4
+ /**
5
+ * Structural (whole row / whole column insert or delete) relocation of the
6
+ * objects Excel anchors to cells rather than storing inside them: floating
7
+ * objects (charts, pictures / embeds), the ranges a chart reads, and
8
+ * AllowEditRange (protected range) rectangles.
9
+ *
10
+ * Excel rules (Sheets agree on every one):
11
+ * - A floating object's anchor cell shifts like any cell: pushed down/right by
12
+ * an insert at or before it, pulled up/left by a delete before it. When the
13
+ * anchor row/column itself is deleted the object snaps to the first
14
+ * surviving cell at the deletion index (Move-and-size / Move-don't-size both
15
+ * move; only absolute anchors stay put). Size never changes.
16
+ * - A range (chart series, AllowEditRange) shifts like a formula reference:
17
+ * insert at/before the start moves it, insert strictly inside grows it,
18
+ * delete inside shrinks it, delete of the whole span removes it (`#REF!`).
19
+ *
20
+ * The span rule here mirrors `shift_facet_span` in `rnc-store` exactly so both
21
+ * engines relocate identically.
22
+ */
23
+ export type StructuralAxis = "row" | "column";
24
+ export type StructuralOp = "insert" | "delete";
25
+ /**
26
+ * Shift the `[start, end]` span of a range along the edited axis. Returns the
27
+ * new span, or `null` when a delete consumes it entirely.
28
+ */
29
+ export declare const shiftSpanLikeReference: (start: number, end: number, op: StructuralOp, index: number, count: number) => [number, number] | null;
30
+ /**
31
+ * Shift a single row/column index the way a cell (and everything anchored to
32
+ * it) moves: pushed by an insert at or before it, pulled back by a delete
33
+ * before it, snapped to the deletion index when its own row/column is
34
+ * removed.
35
+ */
36
+ export declare const shiftAnchorIndex: (anchorIndex: number, op: StructuralOp, index: number, count: number) => number;
37
+ export declare const shiftAnchorCell: (anchor: CellInterface, axis: StructuralAxis, op: StructuralOp, index: number, count: number) => CellInterface;
38
+ /**
39
+ * Shift a grid rectangle with the reference rule along one axis. Returns the
40
+ * same object when nothing moved, a new one when it did, `null` when a delete
41
+ * consumed the whole span.
42
+ */
43
+ export declare const shiftGridRangeLikeReference: <R extends GridRange>(range: R, axis: StructuralAxis, op: StructuralOp, index: number, count: number) => R | null;
44
+ /**
45
+ * Walk a chart spec and rewrite every `SheetRange` it holds on `sheetId` —
46
+ * `dataRange`, per-series / per-domain `sources`, error-bar `plusRange` /
47
+ * `minusRange`, and any future range-valued key — with the reference rule.
48
+ * A range the delete consumes entirely is removed: spliced out of arrays
49
+ * (`sources`), nulled on properties (`dataRange`) — the chart's `#REF!`.
50
+ * Unknown keys are left untouched. Mutates in place; returns whether anything
51
+ * changed.
52
+ */
53
+ export declare const shiftChartSpecRanges: (spec: unknown, sheetId: number, axis: StructuralAxis, op: StructuralOp, index: number, count: number) => boolean;
54
+ /** Shift the anchor cell of every embed (picture, shape, text box…) on the edited sheet. */
55
+ export declare const shiftEmbedsOnStructuralChange: (draft: Draft<EmbeddedObject>[], sheetId: number, axis: StructuralAxis, op: StructuralOp, index: number, count: number) => void;
56
+ /**
57
+ * Shift every chart on the edited sheet: its anchor cell like a floating
58
+ * object, and the ranges inside its spec like references.
59
+ */
60
+ export declare const shiftChartsOnStructuralChange: (draft: Draft<EmbeddedChart>[], sheetId: number, axis: StructuralAxis, op: StructuralOp, index: number, count: number) => void;
61
+ /**
62
+ * Shift AllowEditRange rectangles. A protected range without a rectangle
63
+ * (sheet-scoped protection) is untouched; one the delete consumes is removed.
64
+ */
65
+ export declare const shiftProtectedRangesOnStructuralChange: (draft: Draft<ProtectedRange>[], sheetId: number, axis: StructuralAxis, op: StructuralOp, index: number, count: number) => void;
66
+ //# sourceMappingURL=anchored-objects.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"anchored-objects.d.ts","sourceRoot":"","sources":["../../../api/anchored-objects.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,aAAa,EACb,SAAS,EAEV,MAAM,4BAA4B,CAAC;AACpC,OAAO,KAAK,EACV,aAAa,EACb,cAAc,EACd,cAAc,EACf,MAAM,2BAA2B,CAAC;AACnC,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,OAAO,CAAC;AAEnC;;;;;;;;;;;;;;;;;;GAkBG;AAEH,MAAM,MAAM,cAAc,GAAG,KAAK,GAAG,QAAQ,CAAC;AAC9C,MAAM,MAAM,YAAY,GAAG,QAAQ,GAAG,QAAQ,CAAC;AAE/C;;;GAGG;AACH,eAAO,MAAM,sBAAsB,GACjC,OAAO,MAAM,EACb,KAAK,MAAM,EACX,IAAI,YAAY,EAChB,OAAO,MAAM,EACb,OAAO,MAAM,KACZ,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,IAerB,CAAC;AAEF;;;;;GAKG;AACH,eAAO,MAAM,gBAAgB,GAC3B,aAAa,MAAM,EACnB,IAAI,YAAY,EAChB,OAAO,MAAM,EACb,OAAO,MAAM,KACZ,MASF,CAAC;AAEF,eAAO,MAAM,eAAe,GAC1B,QAAQ,aAAa,EACrB,MAAM,cAAc,EACpB,IAAI,YAAY,EAChB,OAAO,MAAM,EACb,OAAO,MAAM,KACZ,aASF,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,2BAA2B,GAAI,CAAC,SAAS,SAAS,EAC7D,OAAO,CAAC,EACR,MAAM,cAAc,EACpB,IAAI,YAAY,EAChB,OAAO,MAAM,EACb,OAAO,MAAM,KACZ,CAAC,GAAG,IAgBN,CAAC;AAgBF;;;;;;;;GAQG;AACH,eAAO,MAAM,oBAAoB,GAC/B,MAAM,OAAO,EACb,SAAS,MAAM,EACf,MAAM,cAAc,EACpB,IAAI,YAAY,EAChB,OAAO,MAAM,EACb,OAAO,MAAM,KACZ,OAoCF,CAAC;AAEF,4FAA4F;AAC5F,eAAO,MAAM,6BAA6B,GACxC,OAAO,KAAK,CAAC,cAAc,CAAC,EAAE,EAC9B,SAAS,MAAM,EACf,MAAM,cAAc,EACpB,IAAI,YAAY,EAChB,OAAO,MAAM,EACb,OAAO,MAAM,SAUd,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,6BAA6B,GACxC,OAAO,KAAK,CAAC,aAAa,CAAC,EAAE,EAC7B,SAAS,MAAM,EACf,MAAM,cAAc,EACpB,IAAI,YAAY,EAChB,OAAO,MAAM,EACb,OAAO,MAAM,SAad,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,sCAAsC,GACjD,OAAO,KAAK,CAAC,cAAc,CAAC,EAAE,EAC9B,SAAS,MAAM,EACf,MAAM,cAAc,EACpB,IAAI,YAAY,EAChB,OAAO,MAAM,EACb,OAAO,MAAM,SAyCd,CAAC"}
@@ -0,0 +1,212 @@
1
+ /**
2
+ * Shift the `[start, end]` span of a range along the edited axis. Returns the
3
+ * new span, or `null` when a delete consumes it entirely.
4
+ */
5
+ export const shiftSpanLikeReference = (start, end, op, index, count) => {
6
+ if (count <= 0)
7
+ return [start, end];
8
+ if (op === "insert") {
9
+ if (index <= start)
10
+ return [start + count, end + count];
11
+ if (index <= end)
12
+ return [start, end + count];
13
+ return [start, end];
14
+ }
15
+ const deleteEnd = index + count - 1;
16
+ if (start > deleteEnd)
17
+ return [start - count, end - count];
18
+ if (end < index)
19
+ return [start, end];
20
+ const nextStart = start < index ? start : start > deleteEnd ? start - count : index;
21
+ const nextEnd = end < index ? end : end > deleteEnd ? end - count : index - 1;
22
+ if (nextStart > nextEnd)
23
+ return null;
24
+ return [nextStart, nextEnd];
25
+ };
26
+ /**
27
+ * Shift a single row/column index the way a cell (and everything anchored to
28
+ * it) moves: pushed by an insert at or before it, pulled back by a delete
29
+ * before it, snapped to the deletion index when its own row/column is
30
+ * removed.
31
+ */
32
+ export const shiftAnchorIndex = (anchorIndex, op, index, count) => {
33
+ if (count <= 0)
34
+ return anchorIndex;
35
+ if (op === "insert") {
36
+ return anchorIndex >= index ? anchorIndex + count : anchorIndex;
37
+ }
38
+ const deleteEnd = index + count - 1;
39
+ if (anchorIndex > deleteEnd)
40
+ return anchorIndex - count;
41
+ if (anchorIndex >= index)
42
+ return Math.max(1, index);
43
+ return anchorIndex;
44
+ };
45
+ export const shiftAnchorCell = (anchor, axis, op, index, count) => {
46
+ if (axis === "row") {
47
+ const rowIndex = shiftAnchorIndex(anchor.rowIndex, op, index, count);
48
+ return rowIndex === anchor.rowIndex ? anchor : { ...anchor, rowIndex };
49
+ }
50
+ const columnIndex = shiftAnchorIndex(anchor.columnIndex, op, index, count);
51
+ return columnIndex === anchor.columnIndex
52
+ ? anchor
53
+ : { ...anchor, columnIndex };
54
+ };
55
+ /**
56
+ * Shift a grid rectangle with the reference rule along one axis. Returns the
57
+ * same object when nothing moved, a new one when it did, `null` when a delete
58
+ * consumed the whole span.
59
+ */
60
+ export const shiftGridRangeLikeReference = (range, axis, op, index, count) => {
61
+ const [startKey, endKey] = axis === "row"
62
+ ? ["startRowIndex", "endRowIndex"]
63
+ : ["startColumnIndex", "endColumnIndex"];
64
+ const span = shiftSpanLikeReference(range[startKey], range[endKey], op, index, count);
65
+ if (!span)
66
+ return null;
67
+ const [start, end] = span;
68
+ if (start === range[startKey] && end === range[endKey])
69
+ return range;
70
+ return { ...range, [startKey]: start, [endKey]: end };
71
+ };
72
+ const isSheetRangeLike = (value) => {
73
+ if (!value || typeof value !== "object" || Array.isArray(value))
74
+ return false;
75
+ const v = value;
76
+ return (typeof v.sheetId === "number" &&
77
+ typeof v.startRowIndex === "number" &&
78
+ typeof v.endRowIndex === "number" &&
79
+ typeof v.startColumnIndex === "number" &&
80
+ typeof v.endColumnIndex === "number");
81
+ };
82
+ /**
83
+ * Walk a chart spec and rewrite every `SheetRange` it holds on `sheetId` —
84
+ * `dataRange`, per-series / per-domain `sources`, error-bar `plusRange` /
85
+ * `minusRange`, and any future range-valued key — with the reference rule.
86
+ * A range the delete consumes entirely is removed: spliced out of arrays
87
+ * (`sources`), nulled on properties (`dataRange`) — the chart's `#REF!`.
88
+ * Unknown keys are left untouched. Mutates in place; returns whether anything
89
+ * changed.
90
+ */
91
+ export const shiftChartSpecRanges = (spec, sheetId, axis, op, index, count) => {
92
+ let changed = false;
93
+ const shiftRange = (range) => {
94
+ if (range.sheetId !== sheetId)
95
+ return range;
96
+ const next = shiftGridRangeLikeReference(range, axis, op, index, count);
97
+ if (next !== range)
98
+ changed = true;
99
+ return next;
100
+ };
101
+ const walk = (node) => {
102
+ if (!node || typeof node !== "object")
103
+ return;
104
+ if (Array.isArray(node)) {
105
+ for (let i = node.length - 1; i >= 0; i--) {
106
+ const item = node[i];
107
+ if (isSheetRangeLike(item)) {
108
+ const next = shiftRange(item);
109
+ if (next === null)
110
+ node.splice(i, 1);
111
+ else if (next !== item)
112
+ node[i] = next;
113
+ }
114
+ else {
115
+ walk(item);
116
+ }
117
+ }
118
+ return;
119
+ }
120
+ const obj = node;
121
+ for (const key of Object.keys(obj)) {
122
+ const value = obj[key];
123
+ if (isSheetRangeLike(value)) {
124
+ const next = shiftRange(value);
125
+ if (next !== value)
126
+ obj[key] = next;
127
+ }
128
+ else {
129
+ walk(value);
130
+ }
131
+ }
132
+ };
133
+ walk(spec);
134
+ return changed;
135
+ };
136
+ /** Shift the anchor cell of every embed (picture, shape, text box…) on the edited sheet. */
137
+ export const shiftEmbedsOnStructuralChange = (draft, sheetId, axis, op, index, count) => {
138
+ for (const embed of draft) {
139
+ const position = embed.position;
140
+ if (!position || position.sheetId !== sheetId)
141
+ continue;
142
+ const overlay = position.overlayPosition;
143
+ if (!overlay?.anchorCell)
144
+ continue;
145
+ const next = shiftAnchorCell(overlay.anchorCell, axis, op, index, count);
146
+ if (next !== overlay.anchorCell)
147
+ overlay.anchorCell = next;
148
+ }
149
+ };
150
+ /**
151
+ * Shift every chart on the edited sheet: its anchor cell like a floating
152
+ * object, and the ranges inside its spec like references.
153
+ */
154
+ export const shiftChartsOnStructuralChange = (draft, sheetId, axis, op, index, count) => {
155
+ for (const chart of draft) {
156
+ const position = chart.position;
157
+ if (position?.sheetId === sheetId && position.overlayPosition?.anchorCell) {
158
+ const overlay = position.overlayPosition;
159
+ const next = shiftAnchorCell(overlay.anchorCell, axis, op, index, count);
160
+ if (next !== overlay.anchorCell)
161
+ overlay.anchorCell = next;
162
+ }
163
+ // Series ranges may point at ANY sheet, so the spec walk is not gated on
164
+ // the chart's own sheet.
165
+ shiftChartSpecRanges(chart.spec, sheetId, axis, op, index, count);
166
+ }
167
+ };
168
+ /**
169
+ * Shift AllowEditRange rectangles. A protected range without a rectangle
170
+ * (sheet-scoped protection) is untouched; one the delete consumes is removed.
171
+ */
172
+ export const shiftProtectedRangesOnStructuralChange = (draft, sheetId, axis, op, index, count) => {
173
+ const [startKey, endKey] = axis === "row"
174
+ ? ["startRowIndex", "endRowIndex"]
175
+ : ["startColumnIndex", "endColumnIndex"];
176
+ for (let i = draft.length - 1; i >= 0; i--) {
177
+ const protectedRange = draft[i];
178
+ const range = protectedRange.range;
179
+ if (range.sheetId !== sheetId)
180
+ continue;
181
+ const start = range[startKey];
182
+ const end = range[endKey];
183
+ if (typeof start !== "number" || typeof end !== "number")
184
+ continue;
185
+ const span = shiftSpanLikeReference(start, end, op, index, count);
186
+ if (!span) {
187
+ draft.splice(i, 1);
188
+ continue;
189
+ }
190
+ if (span[0] !== start)
191
+ range[startKey] = span[0];
192
+ if (span[1] !== end)
193
+ range[endKey] = span[1];
194
+ if (protectedRange.unprotectedRanges) {
195
+ const kept = [];
196
+ let unprotectedChanged = false;
197
+ for (const unprotected of protectedRange.unprotectedRanges) {
198
+ if (unprotected.sheetId !== sheetId) {
199
+ kept.push(unprotected);
200
+ continue;
201
+ }
202
+ const next = shiftGridRangeLikeReference(unprotected, axis, op, index, count);
203
+ if (next !== unprotected)
204
+ unprotectedChanged = true;
205
+ if (next)
206
+ kept.push(next);
207
+ }
208
+ if (unprotectedChanged)
209
+ protectedRange.unprotectedRanges = kept;
210
+ }
211
+ }
212
+ };
@@ -1 +1 @@
1
- {"version":3,"file":"datatype.d.ts","sourceRoot":"","sources":["../../../api/datatype.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,UAAU,EACV,aAAa,EACb,gBAAgB,EACjB,MAAM,2BAA2B,CAAC;AAYnC,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAqBlE,MAAM,MAAM,SAAS,GAAG,MAAM,aAAa,CAAC;AAE5C,eAAO,MAAM,eAAe,OAAO,CAAC;AACpC,eAAO,MAAM,uBAAuB,UAAU,CAAC;AAM/C,eAAO,MAAM,gBAAgB,8BAA0B,CAAC;AACxD,eAAO,MAAM,wBAAwB,oCAAgC,CAAC;AACtE,eAAO,MAAM,YAAY,eAAe,CAAC;AACzC,eAAO,MAAM,iBAAiB,aAAa,CAAC;AAC5C,eAAO,MAAM,YAAY,mBAAmB,CAAC;AAC7C,eAAO,MAAM,kBAAkB,eAAe,CAAC;AA6V/C;;;;;;;;;;;;;;;GAeG;AACH,eAAO,MAAM,UAAU,GACrB,OAAO,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,IAAI,GAAG,SAAS,EACnD,SAAS,MAAM,EACf,yBAAsB,YAUvB,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,SAAS,GAAI,OAAO,GAAG,YAKnC,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,YAAY,GACvB,OAAO,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,IAAI,GAAG,SAAS,EACnD,SAAS,MAAM,EACf,yBAAsB,YAcvB,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,gBAAgB,GAC3B,OAAO,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,IAAI,GAAG,SAAS,GAAG,IAAI,EAC1D,SAAS,MAAM,WAWhB,CAAC;AAEF,eAAO,MAAM,eAAe,GAC1B,MAAM,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,IAAI,GAAG,SAAS,EAClD,SAAS,MAAM,EACf,yBAAsB,WAMvB,CAAC;AACF;;;;GAIG;AACH,eAAO,MAAM,iBAAiB,GAC5B,OAAO,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,IAAI,GAAG,SAAS,EACnD,eAAe,gBAAgB,GAAG,SAAS,EAC3C,QAAQ,MAAM,GAAG,SAAS,EAC1B,UAAU,OAAO,EACjB,yBAAsB,uBAiCvB,CAAC;AAEF,eAAO,MAAM,yBAAyB,GACpC,OAAO,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,IAAI,GAAG,SAAS,GAAG,UAAU,EAChE,UAAU,OAAO,qDAMlB,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,QAAQ,GACnB,OAAO,GAAG,EACV,SAAS,MAAM,EACf,yBAAsB,KACrB,KAAK,IAAI,MASX,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,sBAAsB,GACjC,OAAO,GAAG,EACV,QAAQ,MAAM,GAAG,SAAS,EAC1B,yBAAsB,KACrB,gBAAgB,GAAG,SAmBrB,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,yBAAyB,GACpC,OAAO,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,IAAI,GAAG,SAAS,EACnD,aAAa,MAAM,GAAG,SAAS,EAC/B,MAAM,gBAAgB,GAAG,SAAS,EAClC,QAAQ,MAAM,GAAG,SAAS,EAC1B,UAAU,OAAO,KAChB,MAAM,GAAG,SAyCX,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,eAAe,GAC1B,OAAO,iBAAiB,EACxB,QAAQ,MAAM,GAAG,SAAS,EAC1B,yBAAsB,KACrB,SAkBF,CAAC;AAEF,eAAO,MAAM,yBAAyB,GACpC,OAAO,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,IAAI,GAAG,SAAS,EACnD,QAAQ,MAAM,GAAG,SAAS,EAC1B,yBAAsB,EACtB,UAAU,OAAO,KAChB,CACD,WAAW,EAAE,MAAM,aAAa,EAChC,aAAa,CAAC,EAAE,gBAAgB,EAChC,WAAW,CAAC,EAAE,MAAM,EACpB,OAAO,CAAC,EAAE,MAAM,CA4GjB,CAAC;AAEF;;;;;GAKG;AACH,eAAO,MAAM,oBAAoB,GAC/B,OAAO,iBAAiB,EACxB,WAAW,SAAS,GAAG,SAAS,EAChC,SAAS,MAAM,EACf,SAAS,MAAM,WAOhB,CAAC;AAEF,eAAO,MAAM,oBAAoB,GAC/B,OAAO,iBAAiB,EACxB,WAAW,SAAS,GAAG,SAAS,EAChC,SAAS,MAAM,KACd,MAAM,GAAG,SAMX,CAAC;AAEF,eAAO,MAAM,WAAW,GAAI,KAAK,GAAG,YAEnC,CAAC;AAEF,eAAO,MAAM,iBAAiB,GAAI,KAAK,MAAM,KAAG,OAe/C,CAAC"}
1
+ {"version":3,"file":"datatype.d.ts","sourceRoot":"","sources":["../../../api/datatype.ts"],"names":[],"mappings":"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"}
@@ -574,11 +574,18 @@ export const detectValueTypeAndPattern = (value, locale, lenientGrouping = true,
574
574
  const percentValue = convertToNumber(value, locale, lenientGrouping) / 100;
575
575
  return ["numberValue", "PERCENT", percentValue, pattern];
576
576
  }
577
+ // A JS number carries no typed digits: its decimal expansion is float
578
+ // noise (0.1 + 0.2, the 5.333333333333333 of a fitted trend), never a
579
+ // format the user asked for. Excel keeps a computed or programmatic
580
+ // number General and clips it to General's significant digits, so only
581
+ // TEXT entry infers a decimal pattern from what was typed.
577
582
  return [
578
583
  "numberValue",
579
584
  "NUMBER",
580
585
  convertToNumber(value, locale, lenientGrouping),
581
- detectNumberFormatPattern(value, numberValue, "NUMBER", locale),
586
+ typeof value === "number"
587
+ ? "General"
588
+ : detectNumberFormatPattern(value, numberValue, "NUMBER", locale),
582
589
  ];
583
590
  }
584
591
  // Date time (check before date to catch time-only formats like "1:00 AM")
@@ -3,8 +3,8 @@ import type { CellData } from "@rowsncolumns/spreadsheet";
3
3
  import type { Draft } from "immer";
4
4
  import type { useCalculation } from "../hooks/use-calculation";
5
5
  import type { CellXfsRegistry } from "../hooks/use-cellxfs-registry";
6
- import type { SharedStringRegistry } from "../hooks/use-ss-registry";
7
6
  import type { SheetData } from "../hooks/use-spreadsheet-state";
7
+ import type { SharedStringRegistry } from "../hooks/use-ss-registry";
8
8
  import type { RecalcCellCoordinate } from "../types";
9
9
  type ProcessDependentCellsProps<T extends CellData> = {
10
10
  rowIndex: number;
@@ -38,7 +38,7 @@ export declare const collectUniqueDependentsForRange: <T extends CellData>(param
38
38
  rowIndex: number;
39
39
  columnIndex: number;
40
40
  }>;
41
- export declare const moveFormulaAtPosition: <T extends CellData>({ draft, position, destinationSheetId, activeSheetName, enqueueCalculation, enqueueGraphOperation, recalcCells, movedKeys, rowDelta, columnDelta, sourceRange, locale, rowCount, columnCount, cellXfsRegistry, sharedStringRegistry, }: {
41
+ export declare const moveFormulaAtPosition: <T extends CellData>({ draft, position, destinationSheetId, activeSheetName, enqueueCalculation, enqueueGraphOperation, recalcCells, movedKeys, rowDelta, columnDelta, sourceRange, deletedRange, destinationPosition, locale, rowCount, columnCount, cellXfsRegistry, sharedStringRegistry, }: {
42
42
  draft: Draft<SheetData<T>>;
43
43
  position: {
44
44
  sheetId: number;
@@ -54,6 +54,17 @@ export declare const moveFormulaAtPosition: <T extends CellData>({ draft, positi
54
54
  rowDelta?: number;
55
55
  columnDelta?: number;
56
56
  sourceRange?: GridRange;
57
+ /** Cells removed by a delete-cells shift — references into it become `#REF!` (SHF-09). */
58
+ deletedRange?: GridRange;
59
+ /**
60
+ * Where the formula cell itself ends up. Defaults to `position + delta` (the cell moves with the
61
+ * shift). A dependent OUTSIDE the shifted band keeps its place while its references into the
62
+ * band still move by the delta — pass its own position here so the graph is re-keyed correctly.
63
+ */
64
+ destinationPosition?: {
65
+ rowIndex: number;
66
+ columnIndex: number;
67
+ };
57
68
  locale?: string;
58
69
  rowCount?: number;
59
70
  columnCount?: number;
@@ -1 +1 @@
1
- {"version":3,"file":"dependency.d.ts","sourceRoot":"","sources":["../../../api/dependency.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"dependency.d.ts","sourceRoot":"","sources":["../../../api/dependency.ts"],"names":[],"mappings":"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"}
@@ -205,7 +205,7 @@ export const collectUniqueDependentsForRange = (params) => {
205
205
  return dependentMap;
206
206
  };
207
207
  // Process a single formula move at a specific position with the specified deltas.
208
- export const moveFormulaAtPosition = ({ draft, position, destinationSheetId, activeSheetName, enqueueCalculation, enqueueGraphOperation, recalcCells, movedKeys, rowDelta = 0, columnDelta = 0, sourceRange, locale, rowCount, columnCount, cellXfsRegistry, sharedStringRegistry, }) => {
208
+ export const moveFormulaAtPosition = ({ draft, position, destinationSheetId, activeSheetName, enqueueCalculation, enqueueGraphOperation, recalcCells, movedKeys, rowDelta = 0, columnDelta = 0, sourceRange, deletedRange, destinationPosition, locale, rowCount, columnCount, cellXfsRegistry, sharedStringRegistry, }) => {
209
209
  const sheetCell = new SheetCell();
210
210
  const currentSheet = createSheetDraft(draft, position.sheetId, position.rowIndex);
211
211
  const cellData = currentSheet[position.rowIndex]?.values?.[position.columnIndex];
@@ -213,11 +213,17 @@ export const moveFormulaAtPosition = ({ draft, position, destinationSheetId, act
213
213
  if (!movedKeys.has(sheetCell.key) && sheetCell.isFormula()) {
214
214
  movedKeys.add(sheetCell.key);
215
215
  const previousFormula = sheetCell.formula;
216
- const newRowIndex = position.rowIndex + rowDelta;
217
- const newColumnIndex = position.columnIndex + columnDelta;
216
+ const newRowIndex = destinationPosition?.rowIndex ?? position.rowIndex + rowDelta;
217
+ const newColumnIndex = destinationPosition?.columnIndex ?? position.columnIndex + columnDelta;
218
218
  const resolvedSheetName = activeSheetName ?? "";
219
- sheetCell.moveFormula({ rowIndex: position.rowIndex, columnIndex: position.columnIndex }, { rowIndex: newRowIndex, columnIndex: newColumnIndex }, resolvedSheetName, {
219
+ // The delta is applied to the references inside `sourceRange`; the formula cell's own
220
+ // destination (for the graph re-key) may differ when it does not move itself.
221
+ sheetCell.moveFormula({ rowIndex: position.rowIndex, columnIndex: position.columnIndex }, {
222
+ rowIndex: position.rowIndex + rowDelta,
223
+ columnIndex: position.columnIndex + columnDelta,
224
+ }, resolvedSheetName, {
220
225
  exclusionRange: sourceRange,
226
+ deletedRange,
221
227
  rowCount,
222
228
  columnCount,
223
229
  });
@@ -0,0 +1,35 @@
1
+ import type { FillSeriesSpec } from "@rowsncolumns/spreadsheet";
2
+ /** One fill line's Series-dialog result (see {@link generateSeriesSpecValues}). */
3
+ export type SeriesSpecLine = {
4
+ /**
5
+ * Trend only: the fitted value of every numeric seed as `{ index, value }`
6
+ * (`index` into the caller's `sourceValues`) — Excel replaces the starting
7
+ * values with the trend it fitted through them. Empty for every other spec.
8
+ */
9
+ seeds: {
10
+ index: number;
11
+ value: number;
12
+ }[];
13
+ /**
14
+ * The target values in fill order. SHORTER than the requested count when
15
+ * `stop` ends the series early — the targets past it are left untouched
16
+ * (Excel writes nothing there).
17
+ */
18
+ values: unknown[];
19
+ };
20
+ /**
21
+ * Value generator behind Excel's Series dialog (Home > Fill > Series…). The
22
+ * spec is explicit user intent, so unlike drag auto-fill nothing is detected:
23
+ * Linear adds `step`, Growth multiplies by `step`, Date advances `step`
24
+ * `dateUnit`s (weekday skips Sat/Sun, month clamps to month-end). `trend` fits
25
+ * a least-squares line (Linear) / exponential (Growth) through the seeds and,
26
+ * as Excel does, REWRITES the seeds with the fitted values before continuing
27
+ * the fit (a lone seed fits a flat line — the value repeats). A `stop` value
28
+ * ends the series at the last value that does not pass it: the line comes
29
+ * back shorter and the remaining selected cells are left alone. Returns
30
+ * `undefined` when the spec does not apply (AutoFill type, or seeds that are
31
+ * not numbers/dates) so the caller falls back to the regular fill-type
32
+ * generator.
33
+ */
34
+ export declare const generateSeriesSpecValues: (sourceValues: unknown[], spec: FillSeriesSpec, count: number, locale?: string) => SeriesSpecLine | undefined;
35
+ //# sourceMappingURL=fill-series-spec.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fill-series-spec.d.ts","sourceRoot":"","sources":["../../../api/fill-series-spec.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAEhE,mFAAmF;AACnF,MAAM,MAAM,cAAc,GAAG;IAC3B;;;;OAIG;IACH,KAAK,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;IAC1C;;;;OAIG;IACH,MAAM,EAAE,OAAO,EAAE,CAAC;CACnB,CAAC;AAEF;;;;;;;;;;;;;GAaG;AACH,eAAO,MAAM,wBAAwB,GACnC,cAAc,OAAO,EAAE,EACvB,MAAM,cAAc,EACpB,OAAO,MAAM,EACb,SAAS,MAAM,KACd,cAAc,GAAG,SAqDnB,CAAC"}
@@ -0,0 +1,160 @@
1
+ /**
2
+ * Value generator behind Excel's Series dialog (Home > Fill > Series…). The
3
+ * spec is explicit user intent, so unlike drag auto-fill nothing is detected:
4
+ * Linear adds `step`, Growth multiplies by `step`, Date advances `step`
5
+ * `dateUnit`s (weekday skips Sat/Sun, month clamps to month-end). `trend` fits
6
+ * a least-squares line (Linear) / exponential (Growth) through the seeds and,
7
+ * as Excel does, REWRITES the seeds with the fitted values before continuing
8
+ * the fit (a lone seed fits a flat line — the value repeats). A `stop` value
9
+ * ends the series at the last value that does not pass it: the line comes
10
+ * back shorter and the remaining selected cells are left alone. Returns
11
+ * `undefined` when the spec does not apply (AutoFill type, or seeds that are
12
+ * not numbers/dates) so the caller falls back to the regular fill-type
13
+ * generator.
14
+ */
15
+ export const generateSeriesSpecValues = (sourceValues, spec, count, locale) => {
16
+ if (spec.type === "autofill" || count <= 0)
17
+ return undefined;
18
+ if (spec.type === "date") {
19
+ const values = generateDateSeries(sourceValues, spec, count, locale);
20
+ return values ? { seeds: [], values } : undefined;
21
+ }
22
+ const indexed = sourceValues
23
+ .map((v, index) => ({ index, value: toNumber(v) }))
24
+ .filter((seed) => Number.isFinite(seed.value));
25
+ if (!indexed.length)
26
+ return undefined;
27
+ const numbers = indexed.map((seed) => seed.value);
28
+ const step = spec.step ?? 1;
29
+ const n = numbers.length;
30
+ if (spec.trend) {
31
+ // Least-squares trend through the seeds (x = 0..n-1), continued at x = n…
32
+ // A single seed has no slope: the fit is the flat line through it.
33
+ const ys = spec.type === "growth"
34
+ ? numbers.map((y) => (y > 0 ? Math.log(y) : NaN))
35
+ : numbers;
36
+ if (ys.some((y) => !Number.isFinite(y)))
37
+ return undefined;
38
+ const xs = ys.map((_, i) => i);
39
+ const sumX = xs.reduce((a, b) => a + b, 0);
40
+ const sumY = ys.reduce((a, b) => a + b, 0);
41
+ const sumXY = xs.reduce((a, x, i) => a + x * ys[i], 0);
42
+ const sumXX = xs.reduce((a, x) => a + x * x, 0);
43
+ const denom = n * sumXX - sumX * sumX;
44
+ const slope = denom === 0 ? 0 : (n * sumXY - sumX * sumY) / denom;
45
+ const intercept = (sumY - slope * sumX) / n;
46
+ const fit = (x) => {
47
+ const fitted = slope * x + intercept;
48
+ return normalize(spec.type === "growth" ? Math.exp(fitted) : fitted);
49
+ };
50
+ return {
51
+ seeds: indexed.map((seed, position) => ({
52
+ index: seed.index,
53
+ value: fit(position),
54
+ })),
55
+ values: Array.from({ length: count }, (_, i) => fit(n + i)),
56
+ };
57
+ }
58
+ const values = [];
59
+ let current = numbers[n - 1];
60
+ for (let i = 0; i < count; i++) {
61
+ current =
62
+ spec.type === "growth" ? current * step : current + step;
63
+ current = normalize(current);
64
+ if (passesStop(current, step, spec))
65
+ break;
66
+ values.push(current);
67
+ }
68
+ return { seeds: [], values };
69
+ };
70
+ const toNumber = (v) => typeof v === "number"
71
+ ? v
72
+ : typeof v === "string" && v.trim() !== "" && !isNaN(Number(v))
73
+ ? Number(v)
74
+ : NaN;
75
+ /** Excel's stop rule: the series ends once a value would move past `stop` in the series' direction. */
76
+ const passesStop = (value, step, spec) => {
77
+ const { stop } = spec;
78
+ if (stop === undefined || !Number.isFinite(stop))
79
+ return false;
80
+ const ascending = spec.type === "growth" ? Math.abs(step) > 1 === value > 0 : step > 0;
81
+ return ascending ? value > stop + 1e-9 : value < stop - 1e-9;
82
+ };
83
+ /** Snap float noise (0.1 + 0.2) to a clean decimal. */
84
+ const normalize = (x) => {
85
+ if (!Number.isFinite(x))
86
+ return x;
87
+ const r = Math.round(x * 1e10) / 1e10;
88
+ return Math.abs(r - Math.round(r)) < 1e-9 ? Math.round(r) : r;
89
+ };
90
+ const toDateValue = (value) => {
91
+ if (value instanceof Date)
92
+ return isNaN(value.getTime()) ? null : value;
93
+ if (typeof value === "string" && value.trim()) {
94
+ const parsed = new Date(value);
95
+ return isNaN(parsed.getTime()) ? null : parsed;
96
+ }
97
+ return null;
98
+ };
99
+ const generateDateSeries = (sourceValues, spec, count, locale) => {
100
+ const dates = sourceValues
101
+ .map(toDateValue)
102
+ .filter((d) => d !== null);
103
+ if (!dates.length)
104
+ return undefined;
105
+ const last = dates[dates.length - 1];
106
+ const step = Math.trunc(spec.step ?? 1) || 1;
107
+ const unit = spec.dateUnit ?? "day";
108
+ const result = [];
109
+ const current = new Date(last);
110
+ const lastDayOfMonth = last.getDate();
111
+ for (let i = 0; i < count; i++) {
112
+ switch (unit) {
113
+ case "day":
114
+ current.setDate(current.getDate() + step);
115
+ break;
116
+ case "weekday": {
117
+ const dir = step > 0 ? 1 : -1;
118
+ for (let k = 0; k < Math.abs(step); k++) {
119
+ do {
120
+ current.setDate(current.getDate() + dir);
121
+ } while (current.getDay() === 0 || current.getDay() === 6);
122
+ }
123
+ break;
124
+ }
125
+ case "month": {
126
+ // Keep the seed's day-of-month, clamped to the target month's length.
127
+ const target = new Date(last);
128
+ target.setDate(1);
129
+ target.setMonth(last.getMonth() + step * (i + 1));
130
+ const daysInMonth = new Date(target.getFullYear(), target.getMonth() + 1, 0).getDate();
131
+ target.setDate(Math.min(lastDayOfMonth, daysInMonth));
132
+ current.setTime(target.getTime());
133
+ break;
134
+ }
135
+ case "year": {
136
+ const target = new Date(last);
137
+ target.setDate(1);
138
+ target.setFullYear(last.getFullYear() + step * (i + 1));
139
+ const daysInMonth = new Date(target.getFullYear(), target.getMonth() + 1, 0).getDate();
140
+ target.setDate(Math.min(lastDayOfMonth, daysInMonth));
141
+ current.setTime(target.getTime());
142
+ break;
143
+ }
144
+ }
145
+ if (spec.stop !== undefined && Number.isFinite(spec.stop)) {
146
+ // Date stop values are Excel serials; compare on whole days since epoch.
147
+ // Past the stop the line ends — the remaining cells stay untouched.
148
+ const serial = (current.getTime() - Date.UTC(1899, 11, 30)) / 86_400_000 +
149
+ current.getTimezoneOffset() / 1440;
150
+ const ascending = step > 0;
151
+ if (ascending ? serial > spec.stop + 1e-6 : serial < spec.stop - 1e-6) {
152
+ break;
153
+ }
154
+ }
155
+ // Mirrors `generateFillValues`' date cases, which hand back locale date
156
+ // strings that `SheetCell` re-parses into a date-formatted serial.
157
+ result.push(new Date(current).toLocaleDateString(locale));
158
+ }
159
+ return result;
160
+ };