@ex-grid/pivot 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
@@ -2998,7 +2998,7 @@ import {
2998
2998
  } from "@ex-grid/pivot-engine";
2999
2999
 
3000
3000
  // src/report-find.ts
3001
- import { findMatches } from "@ex-grid/core";
3001
+ import { findAllPage, findMatches } from "@ex-grid/core";
3002
3002
  var findBlockCells = 2e4;
3003
3003
  var notFound = Object.freeze({ kind: "answered", answer: Object.freeze({ found: false }) });
3004
3004
  var notHeld = Object.freeze({ kind: "notHeld" });
@@ -3067,6 +3067,81 @@ async function findInReport(source, metadata, request, signal) {
3067
3067
  }
3068
3068
  return notFound;
3069
3069
  }
3070
+ var ReportFindAllMatches = class {
3071
+ #columns;
3072
+ #ordinals;
3073
+ #texts;
3074
+ constructor(columns, ordinals, texts) {
3075
+ this.#columns = columns;
3076
+ this.#ordinals = ordinals;
3077
+ this.#texts = texts;
3078
+ }
3079
+ /** How many cells match. */
3080
+ get total() {
3081
+ return this.#ordinals.length;
3082
+ }
3083
+ /** The entries from `start`, `count` of them or every one left, under `rowSequenceVersion`. */
3084
+ page(start, count, rowSequenceVersion) {
3085
+ if (!Number.isInteger(start) || start < 0) throw new RangeError(`A Find All page starts at an entry at or after 0, not ${String(start)}.`);
3086
+ if (!Number.isInteger(count) || count < 1) throw new RangeError(`A Find All page asks for 1 entry or more, not ${String(count)}.`);
3087
+ const columns = this.#columns.length;
3088
+ const matches = this.#ordinals.slice(start, start + count).map((ordinal, i) => ({
3089
+ row: Math.floor(ordinal / columns),
3090
+ column: elementAt(this.#columns, ordinal % columns),
3091
+ text: elementAt(this.#texts, start + i)
3092
+ }));
3093
+ return findAllPage(this.total, matches, rowSequenceVersion);
3094
+ }
3095
+ };
3096
+ async function findAllInReport(source, metadata, request, signal) {
3097
+ const rows = metadata.rowCount;
3098
+ const known = /* @__PURE__ */ new Set([...metadata.labelColumns.map((column) => column.name), ...metadata.valueColumns.map((column) => column.name)]);
3099
+ const read = request.columns.flatMap((name, position) => known.has(name) ? [{ name, position }] : []);
3100
+ const columns = request.columns.length;
3101
+ const ordinals = [];
3102
+ const texts = [];
3103
+ const done = () => Object.freeze({ kind: "answered", matches: new ReportFindAllMatches(Object.freeze([...request.columns]), ordinals, texts) });
3104
+ if (request.text === "" || rows === 0 || read.length === 0) return done();
3105
+ const { scope } = request;
3106
+ const names = Object.freeze(read.map((column) => column.name));
3107
+ const blockRows = Math.max(1, Math.floor(findBlockCells / names.length));
3108
+ let first = scope === void 0 ? 0 : rows - 1;
3109
+ let last = scope === void 0 ? rows - 1 : 0;
3110
+ if (scope !== void 0) {
3111
+ for (const range of scope) {
3112
+ first = Math.min(first, Math.max(0, range.topRow));
3113
+ last = Math.max(last, Math.min(rows - 1, range.topRow + range.rowCount - 1));
3114
+ }
3115
+ }
3116
+ for (let top = first; top <= last; top += blockRows) {
3117
+ signal.throwIfAborted();
3118
+ const bottom = Math.min(last, top + blockRows - 1);
3119
+ const answer = await source.copy(Object.freeze({
3120
+ version: metadata.version,
3121
+ columns: names,
3122
+ ranges: Object.freeze([Object.freeze({ top, left: 0, bottom, right: names.length - 1 })]),
3123
+ maxCells: (bottom - top + 1) * names.length
3124
+ }), signal);
3125
+ signal.throwIfAborted();
3126
+ if (answer.refusal?.kind === "reportVersionNotHeld") return notHeld;
3127
+ if (answer.refusal !== void 0) return Object.freeze({ kind: "refused", refusal: answer.refusal });
3128
+ const block = answer.blocks[0];
3129
+ if (answer.version !== metadata.version || answer.blocks.length !== 1 || block === void 0 || block.rows.length !== bottom - top + 1 || block.rows.some((cells) => cells.length !== names.length)) {
3130
+ return invalid;
3131
+ }
3132
+ for (let row = top; row <= bottom; row++) {
3133
+ const cells = elementAt(block.rows, row - top);
3134
+ read.forEach(({ position }, index) => {
3135
+ if (scope !== void 0 && !scope.some((range) => row >= range.topRow && row < range.topRow + range.rowCount && position >= range.leftColumn && position < range.leftColumn + range.columnCount)) return;
3136
+ const { text } = elementAt(cells, index);
3137
+ if (!findMatches(text, request)) return;
3138
+ ordinals.push(row * columns + position);
3139
+ texts.push(text);
3140
+ });
3141
+ }
3142
+ }
3143
+ return done();
3144
+ }
3070
3145
 
