@ex-grid/sheet 0.2.0-beta.3 → 0.2.0-rc.1

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.
package/dist/index.js CHANGED
@@ -646,7 +646,11 @@ function overlap(a, b) {
646
646
  }
647
647
 
648
648
  // src/sheet-find.ts
649
- import { findMatches, replacedEntry } from "@ex-grid/core";
649
+ import {
650
+ findAllPage,
651
+ findMatches,
652
+ replacedEntry
653
+ } from "@ex-grid/core";
650
654
  import { CellAddress as CellAddress6, Sheet as Sheet3 } from "@ex-grid/sheet-engine";
651
655
  function sheetFindStep(sheet, request) {
652
656
  if (request.text === "" || request.columns.length === 0) return { found: false };
@@ -670,6 +674,69 @@ function sheetFindStep(sheet, request) {
670
674
  }
671
675
  return found;
672
676
  }
677
+ function sheetFindAll(sheet, request, rowSequenceVersion) {
678
+ const { start, count } = request;
679
+ if (!Number.isInteger(start) || start < 0) throw new RangeError(`A Find All page starts at an entry at or after 0, not ${String(start)}.`);
680
+ if (!Number.isInteger(count) || count < 1) throw new RangeError(`A Find All page asks for 1 entry or more, not ${String(count)}.`);
681
+ const positions = positionsOf(request.columns);
682
+ const columnCount2 = request.columns.length;
683
+ const ordinals = [];
684
+ if (request.text !== "") {
685
+ for (const address of sheet.entryAddresses) {
686
+ const position = positions.get(address.column);
687
+ if (position === void 0) continue;
688
+ if (request.scope !== void 0 && !inScope(request.scope, address.row, position)) continue;
689
+ if (sheetCellMatches(sheet, address, request)) ordinals.push(address.row * columnCount2 + position);
690
+ }
691
+ }
692
+ ordinals.sort((a, b) => a - b);
693
+ const matches = ordinals.slice(start, start + count).map((ordinal) => {
694
+ const row = Math.floor(ordinal / columnCount2);
695
+ const position = ordinal % columnCount2;
696
+ const column = columnName(request.columns, position);
697
+ const sheetColumn = CellAddress6.tryParseColumn(column);
698
+ if (sheetColumn === void 0) throw new Error(`Internal: '${column}' names no Sheet column.`);
699
+ return { row, column, text: shownTextOf(sheet, new CellAddress6(row, sheetColumn)) };
700
+ });
701
+ return findAllPage(ordinals.length, matches, rowSequenceVersion);
702
+ }
703
+ var SheetWorkbookMatches = class {
704
+ #sheets;
705
+ #sheetOf;
706
+ #ordinals;
707
+ constructor(sheets, pattern) {
708
+ const sheetOf = [];
709
+ const ordinals = [];
710
+ if (pattern.text !== "") {
711
+ sheets.forEach((sheet, index) => {
712
+ const found = [];
713
+ for (const address of sheet.entryAddresses) {
714
+ if (sheetCellMatches(sheet, address, pattern)) found.push(address.row * Sheet3.columnCount + address.column);
715
+ }
716
+ found.sort((a, b) => a - b);
717
+ for (const ordinal of found) {
718
+ sheetOf.push(index);
719
+ ordinals.push(ordinal);
720
+ }
721
+ });
722
+ }
723
+ this.#sheets = sheets;
724
+ this.#sheetOf = sheetOf;
725
+ this.#ordinals = ordinals;
726
+ }
727
+ /** How many cells match. */
728
+ get count() {
729
+ return this.#ordinals.length;
730
+ }
731
+ /** Match `index`: its Sheet and its cell. */
732
+ at(index) {
733
+ const sheetIndex = this.#sheetOf[index];
734
+ const ordinal = this.#ordinals[index];
735
+ const sheet = sheetIndex === void 0 ? void 0 : this.#sheets[sheetIndex];
736
+ if (sheet === void 0 || ordinal === void 0) throw new RangeError(`The Workbook's Find All holds ${String(this.count)} matches, not one at ${String(index)}.`);
737
+ return { sheet, address: new CellAddress6(Math.floor(ordinal / Sheet3.columnCount), ordinal % Sheet3.columnCount) };
738
+ }
739
+ };
673
740
  function sheetFindStepWorkbook(sheets, shown, request) {
674
741
  if (request.text === "" || request.columns.length === 0) return void 0;
675
742
  const positions = positionsOf(request.columns);
@@ -814,7 +881,7 @@ function sheetFindPanelSlot(host) {
814
881
  input.checked = host.within() === within2;
815
882
  input.setAttribute("data-ex-claims", "click");
816
883
  input.addEventListener("change", () => {
817
- if (input.checked) host.chooseWithin(within2);
884
+ if (input.checked) host.chooseWithin(within2, context);
818
885
  });
819
886
  const element = doc.createElement("label");
820
887
  element.append(input, label(id));
@@ -835,7 +902,10 @@ function sheetFindPanelSlot(host) {
835
902
  );
836
903
  const steps = doc.createElement("div");
837
904
  steps.className = "ex-popover-actions";
838
- steps.append(button("ex-find-previous", findPanelLabelIds.previous, context.previous), button("ex-find-next", findPanelLabelIds.next, context.next));
905
+ const findAll = button("ex-find-all-button", findPanelLabelIds.findAll, () => {
906
+ host.findAll(context);
907
+ });
908
+ steps.append(findAll, button("ex-find-previous", findPanelLabelIds.previous, context.previous), button("ex-find-next", findPanelLabelIds.next, context.next));
839
909
  const outcome = doc.createElement("div");
840
910
  outcome.className = "ex-find-outcome";
841
911
  outcome.setAttribute("role", "status");
@@ -843,6 +913,7 @@ function sheetFindPanelSlot(host) {
843
913
  let replace;
844
914
  const paint = () => {
845
915
  view = context.view();
916
+ if (findAll.hidden === view.findAllShown) findAll.hidden = !view.findAllShown;
846
917
  if (matchCase.box.checked !== view.matchCase) matchCase.box.checked = view.matchCase;
847
918
  if (wholeCell.box.checked !== view.wholeCell) wholeCell.box.checked = view.wholeCell;
848
919
  if (view.replaceShown && replace === void 0) {
@@ -1029,6 +1100,16 @@ var SheetSource = class {
1029
1100
  if (sheet === void 0) return Promise.reject(new DOMException("The step was asked of a Sheet shown before the last one.", "AbortError"));
1030
1101
  return this.#step(sheet, request);
1031
1102
  }
1103
+ /** A page of a Find All over the Sheet its Row Sequence Version names (ADR-0470 §7), as a step is answered: the
1104
+ * one shown, or the one before it. Asked under an older version, the list named rows of a Sheet no longer shown:
1105
+ * given up, never answered about cells nobody searched. Within the Workbook, the Sheet lists the matches itself. */
1106
+ findAll(request, signal) {
1107
+ signal.throwIfAborted();
1108
+ const before = this.#before;
1109
+ const sheet = request.rowSequenceVersion === this.#version ? this.#sheet : request.rowSequenceVersion === before?.version ? before.sheet : void 0;
1110
+ if (sheet === void 0) return Promise.reject(new DOMException("The Find All was asked of a Sheet shown before the last one.", "AbortError"));
1111
+ return Promise.resolve(sheetFindAll(sheet, request, request.rowSequenceVersion));
1112
+ }
1032
1113
  /** A Selection Summary over the Sheet its Row Sequence Version names (ADR-0130), as C#'s `SheetSummary` answers
1033
1114
  * one: the Values of the selected cells in Excel's doubles, the figures that read numbers written in the Focus
1034
1115
  * cell's Number Format, or the summary declined over the first refused cell. Asked under an older version, the
@@ -4986,6 +5067,7 @@ import {
4986
5067
  formulaHintAt,
4987
5068
  formulaPointAt,
4988
5069
  LinkedTableColumn,
5070
+ moveReference,
4989
5071
  referenceText
4990
5072
  } from "@ex-grid/sheet-engine";
4991
5073
  function sheetPointAt(text, caret2) {
@@ -5022,6 +5104,9 @@ function sheetReferenceText(range) {
5022
5104
  function sheetReferenceTextOn(range, shown, home) {
5023
5105
  return home === void 0 || home === shown ? sheetReferenceText(range) : referenceText(cellRangeOf(range), shown.name);
5024
5106
  }
5107
+ function sheetMoveReference(sheet, reference, range) {
5108
+ return moveReference(reference, cellRangeOf(range), sheet.workbook.size);
5109
+ }
5025
5110
  function cellRangeOf(range) {
5026
5111
  return new CellRange5(
5027
5112
  new CellAddress11(range.topRow, range.leftColumn),
@@ -5931,6 +6016,7 @@ var SheetView = class _SheetView {
5931
6016
  // and its views go with it, under a new Row Sequence Version, which drops the Selection and refuses what was aimed
5932
6017
  // at the old cells (ADR-0011, ADR-0142).
5933
6018
  #replaceWorkbook(opened, fromFile) {
6019
+ this.#dropWorkbookFindAll();
5934
6020
  this.#fileOpened = fromFile;
5935
6021
  this.#workbook = opened;
5936
6022
  this.#history.clear();
@@ -6074,6 +6160,8 @@ var SheetView = class _SheetView {
6074
6160
  // Formula is typed on, all of them; on another shown to point at its cells, those naming it (ADR-0331 §5).
6075
6161
  referencesIn: this.#referencesIn,
6076
6162
  onReferenceKeyColoursChanged: this.#onKeyColoursChanged,
6163
+ // An outline dragged by its edge or a corner square rewrites its Reference in its own form (ADR-0480).
6164
+ moveReference: this.#moveReference,
6077
6165
  // Point: the arrows and a press write a Reference where one can go, and F4 cycles its forms (ADR-0051).
6078
6166
  pointAt: sheetPointAt,
6079
6167
  referenceText: this.#referenceText,
@@ -6400,6 +6488,8 @@ var SheetView = class _SheetView {
6400
6488
  }
6401
6489
  // The Reference Point writes: bare on the Sheet the Formula is typed on, named with its Sheet on another (ADR-0331 §5).
6402
6490
  #referenceText = (range) => sheetReferenceTextOn(range, this.#source.sheet, this.#editHome);
6491
+ // A dragged Reference rewritten to name other cells of the Sheet shown, written as it was (ADR-0480).
6492
+ #moveReference = (reference, range) => sheetMoveReference(this.#source.sheet, reference, range);
6403
6493
  // The Sheet the open edit was opened on, once another Sheet has been shown while it is typed (ADR-0331 §5): its
6404
6494
  // Formula is committed there, and the edit's end shows it again.
6405
6495
  #editHome;
@@ -7095,6 +7185,8 @@ var SheetView = class _SheetView {
7095
7185
  // ---- Find Within (ADR-0332 §5, ADR-0331 §8) -------------------------------------------------------------------
7096
7186
  // Where the panel searches, as it last chose: kept across a close and a reopen, as the grid keeps the text.
7097
7187
  #findWithin = "sheet";
7188
+ // The panel a Find All over the Workbook was listed in, while its list may stand (ADR-0470 §7).
7189
+ #workbookFindAll;
7098
7190
  // Every answer that changes what the panel says moves this on: a step asked, the grid's Replace Request, a choice
7099
7191
  // of Within. The Sheet's own Replace All's outcome is said while nothing has moved it since, and the panel has not
7100
7192
  // been mounted again.
@@ -7119,14 +7211,23 @@ var SheetView = class _SheetView {
7119
7211
  within: () => this.#findWithin,
7120
7212
  // A choice of Within is a click taken in its place in the Input Order (ADR-0240): a step numbered before it
7121
7213
  // searches where the panel searched then, one numbered after it where it searches now.
7122
- chooseWithin: (within) => {
7214
+ chooseWithin: (within, context) => {
7123
7215
  this.#findWithin = within;
7124
7216
  this.#findMoved();
7217
+ context.dropFindAll();
7218
+ this.#workbookFindAll = void 0;
7219
+ },
7220
+ // Over the Sheet, the grid's list; over the Workbook, the Sheet's own, which the grid draws (ADR-0470 §7).
7221
+ findAll: (context) => {
7222
+ if (this.#findWithin === "workbook") context.listFindAll(() => this.#listWorkbook(context));
7223
+ else context.findAll();
7125
7224
  },
7126
7225
  // Over the Sheet, the grid's Replace Request; over the Workbook, the Sheet's own.
7127
7226
  replaceAll: (context) => {
7128
- if (this.#findWithin === "workbook") this.#replaceAllInWorkbook(context);
7129
- else context.replaceAll();
7227
+ if (this.#findWithin === "workbook") {
7228
+ this.#dropWorkbookFindAll();
7229
+ this.#replaceAllInWorkbook(context);
7230
+ } else context.replaceAll();
7130
7231
  },
7131
7232
  outcome: (context) => {
7132
7233
  const own = this.#ownFind;
@@ -7165,6 +7266,50 @@ var SheetView = class _SheetView {
7165
7266
  throw new DOMException("The match is on another Sheet, now shown with it selected.", "AbortError");
7166
7267
  });
7167
7268
  };
7269
+ /**
7270
+ * Find All over the Workbook (ADR-0470 §7), asked in the press's turn: every Sheet's matches, in tab order, each line
7271
+ * named by its Sheet and address (`Sheet2!B12`) and showing its cell's text, for the grid to draw. The Sheet holds
7272
+ * the cells, so it drops the list at any change to the Workbook.
7273
+ */
7274
+ #listWorkbook(context) {
7275
+ const view = context.view();
7276
+ const matches = new SheetWorkbookMatches(this.#workbook.sheets, { text: view.text, matchCase: view.matchCase, wholeCell: view.wholeCell });
7277
+ this.#workbookFindAll = context;
7278
+ return {
7279
+ count: matches.count,
7280
+ line: (index) => {
7281
+ const { sheet, address } = matches.at(index);
7282
+ return { where: referenceText2(new CellRange6(address), sheet.name), text: shownTextOf(sheet, address) };
7283
+ },
7284
+ choose: (index) => this.#chooseWorkbookMatch(matches.at(index))
7285
+ };
7286
+ }
7287
+ // A line of the Workbook's list chosen (ADR-0470 §4): a match on the Sheet shown is placed as a step's answer is;
7288
+ // one on another Sheet shows that Sheet with the cell selected, as a step over the Workbook does. While an edit is
7289
+ // open nothing moves, and the notice says why. Answers whether the Focus moved, so the list marks the line only then.
7290
+ #chooseWorkbookMatch({ sheet, address }) {
7291
+ if (this.#destroyed) return false;
7292
+ if (this.#editing) {
7293
+ this.#tell(this.#words.editIsOpen);
7294
+ return false;
7295
+ }
7296
+ const cell = { row: address.row, column: address.column };
7297
+ if (sheet === this.#source.sheet) {
7298
+ const grid = this.#grid;
7299
+ if (grid === void 0) throw new Error("Internal: the Workbook's Find All list was chosen from with no grid drawn.");
7300
+ return grid.placeMatch(cell, this.#source.snapshot().rowSequenceVersion);
7301
+ }
7302
+ this.#clearNotice();
7303
+ this.#showSheet(sheet, cell);
7304
+ this.#raiseDocument();
7305
+ return true;
7306
+ }
7307
+ // The Workbook's Find All list goes: the cells it was read from changed.
7308
+ #dropWorkbookFindAll() {
7309
+ const context = this.#workbookFindAll;
7310
+ this.#workbookFindAll = void 0;
7311
+ context?.dropFindAll();
7312
+ }
7168
7313
  /**
7169
7314
  * Replace All over the Workbook (ADR-0332 §5), from the panel's button in its place in the Input Order: every
7170
7315
  * cell of every Sheet whose Entry matches, all or nothing, as one step on the undo stack, which shows the Sheet it
@@ -7713,6 +7858,7 @@ var SheetView = class _SheetView {
7713
7858
  * the C# Sheet's does, since it changes Values and no format Format Cells read.
7714
7859
  */
7715
7860
  #changed(changes, raiseDocument = true, byUser = true) {
7861
+ this.#dropWorkbookFindAll();
7716
7862
  if (byUser) {
7717
7863
  this.#endFormatCells();
7718
7864
  this.#endChoices();