@sheetxl/sdk 0.7.28-beta.3 → 0.7.28-beta.4

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 (57) hide show
  1. package/browser/cjs/{D6cjnwWR_iUSe1f6.cjs → BF14ZEAnaqxXroSj.cjs} +1 -1
  2. package/browser/cjs/{CWCKcp58KidyndaL.cjs → BXtvdT1Z-MsB_o5F.cjs} +1 -1
  3. package/browser/cjs/Bc4JjVVZfFo3R4He.cjs +33 -0
  4. package/browser/cjs/{BX6A6xGDOr_td9mw.cjs → CD2RXdnfqSYNc6gX.cjs} +1 -1
  5. package/browser/cjs/{B4PKKgaDTG9aSO-f.cjs → DcLpXGexEtOxi-dD.cjs} +1 -1
  6. package/browser/cjs/index.cjs +2 -2
  7. package/browser/esm/{CX1NO_a1QPjXDvTU.mjs → 0Mj5WKM362q6CECb.mjs} +3 -3
  8. package/browser/esm/{Rj8e7SashcMlcdZJ.mjs → CHSahmMFYNB0Ajkf.mjs} +2 -2
  9. package/browser/esm/{B1gpnr-7kLU7jTy-.mjs → CKk58ZLcrllMzfou.mjs} +2 -2
  10. package/browser/esm/{CPgz9_iM7xyAcytg.mjs → CPTtL2f6_4iblmFM.mjs} +2 -2
  11. package/browser/esm/{Dv8FyXyeygJPXoHo.mjs → CoA-sUxjiIUIpTUF.mjs} +2 -2
  12. package/browser/esm/{DZfds6s3ayTZrozO.mjs → DBIu6NUHIcxOOBQp.mjs} +1 -1
  13. package/browser/esm/{C78IaCXqwCcraBPe.mjs → Dy4Sdpju1T2icURu.mjs} +6266 -5497
  14. package/browser/esm/index.mjs +17 -14
  15. package/node/esm/{BkY99r-c3BhlT_Kv.mjs → BtGxbEbBm79YvF_k.mjs} +1 -1
  16. package/node/esm/{DE3eIaqkk5xzmV1c.mjs → DUYP6faJJHCaW1Xf.mjs} +1 -1
  17. package/node/esm/{8VtzCFSmLPKxJjOa.mjs → DqgWsVXROpSgKq6c.mjs} +1 -1
  18. package/node/esm/index.mjs +8589 -7804
  19. package/package.json +6 -6
  20. package/types/scripting-enums.json +2 -0
  21. package/types/scripting.d.ts +265 -8
  22. package/types/src/anchored/IAnchored.d.ts +27 -0
  23. package/types/src/calculation/Calculation.d.ts +21 -12
  24. package/types/src/calculation/ICalculation.d.ts +178 -0
  25. package/types/src/calculation/executor/CalcExecutor.d.ts +204 -13
  26. package/types/src/calculation/executor/CalcExecutorUtils.d.ts +31 -0
  27. package/types/src/calculation/executor/CircularReference.d.ts +81 -0
  28. package/types/src/calculation/grid/CalcGrid.d.ts +3 -1
  29. package/types/src/calculation/grid/CalcGridUtils.d.ts +3 -2
  30. package/types/src/calculation/grid/ICalcGrid.d.ts +12 -1
  31. package/types/src/calculation/spatial/CircularEntry.d.ts +18 -0
  32. package/types/src/calculation/spatial/index.d.ts +1 -0
  33. package/types/src/calculation/state/CalcNode.d.ts +24 -17
  34. package/types/src/calculation/state/CalcState.d.ts +78 -15
  35. package/types/src/calculation/state/CalculationContext.d.ts +39 -0
  36. package/types/src/calculation/state/_ReadObservedGrid.d.ts +90 -0
  37. package/types/src/cell/ICell.d.ts +16 -0
  38. package/types/src/cellRange/ICellRange.d.ts +12 -3
  39. package/types/src/condition/AnchoredConditional.d.ts +26 -6
  40. package/types/src/conditionalFormat/ConditionalFormat.d.ts +8 -1
  41. package/types/src/conditionalFormat/IConditionalFormat.d.ts +4 -1
  42. package/types/src/conditionalFormat/IConditionalFormatCollection.d.ts +6 -2
  43. package/types/src/dataValidation/IDataValidationCollection.d.ts +6 -2
  44. package/types/src/hyperlink/IHyperlink.d.ts +3 -1
  45. package/types/src/hyperlink/_Hyperlink.d.ts +6 -0
  46. package/types/src/lib/utils/utils.browser.d.ts +5 -0
  47. package/types/src/license/LicenseDetails.d.ts +5 -0
  48. package/types/src/primitives/CalcSignal.d.ts +20 -0
  49. package/types/src/protectedRange/IProtectedRangeCollection.d.ts +7 -2
  50. package/types/src/scripting/_ScriptUtils.d.ts +13 -0
  51. package/types/src/sheet/Sheet.d.ts +33 -2
  52. package/types/src/sheet/SheetCell.d.ts +2 -0
  53. package/types/src/sheet/_SheetStateTypes.d.ts +14 -1
  54. package/types/src/style/IStyle.d.ts +5 -0
  55. package/types/src/table/AnchoredTable.d.ts +17 -1
  56. package/types/src/text/TextUtils.d.ts +18 -0
  57. package/browser/cjs/1mH2uhx_Dmceu88H.cjs +0 -33