3071
3146
  // src/report-summary.ts
3072
3147
  import { answeredSummary, declinedSummary, summaryFigureOrder } from "@ex-grid/core";
@@ -3360,10 +3435,24 @@ function reportRows(request) {
3360
3435
  request.findGivenUp(read);
3361
3436
  throw new DOMException("The Find step over the report was given up.", "AbortError");
3362
3437
  };
3438
+ let listed;
3439
+ const findAll = async (asked, _query, signal) => {
3440
+ const key = JSON.stringify([asked.text, asked.matchCase, asked.wholeCell, asked.scope, asked.columns]);
3441
+ if (listed?.key !== key) {
3442
+ const read = await findAllInReport(request.source, answered.metadata, asked, signal);
3443
+ if (read.kind !== "answered") {
3444
+ request.findGivenUp(read);
3445
+ throw new DOMException("The Find All over the report was given up.", "AbortError");
3446
+ }
3447
+ listed = { key, matches: read.matches };
3448
+ }
3449
+ return listed.matches.page(asked.start, asked.count, asked.rowSequenceVersion);
3450
+ };
3363
3451
  return GridSource.fetch(fetch, {
3364
3452
  rowKey: reportRowKey,
3365
3453
  readAheadRows: 60,
3366
3454
  find,
3455
+ findAll,
3367
3456
  // The Selection Summary is the report source's, over the report the selection was made on (ADR-0130).
3368
3457
  summarize: (summary, _query, signal) => summarizeReport(request.source, version, summary, request.words(), signal),
3369
3458
  // A Window of another report is never shown beside this one's rows: the pivot asks again, and the grid
@@ -3865,6 +3954,11 @@ var PivotView = class {
3865
3954
  #counts;
3866
3955
  #countsAsked;
3867
3956
  #grid;
3957
+ // The report grid's Settled Mark, held while a question under the loading indication is out (ADR-0220 section 1):
3958
+ // the report that question brings is the effect of the move, the Consumer's layout or the Refresh that asked it,
3959
+ // and a reading taken before it lands reads the report before. A quiet question a source's notice asked holds
3960
+ // nothing, as it shows no loading either: a live report would otherwise never settle.
3961
+ #loadingHold;
3868
3962
  #rows;
3869
3963
  // The grid's columns as last drawn, whose names a copy asks the report source for.
3870
3964
  #gridColumns = [];
@@ -4203,6 +4297,7 @@ var PivotView = class {
4203
4297
  this.#generation++;
4204
4298
  this.#asked?.controller.abort();
4205
4299
  this.#asked = void 0;
4300
+ this.#holdWhileLoading();
4206
4301
  this.#countsAsked?.abort();
4207
4302
  this.#placing?.();
4208
4303
  this.#grid?.destroy();
@@ -4393,8 +4488,18 @@ var PivotView = class {
4393
4488
  toggled: focusOn
4394
4489
  };
4395
4490
  this.#asked = question;
4491
+ this.#holdWhileLoading();
4396
4492
  void this.#run(question);
4397
4493
  }
4494
+ // Holds the report grid's Settled Mark while a question under the loading indication is out, and lets it go once
4495
+ // none is: called wherever the question out or the grid changes, and by every draw, which follows each landing
4496
+ // after the grid has the report it brought.
4497
+ #holdWhileLoading() {
4498
+ const grid = this.#loading() ? this.#grid : void 0;
4499
+ if (this.#loadingHold?.grid === grid) return;
4500
+ this.#loadingHold?.release();
4501
+ this.#loadingHold = grid === void 0 ? void 0 : { grid, release: grid.holdSettled() };
4502
+ }
4398
4503
  async #run(question) {
4399
4504
  const current = () => question.generation === this.#generation && !this.#destroyed;
4400
4505
  let update;
@@ -4659,6 +4764,7 @@ var PivotView = class {
4659
4764
  if (answered === void 0 || !this.#reportDrawn) {
4660
4765
  this.#grid?.destroy();
4661
4766
  this.#grid = void 0;
4767
+ this.#holdWhileLoading();
4662
4768
  return;
4663
4769
  }
4664
4770
  const { answer, question } = answered;
@@ -4796,6 +4902,7 @@ var PivotView = class {
4796
4902
  if (this.#grid === void 0) {
4797
4903
  if (this.#gridRoot.parentNode !== this.#sheet) this.#sheet.prepend(this.#gridRoot);
4798
4904
  this.#grid = this.#mountGrid(this.#gridRoot, options);
4905
+ this.#holdWhileLoading();
4799
4906
  } else {
4800
4907
  this.#grid.update(options);
4801
4908
  }
@@ -5677,6 +5784,7 @@ var PivotView = class {
5677
5784
  }
5678
5785
  #draw() {
5679
5786
  if (this.#destroyed) return;
5787
+ this.#holdWhileLoading();
5680
5788
  const words = this.#words;
5681
5789
  const layout = this.#paneLayout;
5682
5790
  const fields = this.#options.source.fields;