@@ -5,7 +5,7 @@ import { IListener } from '../../listener';
5
5
  import { IHistory } from '../../history';
6
6
  import { ISpatialQuery, ISpatialMap, ISparseGrid, Tuple } from '../../collections';
7
7
  import { IFormulaBlock } from '../formula';
8
- import { ContentfulSpatialValue, SpillEntry } from '../spatial';
8
+ import { ContentfulSpatialValue, SpillEntry, CircularEntry } from '../spatial';
9
9
  import { ReferenceCoords, NamedReference } from '../Types';
10
10
  import { ICalculation } from '../ICalculation';
11
11
  /**
@@ -311,6 +311,14 @@ export declare namespace ICalcGrid {
311
311
  * These are guaranteed to not overlap.
312
312
  */
313
313
  pendingUpdates?: ISpatialMap.Entry<boolean>[];
314
+ /**
315
+ * Cells that entered or left a reference cycle (or the set downstream of one). A `null`
316
+ * value is a removal.
317
+ *
318
+ * @remarks
319
+ * These are guaranteed to not overlap.
320
+ */
321
+ circularUpdates?: ISpatialMap.Entry<CircularEntry | null>[];
314
322
  }
315
323
  /**
316
324
  * Returns from `ICalcGrid.beginUpdates()`.
@@ -324,13 +332,16 @@ export declare namespace ICalcGrid {
324
332
  spillSpatial: ISpatialMap<SpillEntry>;
325
333
  errorSpatial: ISpatialMap<string>;
326
334
  pendingSpatial: ISpatialMap<boolean>;
335
+ circularSpatial: ISpatialMap<CircularEntry>;
327
336
  contentfulSpatial: ISpatialMap<ContentfulSpatialValue>;
328
337
  notifyValues: ISpatialMap;
329
338
  notifySpillsInsert: ISpatialMap.Entry<SpillEntry>[];
330
339
  notifySpillsRemove: IRange.Coords[];
331
340
  notifyFormats: ISpatialMap;
332
341
  notifyPending: ISpatialMap<boolean>;
342
+ notifyCircular: ISpatialMap<CircularEntry | false>;
333
343
  pendingConflating: ISpatialMap.IConflatingEntries<boolean> | null;
344
+ circularConflating: ISpatialMap.IConflatingEntries<CircularEntry | false> | null;
334
345
  errorRemovesConflating: ISpatialMap.IConflatingEntries<null> | null;
335
346
  errorInsertsConflating: ISpatialMap.IConflatingEntries<string> | null;
336
347
  formatsConflating: ISpatialMap.IConflatingEntries | null;
@@ -0,0 +1,18 @@
1
+ import { ICalculation } from '../ICalculation';
2
+ /**
3
+ * What a sheet's circular index says about a cell (DESIGN-CIRCULAR-CALC.md §7.2): which
4
+ * reference cycle it belongs to, and whether it is in the cycle or merely downstream of it.
5
+ *
6
+ * @remarks
7
+ * The value stays what it is (`0`, Excel's answer with iterative calculation off); this is
8
+ * metadata beside it, the way `SpillEntry` marks a spill zone. Entries are interned per
9
+ * `(cycle, kind)` by the executor, so equal payloads are the same object and adjacent cells of
10
+ * one cycle coalesce into one region — and a region's payload IS the cycle, no id to look up.
11
+ */
12
+ export interface CircularEntry {
13
+ /** The cycle; one live object per cycle, shared by every cell in it or downstream of it. */
14
+ readonly cycle: ICalculation.ICircularReference;
15
+ /** In the cycle, or a reader of it (transitively). Both evaluate to `0`. */
16
+ readonly kind: 'member' | 'downstream';
17
+ }
18
+ //# sourceMappingURL=CircularEntry.d.ts.map
@@ -1,4 +1,5 @@
1
1
  export * from './SpillEntry';
2
+ export * from './CircularEntry';
2
3
  export * from './ContentfulSpatialValue';
3
4
  export * from './FormulaSpatialValue';
4
5
  export * from './PrecedentSpatialValue';
@@ -40,31 +40,38 @@ export interface CalcNode {
40
40
  cachedValue: Scalar | IRange | undefined;
41
41
  pendingPromise: Promise<any> | null;
42
42
  /**
43
- * Indicates if the pending is in the pending spatial (to avoid lookup)
43
+ * The demand evaluation's result — finalized for the cell, or a pending promise — which
44
+ * `doEvaluate` consumes in place of an `evaluateAt` of its own. Cleared once consumed.
45
+ * Meaningful only while `CalcState.Circular` is set.
44
46
  */
45
- pending: boolean;
47
+ demandValue: any;
46
48
  /**
47
- * Indicates the pending is waiting on a precedent to resolve.
49
+ * Identifies the cycle a `CycleRole.Member` belongs to (and the one a `CycleRole.Downstream`
50
+ * node read). `0` for none. Slices that share a node share an id. Reset every mark phase.
48
51
  */
49
- pendingPrecedents: boolean;
52
+ cycleGroup: number;
50
53
  /**
51
- * Indicates the pending is full filled and waiting for the next cycle to resolve.
54
+ * For a `CycleRole.Member`: the member this one READ that continues the cycle — the next step
55
+ * of the walk `ICircularReference.getPath` answers. A cycle of one points at itself. Written
56
+ * from the `Circular` slice (whose stack order is the read order) and rewritten whenever the
57
+ * cycle is detected again; stale otherwise, so a walk checks each step is still a live member.
52
58
  */
53
- pendingResolved: boolean;
59
+ cycleNext: CalcNode | null;
54
60
  /**
55
- * Set when the topological sort could not order this node — it is part of a reference cycle, or
56
- * downstream of one. Reset for every affected node at the start of each mark phase, so like
57
- * `inDegree` it only describes the CURRENT cycle.
58
- *
59
- * @remarks
60
- * Deliberately not folded into {@link state}: `state` carries the Skip/Pending transitions that
61
- * `doEvaluate` reads and rewrites mid-pass, and this has to survive being set BEFORE that runs.
61
+ * The cycle the sheet's circular index currently shows this cell in (`0` none) — what the last
62
+ * commit wrote, so the next can write the delta. Persists across passes, unlike
63
+ * {@link cycleGroup}; the role it shows is the `CalcState.ShownRoleMask` field of {@link state}.
62
64
  */
63
- circular: boolean;
65
+ shownGroup: number;
64
66
  /**
65
- * The state is a bit mask with transient states.
66
- * The CalcNode is reused across cycles and cloned records for performance.
67
- * To ensure that it is correct the cycleId id must be consulted.
67
+ * Bit mask, laid out by `CalcState`: the pending flags, `Skip`, `Circular`, and the
68
+ * `DemandState`/`CycleRole` fields of the current pass.
69
+ *
70
+ * @remarks
71
+ * The node is reused across passes, so a per-pass bit is only meaningful when {@link cycleId}
72
+ * and {@link markId} say the node is in the current pass; the mark phase resets them
73
+ * (`CalcState.PassMask`) as it visits each affected node. `Skip` and the shown role outlive a
74
+ * pass on purpose.
68
75
  */
69
76
  state: number;
70
77
  }
@@ -1,28 +1,91 @@
1
+ /**
2
+ * The bit layout of `CalcNode.state`: single-bit flags in the low byte, then three 2-bit fields.
3
+ *
4
+ * @remarks
5
+ * Every bit is independent, so a phase touches only its own: the mark phase clears
6
+ * {@link PassMask} (what the last pass decided), `doEvaluate` consumes {@link Skip}, and the
7
+ * promise path flips the pending bits — none of them assigns the whole word.
8
+ *
9
+ * The 2-bit fields hold a {@link DemandState} and two {@link CycleRole}s. Their values are
10
+ * pre-shifted into place, so a read is `(state & Mask) === Value` and a write is
11
+ * `state = (state & ~Mask) | Value`. The `ShownRole` field sits two bits above `CycleRole`, so
12
+ * copying the role the pass decided into what the sheet shows is `(state & CycleRoleMask) << 2`.
13
+ */
1
14
  export declare const CalcState: {
15
+ /** Nothing set. */
16
+ readonly Idle: 0;
2
17
  /**
3
- * The default state.
18
+ * Evaluate-once guard for a dynamic dependency (a dynamic precedent or a spill output) that
19
+ * caused a recalc: the next pass skips the node instead of re-evaluating it.
4
20
  */
5
- readonly Active: 0;
21
+ readonly Skip: number;
22
+ /** Reserved. */
23
+ readonly Removed: number;
24
+ /** The node is in the pending spatial (the user has been given a pending status). */
25
+ readonly Pending: number;
26
+ /** A precedent evaluated to a pending value this pass, so the node keeps its cached value. */
27
+ readonly PendingPrecedents: number;
28
+ /** The node's promise resolved; the result waits in `cachedValue` for the next pass. */
29
+ readonly PendingResolved: number;
6
30
  /**
7
- * Causing a recalc due to a dynamic dependency. This is either a
8
- * dynamic precedent or a spill output.
31
+ * The topological sort could not order the node this pass — it is in a reference cycle, or
32
+ * downstream of one — so it was (or will be) evaluated by demand and `doEvaluate` takes its
33
+ * `demandValue` in place of an `evaluateAt`.
9
34
  */
10
- readonly Skip: 1;
11
- readonly Removed: 2;
35
+ readonly Circular: number;
12
36
  /**
13
- * The calc node is pending and waiting for a precedent to resolve.
14
- * This is used to indicate that the user has been given a pending status.
37
+ * A `Waiting` node the evaluation in progress has read under iterative calculation — it is in
38
+ * the executor's hit list already, so a second read of it in the same evaluation adds nothing.
39
+ * Cleared when the list is consumed.
15
40
  */
16
- readonly Pending: 3;
41
+ readonly IterHit: number;
42
+ /** Field: the {@link DemandState}. */
43
+ readonly DemandMask: number;
44
+ /** Field: the {@link CycleRole} this pass decided. */
45
+ readonly CycleRoleMask: number;
46
+ /** Field: the {@link CycleRole} the sheet's circular index currently shows (persists). */
47
+ readonly ShownRoleMask: number;
17
48
  /**
18
- * The calc node is pending and waiting for a precedent to resolve.
19
- * This is used for dynamic dependencies that are not yet resolved.
49
+ * In the executor's circular roster for the pass in progress. Outside {@link PassMask} on
50
+ * purpose: the roster outlives the re-marks a pass makes while it re-dirties, so the executor
51
+ * clears this when it empties the roster.
20
52
  */
21
- readonly PendingPrecedents: 4;
53
+ readonly Rostered: number;
54
+ /** What the mark phase resets: everything a single pass decides. `Skip` and the shown role survive. */
55
+ readonly PassMask: number;
56
+ };
57
+ /**
58
+ * Where a node the topological sort could not order stands in the demand evaluation
59
+ * (DESIGN-CIRCULAR-CALC.md §4.3). Meaningful only while `CalcState.Circular` is set for the
60
+ * current pass. Values sit in the `CalcState.DemandMask` field.
61
+ */
62
+ export declare const DemandState: {
63
+ /** Not yet evaluated; a read of it suspends the reader so it can go first. */
64
+ readonly Unevaluated: 0;
65
+ /** On the in-progress stack; a read of it is a reference cycle. */
66
+ readonly Waiting: number;
67
+ /** Evaluated (or written `0` as a cycle member); reads see its value. */
68
+ readonly Done: number;
69
+ /**
70
+ * Evaluated on the ordered path but not yet committed — its value is in the pending batch, so a
71
+ * lazy read of the grid would still see the previous one. Reads treat it as {@link Unevaluated}
72
+ * until the batch is flushed, which makes it {@link Done}.
73
+ */
74
+ readonly Evaluated: number;
75
+ };
76
+ /**
77
+ * How a node relates to a reference cycle, decided by the demand evaluation's reads. Values sit
78
+ * in the `CalcState.CycleRoleMask` field.
79
+ */
80
+ export declare const CycleRole: {
81
+ /** Not in a cycle and reads none — an unorderable node that simply computed. */
82
+ readonly None: 0;
83
+ /** Named by a `Circular` read: its evaluation needed its own value. Writes `0`. */
84
+ readonly Member: number;
22
85
  /**
23
- * The calc node is pending and waiting for a precedent to resolve.
24
- * This is used for dynamic dependencies that are not yet resolved.
86
+ * Read a member (transitively). Writes `0` too — Excel gives every cell downstream of a cycle
87
+ * `0`, not a value computed from the members' `0` (design §2.1: `=A1+100` is `0`).
25
88
  */
26
- readonly PendingResolved: 5;
89
+ readonly Downstream: number;
27
90
  };
28
91
  //# sourceMappingURL=CalcState.d.ts.map
@@ -5,6 +5,7 @@ import { IFunctionCollection } from '../../scripting';
5
5
  import { Tuple } from '../../collections';
6
6
  import { IContextContainer } from './IContextContainer';
7
7
  import { CalcScope } from './CalcScope';
8
+ import { ReadHook } from './_ReadObservedGrid';
8
9
  export declare class CalculationContext implements IFormulaContext {
9
10
  protected _instanceScope: any;
10
11
  protected _runtime: IRuntime;
@@ -14,9 +15,39 @@ export declare class CalculationContext implements IFormulaContext {
14
15
  protected _axis: IRange.Axis;
15
16
  protected _coerceToNumber: (value: Scalar, fromType: ScalarType, options?: IFormulaContext.ParseNumberOptions) => Scalar;
16
17
  protected _functionProviders?: readonly FunctionProvider[];
18
+ /**
19
+ * Receives every value read while armed; `null` on the ordinary path.
20
+ *
21
+ * @remarks
22
+ * Two paths read the grid on a formula's behalf and both report here: a reference built by
23
+ * {@link _toReference} (its grid is wrapped in a {@link ReadObservedGrid}) and the direct
24
+ * single-cell read {@link getValueAt} falls back to. Constructing a reference is not a read.
25
+ */
26
+ protected _onRead: ReadHook | null;
27
+ /**
28
+ * Receives the reads of references built on the DYNAMIC branch of {@link getReference} — the
29
+ * result of `OFFSET`/`INDIRECT`/`INDEX` — when {@link _onRead} is not armed. The executor arms
30
+ * it for the length of an ordinary pass so that a dynamic read landing on the evaluating cell
31
+ * is seen (DESIGN-CIRCULAR-CALC.md §5); `null` outside a pass.
32
+ */
33
+ protected _dynamicRead: ReadHook | null;
17
34
  constructor(container: IContextContainer, axis?: IRange.Axis, functionProviders?: readonly FunctionProvider[]);
18
35
  /** @hidden */
19
36
  _setInstanceScope(instanceScope: any): void;
37
+ /**
38
+ * @hidden
39
+ * Arms (or, with `null`, disarms) the read hook. While armed, every reference this context
40
+ * builds observes its reads and every direct cell read is reported — the funnel a demand
41
+ * evaluation decides circularity through. The ordinary evaluation path leaves it `null` and
42
+ * builds references exactly as before.
43
+ */
44
+ _setReadHook(hook: ReadHook | null): void;
45
+ /**
46
+ * @hidden
47
+ * Arms (or, with `null`, disarms) the hook dynamic-branch references report to while no read
48
+ * hook is armed. See {@link _dynamicRead}.
49
+ */
50
+ _setDynamicReadHook(hook: ReadHook | null): void;
20
51
  /**
21
52
  * @hidden
22
53
  *
@@ -100,6 +131,14 @@ export declare class CalculationContext implements IFormulaContext {
100
131
  * A caller that reads a WINDOW rather than returning a reference - `SUMIF`'s `sum_range`,
101
132
  * `LOOKUP`'s `result_vector`, both anchor-plus-length - goes through
102
133
  * {@link getResizedReference} instead: Excel reads the part that fits rather than failing.
134
+ *
135
+ * This is the one place a reference is built on a formula's behalf, so it is where the read
136
+ * hook attaches: while {@link _onRead} is armed the reference is built over a
137
+ * {@link ReadObservedGrid} and every value it (or a view derived from it) opens is reported.
138
+ * Unarmed, a static reference's grid is used as is — the ordinary path pays nothing, not even a
139
+ * branch per read — while a `dynamic` one (the result of `OFFSET`/`INDIRECT`/`INDEX`, the rare
140
+ * path) reports to {@link _dynamicRead} when that is armed: a dynamic read that lands on the
141
+ * evaluating cell is a cycle on any path (design §5).
103
142
  */
104
143
  private _toReference;
105
144
  /** @inheritdoc IFormulaContext.getAddress */
@@ -0,0 +1,90 @@
1
+ import { Scalar } from '@sheetxl/primitives';
2
+ import { Direction, RangeAxis, CellCoords, RangeCoords } from '@sheetxl/utils';
3
+ import { IGrid, ISparseGrid, Tuple } from '../../collections';
4
+ /**
5
+ * Receives every value read a formula makes while a read hook is armed.
6
+ *
7
+ * @remarks
8
+ * A single-cell read reports a 1x1 rectangle; a block read (iteration, runs, bounded tuples)
9
+ * reports the rectangle it was asked for — the cells it *may* open — because a sparse iterator
10
+ * cannot tell an empty cell from a formula cell whose value is not there yet, and the second is
11
+ * exactly the read a cycle check must see. Coordinates are absolute and closed.
12
+ *
13
+ * The hook may throw; the throw propagates through the reading function up to the evaluation
14
+ * that armed it. Nothing is reported for constructing a reference, for its coords or size, or for
15
+ * a copy made to hold derived values.
16
+ */
17
+ export type ReadHook = (gridId: string, rowStart: number, colStart: number, rowEnd: number, colEnd: number) => void;
18
+ /**
19
+ * An `ISparseGrid` that reports every value access on an inner grid to a {@link ReadHook}.
20
+ *
21
+ * @remarks
22
+ * Every `ReferenceRange` a formula receives reads its cells through the grid it was built over
23
+ * and never touches the sheet directly, so wrapping that grid observes every value read the
24
+ * reference makes — through any `Range` view derived from it, since views share the grid.
25
+ *
26
+ * `clone`/`cloneEmpty` hand back the inner grid's copy UNWRAPPED. A `Range` operation clones
27
+ * its grid only as scratch space for a derived result (`fill`, `map`, a scalar broadcast) and
28
+ * overwrites what it later reads back; the coordinates in such a copy no longer name sheet
29
+ * cells (a broadcast writes its scalar at (0,0)), so reporting them would invent reads of A1.
30
+ *
31
+ * Writes are delegated verbatim; nothing on a reference's path writes to its grid.
32
+ */
33
+ export declare class ReadObservedGrid implements ISparseGrid<Scalar> {
34
+ /**
35
+ * Number of wrappers constructed since module load.
36
+ *
37
+ * @remarks
38
+ * A pass that Kahn orders builds none; tests pin that the ordinary path stays unwrapped.
39
+ */
40
+ static created: number;
41
+ protected readonly _inner: ISparseGrid<Scalar>;
42
+ protected readonly _gridId: string;
43
+ protected readonly _onRead: ReadHook;
44
+ constructor(inner: ISparseGrid<Scalar>, gridId: string, onRead: ReadHook);
45
+ /** The grid being observed. */
46
+ getInner(): ISparseGrid<Scalar>;
47
+ /**
48
+ * Reports a block read. Missing sides of a partial bound are taken from the grid's maximum
49
+ * extent, then from its data extent; a grid with neither has nothing to read.
50
+ */
51
+ protected _reportBounds(bounds: Partial<RangeCoords> | null | undefined): void;
52
+ /** {@inheritDoc IGrid.getValueAt} */
53
+ getValueAt(row: number, column: number): Scalar;
54
+ /** {@inheritDoc ISparseGrid.getRuns} */
55
+ getRuns(options?: ISparseGrid.RunIteratorOptions): ISparseGrid.RunIterableIterator<Scalar>;
56
+ /** {@inheritDoc IGrid.entries} */
57
+ entries(options?: IGrid.IteratorOptions): IGrid.EntryIterator<Scalar>;
58
+ /** {@inheritDoc IGrid.values} */
59
+ values(options?: IGrid.IteratorOptions): IGrid.ValueIterator;
60
+ /** {@inheritDoc IGrid.keys} */
61
+ keys(options?: IGrid.IteratorOptions): IGrid.KeyIterator;
62
+ /** {@inheritDoc IGrid.getValues} */
63
+ getValues(coords?: RangeCoords): Tuple.BoundedTuples<Scalar> | null;
64
+ /** {@inheritDoc IGrid.copyTo} */
65
+ copyTo(destination: IGrid, topLeft: CellCoords, from: RangeCoords): void;
66
+ /** {@inheritDoc IGrid.getAxis} */
67
+ getAxis(): RangeAxis;
68
+ /** {@inheritDoc IGrid.getCount} */
69
+ getCount(): number;
70
+ /** {@inheritDoc IGrid.getCoords} */
71
+ getCoords(): RangeCoords | null;
72
+ /** {@inheritDoc IGrid.getMaxCoords} */
73
+ getMaxCoords(): RangeCoords | null;
74
+ /** {@inheritDoc IGrid.clone} */
75
+ clone(cloneKey?: any): this;
76
+ /** {@inheritDoc IGrid.cloneEmpty} */
77
+ cloneEmpty(cloneKey?: any): this;
78
+ /** {@inheritDoc IGrid.setValues} */
79
+ setValues(values: Tuple.GridTuple<Scalar>): this;
80
+ /** {@inheritDoc IGrid.setValueAt} */
81
+ setValueAt(row: number, column: number, value: Scalar): void;
82
+ /** {@inheritDoc IGrid.delete} */
83
+ delete(coords: RangeCoords | null): boolean;
84
+ /** {@inheritDoc IGrid.clear} */
85
+ clear(): void;
86
+ /** {@inheritDoc IGrid.shift} */
87
+ shift(coords: RangeCoords, direction: Direction): boolean;
88
+ get [Symbol.toStringTag](): string;
89
+ }
90
+ //# sourceMappingURL=_ReadObservedGrid.d.ts.map
@@ -124,12 +124,28 @@ export interface ICell {
124
124
  *
125
125
  * @remarks
126
126
  * Warnings differ from errors in that they may alter the display of the cell's value or type.
127
+ * A cell in a reference cycle, or downstream of one, carries one here — the text form of
128
+ * {@link getCircularReference}: the walk from this cell around the cycle and back
129
+ * ("Circular reference: A1 → B1 → A1"), or "Reads a circular reference at A1".
127
130
  */
128
131
  getWarnings(): readonly string[];
129
132
  /**
130
133
  * Retrieves any errors attached to the cell.
131
134
  */
132
135
  getErrors(): readonly string[];
136
+ /**
137
+ * The reference cycle this cell is in, or downstream of — or `null` when it is neither.
138
+ *
139
+ * @remarks
140
+ * Evaluated state, beside the value: a cell in a cycle, and every cell that reads one, is `0`
141
+ * (Excel, iterative calculation off), and this is the only thing that says why. Ask the cycle
142
+ * whether this cell is a member or a reader ({@link ICalculation.ICircularReference.isMember})
143
+ * and, under iterative calculation, whether it converged.
144
+ *
145
+ * The range-level view is `ICellRange.Feature.Circular` — `getCounts` for how many cells,
146
+ * `getRegions` for which, each region carrying this same object as its payload.
147
+ */
148
+ getCircularReference(): ICalculation.ICircularReference | null;
133
149
  /**
134
150
  * Returns the style information applied to the cell.
135
151
  *
@@ -2191,11 +2191,20 @@ export declare namespace ICellRange {
2191
2191
  /** Cells inside a dynamic-array spill zone. Writing into one is a real failure mode. */
2192
2192
  readonly Spills: "spills";
2193
2193
  /**
2194
- * Evaluated state: cells whose calculation itself failed — mostly circular references.
2195
- * Distinct from {@link Feature.Error}: `#DIV/0!` is a successfully calculated error VALUE
2196
- * (the `Error` kind); `CalcError` is the engine failing to evaluate at all.
2194
+ * Evaluated state: cells whose calculation itself failed. Distinct from
2195
+ * {@link Feature.Error}: `#DIV/0!` is a successfully calculated error VALUE (the `Error`
2196
+ * kind); `CalcError` is the engine failing to evaluate at all. A reference cycle is not a
2197
+ * failure — its cells evaluate, to `0` — and is {@link Feature.Circular}.
2197
2198
  */
2198
2199
  readonly CalcError: "calcError";
2200
+ /**
2201
+ * Evaluated state: cells in a reference cycle, or downstream of one. Both evaluate to `0`
2202
+ * (Excel, iterative calculation off) with nothing else to show for it — this is the marker.
2203
+ * Regions group by cycle and by kind (`member` | `downstream`), so a block that reads one bad
2204
+ * cell is ONE region, and each region's payload is the cycle itself
2205
+ * (`ICalculation.ICircularReference` — members, counts, whether iteration settled it).
2206
+ */
2207
+ readonly Circular: "circular";
2199
2208
  /** Direct fill. */
2200
2209
  readonly Fill: "fill";
2201
2210
  /** Direct borders. */
@@ -163,21 +163,41 @@ export declare abstract class AnchoredConditional<STATE extends AnchoredConditio
163
163
  protected _rebaseConditionFormulas(json: any, from: IRange.CellCoords, to: IRange.CellCoords): boolean | null;
164
164
  /**
165
165
  * The extend half of a paste: fold the pasted `ranges` into THIS live rule — coalescing
166
- * into clean rectangles where the union is exact — rather than minting a duplicate.
166
+ * into one clean rectangle — rather than minting a duplicate.
167
167
  *
168
168
  * @param ranges The pasted images of the rule's marked areas (already tiled/clipped).
169
169
  * @param jsonAtMark `JSON.stringify` of the rule's `toJSON()` at mark time.
170
- * @returns `false` when this rule can no longer absorb the paste — deleted, or its
171
- * definition changed since the mark — and the caller must clone instead.
170
+ * @returns `false` when this rule cannot absorb the paste — deleted, its definition changed
171
+ * since the mark, or the union would move the anchor — and the caller must clone instead.
172
172
  *
173
173
  * @remarks
174
174
  * Merging is provenance-keyed: only THE rule the areas were copied from extends, which is
175
- * what keeps manually authored duplicates separate. When coalescing would move the anchor
176
- * cell (first range's top-left), formulas rebase ({@link _rebaseAnchorFormulas}); if the
177
- * rebase refuses, the new cells append as separate areas so the anchor stays put.
175
+ * what keeps manually authored duplicates separate.
176
+ *
177
+ * On top of provenance, a paste merges only when the union is a single rectangle whose
178
+ * top-left is still the rule's anchor. That is Excel's rule (desktop and online alike): a
179
+ * paste flush below or to the right of the applies-to merges into it, while one above, to
180
+ * the left, or with a gap mints a separate rule at top priority. The shape of it is that
181
+ * PASTE NEVER MOVES THE ANCHOR — growing down or right leaves the stored formula's frame
182
+ * alone, whereas growing up or left forces a rebase, which Excel is only willing to do for
183
+ * autofill. Hence fill merges in all four directions and paste in two.
178
184
  * @internal
179
185
  */
180
186
  _extendPastedRanges(ranges: readonly IRange.Coords[], jsonAtMark: string): boolean;
187
+ /**
188
+ * Re-anchors a freshly pasted CLONE, whose formulas still carry the SOURCE rule's frame, to
189
+ * its own anchor — the shift Excel applies when a copied rule lands as a new rule (copying
190
+ * `F5:F10`/`G5>5` to `F20` stores `G20>5`).
191
+ *
192
+ * The shift is source-anchor to clone-anchor; the hop through the copied cell cancels, since
193
+ * relative offsets are preserved by both halves of it.
194
+ *
195
+ * A rebase that cannot survive the move leaves the formulas as authored — the wrong frame,
196
+ * but live, which beats a rule of `#REF!`. Excel never hits this: it wraps modulo the sheet
197
+ * instead, the same divergence the io layer converts across.
198
+ * @internal
199
+ */
200
+ _rebaseClonedAnchor(anchorFrom: IRange.Coords): void;
181
201
  /**
182
202
  * The geometry half of {@link _extendPastedRanges}, shared with autofill (which needs no
183
203
  * liveness or definition guards — the rule was read live inside the fill's transaction):
@@ -134,7 +134,14 @@ export declare class ConditionalFormat extends AnchoredConditional<State, Commit
134
134
  /** @internal */
135
135
  protected _createSpatial(coords: IRange.Coords): ISpatialMap.IUpdatableValue;
136
136
  /** {@inheritDoc IConditionalFormat.update} */
137
- update(properties: IConditionalFormat.Modifiers, options?: ITransaction.OperationOptions): this;
137
+ update(properties: IConditionalFormat.Modifiers | IConditionalFormat, options?: ITransaction.OperationOptions): this;
138
+ /**
139
+ * The modifiers that make one rule's definition another's: every mutually-exclusive key is
140
+ * named, so the target's old shape (`scale` vs `condition`+`style`) is cleared rather than
141
+ * merged with.
142
+ * @internal
143
+ */
144
+ static replaceModifiers(json: IConditionalFormat.JSON | null): IConditionalFormat.Modifiers;
138
145
  /** {@inheritDoc IConditionalFormat.toJSON} */
139
146
  toJSON(): IConditionalFormat.JSON | null;
140
147
  /** @internal */
@@ -123,8 +123,11 @@ export interface IConditionalFormat extends IAnchored, ICondition.Stateful, IPro
123
123
  * Only the keys named are touched. An explicit `null` **clears** a key — required when switching
124
124
  * a rule between its two shapes, since `condition`+`style` and `scale` are mutually exclusive
125
125
  * (setting one side also clears the other unless the caller named both).
126
+ *
127
+ * Passing another rule takes its whole definition — every key, cleared where the other rule
128
+ * has none — so the shape switches with it. The anchor is not part of it.
126
129
  */
127
- update(properties: IConditionalFormat.Modifiers, options?: ITransaction.OperationOptions): this;
130
+ update(properties: IConditionalFormat.Modifiers | IConditionalFormat, options?: ITransaction.OperationOptions): this;
128
131
  /**
129
132
  * Returns a snapshot of the conditional that can be used for copying and archiving.
130
133
  */
@@ -1,7 +1,7 @@
1
1
  import { ICellRange, ICellRanges } from '../cellRange';
2
2
  import { ICollection } from '../type';
3
+ import { IAnchored } from '../anchored';
3
4
  import { IConditionalFormat } from './IConditionalFormat';
4
- import { ITransaction } from '../transaction';
5
5
  /**
6
6
  * Holds a collection of {@link IConditionalFormat}s.
7
7
  */
@@ -38,8 +38,12 @@ export interface IConditionalFormatCollection extends ICollection<IConditionalFo
38
38
  export declare namespace IConditionalFormatCollection {
39
39
  /**
40
40
  * Options for adding a {@link IConditionalFormat}.
41
+ *
42
+ * @remarks
43
+ * `replaceExisting` redefines the rule at `index` only when it is a scale rule of the same
44
+ * kind on exactly the same ranges — see {@link IAnchored.AddOptions.replaceExisting}.
41
45
  */
42
- interface AddOptions extends IConditionalFormat.Properties, ITransaction.OperationOptions {
46
+ interface AddOptions extends IConditionalFormat.Properties, IAnchored.AddOptions {
43
47
  }
44
48
  /**
45
49
  * Options for searching for {@link IConditionalFormat}s.
@@ -1,6 +1,6 @@
1
- import { ITransaction } from '../transaction';
2
1
  import { ICollection } from '../type';
3
2
  import { ICellRange, ICellRanges } from '../cellRange';
3
+ import { IAnchored } from '../anchored';
4
4
  import { IDataValidation } from './IDataValidation';
5
5
  /**
6
6
  * Holds a collection of {@link IDataValidation}s.
@@ -38,8 +38,12 @@ export interface IDataValidationCollection extends ICollection<IDataValidation>
38
38
  export declare namespace IDataValidationCollection {
39
39
  /**
40
40
  * Options for adding a data validation to the collection.
41
+ *
42
+ * @remarks
43
+ * `replaceExisting` redefines the validation at `index` when it covers exactly the same ranges —
44
+ * see {@link IAnchored.AddOptions.replaceExisting}.
41
45
  */
42
- interface AddOptions extends IDataValidation.Properties, ITransaction.OperationOptions {
46
+ interface AddOptions extends IDataValidation.Properties, IAnchored.AddOptions {
43
47
  }
44
48
  interface GetItemsOptions {
45
49
  /**
@@ -49,7 +49,9 @@ export interface IHyperlink {
49
49
  * @remarks
50
50
  * This has no counterpart in Excel; it is ours and applies to links opened in a browser.
51
51
  *
52
- * @defaultValue `_self` for a location within this workbook, otherwise `_blank`.
52
+ * @defaultValue `_self` for a location within this workbook or a `mailto:`/`tel:`/`sms:`
53
+ * address (handled by another application, so there is nothing to show in a new tab),
54
+ * otherwise `_blank`.
53
55
  */
54
56
  getTarget(): string;
55
57
  /**
@@ -1,5 +1,11 @@
1
1
  import { ITypes } from '../type';
2
2
  import { IHyperlink } from './IHyperlink';
3
+ /**
4
+ * `true` for an address the browser hands to another application (`mailto:`, `tel:`, `sms:`)
5
+ * rather than rendering.
6
+ * @internal
7
+ */
8
+ export declare const isHandlerScheme: (address: string) => boolean;
3
9
  export declare class Hyperlink implements IHyperlink {
4
10
  protected _t: () => string;
5
11
  protected _p: IHyperlink.Properties;
@@ -1,6 +1,11 @@
1
1
  import { HostDetails } from './_Utils';
2
2
  import { LicenseDetails } from '../../license';
3
3
  export declare function getHostDetails(): Promise<HostDetails>;
4
+ /**
5
+ * Only the loopback host is a dev environment. A dev *build* served on any other host (a LAN IP,
6
+ * a tunnel) is checked exactly like production: license domains apply and an evaluation shows
7
+ * the watermark.
8
+ */
4
9
  export declare function isDevEnv(): Promise<boolean>;
5
10
  /**
6
11
  * The runtime location - the current page url in the browser.
@@ -8,6 +8,11 @@ export interface LicenseDetails {
8
8
  getCpuCount(): number;
9
9
  getMemory(): number;
10
10
  isEval(): boolean;
11
+ /**
12
+ * `true` when the licensed product may run `feature` without the license watermark: a valid
13
+ * license with no exceptions, or an evaluation on localhost / in a dev build. An evaluation on
14
+ * any other host answers `false` so the watermark shows.
15
+ */
11
16
  isValidFor: (feature: string) => boolean;
12
17
  getDeveloperCount(): number;
13
18
  getType(): string;
@@ -0,0 +1,20 @@
1
+ /**
2
+ * Base of the control-flow signals the calculation engine throws THROUGH a formula's evaluation.
3
+ *
4
+ * @remarks
5
+ * A demand evaluation (a cell the topological sort could not order) reads its precedents lazily;
6
+ * a read that lands on a cell not yet calculated suspends the formula so that cell can go first,
7
+ * and a read that lands on a cell already suspended is a reference cycle. Both are raised from
8
+ * inside the read and unwind the whole evaluation to the executor, which is the only catcher
9
+ * that knows what to do with them.
10
+ *
11
+ * Every catch site on the evaluation path that turns an arbitrary throw into a `#VALUE!` — a
12
+ * function call, a lambda body, a lift over range members, the commit-site dereference — must
13
+ * let a signal pass: {@link isCalcSignal}. A signal is not an error and never becomes a value.
14
+ */
15
+ export declare class CalcSignal {
16
+ readonly isCalcSignal: true;
17
+ }
18
+ /** `true` for a {@link CalcSignal} — a throw that must be rethrown, never turned into a value. */
19
+ export declare const isCalcSignal: (e: unknown) => e is CalcSignal;
20
+ //# sourceMappingURL=CalcSignal.d.ts.map