@ex-grid/core 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.d.ts +172 -0
- package/dist/index.js +1268 -193
- package/dist/index.js.map +4 -4
- package/ex-grid.min.css +3 -3
- package/ex-grid.min.css.map +1 -1
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -857,7 +857,23 @@ var findPanelLabelIds = Object.freeze({
|
|
|
857
857
|
/** The refused cells past those named, their count at `{count}`. */
|
|
858
858
|
replaceRefusedMore: "find-replace-refused-more",
|
|
859
859
|
/** Why a match in a column that is not Editable cannot be written. */
|
|
860
|
-
notEditable: "find-not-editable"
|
|
860
|
+
notEditable: "find-not-editable",
|
|
861
|
+
/** The Find All button (ADR-0470 §1). */
|
|
862
|
+
findAll: "find-all",
|
|
863
|
+
/** The list of a Find All's matches: its accessible name. */
|
|
864
|
+
findAllList: "find-all-list",
|
|
865
|
+
/** What a Find All that matched several cells says, their count at `{count}`. */
|
|
866
|
+
findAllFound: "find-all-found",
|
|
867
|
+
/** What a Find All that matched one cell says. */
|
|
868
|
+
findAllFoundOne: "find-all-found-one",
|
|
869
|
+
/** What a Find All that matched nothing says. */
|
|
870
|
+
findAllNone: "find-all-none",
|
|
871
|
+
/** Where a match in a row is, its row's number from 1 at `{row}` and its column's header at `{column}`. */
|
|
872
|
+
findAllInRow: "find-all-in-row",
|
|
873
|
+
/** Where a match in a row is, by the Consumer's label for the row at `{row}` and its column's header at `{column}`. */
|
|
874
|
+
findAllInLabelledRow: "find-all-in-labelled-row",
|
|
875
|
+
/** Where a match in a header is, the header's text at `{column}`. */
|
|
876
|
+
findAllInHeader: "find-all-in-header"
|
|
861
877
|
});
|
|
862
878
|
var findPanelWords = Object.freeze([
|
|
863
879
|
[findPanelLabelIds.title, "Find"],
|
|
@@ -879,7 +895,15 @@ var findPanelWords = Object.freeze([
|
|
|
879
895
|
[findPanelLabelIds.replaceRefused, "Nothing was replaced."],
|
|
880
896
|
[findPanelLabelIds.replaceRefusedCell, "Row {row}, {column}: {reason}."],
|
|
881
897
|
[findPanelLabelIds.replaceRefusedMore, "And {count} more."],
|
|
882
|
-
[findPanelLabelIds.notEditable, "this column cannot be edited"]
|
|
898
|
+
[findPanelLabelIds.notEditable, "this column cannot be edited"],
|
|
899
|
+
[findPanelLabelIds.findAll, "Find All"],
|
|
900
|
+
[findPanelLabelIds.findAllList, "Matches"],
|
|
901
|
+
[findPanelLabelIds.findAllFound, "{count} cells found"],
|
|
902
|
+
[findPanelLabelIds.findAllFoundOne, "1 cell found"],
|
|
903
|
+
[findPanelLabelIds.findAllNone, "No cells found"],
|
|
904
|
+
[findPanelLabelIds.findAllInRow, "Row {row}, {column}"],
|
|
905
|
+
[findPanelLabelIds.findAllInLabelledRow, "{row}, {column}"],
|
|
906
|
+
[findPanelLabelIds.findAllInHeader, "Header {column}"]
|
|
883
907
|
]);
|
|
884
908
|
var refusedCellsNamed = 5;
|
|
885
909
|
function findOutcomeText(outcome, words2) {
|
|
@@ -5169,6 +5193,16 @@ var GridMetrics = class _GridMetrics {
|
|
|
5169
5193
|
get fillHandleSizePx() {
|
|
5170
5194
|
return Math.max(5, roundHalfToEven(this.rowHeightPx * 0.3));
|
|
5171
5195
|
}
|
|
5196
|
+
/** The side of a Reference Outline's corner square (ADR-0480): 5px, as Excel draws it, in the Reference's colour
|
|
5197
|
+
* with a 1px margin of the ground, centred on the outline's corner. */
|
|
5198
|
+
get referenceHandleSizePx() {
|
|
5199
|
+
return 5;
|
|
5200
|
+
}
|
|
5201
|
+
/** How wide the strip along a Reference Outline's line is that a press grabs it by (ADR-0480): 5px, centred on
|
|
5202
|
+
* the line, wider than the line so that it can be pressed. */
|
|
5203
|
+
get referenceGripPx() {
|
|
5204
|
+
return 5;
|
|
5205
|
+
}
|
|
5172
5206
|
/** A cell's horizontal padding on one side; a cell pays it twice. */
|
|
5173
5207
|
get cellPaddingXPx() {
|
|
5174
5208
|
return this.cellMetrics.cellHorizontalPaddingPx;
|
|
@@ -6974,6 +7008,187 @@ function beyond(position, first, last) {
|
|
|
6974
7008
|
return position < first ? position - first : 0;
|
|
6975
7009
|
}
|
|
6976
7010
|
|
|
7011
|
+
// src/paint/selection-styles.ts
|
|
7012
|
+
var outlineSideStyles = Object.freeze(Array.from({ length: 16 }, (_, flags) => ((flags & 1) === 0 ? "" : "; --ex-outline-in-t: 1") + ((flags & 2) === 0 ? "" : "; --ex-outline-in-l: 1") + ((flags & 4) === 0 ? "" : "; --ex-outline-heading-t: 1") + ((flags & 8) === 0 ? "" : "; --ex-outline-heading-l: 1")));
|
|
7013
|
+
var flushPx = 0.01;
|
|
7014
|
+
function cellRange(cell2) {
|
|
7015
|
+
return selectionRange(cell2.row, cell2.column, 1, 1);
|
|
7016
|
+
}
|
|
7017
|
+
function box(range, focus, columns, rowHeightPx, painted, pinnedLayer, cover) {
|
|
7018
|
+
if (rangeCellCount(range) === 1 && rangeContains(range, focus)) return void 0;
|
|
7019
|
+
const style = whole3(range, columns, rowHeightPx, painted, pinnedLayer, rowHeightPx);
|
|
7020
|
+
const side = sideOf(range, columns, pinnedLayer);
|
|
7021
|
+
if (style === void 0 || side === void 0) return void 0;
|
|
7022
|
+
return style + outlineSides(range.topRow, side.first, columns, pinnedLayer, cover, true);
|
|
7023
|
+
}
|
|
7024
|
+
function tint(range, focus, columns, rowHeightPx, painted, pinnedLayer) {
|
|
7025
|
+
const side = sideOf(range, columns, pinnedLayer);
|
|
7026
|
+
if (side === void 0 || focusAlone(range, side, focus)) return void 0;
|
|
7027
|
+
const rows = clip(range, painted);
|
|
7028
|
+
if (rows === void 0) return void 0;
|
|
7029
|
+
const leftPx = columns.offsetPxOf(side.first);
|
|
7030
|
+
let style = rect(leftPx, columns.offsetPxOf(side.last + 1) - leftPx, rows, rowHeightPx, painted.start);
|
|
7031
|
+
if (rangeContains(range, focus) && sideOf(cellRange(focus), columns, pinnedLayer) !== void 0 && focus.row >= rows.top && focus.row < rows.top + rows.count) {
|
|
7032
|
+
const holeLeftPx = columns.offsetPxOf(focus.column) - leftPx;
|
|
7033
|
+
const holeRightPx = columns.offsetPxOf(focus.column + 1) - leftPx;
|
|
7034
|
+
const holeTopPx = (focus.row - rows.top) * rowHeightPx;
|
|
7035
|
+
const holeBottomPx = holeTopPx + rowHeightPx;
|
|
7036
|
+
style += `; --ex-range-hole: polygon(evenodd, 0 0, 100% 0, 100% 100%, 0 100%, 0 0, ${holeLeftPx}px ${holeTopPx}px, ${holeRightPx}px ${holeTopPx}px, ${holeRightPx}px ${holeBottomPx}px, ${holeLeftPx}px ${holeBottomPx}px, ${holeLeftPx}px ${holeTopPx}px)`;
|
|
7037
|
+
}
|
|
7038
|
+
return style;
|
|
7039
|
+
}
|
|
7040
|
+
function tinted(range, focus, columns, painted, pinnedLayer) {
|
|
7041
|
+
const side = sideOf(range, columns, pinnedLayer);
|
|
7042
|
+
return side !== void 0 && !focusAlone(range, side, focus) && clip(range, painted) !== void 0;
|
|
7043
|
+
}
|
|
7044
|
+
function reaches(range, columns, painted, pinnedLayer) {
|
|
7045
|
+
return sideOf(range, columns, pinnedLayer) !== void 0 && clip(range, painted) !== void 0;
|
|
7046
|
+
}
|
|
7047
|
+
function whole3(range, columns, rowHeightPx, painted, pinnedLayer, outsidePx = 0) {
|
|
7048
|
+
const rows = clip(range, painted);
|
|
7049
|
+
if (sideOf(range, columns, pinnedLayer) === void 0 || rows === void 0) return void 0;
|
|
7050
|
+
const leftPx = columns.offsetPxOf(range.leftColumn);
|
|
7051
|
+
const rightPx = columns.offsetPxOf(rightColumn(range) + 1);
|
|
7052
|
+
let style = rect(leftPx, rightPx - leftPx, rows, rowHeightPx, painted.start);
|
|
7053
|
+
if (sideOf(range, columns, !pinnedLayer) !== void 0) {
|
|
7054
|
+
const boundaryPx = columns.offsetPxOf(columns.pinnedCount);
|
|
7055
|
+
const o = outsidePx > 0 ? `${-outsidePx}px` : "0";
|
|
7056
|
+
style += pinnedLayer ? `; clip-path: inset(${o} ${rightPx - boundaryPx}px ${o} ${o})` : `; clip-path: inset(${o} ${o} ${o} ${boundaryPx - leftPx}px)`;
|
|
7057
|
+
}
|
|
7058
|
+
return style;
|
|
7059
|
+
}
|
|
7060
|
+
function copied(range, columns, rowHeightPx, painted, pinnedLayer, cover) {
|
|
7061
|
+
const style = whole3(range, columns, rowHeightPx, painted, pinnedLayer, rowHeightPx);
|
|
7062
|
+
const side = sideOf(range, columns, pinnedLayer);
|
|
7063
|
+
if (style === void 0 || side === void 0) return void 0;
|
|
7064
|
+
return style + outlineSides(range.topRow, side.first, columns, pinnedLayer, cover, false);
|
|
7065
|
+
}
|
|
7066
|
+
function focusStyle(focus, columns, rowHeightPx, painted, pinnedLayer, cover) {
|
|
7067
|
+
const style = part(cellRange(focus), columns, rowHeightPx, painted, pinnedLayer);
|
|
7068
|
+
if (style === void 0) return void 0;
|
|
7069
|
+
return style + outlineSides(focus.row, focus.column, columns, pinnedLayer, cover, true);
|
|
7070
|
+
}
|
|
7071
|
+
function gripResizes(kind) {
|
|
7072
|
+
return kind === "topLeft" || kind === "topRight" || kind === "bottomLeft" || kind === "bottomRight";
|
|
7073
|
+
}
|
|
7074
|
+
var referenceSquareMarginPx = 1;
|
|
7075
|
+
function gripCursor(kind) {
|
|
7076
|
+
if (kind === "topLeft" || kind === "bottomRight") return "nwse";
|
|
7077
|
+
return kind === "topRight" || kind === "bottomLeft" ? "nesw" : "move";
|
|
7078
|
+
}
|
|
7079
|
+
function referenceGrips(range, columns, rowHeightPx, painted, pinnedLayer, gripPx, squarePx, readableLeftPx, named3 = range) {
|
|
7080
|
+
const side = sideOf(range, columns, pinnedLayer);
|
|
7081
|
+
const rows = clip(range, painted);
|
|
7082
|
+
if (side === void 0 || rows === void 0) return [];
|
|
7083
|
+
const rowPainted = (row) => row >= painted.start - 1 && row <= painted.start + painted.count;
|
|
7084
|
+
const hasLeft = sideOf(cellRange({ row: range.topRow, column: range.leftColumn }), columns, pinnedLayer) !== void 0 && range.leftColumn === named3.leftColumn;
|
|
7085
|
+
const hasRight = sideOf(cellRange({ row: range.topRow, column: rightColumn(range) }), columns, pinnedLayer) !== void 0 && rightColumn(range) === rightColumn(named3);
|
|
7086
|
+
const hasTop = rowPainted(range.topRow) && range.topRow === named3.topRow;
|
|
7087
|
+
const hasBottom = rowPainted(bottomRow(range)) && bottomRow(range) === bottomRow(named3);
|
|
7088
|
+
const leftX = columns.offsetPxOf(range.leftColumn);
|
|
7089
|
+
const rightX = columns.offsetPxOf(rightColumn(range) + 1);
|
|
7090
|
+
const topY = (range.topRow - painted.start) * rowHeightPx;
|
|
7091
|
+
const bottomY = (bottomRow(range) + 1 - painted.start) * rowHeightPx;
|
|
7092
|
+
const spanLeft = Math.max(columns.offsetPxOf(side.first), readableLeftPx);
|
|
7093
|
+
const spanRight = columns.offsetPxOf(side.last + 1);
|
|
7094
|
+
const spanTop = (rows.top - painted.start) * rowHeightPx;
|
|
7095
|
+
const spanBottom = spanTop + rows.count * rowHeightPx;
|
|
7096
|
+
const half = gripPx / 2;
|
|
7097
|
+
const grips = [];
|
|
7098
|
+
const strip = (kind, leftPx, topPx, widthPx, heightPx) => {
|
|
7099
|
+
const clippedLeft = Math.max(leftPx, readableLeftPx);
|
|
7100
|
+
const clippedWidth = widthPx - (clippedLeft - leftPx);
|
|
7101
|
+
if (clippedWidth > 0 && heightPx > 0) grips.push(Object.freeze({ kind, leftPx: clippedLeft, topPx, widthPx: clippedWidth, heightPx }));
|
|
7102
|
+
};
|
|
7103
|
+
if (hasTop) strip("top", spanLeft, topY - half, spanRight - spanLeft, gripPx);
|
|
7104
|
+
if (hasBottom) strip("bottom", spanLeft, bottomY - half, spanRight - spanLeft, gripPx);
|
|
7105
|
+
if (hasLeft) strip("left", leftX - half, spanTop, gripPx, spanBottom - spanTop);
|
|
7106
|
+
if (hasRight) strip("right", rightX - half, spanTop, gripPx, spanBottom - spanTop);
|
|
7107
|
+
const squareBox = squarePx + 2 * referenceSquareMarginPx;
|
|
7108
|
+
const square = (kind, x, y) => {
|
|
7109
|
+
if (x < readableLeftPx) return;
|
|
7110
|
+
grips.push(Object.freeze({ kind, leftPx: x - squareBox / 2, topPx: y - squareBox / 2, widthPx: squareBox, heightPx: squareBox }));
|
|
7111
|
+
};
|
|
7112
|
+
if (hasTop && hasLeft) square("topLeft", leftX, topY);
|
|
7113
|
+
if (hasTop && hasRight) square("topRight", rightX, topY);
|
|
7114
|
+
if (hasBottom && hasLeft) square("bottomLeft", leftX, bottomY);
|
|
7115
|
+
if (hasBottom && hasRight) square("bottomRight", rightX, bottomY);
|
|
7116
|
+
return grips;
|
|
7117
|
+
}
|
|
7118
|
+
function scrollable(range, columns, rowHeightPx, painted) {
|
|
7119
|
+
return part(range, columns, rowHeightPx, painted, false);
|
|
7120
|
+
}
|
|
7121
|
+
function pinned(range, columns, rowHeightPx, painted) {
|
|
7122
|
+
return part(range, columns, rowHeightPx, painted, true);
|
|
7123
|
+
}
|
|
7124
|
+
function handle(range, corner, columns, rowHeightPx, painted, sizePx, pinnedLayer, readable) {
|
|
7125
|
+
const cell2 = handleCell(range, corner);
|
|
7126
|
+
if (sideOf(cellRange(cell2), columns, pinnedLayer) === void 0) return void 0;
|
|
7127
|
+
const heldAtTheTop = corner === "topRight";
|
|
7128
|
+
if (!heldAtTheTop && cell2.row < painted.start - 1 || cell2.row > painted.start + painted.count) return void 0;
|
|
7129
|
+
const [leftPx, topPx] = handleCentrePx(range, corner, columns, rowHeightPx, painted.start, sizePx, readable);
|
|
7130
|
+
return `left: ${leftPx - sizePx / 2}px; top: ${topPx - sizePx / 2}px; width: ${sizePx}px; height: ${sizePx}px`;
|
|
7131
|
+
}
|
|
7132
|
+
function handleCell(range, corner) {
|
|
7133
|
+
switch (corner) {
|
|
7134
|
+
case "topRight":
|
|
7135
|
+
return Object.freeze({ row: range.topRow, column: rightColumn(range) });
|
|
7136
|
+
case "bottomLeft":
|
|
7137
|
+
return Object.freeze({ row: bottomRow(range), column: range.leftColumn });
|
|
7138
|
+
case "bottomRight":
|
|
7139
|
+
return Object.freeze({ row: bottomRow(range), column: rightColumn(range) });
|
|
7140
|
+
default:
|
|
7141
|
+
return unreachable(corner);
|
|
7142
|
+
}
|
|
7143
|
+
}
|
|
7144
|
+
function handleCentrePx(range, corner, columns, rowHeightPx, firstPaintedRow, sizePx, readable) {
|
|
7145
|
+
const half = sizePx / 2;
|
|
7146
|
+
switch (corner) {
|
|
7147
|
+
case "topRight":
|
|
7148
|
+
return [columns.offsetPxOf(rightColumn(range) + 1), Math.max((range.topRow - firstPaintedRow) * rowHeightPx, readable.topPx) + half];
|
|
7149
|
+
case "bottomLeft":
|
|
7150
|
+
return [
|
|
7151
|
+
(range.leftColumn < columns.pinnedCount ? columns.offsetPxOf(range.leftColumn) : Math.max(columns.offsetPxOf(range.leftColumn), readable.leftPx)) + half,
|
|
7152
|
+
(bottomRow(range) + 1 - firstPaintedRow) * rowHeightPx
|
|
7153
|
+
];
|
|
7154
|
+
case "bottomRight":
|
|
7155
|
+
return [columns.offsetPxOf(rightColumn(range) + 1), (bottomRow(range) + 1 - firstPaintedRow) * rowHeightPx];
|
|
7156
|
+
default:
|
|
7157
|
+
return unreachable(corner);
|
|
7158
|
+
}
|
|
7159
|
+
}
|
|
7160
|
+
function outlineSides(topRow, firstColumn, columns, pinnedLayer, cover, headingMark) {
|
|
7161
|
+
const top = topRow < cover.firstOpenRow;
|
|
7162
|
+
const left = pinnedLayer ? columns.offsetPxOf(firstColumn) <= columns.leadWidthPx + flushPx : columns.offsetPxOf(firstColumn) - cover.scrollLeftPx <= columns.pinnedWidthPx + flushPx;
|
|
7163
|
+
const headingTop = top && headingMark && cover.hasHeader;
|
|
7164
|
+
const headingLeft = left && headingMark && columns.leadWidthPx > 0 && (pinnedLayer || columns.pinnedCount === 0);
|
|
7165
|
+
const flags = (top && !headingTop ? 1 : 0) | (left && !headingLeft ? 2 : 0) | (headingTop ? 4 : 0) | (headingLeft ? 8 : 0);
|
|
7166
|
+
return itemAt(outlineSideStyles, flags);
|
|
7167
|
+
}
|
|
7168
|
+
function focusAlone(range, side, focus) {
|
|
7169
|
+
return range.rowCount === 1 && side.first === side.last && focus.row === range.topRow && focus.column === side.first;
|
|
7170
|
+
}
|
|
7171
|
+
function part(range, columns, rowHeightPx, painted, pinnedLayer) {
|
|
7172
|
+
const side = sideOf(range, columns, pinnedLayer);
|
|
7173
|
+
const rows = clip(range, painted);
|
|
7174
|
+
if (side === void 0 || rows === void 0) return void 0;
|
|
7175
|
+
return rect(columns.offsetPxOf(side.first), columns.offsetPxOf(side.last + 1) - columns.offsetPxOf(side.first), rows, rowHeightPx, painted.start);
|
|
7176
|
+
}
|
|
7177
|
+
function sideOf(range, columns, pinnedLayer) {
|
|
7178
|
+
const first = pinnedLayer ? range.leftColumn : Math.max(range.leftColumn, columns.pinnedCount);
|
|
7179
|
+
const last = pinnedLayer ? Math.min(rightColumn(range), columns.pinnedCount - 1) : rightColumn(range);
|
|
7180
|
+
return first > last ? void 0 : { first, last };
|
|
7181
|
+
}
|
|
7182
|
+
function clip(range, painted) {
|
|
7183
|
+
const top = Math.max(range.topRow, painted.start - 1);
|
|
7184
|
+
const bottom = Math.min(bottomRow(range), painted.start + painted.count);
|
|
7185
|
+
return bottom < top ? void 0 : { top, count: bottom - top + 1 };
|
|
7186
|
+
}
|
|
7187
|
+
function rect(leftPx, widthPx, rows, rowHeightPx, firstPaintedRow) {
|
|
7188
|
+
const topPx = (rows.top - firstPaintedRow) * rowHeightPx;
|
|
7189
|
+
return `left: ${leftPx}px; top: ${topPx}px; width: ${widthPx}px; height: ${rows.count * rowHeightPx}px`;
|
|
7190
|
+
}
|
|
7191
|
+
|
|
6977
7192
|
// src/query/sort.ts
|
|
6978
7193
|
function nextSort(current, column) {
|
|
6979
7194
|
if (column === "") throw new TypeError("A sort names a column.");
|
|
@@ -7840,6 +8055,81 @@ var InMemoryRowMarks = class {
|
|
|
7840
8055
|
}
|
|
7841
8056
|
};
|
|
7842
8057
|
|
|
8058
|
+
// src/finding/find-all.ts
|
|
8059
|
+
function findAllPage(total, matches3, rowSequenceVersion) {
|
|
8060
|
+
if (!Number.isInteger(total) || total < 0) throw new RangeError(`A Find All counts 0 matches or more, not ${total}.`);
|
|
8061
|
+
if (matches3.length > total) throw new RangeError(`A Find All page holds ${matches3.length} matches of a list of ${total}.`);
|
|
8062
|
+
return Object.freeze({
|
|
8063
|
+
total,
|
|
8064
|
+
rowSequenceVersion,
|
|
8065
|
+
matches: Object.freeze(matches3.map(({ row, column, text: text3, rowLabel }) => Object.freeze(rowLabel === void 0 ? { row, column, text: text3 } : { row, column, text: text3, rowLabel })))
|
|
8066
|
+
});
|
|
8067
|
+
}
|
|
8068
|
+
var FindAllMatches = class _FindAllMatches {
|
|
8069
|
+
#rows;
|
|
8070
|
+
#columns;
|
|
8071
|
+
#texts;
|
|
8072
|
+
#ordinals;
|
|
8073
|
+
#rowLabel;
|
|
8074
|
+
constructor(rows, columns, texts, ordinals, rowLabel) {
|
|
8075
|
+
this.#rows = rows;
|
|
8076
|
+
this.#columns = columns;
|
|
8077
|
+
this.#texts = texts;
|
|
8078
|
+
this.#ordinals = ordinals;
|
|
8079
|
+
this.#rowLabel = rowLabel;
|
|
8080
|
+
}
|
|
8081
|
+
/**
|
|
8082
|
+
* Walks `rows` once (ADR-0470 §2), by rows and across a row in the request's column order. `textOf` answers a
|
|
8083
|
+
* column's displayed text by name, or `undefined` for a column with no text to search or one not known, which is
|
|
8084
|
+
* skipped, as a step skips it. An empty pattern matches nothing. `rowLabel`, where given, names each match's row in
|
|
8085
|
+
* the Consumer's words.
|
|
8086
|
+
*/
|
|
8087
|
+
static of(rows, request, textOf4, rowLabel) {
|
|
8088
|
+
const columns = Object.freeze([...request.columns]);
|
|
8089
|
+
const texts = columns.map(textOf4);
|
|
8090
|
+
const matches3 = matcherOf(request);
|
|
8091
|
+
const ordinals = [];
|
|
8092
|
+
if (request.text !== "") {
|
|
8093
|
+
const columnCount = columns.length;
|
|
8094
|
+
rows.forEach((item, row) => {
|
|
8095
|
+
texts.forEach((text3, column) => {
|
|
8096
|
+
if (text3 === void 0) return;
|
|
8097
|
+
if (request.scope !== void 0 && !inScope(request.scope, row, column)) return;
|
|
8098
|
+
if (matches3(text3(item))) ordinals.push(row * columnCount + column);
|
|
8099
|
+
});
|
|
8100
|
+
});
|
|
8101
|
+
}
|
|
8102
|
+
return new _FindAllMatches(rows, columns, texts, Object.freeze(ordinals), rowLabel);
|
|
8103
|
+
}
|
|
8104
|
+
/** How many cells match. */
|
|
8105
|
+
get total() {
|
|
8106
|
+
return this.#ordinals.length;
|
|
8107
|
+
}
|
|
8108
|
+
/** The entries from `start`, `count` of them or every one left, under `rowSequenceVersion`. A range past the end
|
|
8109
|
+
* holds none; a range outside the list's positions is refused. */
|
|
8110
|
+
page(start, count, rowSequenceVersion) {
|
|
8111
|
+
if (!Number.isInteger(start) || start < 0) throw new RangeError(`A Find All page starts at an entry at or after 0, not ${start}.`);
|
|
8112
|
+
if (!Number.isInteger(count) || count < 1) throw new RangeError(`A Find All page asks for 1 entry or more, not ${count}.`);
|
|
8113
|
+
const columnCount = this.#columns.length;
|
|
8114
|
+
const matches3 = this.#ordinals.slice(start, start + count).map((ordinal2) => {
|
|
8115
|
+
const row = Math.floor(ordinal2 / columnCount);
|
|
8116
|
+
const column = ordinal2 % columnCount;
|
|
8117
|
+
const text3 = itemAt(this.#texts, column);
|
|
8118
|
+
if (text3 === void 0) throw new Error("Internal: a Find All match in a column with no text.");
|
|
8119
|
+
const item = itemAt(this.#rows, row);
|
|
8120
|
+
const match = { row, column: itemAt(this.#columns, column), text: text3(item) };
|
|
8121
|
+
if (this.#rowLabel === void 0) return match;
|
|
8122
|
+
const label = this.#rowLabel(item);
|
|
8123
|
+
if (typeof label !== "string") throw new TypeError(`findAllRowLabel answers text for every row, not ${typeof label} (ADR-0470 \xA73).`);
|
|
8124
|
+
return { ...match, rowLabel: label };
|
|
8125
|
+
});
|
|
8126
|
+
return findAllPage(this.total, matches3, rowSequenceVersion);
|
|
8127
|
+
}
|
|
8128
|
+
};
|
|
8129
|
+
function findAll(rows, rowSequenceVersion, request, textOf4) {
|
|
8130
|
+
return FindAllMatches.of(rows, request, textOf4).page(request.start, request.count, rowSequenceVersion);
|
|
8131
|
+
}
|
|
8132
|
+
|
|
7843
8133
|
// src/source/row-key.ts
|
|
7844
8134
|
function keyOf2(rowKey, row, which2) {
|
|
7845
8135
|
return checkedKey(rowKey(row), which2);
|
|
@@ -8560,8 +8850,13 @@ var InMemoryGridSource = class _InMemoryGridSource {
|
|
|
8560
8850
|
#marks;
|
|
8561
8851
|
#columns;
|
|
8562
8852
|
#state;
|
|
8563
|
-
|
|
8853
|
+
// The last Find All's matches, kept while the result, the columns and the question stand, so a list scrolled
|
|
8854
|
+
// through is walked once (ADR-0470 §2).
|
|
8855
|
+
#findAllRowLabel;
|
|
8856
|
+
#findAll;
|
|
8857
|
+
constructor(rows, { rowKey, clock = systemClock, findAllRowLabel }) {
|
|
8564
8858
|
this.#rowKey = rowKey;
|
|
8859
|
+
this.#findAllRowLabel = findAllRowLabel;
|
|
8565
8860
|
let window2;
|
|
8566
8861
|
if (rowKey === void 0) {
|
|
8567
8862
|
this.#rows = Object.freeze([...rows]);
|
|
@@ -8806,6 +9101,24 @@ var InMemoryGridSource = class _InMemoryGridSource {
|
|
|
8806
9101
|
const columns = this.#queryColumns();
|
|
8807
9102
|
return findStep(this.#state.window, request, (name) => textsOf(columns, name, textFor));
|
|
8808
9103
|
}
|
|
9104
|
+
/**
|
|
9105
|
+
* The reference Find All (ADR-0470): `findAll` over the current result, matching each column's displayed text as
|
|
9106
|
+
* `find` does. The matches are found once for a question and read a page at a time while the result stands. A
|
|
9107
|
+
* request read under another version is answered anyway, under this source's: the grid discards it by the
|
|
9108
|
+
* version.
|
|
9109
|
+
*/
|
|
9110
|
+
async findAll(request, signal) {
|
|
9111
|
+
signal.throwIfAborted();
|
|
9112
|
+
const columns = this.#queryColumns();
|
|
9113
|
+
const { window: window2, rowSequenceVersion } = this.#state;
|
|
9114
|
+
const key2 = JSON.stringify([request.text, request.matchCase, request.wholeCell, request.scope, request.columns]);
|
|
9115
|
+
let held2 = this.#findAll;
|
|
9116
|
+
if (held2?.key !== key2 || held2.window !== window2 || held2.columns !== columns) {
|
|
9117
|
+
held2 = { key: key2, window: window2, columns, matches: FindAllMatches.of(window2, request, (name) => textsOf(columns, name, textFor), this.#findAllRowLabel) };
|
|
9118
|
+
this.#findAll = held2;
|
|
9119
|
+
}
|
|
9120
|
+
return held2.matches.page(request.start, request.count, rowSequenceVersion);
|
|
9121
|
+
}
|
|
8809
9122
|
/**
|
|
8810
9123
|
* The reference Selection Summary (ADR-0130): `summaryOf` over the current result, reading each column's
|
|
8811
9124
|
* value. A column this source was not told about, or one with no value of its own, is blank. It never
|
|
@@ -9425,172 +9738,38 @@ var ClipboardLedger = class _ClipboardLedger {
|
|
|
9425
9738
|
const write = this.#pending.shift() ?? null;
|
|
9426
9739
|
this.#heard.set(change, write);
|
|
9427
9740
|
return write;
|
|
9428
|
-
}
|
|
9429
|
-
};
|
|
9430
|
-
|
|
9431
|
-
// src/dom/column-styles.ts
|
|
9432
|
-
var ColumnStyles = class {
|
|
9433
|
-
/** The geometry the styles are made from. */
|
|
9434
|
-
geometry;
|
|
9435
|
-
#cells = [];
|
|
9436
|
-
#pinnedCells = [];
|
|
9437
|
-
#gaps = [];
|
|
9438
|
-
constructor(geometry) {
|
|
9439
|
-
this.geometry = geometry;
|
|
9440
|
-
}
|
|
9441
|
-
/** A scrollable cell's width. */
|
|
9442
|
-
cell(column) {
|
|
9443
|
-
return this.#cells[column] ??= `width: ${this.geometry.widthPxOf(column)}px`;
|
|
9444
|
-
}
|
|
9445
|
-
/** A pinned cell's width and its own offset: a sticky cell still occupies its place in the flow, so it
|
|
9446
|
-
* sticks exactly where it would otherwise have been. */
|
|
9447
|
-
pinnedCell(column) {
|
|
9448
|
-
return this.#pinnedCells[column] ??= `width: ${this.geometry.widthPxOf(column)}px; left: ${this.geometry.offsetPxOf(column)}px`;
|
|
9449
|
-
}
|
|
9450
|
-
/** The spacer standing for the scrollable columns virtualised away to the left (ADR-0004). The pinned
|
|
9451
|
-
* block is already in the flow ahead of it, so its width comes off. */
|
|
9452
|
-
gap(firstScrollable) {
|
|
9453
|
-
return this.#gaps[firstScrollable] ??= `width: ${Math.max(0, this.geometry.offsetPxOf(firstScrollable) - this.geometry.pinnedWidthPx)}px`;
|
|
9454
|
-
}
|
|
9455
|
-
/** Whether any scrollable column lies to the left of `firstScrollable`, so a gap stands for it. */
|
|
9456
|
-
hasGap(firstScrollable) {
|
|
9457
|
-
return this.geometry.offsetPxOf(firstScrollable) > this.geometry.pinnedWidthPx;
|
|
9458
|
-
}
|
|
9459
|
-
};
|
|
9460
|
-
|
|
9461
|
-
// src/paint/selection-styles.ts
|
|
9462
|
-
var outlineSideStyles = Object.freeze(Array.from({ length: 16 }, (_, flags) => ((flags & 1) === 0 ? "" : "; --ex-outline-in-t: 1") + ((flags & 2) === 0 ? "" : "; --ex-outline-in-l: 1") + ((flags & 4) === 0 ? "" : "; --ex-outline-heading-t: 1") + ((flags & 8) === 0 ? "" : "; --ex-outline-heading-l: 1")));
|
|
9463
|
-
var flushPx = 0.01;
|
|
9464
|
-
function cellRange(cell2) {
|
|
9465
|
-
return selectionRange(cell2.row, cell2.column, 1, 1);
|
|
9466
|
-
}
|
|
9467
|
-
function box(range, focus, columns, rowHeightPx, painted, pinnedLayer, cover) {
|
|
9468
|
-
if (rangeCellCount(range) === 1 && rangeContains(range, focus)) return void 0;
|
|
9469
|
-
const style = whole3(range, columns, rowHeightPx, painted, pinnedLayer, rowHeightPx);
|
|
9470
|
-
const side = sideOf(range, columns, pinnedLayer);
|
|
9471
|
-
if (style === void 0 || side === void 0) return void 0;
|
|
9472
|
-
return style + outlineSides(range.topRow, side.first, columns, pinnedLayer, cover, true);
|
|
9473
|
-
}
|
|
9474
|
-
function tint(range, focus, columns, rowHeightPx, painted, pinnedLayer) {
|
|
9475
|
-
const side = sideOf(range, columns, pinnedLayer);
|
|
9476
|
-
if (side === void 0 || focusAlone(range, side, focus)) return void 0;
|
|
9477
|
-
const rows = clip(range, painted);
|
|
9478
|
-
if (rows === void 0) return void 0;
|
|
9479
|
-
const leftPx = columns.offsetPxOf(side.first);
|
|
9480
|
-
let style = rect(leftPx, columns.offsetPxOf(side.last + 1) - leftPx, rows, rowHeightPx, painted.start);
|
|
9481
|
-
if (rangeContains(range, focus) && sideOf(cellRange(focus), columns, pinnedLayer) !== void 0 && focus.row >= rows.top && focus.row < rows.top + rows.count) {
|
|
9482
|
-
const holeLeftPx = columns.offsetPxOf(focus.column) - leftPx;
|
|
9483
|
-
const holeRightPx = columns.offsetPxOf(focus.column + 1) - leftPx;
|
|
9484
|
-
const holeTopPx = (focus.row - rows.top) * rowHeightPx;
|
|
9485
|
-
const holeBottomPx = holeTopPx + rowHeightPx;
|
|
9486
|
-
style += `; --ex-range-hole: polygon(evenodd, 0 0, 100% 0, 100% 100%, 0 100%, 0 0, ${holeLeftPx}px ${holeTopPx}px, ${holeRightPx}px ${holeTopPx}px, ${holeRightPx}px ${holeBottomPx}px, ${holeLeftPx}px ${holeBottomPx}px, ${holeLeftPx}px ${holeTopPx}px)`;
|
|
9487
|
-
}
|
|
9488
|
-
return style;
|
|
9489
|
-
}
|
|
9490
|
-
function tinted(range, focus, columns, painted, pinnedLayer) {
|
|
9491
|
-
const side = sideOf(range, columns, pinnedLayer);
|
|
9492
|
-
return side !== void 0 && !focusAlone(range, side, focus) && clip(range, painted) !== void 0;
|
|
9493
|
-
}
|
|
9494
|
-
function reaches(range, columns, painted, pinnedLayer) {
|
|
9495
|
-
return sideOf(range, columns, pinnedLayer) !== void 0 && clip(range, painted) !== void 0;
|
|
9496
|
-
}
|
|
9497
|
-
function whole3(range, columns, rowHeightPx, painted, pinnedLayer, outsidePx = 0) {
|
|
9498
|
-
const rows = clip(range, painted);
|
|
9499
|
-
if (sideOf(range, columns, pinnedLayer) === void 0 || rows === void 0) return void 0;
|
|
9500
|
-
const leftPx = columns.offsetPxOf(range.leftColumn);
|
|
9501
|
-
const rightPx = columns.offsetPxOf(rightColumn(range) + 1);
|
|
9502
|
-
let style = rect(leftPx, rightPx - leftPx, rows, rowHeightPx, painted.start);
|
|
9503
|
-
if (sideOf(range, columns, !pinnedLayer) !== void 0) {
|
|
9504
|
-
const boundaryPx = columns.offsetPxOf(columns.pinnedCount);
|
|
9505
|
-
const o = outsidePx > 0 ? `${-outsidePx}px` : "0";
|
|
9506
|
-
style += pinnedLayer ? `; clip-path: inset(${o} ${rightPx - boundaryPx}px ${o} ${o})` : `; clip-path: inset(${o} ${o} ${o} ${boundaryPx - leftPx}px)`;
|
|
9507
|
-
}
|
|
9508
|
-
return style;
|
|
9509
|
-
}
|
|
9510
|
-
function copied(range, columns, rowHeightPx, painted, pinnedLayer, cover) {
|
|
9511
|
-
const style = whole3(range, columns, rowHeightPx, painted, pinnedLayer, rowHeightPx);
|
|
9512
|
-
const side = sideOf(range, columns, pinnedLayer);
|
|
9513
|
-
if (style === void 0 || side === void 0) return void 0;
|
|
9514
|
-
return style + outlineSides(range.topRow, side.first, columns, pinnedLayer, cover, false);
|
|
9515
|
-
}
|
|
9516
|
-
function focusStyle(focus, columns, rowHeightPx, painted, pinnedLayer, cover) {
|
|
9517
|
-
const style = part(cellRange(focus), columns, rowHeightPx, painted, pinnedLayer);
|
|
9518
|
-
if (style === void 0) return void 0;
|
|
9519
|
-
return style + outlineSides(focus.row, focus.column, columns, pinnedLayer, cover, true);
|
|
9520
|
-
}
|
|
9521
|
-
function scrollable(range, columns, rowHeightPx, painted) {
|
|
9522
|
-
return part(range, columns, rowHeightPx, painted, false);
|
|
9523
|
-
}
|
|
9524
|
-
function pinned(range, columns, rowHeightPx, painted) {
|
|
9525
|
-
return part(range, columns, rowHeightPx, painted, true);
|
|
9526
|
-
}
|
|
9527
|
-
function handle(range, corner, columns, rowHeightPx, painted, sizePx, pinnedLayer, readable) {
|
|
9528
|
-
const cell2 = handleCell(range, corner);
|
|
9529
|
-
if (sideOf(cellRange(cell2), columns, pinnedLayer) === void 0) return void 0;
|
|
9530
|
-
const heldAtTheTop = corner === "topRight";
|
|
9531
|
-
if (!heldAtTheTop && cell2.row < painted.start - 1 || cell2.row > painted.start + painted.count) return void 0;
|
|
9532
|
-
const [leftPx, topPx] = handleCentrePx(range, corner, columns, rowHeightPx, painted.start, sizePx, readable);
|
|
9533
|
-
return `left: ${leftPx - sizePx / 2}px; top: ${topPx - sizePx / 2}px; width: ${sizePx}px; height: ${sizePx}px`;
|
|
9534
|
-
}
|
|
9535
|
-
function handleCell(range, corner) {
|
|
9536
|
-
switch (corner) {
|
|
9537
|
-
case "topRight":
|
|
9538
|
-
return Object.freeze({ row: range.topRow, column: rightColumn(range) });
|
|
9539
|
-
case "bottomLeft":
|
|
9540
|
-
return Object.freeze({ row: bottomRow(range), column: range.leftColumn });
|
|
9541
|
-
case "bottomRight":
|
|
9542
|
-
return Object.freeze({ row: bottomRow(range), column: rightColumn(range) });
|
|
9543
|
-
default:
|
|
9544
|
-
return unreachable(corner);
|
|
9545
|
-
}
|
|
9546
|
-
}
|
|
9547
|
-
function handleCentrePx(range, corner, columns, rowHeightPx, firstPaintedRow, sizePx, readable) {
|
|
9548
|
-
const half = sizePx / 2;
|
|
9549
|
-
switch (corner) {
|
|
9550
|
-
case "topRight":
|
|
9551
|
-
return [columns.offsetPxOf(rightColumn(range) + 1), Math.max((range.topRow - firstPaintedRow) * rowHeightPx, readable.topPx) + half];
|
|
9552
|
-
case "bottomLeft":
|
|
9553
|
-
return [
|
|
9554
|
-
(range.leftColumn < columns.pinnedCount ? columns.offsetPxOf(range.leftColumn) : Math.max(columns.offsetPxOf(range.leftColumn), readable.leftPx)) + half,
|
|
9555
|
-
(bottomRow(range) + 1 - firstPaintedRow) * rowHeightPx
|
|
9556
|
-
];
|
|
9557
|
-
case "bottomRight":
|
|
9558
|
-
return [columns.offsetPxOf(rightColumn(range) + 1), (bottomRow(range) + 1 - firstPaintedRow) * rowHeightPx];
|
|
9559
|
-
default:
|
|
9560
|
-
return unreachable(corner);
|
|
9561
|
-
}
|
|
9562
|
-
}
|
|
9563
|
-
function outlineSides(topRow, firstColumn, columns, pinnedLayer, cover, headingMark) {
|
|
9564
|
-
const top = topRow < cover.firstOpenRow;
|
|
9565
|
-
const left = pinnedLayer ? columns.offsetPxOf(firstColumn) <= columns.leadWidthPx + flushPx : columns.offsetPxOf(firstColumn) - cover.scrollLeftPx <= columns.pinnedWidthPx + flushPx;
|
|
9566
|
-
const headingTop = top && headingMark && cover.hasHeader;
|
|
9567
|
-
const headingLeft = left && headingMark && columns.leadWidthPx > 0 && (pinnedLayer || columns.pinnedCount === 0);
|
|
9568
|
-
const flags = (top && !headingTop ? 1 : 0) | (left && !headingLeft ? 2 : 0) | (headingTop ? 4 : 0) | (headingLeft ? 8 : 0);
|
|
9569
|
-
return itemAt(outlineSideStyles, flags);
|
|
9570
|
-
}
|
|
9571
|
-
function focusAlone(range, side, focus) {
|
|
9572
|
-
return range.rowCount === 1 && side.first === side.last && focus.row === range.topRow && focus.column === side.first;
|
|
9573
|
-
}
|
|
9574
|
-
function part(range, columns, rowHeightPx, painted, pinnedLayer) {
|
|
9575
|
-
const side = sideOf(range, columns, pinnedLayer);
|
|
9576
|
-
const rows = clip(range, painted);
|
|
9577
|
-
if (side === void 0 || rows === void 0) return void 0;
|
|
9578
|
-
return rect(columns.offsetPxOf(side.first), columns.offsetPxOf(side.last + 1) - columns.offsetPxOf(side.first), rows, rowHeightPx, painted.start);
|
|
9579
|
-
}
|
|
9580
|
-
function sideOf(range, columns, pinnedLayer) {
|
|
9581
|
-
const first = pinnedLayer ? range.leftColumn : Math.max(range.leftColumn, columns.pinnedCount);
|
|
9582
|
-
const last = pinnedLayer ? Math.min(rightColumn(range), columns.pinnedCount - 1) : rightColumn(range);
|
|
9583
|
-
return first > last ? void 0 : { first, last };
|
|
9584
|
-
}
|
|
9585
|
-
function clip(range, painted) {
|
|
9586
|
-
const top = Math.max(range.topRow, painted.start - 1);
|
|
9587
|
-
const bottom = Math.min(bottomRow(range), painted.start + painted.count);
|
|
9588
|
-
return bottom < top ? void 0 : { top, count: bottom - top + 1 };
|
|
9589
|
-
}
|
|
9590
|
-
function rect(leftPx, widthPx, rows, rowHeightPx, firstPaintedRow) {
|
|
9591
|
-
const topPx = (rows.top - firstPaintedRow) * rowHeightPx;
|
|
9592
|
-
return `left: ${leftPx}px; top: ${topPx}px; width: ${widthPx}px; height: ${rows.count * rowHeightPx}px`;
|
|
9593
|
-
}
|
|
9741
|
+
}
|
|
9742
|
+
};
|
|
9743
|
+
|
|
9744
|
+
// src/dom/column-styles.ts
|
|
9745
|
+
var ColumnStyles = class {
|
|
9746
|
+
/** The geometry the styles are made from. */
|
|
9747
|
+
geometry;
|
|
9748
|
+
#cells = [];
|
|
9749
|
+
#pinnedCells = [];
|
|
9750
|
+
#gaps = [];
|
|
9751
|
+
constructor(geometry) {
|
|
9752
|
+
this.geometry = geometry;
|
|
9753
|
+
}
|
|
9754
|
+
/** A scrollable cell's width. */
|
|
9755
|
+
cell(column) {
|
|
9756
|
+
return this.#cells[column] ??= `width: ${this.geometry.widthPxOf(column)}px`;
|
|
9757
|
+
}
|
|
9758
|
+
/** A pinned cell's width and its own offset: a sticky cell still occupies its place in the flow, so it
|
|
9759
|
+
* sticks exactly where it would otherwise have been. */
|
|
9760
|
+
pinnedCell(column) {
|
|
9761
|
+
return this.#pinnedCells[column] ??= `width: ${this.geometry.widthPxOf(column)}px; left: ${this.geometry.offsetPxOf(column)}px`;
|
|
9762
|
+
}
|
|
9763
|
+
/** The spacer standing for the scrollable columns virtualised away to the left (ADR-0004). The pinned
|
|
9764
|
+
* block is already in the flow ahead of it, so its width comes off. */
|
|
9765
|
+
gap(firstScrollable) {
|
|
9766
|
+
return this.#gaps[firstScrollable] ??= `width: ${Math.max(0, this.geometry.offsetPxOf(firstScrollable) - this.geometry.pinnedWidthPx)}px`;
|
|
9767
|
+
}
|
|
9768
|
+
/** Whether any scrollable column lies to the left of `firstScrollable`, so a gap stands for it. */
|
|
9769
|
+
hasGap(firstScrollable) {
|
|
9770
|
+
return this.geometry.offsetPxOf(firstScrollable) > this.geometry.pinnedWidthPx;
|
|
9771
|
+
}
|
|
9772
|
+
};
|
|
9594
9773
|
|
|
9595
9774
|
// src/dom/cell-editing.ts
|
|
9596
9775
|
var waitingStyle = "left: 0px; top: 0px; width: 0px; height: 0px";
|
|
@@ -10278,6 +10457,8 @@ var FindPanel = class {
|
|
|
10278
10457
|
#replace;
|
|
10279
10458
|
// Whether a Replace All is out with the Consumer.
|
|
10280
10459
|
#waiting = false;
|
|
10460
|
+
#findAllButton;
|
|
10461
|
+
#findAllPart;
|
|
10281
10462
|
constructor(doc, held2, words2, answers) {
|
|
10282
10463
|
this.#doc = doc;
|
|
10283
10464
|
this.#held = held2;
|
|
@@ -10293,7 +10474,12 @@ var FindPanel = class {
|
|
|
10293
10474
|
});
|
|
10294
10475
|
const actions = doc.createElement("div");
|
|
10295
10476
|
actions.className = "ex-popover-actions";
|
|
10477
|
+
this.#findAllButton = this.#button("ex-find-all-button", findPanelLabelIds.findAll, () => {
|
|
10478
|
+
answers.findAll();
|
|
10479
|
+
});
|
|
10480
|
+
this.#findAllButton.hidden = true;
|
|
10296
10481
|
actions.append(
|
|
10482
|
+
this.#findAllButton,
|
|
10297
10483
|
this.#button("ex-find-previous", findPanelLabelIds.previous, () => {
|
|
10298
10484
|
answers.step(true);
|
|
10299
10485
|
}),
|
|
@@ -10364,6 +10550,15 @@ var FindPanel = class {
|
|
|
10364
10550
|
say(text3) {
|
|
10365
10551
|
if (this.#outcome.textContent !== text3) this.#outcome.textContent = text3;
|
|
10366
10552
|
}
|
|
10553
|
+
offerFindAll(offered) {
|
|
10554
|
+
this.#findAllButton.hidden = !offered;
|
|
10555
|
+
}
|
|
10556
|
+
showFindAll(part2) {
|
|
10557
|
+
if (part2 === this.#findAllPart) return;
|
|
10558
|
+
this.#findAllPart?.remove();
|
|
10559
|
+
this.#findAllPart = part2;
|
|
10560
|
+
if (part2 !== void 0) this.#outcome.after(part2);
|
|
10561
|
+
}
|
|
10367
10562
|
focusField() {
|
|
10368
10563
|
this.#field.focus({ preventScroll: true });
|
|
10369
10564
|
this.#field.select();
|
|
@@ -10848,6 +11043,9 @@ var SlottedFindPanel = class {
|
|
|
10848
11043
|
#replaceShown = false;
|
|
10849
11044
|
#waiting = false;
|
|
10850
11045
|
#outcome = "";
|
|
11046
|
+
#findAllShown = false;
|
|
11047
|
+
#findAllPart;
|
|
11048
|
+
#body;
|
|
10851
11049
|
#view;
|
|
10852
11050
|
constructor(doc, mount, held2, label, answers, takeFocus) {
|
|
10853
11051
|
this.#held = held2;
|
|
@@ -10863,6 +11061,7 @@ var SlottedFindPanel = class {
|
|
|
10863
11061
|
slot.className = "ex-find-slot";
|
|
10864
11062
|
form.append(slot);
|
|
10865
11063
|
body.append(form);
|
|
11064
|
+
this.#body = body;
|
|
10866
11065
|
const toField = () => {
|
|
10867
11066
|
this.#request(false);
|
|
10868
11067
|
};
|
|
@@ -10929,6 +11128,17 @@ var SlottedFindPanel = class {
|
|
|
10929
11128
|
replaceAll: act(() => {
|
|
10930
11129
|
answers.replaceAll();
|
|
10931
11130
|
}),
|
|
11131
|
+
findAll: act(() => {
|
|
11132
|
+
answers.findAll();
|
|
11133
|
+
}),
|
|
11134
|
+
listFindAll: act((list) => {
|
|
11135
|
+
answers.listFindAll(list);
|
|
11136
|
+
}, (list) => {
|
|
11137
|
+
if (typeof list !== "function") throw new TypeError("listFindAll is handed a function that answers the list, asked in its turn (ADR-0470 \xA77).");
|
|
11138
|
+
}),
|
|
11139
|
+
dropFindAll: act(() => {
|
|
11140
|
+
answers.dropFindAll();
|
|
11141
|
+
}),
|
|
10932
11142
|
close: act(() => {
|
|
10933
11143
|
answers.close();
|
|
10934
11144
|
}),
|
|
@@ -10960,6 +11170,18 @@ var SlottedFindPanel = class {
|
|
|
10960
11170
|
this.#outcome = text3;
|
|
10961
11171
|
this.#changed();
|
|
10962
11172
|
}
|
|
11173
|
+
offerFindAll(offered) {
|
|
11174
|
+
if (offered === this.#findAllShown) return;
|
|
11175
|
+
this.#findAllShown = offered;
|
|
11176
|
+
this.#changed();
|
|
11177
|
+
}
|
|
11178
|
+
/** The list stands under the contents, in the core's own place, whichever Chrome draws them (ADR-0470 §3). */
|
|
11179
|
+
showFindAll(part2) {
|
|
11180
|
+
if (part2 === this.#findAllPart) return;
|
|
11181
|
+
this.#findAllPart?.remove();
|
|
11182
|
+
this.#findAllPart = part2;
|
|
11183
|
+
if (part2 !== void 0) this.#body.append(part2);
|
|
11184
|
+
}
|
|
10963
11185
|
/** Mounts the contents with the next request for the field, whose text is selected. */
|
|
10964
11186
|
focusField() {
|
|
10965
11187
|
this.#request(true);
|
|
@@ -10982,7 +11204,8 @@ var SlottedFindPanel = class {
|
|
|
10982
11204
|
replaceShown: this.#replaceShown,
|
|
10983
11205
|
replaceText: this.#held.replaceText,
|
|
10984
11206
|
replaceWaiting: this.#waiting,
|
|
10985
|
-
outcome: this.#outcome
|
|
11207
|
+
outcome: this.#outcome,
|
|
11208
|
+
findAllShown: this.#findAllShown
|
|
10986
11209
|
});
|
|
10987
11210
|
return this.#view;
|
|
10988
11211
|
}
|
|
@@ -11168,6 +11391,169 @@ var BarField = class _BarField {
|
|
|
11168
11391
|
}
|
|
11169
11392
|
};
|
|
11170
11393
|
|
|
11394
|
+
// src/dom/find-all-list.ts
|
|
11395
|
+
var findAllVisibleLines = 8;
|
|
11396
|
+
var lists = 0;
|
|
11397
|
+
var FindAllList = class {
|
|
11398
|
+
/** The part's box, `.ex-find-all`, which the panel places under its contents. */
|
|
11399
|
+
element;
|
|
11400
|
+
/** The listbox, which takes the keyboard for the list's keys. */
|
|
11401
|
+
list;
|
|
11402
|
+
#countLine;
|
|
11403
|
+
#doc;
|
|
11404
|
+
#model;
|
|
11405
|
+
#lineHeightPx;
|
|
11406
|
+
#spacer;
|
|
11407
|
+
#id;
|
|
11408
|
+
#scrollTopPx = 0;
|
|
11409
|
+
// The active line last brought into view: a line is revealed as it becomes active, never again while it stays so,
|
|
11410
|
+
// so the user scrolls the list away from it freely.
|
|
11411
|
+
#revealed;
|
|
11412
|
+
// The lines drawn, by index, so a refresh rewrites only what changed.
|
|
11413
|
+
#drawn = /* @__PURE__ */ new Map();
|
|
11414
|
+
constructor(doc, model, lineHeightPx) {
|
|
11415
|
+
if (!(lineHeightPx > 0)) throw new RangeError(`A Find All list's lines are taller than 0px, not ${lineHeightPx}.`);
|
|
11416
|
+
this.#doc = doc;
|
|
11417
|
+
this.#model = model;
|
|
11418
|
+
this.#lineHeightPx = lineHeightPx;
|
|
11419
|
+
lists += 1;
|
|
11420
|
+
this.#id = `ex-find-all-${lists}`;
|
|
11421
|
+
this.element = doc.createElement("div");
|
|
11422
|
+
this.element.className = "ex-find-all";
|
|
11423
|
+
this.#countLine = doc.createElement("div");
|
|
11424
|
+
this.#countLine.className = "ex-find-all-count";
|
|
11425
|
+
this.#countLine.setAttribute("role", "status");
|
|
11426
|
+
const element = doc.createElement("div");
|
|
11427
|
+
element.className = "ex-find-all-list";
|
|
11428
|
+
element.setAttribute("role", "listbox");
|
|
11429
|
+
element.setAttribute("aria-label", model.label);
|
|
11430
|
+
element.tabIndex = 0;
|
|
11431
|
+
element.setAttribute("data-ex-claims", "keydown click");
|
|
11432
|
+
element.style.height = `${findAllVisibleLines * lineHeightPx}px`;
|
|
11433
|
+
this.#spacer = doc.createElement("div");
|
|
11434
|
+
this.#spacer.className = "ex-find-all-spacer";
|
|
11435
|
+
element.append(this.#spacer);
|
|
11436
|
+
element.addEventListener("scroll", () => {
|
|
11437
|
+
if (element.scrollTop === this.#scrollTopPx) return;
|
|
11438
|
+
this.#scrollTopPx = element.scrollTop;
|
|
11439
|
+
this.refresh();
|
|
11440
|
+
});
|
|
11441
|
+
element.addEventListener("click", (event) => {
|
|
11442
|
+
const line = event.target instanceof Element ? event.target.closest(".ex-find-all-line") : null;
|
|
11443
|
+
if (!(line instanceof HTMLElement) || !element.contains(line)) return;
|
|
11444
|
+
const index = Number(line.dataset["exIndex"]);
|
|
11445
|
+
if (!Number.isInteger(index)) throw new Error("Internal: a Find All line without its index.");
|
|
11446
|
+
model.answered();
|
|
11447
|
+
model.choose(index);
|
|
11448
|
+
});
|
|
11449
|
+
element.addEventListener("keydown", (event) => {
|
|
11450
|
+
if (event.ctrlKey || event.altKey || event.metaKey || event.isComposing) return;
|
|
11451
|
+
const target = this.#keyTarget(event.key);
|
|
11452
|
+
if (target === void 0) return;
|
|
11453
|
+
event.preventDefault();
|
|
11454
|
+
model.answered();
|
|
11455
|
+
if (target >= 0) model.choose(target);
|
|
11456
|
+
});
|
|
11457
|
+
this.list = element;
|
|
11458
|
+
this.element.append(this.#countLine, element);
|
|
11459
|
+
this.refresh();
|
|
11460
|
+
}
|
|
11461
|
+
/** What the count line says: how many cells were found, or why the list went (ADR-0470 §5). */
|
|
11462
|
+
say(text3) {
|
|
11463
|
+
if (this.#countLine.textContent !== text3) this.#countLine.textContent = text3;
|
|
11464
|
+
}
|
|
11465
|
+
// The line a key moves to (ADR-0470 §4), read or not yet, -1 for a key the list takes that moves nowhere, or
|
|
11466
|
+
// `undefined` for a key that is not the list's.
|
|
11467
|
+
#keyTarget(key2) {
|
|
11468
|
+
const count = this.#model.count();
|
|
11469
|
+
if (!["ArrowDown", "ArrowUp", "Home", "End", "Enter", "PageDown", "PageUp"].includes(key2)) return void 0;
|
|
11470
|
+
if (count === void 0 || count === 0) return -1;
|
|
11471
|
+
const active = this.#model.active();
|
|
11472
|
+
const last = count - 1;
|
|
11473
|
+
switch (key2) {
|
|
11474
|
+
case "ArrowDown":
|
|
11475
|
+
return active === void 0 ? 0 : Math.min(last, active + 1);
|
|
11476
|
+
case "ArrowUp":
|
|
11477
|
+
return active === void 0 ? 0 : Math.max(0, active - 1);
|
|
11478
|
+
case "PageDown":
|
|
11479
|
+
return active === void 0 ? 0 : Math.min(last, active + findAllVisibleLines);
|
|
11480
|
+
case "PageUp":
|
|
11481
|
+
return active === void 0 ? 0 : Math.max(0, active - findAllVisibleLines);
|
|
11482
|
+
case "Home":
|
|
11483
|
+
return 0;
|
|
11484
|
+
case "End":
|
|
11485
|
+
return last;
|
|
11486
|
+
default:
|
|
11487
|
+
return active === void 0 ? -1 : active;
|
|
11488
|
+
}
|
|
11489
|
+
}
|
|
11490
|
+
/** Draws the lines in view as the model now holds them, and brings the active line into view. */
|
|
11491
|
+
refresh() {
|
|
11492
|
+
const count = this.#model.count();
|
|
11493
|
+
const lines = count === void 0 ? 0 : count;
|
|
11494
|
+
this.#spacer.style.height = `${lines * this.#lineHeightPx}px`;
|
|
11495
|
+
const active = this.#model.active();
|
|
11496
|
+
if (active !== this.#revealed) {
|
|
11497
|
+
this.#revealed = active;
|
|
11498
|
+
if (active !== void 0 && active < lines) this.#reveal(active);
|
|
11499
|
+
}
|
|
11500
|
+
const first = Math.min(Math.max(0, lines - 1), Math.floor(this.#scrollTopPx / this.#lineHeightPx));
|
|
11501
|
+
const last = Math.min(lines - 1, first + findAllVisibleLines);
|
|
11502
|
+
for (const [index, line] of this.#drawn) {
|
|
11503
|
+
if (index < first || index > last) {
|
|
11504
|
+
line.remove();
|
|
11505
|
+
this.#drawn.delete(index);
|
|
11506
|
+
}
|
|
11507
|
+
}
|
|
11508
|
+
for (let index = first; index <= last; index++) this.#draw(index, index === active);
|
|
11509
|
+
this.list.hidden = lines === 0;
|
|
11510
|
+
if (active !== void 0 && active < lines) this.list.setAttribute("aria-activedescendant", `${this.#id}-${active}`);
|
|
11511
|
+
else this.list.removeAttribute("aria-activedescendant");
|
|
11512
|
+
if (lines > 0) this.#model.inView(first, last);
|
|
11513
|
+
}
|
|
11514
|
+
// The active line scrolled into view, as far as it must, as the grid reveals its Focus.
|
|
11515
|
+
#reveal(index) {
|
|
11516
|
+
const top = index * this.#lineHeightPx;
|
|
11517
|
+
const room = findAllVisibleLines * this.#lineHeightPx;
|
|
11518
|
+
let scrollTop = this.#scrollTopPx;
|
|
11519
|
+
if (top < scrollTop) scrollTop = top;
|
|
11520
|
+
else if (top + this.#lineHeightPx > scrollTop + room) scrollTop = top + this.#lineHeightPx - room;
|
|
11521
|
+
if (scrollTop === this.#scrollTopPx) return;
|
|
11522
|
+
this.#scrollTopPx = scrollTop;
|
|
11523
|
+
this.list.scrollTop = scrollTop;
|
|
11524
|
+
}
|
|
11525
|
+
#draw(index, active) {
|
|
11526
|
+
let line = this.#drawn.get(index);
|
|
11527
|
+
if (line === void 0) {
|
|
11528
|
+
line = this.#doc.createElement("div");
|
|
11529
|
+
line.className = "ex-find-all-line";
|
|
11530
|
+
line.id = `${this.#id}-${index}`;
|
|
11531
|
+
line.setAttribute("role", "option");
|
|
11532
|
+
line.dataset["exIndex"] = String(index);
|
|
11533
|
+
line.style.top = `${index * this.#lineHeightPx}px`;
|
|
11534
|
+
line.style.height = `${this.#lineHeightPx}px`;
|
|
11535
|
+
const where2 = this.#doc.createElement("span");
|
|
11536
|
+
where2.className = "ex-find-all-where";
|
|
11537
|
+
const text4 = this.#doc.createElement("span");
|
|
11538
|
+
text4.className = "ex-find-all-text";
|
|
11539
|
+
line.append(where2, text4);
|
|
11540
|
+
this.#spacer.append(line);
|
|
11541
|
+
this.#drawn.set(index, line);
|
|
11542
|
+
}
|
|
11543
|
+
const read = this.#model.line(index);
|
|
11544
|
+
const [where, text3] = [line.children[0], line.children[1]];
|
|
11545
|
+
if (where === void 0 || text3 === void 0) throw new Error("Internal: a Find All line without its two parts.");
|
|
11546
|
+
const whereText = read === void 0 ? "" : read.where;
|
|
11547
|
+
const shownText = read === void 0 ? "" : read.text;
|
|
11548
|
+
if (where.textContent !== whereText) where.textContent = whereText;
|
|
11549
|
+
if (text3.textContent !== shownText) text3.textContent = shownText;
|
|
11550
|
+
if (read === void 0) line.setAttribute("aria-busy", "true");
|
|
11551
|
+
else line.removeAttribute("aria-busy");
|
|
11552
|
+
line.setAttribute("aria-selected", active ? "true" : "false");
|
|
11553
|
+
line.classList.toggle("ex-find-all-active", active);
|
|
11554
|
+
}
|
|
11555
|
+
};
|
|
11556
|
+
|
|
11171
11557
|
// src/dom/grid-marks.ts
|
|
11172
11558
|
var headerChecked = { none: "false", some: "mixed", all: "true" };
|
|
11173
11559
|
var GridMarks = class {
|
|
@@ -11725,10 +12111,11 @@ function namesTheStartOfTheRow(action2) {
|
|
|
11725
12111
|
// src/dom/selection-layers.ts
|
|
11726
12112
|
var pieceOf = (className, style) => style === void 0 ? [] : [{ className, style }];
|
|
11727
12113
|
var nothing2 = Object.freeze({ shade: void 0, pinned: Object.freeze([]), scrollable: Object.freeze([]) });
|
|
12114
|
+
var noBands = Object.freeze({ hoverRow: void 0, focusRow: false, focusColumn: false, rowCount: 0 });
|
|
11728
12115
|
var noFill = Object.freeze({ outline: void 0, handle: void 0 });
|
|
11729
12116
|
var noOutlines = Object.freeze({ references: Object.freeze([]), columns: Object.freeze([]), point: void 0, pointDashes: void 0 });
|
|
11730
12117
|
var outlineClass = ([, colour]) => `ex-reference-outline ex-reference-${String(colour)}`;
|
|
11731
|
-
function selectionLayers(selection, copied2, columns, rowHeightPx, painted, cover, bands =
|
|
12118
|
+
function selectionLayers(selection, copied2, columns, rowHeightPx, painted, cover, bands = noBands, fill = noFill, outlines = noOutlines) {
|
|
11732
12119
|
const dashes2 = (pinnedLayer) => copied2.flatMap((range) => pieceOf("ex-copied-range", copied(range, columns, rowHeightPx, painted, pinnedLayer, cover)));
|
|
11733
12120
|
const bandOf = (row) => ({ topRow: row, leftColumn: 0, rowCount: 1, columnCount: columns.count });
|
|
11734
12121
|
const fillPieces = (pinnedLayer) => [
|
|
@@ -11744,12 +12131,24 @@ function selectionLayers(selection, copied2, columns, rowHeightPx, painted, cove
|
|
|
11744
12131
|
// Point's outline is one more rectangle over them; the Selection and the Focus beneath it do not move.
|
|
11745
12132
|
...withReferences && outlines.point !== void 0 ? pieceOf(outlines.point.className, pinnedLayer ? pinned(outlines.point.range, columns, rowHeightPx, painted) : scrollable(outlines.point.range, columns, rowHeightPx, painted)) : [],
|
|
11746
12133
|
// What a press outside the grid wrote for is dashed, Selection or none, cut at the boundary as a column is.
|
|
11747
|
-
...outlines.pointDashes === void 0 ? [] : pieceOf("ex-point-dashes", pinnedLayer ? pinned(outlines.pointDashes, columns, rowHeightPx, painted) : scrollable(outlines.pointDashes, columns, rowHeightPx, painted))
|
|
12134
|
+
...outlines.pointDashes === void 0 ? [] : pieceOf("ex-point-dashes", pinnedLayer ? pinned(outlines.pointDashes, columns, rowHeightPx, painted) : scrollable(outlines.pointDashes, columns, rowHeightPx, painted)),
|
|
12135
|
+
// The grips last, over everything a layer holds, a later outline's over an earlier's (ADR-0480).
|
|
12136
|
+
...withReferences && outlines.grips !== void 0 ? gripPieces(outlines.grips, pinnedLayer) : []
|
|
11748
12137
|
];
|
|
12138
|
+
const gripPieces = (grips, pinnedLayer) => grips.outlines.flatMap(({ outline, range, named: named3, colour }) => referenceGrips(range, columns, rowHeightPx, painted, pinnedLayer, grips.gripPx, grips.squarePx, pinnedLayer ? grips.pinnedLeftPx : grips.scrollableLeftPx, named3).map(({ kind, leftPx, topPx, widthPx, heightPx }) => ({
|
|
12139
|
+
className: `ex-reference-grip ex-reference-grip-${kind}${gripResizes(kind) ? " ex-reference-square" : ""} ex-reference-${String(colour)}`,
|
|
12140
|
+
style: `left: ${String(leftPx)}px; top: ${String(topPx)}px; width: ${String(widthPx)}px; height: ${String(heightPx)}px${gripResizes(kind) ? `; border-width: ${String(referenceSquareMarginPx)}px` : ""}`,
|
|
12141
|
+
grip: { outline, kind, leftPx, topPx }
|
|
12142
|
+
})));
|
|
11749
12143
|
const focus = selection.focus;
|
|
12144
|
+
const columnBandsOf = (at) => !bands.focusRow ? [selectionRange(0, at.column, bands.rowCount, 1)] : [
|
|
12145
|
+
...at.row > 0 ? [selectionRange(0, at.column, at.row, 1)] : [],
|
|
12146
|
+
...at.row + 1 < bands.rowCount ? [selectionRange(at.row + 1, at.column, bands.rowCount - at.row - 1, 1)] : []
|
|
12147
|
+
];
|
|
11750
12148
|
const rowBands = columns.count === 0 ? [] : [
|
|
11751
12149
|
...bands.hoverRow === void 0 ? [] : [{ className: "ex-hover-row", range: bandOf(bands.hoverRow) }],
|
|
11752
|
-
...bands.focusRow && focus !== void 0 ? [{ className: "ex-focus-row", range: bandOf(focus.row) }] : []
|
|
12150
|
+
...bands.focusRow && focus !== void 0 ? [{ className: "ex-focus-row", range: bandOf(focus.row) }] : [],
|
|
12151
|
+
...bands.focusColumn && focus !== void 0 && bands.rowCount > 0 ? columnBandsOf(focus).map((range) => ({ className: "ex-focus-column", range })) : []
|
|
11753
12152
|
];
|
|
11754
12153
|
const pinnedBands = rowBands.flatMap(({ className, range }) => pieceOf(className, pinned(range, columns, rowHeightPx, painted)));
|
|
11755
12154
|
const scrollableBands = rowBands.flatMap(({ className, range }) => pieceOf(className, scrollable(range, columns, rowHeightPx, painted)));
|
|
@@ -12082,7 +12481,7 @@ function boxClass(status) {
|
|
|
12082
12481
|
|
|
12083
12482
|
// src/dom/shipped-stylesheet.ts
|
|
12084
12483
|
var stylesheetName = "ex-grid.css";
|
|
12085
|
-
var stylesheetStamp = "
|
|
12484
|
+
var stylesheetStamp = "63b729dd8e7c4d0d507d810eee14b23894982022d2efbaec94f42280fcca9d7b";
|
|
12086
12485
|
|
|
12087
12486
|
// src/dom/cell-paint.ts
|
|
12088
12487
|
var CellPaint = class _CellPaint {
|
|
@@ -13373,7 +13772,7 @@ function colourOfKey(keys, key2) {
|
|
|
13373
13772
|
|
|
13374
13773
|
// src/dom/reference-outlines.ts
|
|
13375
13774
|
function referenceOutlineOptions(given2) {
|
|
13376
|
-
const { referencesIn, onReferenceKeyColoursChanged, outlinedColumns } = given2;
|
|
13775
|
+
const { referencesIn, onReferenceKeyColoursChanged, outlinedColumns, moveReference } = given2;
|
|
13377
13776
|
if (referencesIn !== void 0 && typeof referencesIn !== "function") {
|
|
13378
13777
|
throw new TypeError("referencesIn is a function of the editor's text, answering its References (ADR-0057).");
|
|
13379
13778
|
}
|
|
@@ -13383,11 +13782,15 @@ function referenceOutlineOptions(given2) {
|
|
|
13383
13782
|
if (outlinedColumns !== void 0 && !Array.isArray(outlinedColumns)) {
|
|
13384
13783
|
throw new TypeError("outlinedColumns is a list of columns, each named with its colour (ADR-0057).");
|
|
13385
13784
|
}
|
|
13785
|
+
if (moveReference !== void 0 && typeof moveReference !== "function") {
|
|
13786
|
+
throw new TypeError("moveReference is a function of a Reference's text and the range it is to name (ADR-0480).");
|
|
13787
|
+
}
|
|
13386
13788
|
const asked = given2.outlinedColumns;
|
|
13387
13789
|
return {
|
|
13388
13790
|
referencesIn: given2.referencesIn,
|
|
13389
13791
|
onReferenceKeyColoursChanged: given2.onReferenceKeyColoursChanged,
|
|
13390
|
-
outlinedColumns: asked === void 0 ? void 0 : Object.freeze(asked.map(outlinedColumn))
|
|
13792
|
+
outlinedColumns: asked === void 0 ? void 0 : Object.freeze(asked.map(outlinedColumn)),
|
|
13793
|
+
moveReference: given2.moveReference
|
|
13391
13794
|
};
|
|
13392
13795
|
}
|
|
13393
13796
|
function outlinedColumn(asked, i) {
|
|
@@ -13750,6 +14153,13 @@ var MatchMarks = class {
|
|
|
13750
14153
|
return shown3 !== void 0 && this.rule === void 0 ? this.#matcher(shown3) : this.#judge(row, column);
|
|
13751
14154
|
}
|
|
13752
14155
|
};
|
|
14156
|
+
var findAllPageSize = 100;
|
|
14157
|
+
function isFindAllList(value) {
|
|
14158
|
+
return typeof value === "object" && value !== null && "count" in value && typeof value.count === "number" && "line" in value && typeof value.line === "function" && "choose" in value && typeof value.choose === "function";
|
|
14159
|
+
}
|
|
14160
|
+
function isFindAllLine(value) {
|
|
14161
|
+
return typeof value === "object" && value !== null && "where" in value && typeof value.where === "string" && "text" in value && typeof value.text === "string";
|
|
14162
|
+
}
|
|
13753
14163
|
var userWriteCellsFollowed = 1024;
|
|
13754
14164
|
var userWritesKept = 64;
|
|
13755
14165
|
function checkedPointedAt(given2) {
|
|
@@ -13762,6 +14172,16 @@ function checkedPointedAt(given2) {
|
|
|
13762
14172
|
function sameDashesAsked(was, now) {
|
|
13763
14173
|
return was.dashes === now.dashes && was.columns === now.columns && was.window === now.window && was.windowStart === now.windowStart && was.start === now.start && was.count === now.count && was.totalRows === now.totalRows;
|
|
13764
14174
|
}
|
|
14175
|
+
function oppositeCorner(range, kind) {
|
|
14176
|
+
const top = kind === "bottomLeft" || kind === "bottomRight";
|
|
14177
|
+
const left = kind === "topRight" || kind === "bottomRight";
|
|
14178
|
+
return cell(top ? range.topRow : bottomRow(range), left ? range.leftColumn : rightColumn(range));
|
|
14179
|
+
}
|
|
14180
|
+
function edgeCellOf(range, kind, at) {
|
|
14181
|
+
const row = kind === "top" ? range.topRow : kind === "bottom" ? bottomRow(range) : clamp(at.row, range.topRow, bottomRow(range));
|
|
14182
|
+
const column = kind === "left" ? range.leftColumn : kind === "right" ? rightColumn(range) : clamp(at.column, range.leftColumn, rightColumn(range));
|
|
14183
|
+
return cell(row, column);
|
|
14184
|
+
}
|
|
13765
14185
|
function toneOf(column, value) {
|
|
13766
14186
|
const tone = defined(column.tone, "a tone rule")(value);
|
|
13767
14187
|
if (tone !== "none" && tone !== "positive" && tone !== "negative") {
|
|
@@ -13923,6 +14343,7 @@ var GridView = class {
|
|
|
13923
14343
|
#handlePointer;
|
|
13924
14344
|
#handleOutline;
|
|
13925
14345
|
#highlightFocusRow = false;
|
|
14346
|
+
#highlightFocusColumn = false;
|
|
13926
14347
|
#highlightHoverRow = false;
|
|
13927
14348
|
#stripeRows = false;
|
|
13928
14349
|
// The pager (ADR-0015): the rows a page holds while one stands, and the page shown, transient view state as the
|
|
@@ -14185,6 +14606,8 @@ var GridView = class {
|
|
|
14185
14606
|
#findHeld = { text: "", matchCase: false, wholeCell: false, replaceText: "" };
|
|
14186
14607
|
#findOutcome = { kind: "none" };
|
|
14187
14608
|
#findStepping;
|
|
14609
|
+
// The list of the last Find All while it stands (ADR-0470).
|
|
14610
|
+
#findAll;
|
|
14188
14611
|
#replacing = 0;
|
|
14189
14612
|
// A Pending Commit (ADR-0380 section 3), and the stamps given so far. `#input` is the last input the root heard
|
|
14190
14613
|
// ahead of everything in it: while its dispatch is under way, it is the gesture a commit made in its handler
|
|
@@ -14239,7 +14662,12 @@ var GridView = class {
|
|
|
14239
14662
|
#topRowOwed;
|
|
14240
14663
|
#layerInputs;
|
|
14241
14664
|
// The Reference Outline options (ADR-0057), and the colouring, columns and key colours they make.
|
|
14242
|
-
#referenceOptions = {
|
|
14665
|
+
#referenceOptions = {
|
|
14666
|
+
referencesIn: void 0,
|
|
14667
|
+
onReferenceKeyColoursChanged: void 0,
|
|
14668
|
+
outlinedColumns: void 0,
|
|
14669
|
+
moveReference: void 0
|
|
14670
|
+
};
|
|
14243
14671
|
#referenceOutlines = new ReferenceOutlines();
|
|
14244
14672
|
// Point (ADR-0051): the options, and the pointing outline as a Focus and an Extent of its own, a one-range
|
|
14245
14673
|
// selection moved by the transitions the Selection's own use; the span of the text its Reference occupies, and
|
|
@@ -14257,6 +14685,10 @@ var GridView = class {
|
|
|
14257
14685
|
#pointLength = 0;
|
|
14258
14686
|
#pointWritten;
|
|
14259
14687
|
#pointDragging = false;
|
|
14688
|
+
// A Reference Outline's grip drag (ADR-0480): what it was pressed on and against, and what it has reached. The
|
|
14689
|
+
// grips as last drawn, each element with what it is, so a press on one is read without the layout.
|
|
14690
|
+
#gripDrag;
|
|
14691
|
+
#gripElements = /* @__PURE__ */ new WeakMap();
|
|
14260
14692
|
// Whether what Point wrote was handed in from outside (ADR-0058): no outline stands over this grid's cells for
|
|
14261
14693
|
// it, and F4 and the arrows change nothing while it stands. With it, the edit as it was before that write.
|
|
14262
14694
|
#pointedFromOutside = false;
|
|
@@ -14903,10 +15335,13 @@ var GridView = class {
|
|
|
14903
15335
|
const { showFillHandle, onFill } = options;
|
|
14904
15336
|
if (showFillHandle !== void 0 && typeof showFillHandle !== "boolean") throw new TypeError("showFillHandle is true or false.");
|
|
14905
15337
|
if (onFill !== void 0 && typeof onFill !== "function") throw new TypeError("onFill is a function of the fill's intent.");
|
|
14906
|
-
const { highlightFocusRow, highlightHoverRow } = options;
|
|
15338
|
+
const { highlightFocusRow, highlightFocusColumn, highlightHoverRow } = options;
|
|
14907
15339
|
if (highlightFocusRow !== void 0 && typeof highlightFocusRow !== "boolean") {
|
|
14908
15340
|
throw new TypeError("highlightFocusRow is true or false.");
|
|
14909
15341
|
}
|
|
15342
|
+
if (highlightFocusColumn !== void 0 && typeof highlightFocusColumn !== "boolean") {
|
|
15343
|
+
throw new TypeError("highlightFocusColumn is true or false.");
|
|
15344
|
+
}
|
|
14910
15345
|
if (highlightHoverRow !== void 0 && typeof highlightHoverRow !== "boolean") {
|
|
14911
15346
|
throw new TypeError("highlightHoverRow is true or false.");
|
|
14912
15347
|
}
|
|
@@ -15102,6 +15537,7 @@ var GridView = class {
|
|
|
15102
15537
|
showFillHandle: options.showFillHandle === true,
|
|
15103
15538
|
onFill: options.onFill,
|
|
15104
15539
|
highlightFocusRow: options.highlightFocusRow === true,
|
|
15540
|
+
highlightFocusColumn: options.highlightFocusColumn === true,
|
|
15105
15541
|
highlightHoverRow: (options.highlightHoverRow ?? options.presentationDefaults?.highlightHoverRow) === true,
|
|
15106
15542
|
cellMessage: options.cellMessage,
|
|
15107
15543
|
declaredKeys,
|
|
@@ -15318,6 +15754,7 @@ var GridView = class {
|
|
|
15318
15754
|
this.#fillHeard = taken.onFill;
|
|
15319
15755
|
if (!taken.showFillHandle && this.#handleDrag !== void 0) this.#setDragging(false);
|
|
15320
15756
|
this.#highlightFocusRow = taken.highlightFocusRow;
|
|
15757
|
+
this.#highlightFocusColumn = taken.highlightFocusColumn;
|
|
15321
15758
|
if (taken.highlightHoverRow !== this.#highlightHoverRow) {
|
|
15322
15759
|
this.#highlightHoverRow = taken.highlightHoverRow;
|
|
15323
15760
|
if (taken.highlightHoverRow) {
|
|
@@ -15907,6 +16344,10 @@ var GridView = class {
|
|
|
15907
16344
|
this.#taken(event);
|
|
15908
16345
|
return;
|
|
15909
16346
|
}
|
|
16347
|
+
if (escape && !event.repeat && this.#gripDrag !== void 0 && this.#cancelGripDrag()) {
|
|
16348
|
+
this.#taken(event);
|
|
16349
|
+
return;
|
|
16350
|
+
}
|
|
15910
16351
|
if (popover !== void 0 && escape && (onGrid || inPopover) && !innerPopupOpen(popover)) {
|
|
15911
16352
|
this.#taken(event);
|
|
15912
16353
|
this.#closePopover(true);
|
|
@@ -16392,12 +16833,20 @@ var GridView = class {
|
|
|
16392
16833
|
}
|
|
16393
16834
|
this.#pressHandedOver = false;
|
|
16394
16835
|
this.#secondaryPress = event.target === this.#viewport && (event.button === 2 || event.button === 0 && event.ctrlKey) ? { at: this.#cellUnder(event), leftPx: event.offsetX - this.#scrollLeftPx, topPx: this.#viewportYOf(event) } : void 0;
|
|
16395
|
-
|
|
16396
|
-
|
|
16836
|
+
const grip = event.button === 0 && event.target instanceof Element ? this.#gripElements.get(event.target) : void 0;
|
|
16837
|
+
if (event.button !== 0 || grip === void 0 && event.target !== this.#viewport) return;
|
|
16838
|
+
const modified = event.shiftKey || event.ctrlKey || event.metaKey || event.altKey;
|
|
16839
|
+
if (grip !== void 0 && !modified && this.#pressGrip(grip.grip, this.#cellAtGrip(event, grip, true))) {
|
|
16840
|
+
this.#answered += 1;
|
|
16841
|
+
event.preventDefault();
|
|
16842
|
+
this.#invalidate();
|
|
16843
|
+
return;
|
|
16844
|
+
}
|
|
16845
|
+
const grabbed = grip !== void 0 || event.shiftKey || event.ctrlKey || event.metaKey ? void 0 : this.#fillHandleUnder(event);
|
|
16397
16846
|
this.#reconcileSelection();
|
|
16398
|
-
const at = this.#cellUnder(event);
|
|
16847
|
+
const at = grip === void 0 ? this.#cellUnder(event) : this.#cellAtGrip(event, grip);
|
|
16399
16848
|
if (at === void 0) return;
|
|
16400
|
-
if (this.#inRowHeadings(event)) {
|
|
16849
|
+
if (grip === void 0 && this.#inRowHeadings(event)) {
|
|
16401
16850
|
this.#pressRowHeading(event, at.row);
|
|
16402
16851
|
return;
|
|
16403
16852
|
}
|
|
@@ -16441,6 +16890,12 @@ var GridView = class {
|
|
|
16441
16890
|
if (event.target !== this.#viewport) return;
|
|
16442
16891
|
const at = this.#cellUnder(event);
|
|
16443
16892
|
if (at === void 0) return;
|
|
16893
|
+
if (this.#gripDrag !== void 0) {
|
|
16894
|
+
this.#moveGripDrag(at);
|
|
16895
|
+
const gripY = this.#viewportYOf(event);
|
|
16896
|
+
if (gripY !== void 0) this.#updateEdgeBand(event.offsetX - this.#scrollLeftPx, gripY);
|
|
16897
|
+
return;
|
|
16898
|
+
}
|
|
16444
16899
|
if (this.#pointDragging) {
|
|
16445
16900
|
this.#pointDrag(at);
|
|
16446
16901
|
return;
|
|
@@ -16463,6 +16918,10 @@ var GridView = class {
|
|
|
16463
16918
|
// would hear every drag (ADR-0018).
|
|
16464
16919
|
#onDragEnd = (event) => {
|
|
16465
16920
|
if (this.#headingDrag && this.#headingHears(event)) this.#moveHeadingDrag(event);
|
|
16921
|
+
if (this.#gripDrag !== void 0 && event.target === this.#viewport) {
|
|
16922
|
+
const at = this.#cellUnder(event);
|
|
16923
|
+
if (at !== void 0) this.#moveGripDrag(at);
|
|
16924
|
+
}
|
|
16466
16925
|
if (this.#handleDrag !== void 0) {
|
|
16467
16926
|
this.#finishHandleDrag(event.target === this.#viewport ? this.#cellUnder(event) : void 0);
|
|
16468
16927
|
return;
|
|
@@ -17971,7 +18430,7 @@ var GridView = class {
|
|
|
17971
18430
|
const edit = this.#edit;
|
|
17972
18431
|
if (edit === void 0) return;
|
|
17973
18432
|
this.#edit = void 0;
|
|
17974
|
-
if (this.#endPointing()) this.#setDragging(false);
|
|
18433
|
+
if (this.#endPointing() || this.#gripDrag !== void 0) this.#setDragging(false);
|
|
17975
18434
|
this.#closeCompletion();
|
|
17976
18435
|
this.#completionSeen = void 0;
|
|
17977
18436
|
this.#tellPointState();
|
|
@@ -18199,6 +18658,185 @@ var GridView = class {
|
|
|
18199
18658
|
this.#pointer = pointer.extendTo(at, this.#extent);
|
|
18200
18659
|
this.#writePointedReference(edit, false);
|
|
18201
18660
|
}
|
|
18661
|
+
// ---- Dragging a Reference Outline (ADR-0480) ---------------------------------------------------------------
|
|
18662
|
+
// Whether the open edit's outlines carry grips: a Reference can be dragged while an edit is open whose References
|
|
18663
|
+
// the Consumer answers and rewrites, its commit not waiting on a verdict, and pointed at from outside by no one.
|
|
18664
|
+
#gripsShown() {
|
|
18665
|
+
const { referencesIn, moveReference } = this.#referenceOptions;
|
|
18666
|
+
return this.#edit !== void 0 && referencesIn !== void 0 && moveReference !== void 0 && this.#pending === void 0 && !this.#pointedAtNow();
|
|
18667
|
+
}
|
|
18668
|
+
// The outlines that carry grips, by their place among the colouring's outlines, as they are drawn on the grid.
|
|
18669
|
+
#gripPaint(colouring, rowCount, columnCount) {
|
|
18670
|
+
const visible = this.#visible;
|
|
18671
|
+
const geometry = this.#geometry;
|
|
18672
|
+
if (visible === void 0 || geometry === void 0) return void 0;
|
|
18673
|
+
const outlines = colouring.outlines.flatMap(([range, colour], outline) => {
|
|
18674
|
+
const drawn = withinExtent(range, { rowCount, columnCount });
|
|
18675
|
+
return drawn === void 0 ? [] : [{ outline, range: drawn, named: range, colour }];
|
|
18676
|
+
});
|
|
18677
|
+
if (outlines.length === 0) return void 0;
|
|
18678
|
+
const readable = this.#readableEdge(visible, geometry);
|
|
18679
|
+
return {
|
|
18680
|
+
outlines,
|
|
18681
|
+
gripPx: this.#metrics.referenceGripPx,
|
|
18682
|
+
squarePx: this.#metrics.referenceHandleSizePx,
|
|
18683
|
+
pinnedLeftPx: this.#styles.geometry.leadWidthPx,
|
|
18684
|
+
scrollableLeftPx: readable.leftPx
|
|
18685
|
+
};
|
|
18686
|
+
}
|
|
18687
|
+
// The cell under a press on a grip, from where the grip was drawn and the press's offset inside it: a pinned
|
|
18688
|
+
// layer's coordinates are the Viewport's less the scroll offset, as it is held against the Viewport's left edge.
|
|
18689
|
+
// `along` reads an edge's strip only along its edge: across it, half the strip lies outside the range, past the
|
|
18690
|
+
// last row or column where the range ends there, and the drag holds the edge's own row or column (edgeCellOf),
|
|
18691
|
+
// so the axis across is not read and is answered as 0.
|
|
18692
|
+
#cellAtGrip(event, drawn, along = false) {
|
|
18693
|
+
const geometry = this.#geometry;
|
|
18694
|
+
const visible = this.#visible;
|
|
18695
|
+
if (geometry === void 0 || visible === void 0) return void 0;
|
|
18696
|
+
const x = drawn.grip.leftPx + event.offsetX + (drawn.pinned ? this.#scrollLeftPx : 0);
|
|
18697
|
+
const row = geometry.rowAt(drawn.grip.topPx + event.offsetY + geometry.offsetPxOf(visible.start));
|
|
18698
|
+
const column = this.#styles.geometry.columnAt(x, this.#scrollLeftPx);
|
|
18699
|
+
const { kind } = drawn.grip;
|
|
18700
|
+
if (along && (kind === "left" || kind === "right")) return row === void 0 ? void 0 : cell(row, 0);
|
|
18701
|
+
if (along && (kind === "top" || kind === "bottom")) return column === void 0 ? void 0 : cell(0, column);
|
|
18702
|
+
return row === void 0 || column === void 0 ? void 0 : cell(row, column);
|
|
18703
|
+
}
|
|
18704
|
+
/**
|
|
18705
|
+
* A press on a grip (ADR-0480, section 3): an edge holds the cell of the range nearest the press, a square the
|
|
18706
|
+
* opposite corner, and the drag begins; the text is not touched until the range reached changes. Taken against
|
|
18707
|
+
* the colouring the grips were drawn for: an outline gone, or text changed since, refuses the press, which does
|
|
18708
|
+
* nothing. Whether the press was the grip's.
|
|
18709
|
+
*/
|
|
18710
|
+
#pressGrip(grip, at) {
|
|
18711
|
+
const edit = this.#edit;
|
|
18712
|
+
const moveReference = this.#referenceOptions.moveReference;
|
|
18713
|
+
if (edit === void 0 || moveReference === void 0 || !this.#gripsShown()) return false;
|
|
18714
|
+
const text3 = this.#editorText(edit);
|
|
18715
|
+
const colouring = this.#referenceOutlines.asked;
|
|
18716
|
+
const named3 = colouring.references.filter((reference) => reference.range !== void 0)[grip.outline];
|
|
18717
|
+
const from = colouring.outlines[grip.outline]?.[0];
|
|
18718
|
+
const resizes = gripResizes(grip.kind);
|
|
18719
|
+
if (this.#referenceOutlines.askedFor !== text3 || named3 === void 0 || from === void 0 || withinExtent(from, this.#extent) === void 0 || !resizes && at === void 0) return true;
|
|
18720
|
+
const surface = this.#surfaceOf(edit);
|
|
18721
|
+
const held2 = resizes ? oppositeCorner(from, grip.kind) : edgeCellOf(from, grip.kind, defined(at, "the cell an edge was pressed on"));
|
|
18722
|
+
this.#gripDrag = {
|
|
18723
|
+
edit,
|
|
18724
|
+
resizes,
|
|
18725
|
+
from,
|
|
18726
|
+
held: held2,
|
|
18727
|
+
start: named3.start,
|
|
18728
|
+
length: named3.length,
|
|
18729
|
+
written: text3,
|
|
18730
|
+
reached: from,
|
|
18731
|
+
before: {
|
|
18732
|
+
text: text3,
|
|
18733
|
+
selectionStart: surface?.selectionStart ?? -1,
|
|
18734
|
+
selectionEnd: surface?.selectionEnd ?? -1,
|
|
18735
|
+
// oxlint-disable-line ex-grid/no-stand-in-default -- ADR-0480: a caret not known is put back as not known
|
|
18736
|
+
mode: edit.mode,
|
|
18737
|
+
pointer: this.#pointer,
|
|
18738
|
+
pointStart: this.#pointStart,
|
|
18739
|
+
pointLength: this.#pointLength,
|
|
18740
|
+
pointWritten: this.#pointWritten
|
|
18741
|
+
}
|
|
18742
|
+
};
|
|
18743
|
+
this.#root.setAttribute("data-ex-reference-drag", gripCursor(grip.kind));
|
|
18744
|
+
this.#setDragging(true);
|
|
18745
|
+
if (surface !== void 0 && this.#root.ownerDocument.activeElement !== surface) surface.focus({ preventScroll: true });
|
|
18746
|
+
return true;
|
|
18747
|
+
}
|
|
18748
|
+
/**
|
|
18749
|
+
* The drag reached `at` (ADR-0480, section 3): a move takes the range by as many rows and columns as `at` lies
|
|
18750
|
+
* from the cell held, kept inside the grid, or where it reached past the grid when pressed, no further past it
|
|
18751
|
+
* than it was; a resize spans the held corner and `at`. Where the range reached
|
|
18752
|
+
* changed, the Reference is rewritten in place by the Consumer's answer, the caret and Point's span moved with the
|
|
18753
|
+
* text around them. Text changed meanwhile by anything but the drag ends it: the span it holds is no longer the
|
|
18754
|
+
* Reference's. Whether anything changed.
|
|
18755
|
+
*/
|
|
18756
|
+
#moveGripDrag(at) {
|
|
18757
|
+
const drag = this.#gripDrag;
|
|
18758
|
+
const edit = this.#edit;
|
|
18759
|
+
const moveReference = this.#referenceOptions.moveReference;
|
|
18760
|
+
if (drag === void 0) return false;
|
|
18761
|
+
if (edit === void 0 || edit !== drag.edit || moveReference === void 0 || this.#editorText(edit) !== drag.written) {
|
|
18762
|
+
this.#setDragging(false);
|
|
18763
|
+
return false;
|
|
18764
|
+
}
|
|
18765
|
+
const extent = this.#extent;
|
|
18766
|
+
const { from, held: held2 } = drag;
|
|
18767
|
+
const reached = drag.resizes ? fromCorners(held2, at) : selectionRange(
|
|
18768
|
+
clamp(from.topRow + at.row - held2.row, 0, Math.max(extent.rowCount - from.rowCount, from.topRow)),
|
|
18769
|
+
clamp(from.leftColumn + at.column - held2.column, 0, Math.max(extent.columnCount - from.columnCount, from.leftColumn)),
|
|
18770
|
+
from.rowCount,
|
|
18771
|
+
from.columnCount
|
|
18772
|
+
);
|
|
18773
|
+
if (sameRange(reached, drag.reached)) return false;
|
|
18774
|
+
const answer = moveReference(drag.written.slice(drag.start, drag.start + drag.length), reached);
|
|
18775
|
+
if (typeof answer !== "string" || answer === "") {
|
|
18776
|
+
throw new TypeError("moveReference answered no text for a dragged Reference: a Reference is a non-empty string (ADR-0480).");
|
|
18777
|
+
}
|
|
18778
|
+
const [text3] = replaceSpan(drag.written, drag.start, drag.length, answer);
|
|
18779
|
+
const end = drag.start + drag.length;
|
|
18780
|
+
const delta = answer.length - drag.length;
|
|
18781
|
+
const moved = (place) => place < 0 || place <= drag.start ? place : place >= end ? place + delta : drag.start + answer.length;
|
|
18782
|
+
const surface = this.#surfaceOf(edit);
|
|
18783
|
+
const selectionStart = moved(surface?.selectionStart ?? -1);
|
|
18784
|
+
const selectionEnd = moved(surface?.selectionEnd ?? -1);
|
|
18785
|
+
if (this.#pointWritten !== void 0 && this.#pointingContinues(edit)) {
|
|
18786
|
+
if (this.#pointStart === drag.start && this.#pointer !== void 0) {
|
|
18787
|
+
this.#pointLength = answer.length;
|
|
18788
|
+
this.#pointer = Selection.empty.click(cell(reached.topRow, reached.leftColumn), extent).extendTo(cell(bottomRow(reached), rightColumn(reached)), extent);
|
|
18789
|
+
} else if (this.#pointStart >= end) {
|
|
18790
|
+
this.#pointStart += delta;
|
|
18791
|
+
}
|
|
18792
|
+
this.#pointWritten = text3;
|
|
18793
|
+
}
|
|
18794
|
+
this.#writeEditorText(edit, text3);
|
|
18795
|
+
if (this.#formulaBarDeclared.shown) this.#bar.showText(text3);
|
|
18796
|
+
if (surface !== void 0 && selectionStart >= 0) surface.setSelectionRange(selectionStart, Math.max(selectionStart, selectionEnd));
|
|
18797
|
+
drag.length = answer.length;
|
|
18798
|
+
drag.written = text3;
|
|
18799
|
+
drag.reached = reached;
|
|
18800
|
+
this.#closeCompletion();
|
|
18801
|
+
this.#askReferences();
|
|
18802
|
+
this.#tellPointState();
|
|
18803
|
+
this.#invalidate();
|
|
18804
|
+
return true;
|
|
18805
|
+
}
|
|
18806
|
+
// Escape mid-drag (ADR-0480, section 6): the edit as the press found it, its text, caret, mode and pointing, and
|
|
18807
|
+
// the drag over. The edit stays open. Text typed since the drag last wrote has ended the drag already, as the
|
|
18808
|
+
// next move would find (#moveGripDrag): the drag is over, nothing is put back, and the Escape is not the drag's.
|
|
18809
|
+
// Whether the Escape was the drag's.
|
|
18810
|
+
#cancelGripDrag() {
|
|
18811
|
+
const drag = this.#gripDrag;
|
|
18812
|
+
const edit = this.#edit;
|
|
18813
|
+
this.#setDragging(false);
|
|
18814
|
+
if (drag === void 0 || edit === void 0 || edit !== drag.edit || this.#editorText(edit) !== drag.written) return false;
|
|
18815
|
+
const { before } = drag;
|
|
18816
|
+
if (this.#editorText(edit) !== before.text) {
|
|
18817
|
+
this.#writeEditorText(edit, before.text);
|
|
18818
|
+
if (this.#formulaBarDeclared.shown) this.#bar.showText(before.text);
|
|
18819
|
+
const surface = this.#surfaceOf(edit);
|
|
18820
|
+
if (surface !== void 0 && before.selectionStart >= 0) surface.setSelectionRange(before.selectionStart, before.selectionEnd);
|
|
18821
|
+
}
|
|
18822
|
+
edit.mode = before.mode;
|
|
18823
|
+
if (before.pointWritten !== void 0) {
|
|
18824
|
+
this.#pointer = before.pointer;
|
|
18825
|
+
this.#pointStart = before.pointStart;
|
|
18826
|
+
this.#pointLength = before.pointLength;
|
|
18827
|
+
this.#pointWritten = before.pointWritten;
|
|
18828
|
+
}
|
|
18829
|
+
this.#askReferences();
|
|
18830
|
+
this.#tellPointState();
|
|
18831
|
+
this.#invalidate();
|
|
18832
|
+
return true;
|
|
18833
|
+
}
|
|
18834
|
+
// The drag is over, wherever it reached: the root's cursor and the grips' pointer events come back.
|
|
18835
|
+
#endGripDrag() {
|
|
18836
|
+
if (this.#gripDrag === void 0) return;
|
|
18837
|
+
this.#gripDrag = void 0;
|
|
18838
|
+
this.#root.removeAttribute("data-ex-reference-drag");
|
|
18839
|
+
}
|
|
18202
18840
|
// F2 moves between the states (ADR-0010), and where pointing is declared between Caret and Point: from Caret it
|
|
18203
18841
|
// points where the Consumer says a Reference can go at the caret, and from Point it moves the caret again, the
|
|
18204
18842
|
// outline gone and its Reference left written (ADR-0051).
|
|
@@ -19601,6 +20239,7 @@ var GridView = class {
|
|
|
19601
20239
|
if (popover.kind === "find") {
|
|
19602
20240
|
this.#findStepping?.abort();
|
|
19603
20241
|
this.#findStepping = void 0;
|
|
20242
|
+
this.#dropFindAll();
|
|
19604
20243
|
}
|
|
19605
20244
|
const active = doc.activeElement;
|
|
19606
20245
|
const ours = active === null || active === doc.body || active === doc.documentElement || this.#root.contains(active);
|
|
@@ -19980,7 +20619,17 @@ var GridView = class {
|
|
|
19980
20619
|
replaceAll: () => {
|
|
19981
20620
|
this.#replaceAll();
|
|
19982
20621
|
},
|
|
20622
|
+
findAll: () => {
|
|
20623
|
+
this.#findAllStart();
|
|
20624
|
+
},
|
|
20625
|
+
listFindAll: (list) => {
|
|
20626
|
+
this.#findAllOwn(list);
|
|
20627
|
+
},
|
|
20628
|
+
dropFindAll: () => {
|
|
20629
|
+
this.#dropFindAll();
|
|
20630
|
+
},
|
|
19983
20631
|
heldChanged: () => {
|
|
20632
|
+
this.#findAllHeldChanged();
|
|
19984
20633
|
this.#invalidate();
|
|
19985
20634
|
},
|
|
19986
20635
|
answered: this.#answer
|
|
@@ -20543,6 +21192,7 @@ var GridView = class {
|
|
|
20543
21192
|
return;
|
|
20544
21193
|
}
|
|
20545
21194
|
this.#askSummaryAgain();
|
|
21195
|
+
this.#dropFindAll();
|
|
20546
21196
|
this.#setFindOutcome({ kind: "replaced", count: result.count });
|
|
20547
21197
|
}
|
|
20548
21198
|
// A Replace that wrote nothing (ADR-0332 §2): the panel names the cells and why, and the Consumer is told.
|
|
@@ -20550,6 +21200,395 @@ var GridView = class {
|
|
|
20550
21200
|
this.#setFindOutcome({ kind: "replaceRefused", cells });
|
|
20551
21201
|
this.#onRefused?.({ kind: "find", reason: "replaceRefused" });
|
|
20552
21202
|
}
|
|
21203
|
+
// ---- Find All (ADR-0470) -----------------------------------------------------------------------------------
|
|
21204
|
+
// Whether Find All can be asked (ADR-0470 §1): the source lists every match beside finding the next.
|
|
21205
|
+
get #canFindAll() {
|
|
21206
|
+
return this.#source.find !== void 0 && this.#source.findAll !== void 0;
|
|
21207
|
+
}
|
|
21208
|
+
/**
|
|
21209
|
+
* Find All (ADR-0470): the list of every match, asked of the source a page at a time under the version its
|
|
21210
|
+
* positions are read in, with the headers the grid searches itself listed first (ADR-0333). Its first page is an
|
|
21211
|
+
* answer out, as a step's is: the inputs made meanwhile wait for it, and an Escape cancels it (ADR-0451 section 3).
|
|
21212
|
+
* The Focus does not move: the list is the whole set, and a line chosen from it moves the Focus there.
|
|
21213
|
+
*/
|
|
21214
|
+
#findAllStart() {
|
|
21215
|
+
if (this.#stepInTurn(() => {
|
|
21216
|
+
this.#findAllStart();
|
|
21217
|
+
})) return;
|
|
21218
|
+
const popover = this.#popover;
|
|
21219
|
+
const source = this.#source;
|
|
21220
|
+
if (popover?.kind !== "find" || this.#findHeld.text === "" || !this.#canFindAll) return;
|
|
21221
|
+
this.#dropFindAll();
|
|
21222
|
+
this.#reconcileSelection();
|
|
21223
|
+
const selection = this.#held.selection;
|
|
21224
|
+
const scope = !selection.isEmpty && selection.cellCount > 1 ? selection.ranges : void 0;
|
|
21225
|
+
const pattern = this.#findPattern();
|
|
21226
|
+
const headers = scope === void 0 ? this.#findHeaders() : [];
|
|
21227
|
+
const request = Object.freeze({
|
|
21228
|
+
...pattern,
|
|
21229
|
+
scope,
|
|
21230
|
+
columns: Object.freeze(this.#columns.map(({ column }) => column.name)),
|
|
21231
|
+
rowSequenceVersion: this.#state.rowSequenceVersion
|
|
21232
|
+
});
|
|
21233
|
+
const list = {
|
|
21234
|
+
source,
|
|
21235
|
+
sequence: this.#sequence(),
|
|
21236
|
+
request,
|
|
21237
|
+
columnCount: request.columns.length,
|
|
21238
|
+
headers: matchingHeaders(headers, pattern).map((index) => itemAt(headers, index)),
|
|
21239
|
+
rowTotal: void 0,
|
|
21240
|
+
pages: /* @__PURE__ */ new Map(),
|
|
21241
|
+
asking: /* @__PURE__ */ new Map(),
|
|
21242
|
+
active: void 0,
|
|
21243
|
+
activeFor: void 0,
|
|
21244
|
+
view: void 0,
|
|
21245
|
+
gone: void 0,
|
|
21246
|
+
part: void 0,
|
|
21247
|
+
own: void 0
|
|
21248
|
+
};
|
|
21249
|
+
this.#showFindAll(popover.panel, list);
|
|
21250
|
+
this.#askFindAllPage(list, 0, "first");
|
|
21251
|
+
}
|
|
21252
|
+
/**
|
|
21253
|
+
* Find All with a list the find panel slot's contents hold themselves (ADR-0470 §7), as ExSheet's over its
|
|
21254
|
+
* Workbook: asked in its turn, drawn as the grid's own list is, its count and lines the contents', a choice taken in
|
|
21255
|
+
* its turn and handed back to them. It goes when the text or an option changes or the panel closes, never with the
|
|
21256
|
+
* order: what the contents list is theirs to drop.
|
|
21257
|
+
*/
|
|
21258
|
+
#findAllOwn(made4) {
|
|
21259
|
+
if (this.#stepInTurn(() => {
|
|
21260
|
+
this.#findAllOwn(made4);
|
|
21261
|
+
})) return;
|
|
21262
|
+
const popover = this.#popover;
|
|
21263
|
+
if (popover?.kind !== "find" || this.#findHeld.text === "") return;
|
|
21264
|
+
this.#dropFindAll();
|
|
21265
|
+
const listed2 = made4();
|
|
21266
|
+
if (!isFindAllList(listed2)) throw new TypeError("listFindAll's function answers a list: { count, line, choose } (ADR-0470 \xA77).");
|
|
21267
|
+
if (!Number.isInteger(listed2.count) || listed2.count < 0) {
|
|
21268
|
+
throw new RangeError(`listFindAll's list holds ${String(listed2.count)} lines: a count is a whole number from 0 (ADR-0470 \xA77).`);
|
|
21269
|
+
}
|
|
21270
|
+
const request = Object.freeze({
|
|
21271
|
+
...this.#findPattern(),
|
|
21272
|
+
columns: Object.freeze(this.#columns.map(({ column }) => column.name)),
|
|
21273
|
+
rowSequenceVersion: this.#state.rowSequenceVersion
|
|
21274
|
+
});
|
|
21275
|
+
const list = {
|
|
21276
|
+
source: this.#source,
|
|
21277
|
+
sequence: this.#sequence(),
|
|
21278
|
+
request,
|
|
21279
|
+
columnCount: request.columns.length,
|
|
21280
|
+
headers: [],
|
|
21281
|
+
rowTotal: listed2.count,
|
|
21282
|
+
pages: /* @__PURE__ */ new Map(),
|
|
21283
|
+
asking: /* @__PURE__ */ new Map(),
|
|
21284
|
+
active: void 0,
|
|
21285
|
+
activeFor: void 0,
|
|
21286
|
+
view: void 0,
|
|
21287
|
+
gone: void 0,
|
|
21288
|
+
part: void 0,
|
|
21289
|
+
own: listed2
|
|
21290
|
+
};
|
|
21291
|
+
this.#showFindAll(popover.panel, list);
|
|
21292
|
+
this.#invalidate();
|
|
21293
|
+
}
|
|
21294
|
+
// The list's part, made and placed under the panel's contents.
|
|
21295
|
+
#showFindAll(panel, list) {
|
|
21296
|
+
this.#findAll = list;
|
|
21297
|
+
const part2 = new FindAllList(this.#root.ownerDocument, {
|
|
21298
|
+
count: () => this.#findAllCount(list),
|
|
21299
|
+
line: (index) => this.#findAllLine(list, index),
|
|
21300
|
+
active: () => list.active,
|
|
21301
|
+
inView: (first, last) => {
|
|
21302
|
+
this.#findAllInView(list, first, last);
|
|
21303
|
+
},
|
|
21304
|
+
choose: (index) => {
|
|
21305
|
+
this.#findAllChoose(list, index);
|
|
21306
|
+
},
|
|
21307
|
+
answered: this.#answer,
|
|
21308
|
+
label: this.#labelOf(findPanelLabelIds.findAllList)
|
|
21309
|
+
}, this.#metrics.rowHeightPx);
|
|
21310
|
+
list.part = part2;
|
|
21311
|
+
panel.showFindAll(part2.element);
|
|
21312
|
+
this.#sayFindAll(list);
|
|
21313
|
+
}
|
|
21314
|
+
// The lines the list holds: the headers matched and every row's match, none once it has gone, or `undefined`
|
|
21315
|
+
// while the first page is out.
|
|
21316
|
+
#findAllCount(list) {
|
|
21317
|
+
if (list.gone !== void 0) return 0;
|
|
21318
|
+
if (list.own !== void 0) return list.own.count;
|
|
21319
|
+
return list.rowTotal === void 0 ? void 0 : list.headers.length + list.rowTotal;
|
|
21320
|
+
}
|
|
21321
|
+
// Line `index` in the grid's words (ADR-0470 §3), or `undefined` while its page is not read.
|
|
21322
|
+
#findAllLine(list, index) {
|
|
21323
|
+
if (list.own !== void 0) {
|
|
21324
|
+
const line = list.own.line(index);
|
|
21325
|
+
if (!isFindAllLine(line)) throw new TypeError(`listFindAll's list answered line ${String(index)} as something other than { where, text } (ADR-0470 \xA77).`);
|
|
21326
|
+
return line;
|
|
21327
|
+
}
|
|
21328
|
+
const header = list.headers[index];
|
|
21329
|
+
if (header !== void 0) {
|
|
21330
|
+
return { where: filledWords(this.#labelOf(findPanelLabelIds.findAllInHeader), { column: header.text }), text: header.text };
|
|
21331
|
+
}
|
|
21332
|
+
const match = this.#findAllMatchAt(list, index - list.headers.length);
|
|
21333
|
+
if (match === void 0) return void 0;
|
|
21334
|
+
const resolved = this.#columns.find(({ column: column2 }) => column2.name === match.column);
|
|
21335
|
+
const column = resolved === void 0 ? match.column : headerOf(resolved);
|
|
21336
|
+
const where = match.rowLabel === void 0 ? filledWords(this.#labelOf(findPanelLabelIds.findAllInRow), { row: String(match.row + 1), column }) : filledWords(this.#labelOf(findPanelLabelIds.findAllInLabelledRow), { row: match.rowLabel, column });
|
|
21337
|
+
return { where, text: match.text };
|
|
21338
|
+
}
|
|
21339
|
+
// The row match at `at` among the rows' matches, where its page has been read.
|
|
21340
|
+
#findAllMatchAt(list, at) {
|
|
21341
|
+
if (at < 0) return void 0;
|
|
21342
|
+
return list.pages.get(Math.floor(at / findAllPageSize))?.[at % findAllPageSize];
|
|
21343
|
+
}
|
|
21344
|
+
// What the count line says (ADR-0470 §3, §5).
|
|
21345
|
+
#sayFindAll(list) {
|
|
21346
|
+
const count = this.#findAllCount(list);
|
|
21347
|
+
const text3 = list.gone !== void 0 ? this.#labelOf(list.gone === "orderChanged" ? findPanelLabelIds.orderChanged : findPanelLabelIds.sourceChanged) : count === void 0 ? "" : count === 0 ? this.#labelOf(findPanelLabelIds.findAllNone) : count === 1 ? this.#labelOf(findPanelLabelIds.findAllFoundOne) : filledWords(this.#labelOf(findPanelLabelIds.findAllFound), { count: String(count) });
|
|
21348
|
+
list.part?.say(text3);
|
|
21349
|
+
}
|
|
21350
|
+
// The list's lines from `first` to `last` are in view: their pages are asked, and the next one ahead, one at a time
|
|
21351
|
+
// (ADR-0470 §2): a page asked while another is out waits for it.
|
|
21352
|
+
#findAllInView(list, first, last) {
|
|
21353
|
+
list.view = { first, last };
|
|
21354
|
+
if (this.#findAll !== list || list.own !== void 0 || list.gone !== void 0 || list.rowTotal === void 0 || list.asking.size > 0) return;
|
|
21355
|
+
const rows = list.rowTotal;
|
|
21356
|
+
const from = Math.max(0, first - list.headers.length);
|
|
21357
|
+
const to = Math.min(rows - 1, last - list.headers.length + findAllVisibleLines);
|
|
21358
|
+
for (let page = Math.floor(from / findAllPageSize); page <= Math.floor(to / findAllPageSize); page++) {
|
|
21359
|
+
if (!list.pages.has(page)) {
|
|
21360
|
+
this.#askFindAllPage(list, page, void 0);
|
|
21361
|
+
return;
|
|
21362
|
+
}
|
|
21363
|
+
}
|
|
21364
|
+
}
|
|
21365
|
+
/**
|
|
21366
|
+
* One page of the list asked of the source. The first, and one a choice waits on, is an answer out in the Input
|
|
21367
|
+
* Order (ADR-0451 section 3): the inputs made meanwhile wait for it, and an Escape cancels it. `then` runs once it
|
|
21368
|
+
* has landed, before those inputs.
|
|
21369
|
+
*/
|
|
21370
|
+
#askFindAllPage(list, page, pended, then) {
|
|
21371
|
+
const { source } = list;
|
|
21372
|
+
const controller = new AbortController();
|
|
21373
|
+
list.asking.set(page, controller);
|
|
21374
|
+
const request = Object.freeze({ ...list.request, start: page * findAllPageSize, count: findAllPageSize });
|
|
21375
|
+
if (pended !== void 0) this.#invalidate();
|
|
21376
|
+
const asked = Promise.resolve().then(() => {
|
|
21377
|
+
if (source.findAll === void 0) throw new Error("Internal: a Find All page asked of a source that lists nothing.");
|
|
21378
|
+
return source.findAll(request, controller.signal);
|
|
21379
|
+
});
|
|
21380
|
+
const next2 = () => {
|
|
21381
|
+
const { view } = list;
|
|
21382
|
+
if (this.#findAll === list && list.gone === void 0 && view !== void 0) this.#findAllInView(list, view.first, view.last);
|
|
21383
|
+
};
|
|
21384
|
+
const landed = asked.then((answer) => {
|
|
21385
|
+
if (this.#destroyed || list.asking.get(page) !== controller) return;
|
|
21386
|
+
list.asking.delete(page);
|
|
21387
|
+
if (pended !== void 0) this.#invalidate();
|
|
21388
|
+
if (this.#findAll === list && list.gone === void 0) this.#findAllAnswered(list, page, request, answer);
|
|
21389
|
+
then?.();
|
|
21390
|
+
next2();
|
|
21391
|
+
}, (error) => {
|
|
21392
|
+
if (this.#destroyed || list.asking.get(page) !== controller) return;
|
|
21393
|
+
list.asking.delete(page);
|
|
21394
|
+
if (pended !== void 0) this.#invalidate();
|
|
21395
|
+
if (error instanceof DOMException && error.name === "AbortError") {
|
|
21396
|
+
if (pended === "first" && this.#findAll === list) this.#dropFindAll();
|
|
21397
|
+
else next2();
|
|
21398
|
+
return;
|
|
21399
|
+
}
|
|
21400
|
+
throw error;
|
|
21401
|
+
});
|
|
21402
|
+
if (pended === void 0) return;
|
|
21403
|
+
this.#pendStep(landed, controller, () => {
|
|
21404
|
+
if (list.asking.get(page) !== controller) return;
|
|
21405
|
+
list.asking.delete(page);
|
|
21406
|
+
if (pended === "first" && this.#findAll === list) this.#dropFindAll();
|
|
21407
|
+
this.#invalidate();
|
|
21408
|
+
});
|
|
21409
|
+
}
|
|
21410
|
+
// A page's answer, judged against what it was asked under (ADR-0470 §2).
|
|
21411
|
+
#findAllAnswered(list, page, request, answer) {
|
|
21412
|
+
const given2 = answer;
|
|
21413
|
+
if (typeof given2 !== "object" || given2 === null || !Array.isArray(given2.matches) || typeof given2.total !== "number" || typeof given2.rowSequenceVersion !== "number") {
|
|
21414
|
+
throw new TypeError("The source's findAll answered something other than a Find All page: { total, matches, rowSequenceVersion }, as findAllPage makes one (ADR-0470).");
|
|
21415
|
+
}
|
|
21416
|
+
if (list.source !== this.#source) {
|
|
21417
|
+
this.#findAllGone(list, "sourceChanged");
|
|
21418
|
+
return;
|
|
21419
|
+
}
|
|
21420
|
+
if (answer.rowSequenceVersion !== request.rowSequenceVersion || list.sequence !== this.#sequence()) {
|
|
21421
|
+
this.#findAllGone(list, "orderChanged");
|
|
21422
|
+
return;
|
|
21423
|
+
}
|
|
21424
|
+
const { total, matches: matches3 } = answer;
|
|
21425
|
+
if (!Number.isInteger(total) || total < 0) throw new RangeError(`The Find All answer counts ${total} matches: a count is a whole number from 0 (ADR-0470).`);
|
|
21426
|
+
if (list.rowTotal !== void 0 && total !== list.rowTotal) {
|
|
21427
|
+
this.#findAllGone(list, "orderChanged");
|
|
21428
|
+
return;
|
|
21429
|
+
}
|
|
21430
|
+
const owed = Math.max(0, Math.min(request.count, total - request.start));
|
|
21431
|
+
if (matches3.length !== owed) {
|
|
21432
|
+
throw new RangeError(`The Find All answer holds ${matches3.length} matches for the entries ${request.start} on of a list of ${total}: it owes ${owed} (ADR-0470 \xA72).`);
|
|
21433
|
+
}
|
|
21434
|
+
let before = -1;
|
|
21435
|
+
for (const match of matches3) {
|
|
21436
|
+
const column = request.columns.indexOf(match.column);
|
|
21437
|
+
const ordinal2 = match.row * list.columnCount + column;
|
|
21438
|
+
if (column < 0 || !Number.isInteger(match.row) || match.row < 0 || match.row >= this.#totalRows || typeof match.text !== "string" || match.rowLabel !== void 0 && typeof match.rowLabel !== "string" || request.scope !== void 0 && !inScope(request.scope, match.row, column) || ordinal2 <= before) {
|
|
21439
|
+
throw new RangeError(`The Find All answer names row ${match.row}, column '${match.column}', outside the request or out of its order: it asked about the columns [${request.columns.join(", ")}] of a result of ${this.#totalRows} rows, by rows (ADR-0470 \xA72).`);
|
|
21440
|
+
}
|
|
21441
|
+
before = ordinal2;
|
|
21442
|
+
}
|
|
21443
|
+
list.rowTotal = total;
|
|
21444
|
+
list.pages.set(page, matches3);
|
|
21445
|
+
this.#sayFindAll(list);
|
|
21446
|
+
list.part?.refresh();
|
|
21447
|
+
}
|
|
21448
|
+
/**
|
|
21449
|
+
* A line chosen from the list (ADR-0470 §4): the Focus moves to its cell and reveals it, as a step that found it
|
|
21450
|
+
* does, or a header becomes the current match. Taken in its turn, against what the list was read under: under
|
|
21451
|
+
* another version or source, the list goes and says so, and nothing moves. A line whose page is not yet read, as
|
|
21452
|
+
* End's in a long list, waits for its page as an answer out, and is chosen once it is in.
|
|
21453
|
+
*/
|
|
21454
|
+
#findAllChoose(list, index) {
|
|
21455
|
+
if (this.#stepInTurn(() => {
|
|
21456
|
+
this.#findAllChoose(list, index);
|
|
21457
|
+
})) return;
|
|
21458
|
+
this.#findAllChooseNow(list, index, true);
|
|
21459
|
+
}
|
|
21460
|
+
#findAllChooseNow(list, index, mayAsk) {
|
|
21461
|
+
if (this.#findAll !== list || list.gone !== void 0) return;
|
|
21462
|
+
if (list.own !== void 0) {
|
|
21463
|
+
if (index < 0 || index >= list.own.count) return;
|
|
21464
|
+
const moved = list.own.choose(index);
|
|
21465
|
+
if (typeof moved !== "boolean") throw new TypeError(`listFindAll's choose answers whether it moved, not ${typeof moved} (ADR-0470 \xA77).`);
|
|
21466
|
+
if (moved && this.#findAll === list) {
|
|
21467
|
+
list.active = index;
|
|
21468
|
+
list.activeFor = this.#findCurrent ?? this.#findCurrentHeader;
|
|
21469
|
+
}
|
|
21470
|
+
if (this.#findAll === list) list.part?.refresh();
|
|
21471
|
+
this.#invalidate();
|
|
21472
|
+
return;
|
|
21473
|
+
}
|
|
21474
|
+
if (list.source !== this.#source) {
|
|
21475
|
+
this.#findAllGone(list, "sourceChanged");
|
|
21476
|
+
return;
|
|
21477
|
+
}
|
|
21478
|
+
if (list.sequence !== this.#sequence()) {
|
|
21479
|
+
this.#findAllGone(list, "orderChanged");
|
|
21480
|
+
return;
|
|
21481
|
+
}
|
|
21482
|
+
const header = list.headers[index];
|
|
21483
|
+
const match = header === void 0 ? this.#findAllMatchAt(list, index - list.headers.length) : void 0;
|
|
21484
|
+
if (header === void 0 && match === void 0) {
|
|
21485
|
+
const count = this.#findAllCount(list);
|
|
21486
|
+
if (!mayAsk || count === void 0 || index < list.headers.length || index >= count) return;
|
|
21487
|
+
for (const controller of list.asking.values()) controller.abort();
|
|
21488
|
+
list.asking.clear();
|
|
21489
|
+
this.#askFindAllPage(list, Math.floor((index - list.headers.length) / findAllPageSize), "choice", () => {
|
|
21490
|
+
this.#findAllChooseNow(list, index, false);
|
|
21491
|
+
});
|
|
21492
|
+
return;
|
|
21493
|
+
}
|
|
21494
|
+
this.#findStepping?.abort();
|
|
21495
|
+
this.#findStepping = void 0;
|
|
21496
|
+
this.#reconcileSelection();
|
|
21497
|
+
if (header !== void 0) {
|
|
21498
|
+
const now = this.#findHeaders().find(({ id }) => id === header.id);
|
|
21499
|
+
if (now === void 0) {
|
|
21500
|
+
this.#findAllGone(list, "orderChanged");
|
|
21501
|
+
return;
|
|
21502
|
+
}
|
|
21503
|
+
list.active = index;
|
|
21504
|
+
this.#landOnHeader(now);
|
|
21505
|
+
list.activeFor = this.#findCurrentHeader;
|
|
21506
|
+
} else if (match !== void 0) {
|
|
21507
|
+
const column = this.#columns.findIndex(({ column: declared }) => declared.name === match.column);
|
|
21508
|
+
if (column < 0) {
|
|
21509
|
+
this.#findAllGone(list, "orderChanged");
|
|
21510
|
+
return;
|
|
21511
|
+
}
|
|
21512
|
+
list.active = index;
|
|
21513
|
+
const found = cell(match.row, column);
|
|
21514
|
+
this.#findCurrent = { cell: found, version: this.#sequence() };
|
|
21515
|
+
list.activeFor = this.#findCurrent;
|
|
21516
|
+
this.#findCurrentHeader = void 0;
|
|
21517
|
+
this.#setFindOutcome({ kind: "found" });
|
|
21518
|
+
const held2 = this.#held.selection;
|
|
21519
|
+
this.#apply(list.request.scope !== void 0 && held2.cellCount > 1 && held2.contains(found) ? held2.focusOn(found) : held2.click(found, this.#extent));
|
|
21520
|
+
this.#revealOwed = { target: found, extending: void 0, rowStart: false, stepRows: 0 };
|
|
21521
|
+
this.#revealHeaderOwed = void 0;
|
|
21522
|
+
this.#followArmed = { focus: found, target: found };
|
|
21523
|
+
}
|
|
21524
|
+
list.part?.refresh();
|
|
21525
|
+
this.#invalidate();
|
|
21526
|
+
}
|
|
21527
|
+
// In each pass: the list's current line follows the current match, which a step, a Replace or a placed match may
|
|
21528
|
+
// have moved since the line was chosen (ADR-0470 §4): the line of the new one where its page is read, else none.
|
|
21529
|
+
// A list of the Chrome's own keeps the line it chose: what its contents' current match is, the contents know.
|
|
21530
|
+
#findAllFollowCurrent() {
|
|
21531
|
+
const list = this.#findAll;
|
|
21532
|
+
if (list === void 0 || list.own !== void 0 || list.gone !== void 0) return;
|
|
21533
|
+
const current = this.#findCurrent ?? this.#findCurrentHeader;
|
|
21534
|
+
if (current === list.activeFor) return;
|
|
21535
|
+
list.activeFor = current;
|
|
21536
|
+
list.active = this.#findAllLineOf(list);
|
|
21537
|
+
list.part?.refresh();
|
|
21538
|
+
}
|
|
21539
|
+
// The line the current match stands on among what the list has read, or none.
|
|
21540
|
+
#findAllLineOf(list) {
|
|
21541
|
+
const header = this.#findCurrentHeader;
|
|
21542
|
+
if (header !== void 0) {
|
|
21543
|
+
const at = list.headers.findIndex(({ id }) => id === header.id);
|
|
21544
|
+
return at < 0 ? void 0 : at;
|
|
21545
|
+
}
|
|
21546
|
+
const current = this.#findCurrent;
|
|
21547
|
+
if (current === void 0 || current.version !== list.sequence) return void 0;
|
|
21548
|
+
const column = this.#columns[current.cell.column]?.column.name;
|
|
21549
|
+
for (const [page, matches3] of list.pages) {
|
|
21550
|
+
const at = matches3.findIndex((match) => match.row === current.cell.row && match.column === column);
|
|
21551
|
+
if (at >= 0) return list.headers.length + page * findAllPageSize + at;
|
|
21552
|
+
}
|
|
21553
|
+
return void 0;
|
|
21554
|
+
}
|
|
21555
|
+
// The list read under another order or from another source (ADR-0470 §5): its lines go, the count line says why,
|
|
21556
|
+
// and nothing is asked again.
|
|
21557
|
+
#findAllGone(list, reason) {
|
|
21558
|
+
if (list.gone !== void 0) return;
|
|
21559
|
+
list.gone = reason;
|
|
21560
|
+
for (const controller of list.asking.values()) controller.abort();
|
|
21561
|
+
list.asking.clear();
|
|
21562
|
+
list.pages.clear();
|
|
21563
|
+
list.active = void 0;
|
|
21564
|
+
this.#sayFindAll(list);
|
|
21565
|
+
list.part?.refresh();
|
|
21566
|
+
}
|
|
21567
|
+
// The list taken away (ADR-0470 §5): a new Find All, a new search, the panel closed, a Replace All.
|
|
21568
|
+
#dropFindAll() {
|
|
21569
|
+
const list = this.#findAll;
|
|
21570
|
+
if (list === void 0) return;
|
|
21571
|
+
this.#findAll = void 0;
|
|
21572
|
+
for (const controller of list.asking.values()) controller.abort();
|
|
21573
|
+
list.asking.clear();
|
|
21574
|
+
const popover = this.#popover;
|
|
21575
|
+
if (popover?.kind === "find") popover.panel.showFindAll(void 0);
|
|
21576
|
+
else list.part?.element.remove();
|
|
21577
|
+
}
|
|
21578
|
+
// In each pass: a list whose order or source has moved since it was read goes (ADR-0470 §5).
|
|
21579
|
+
#forgetFindAllOffSequence() {
|
|
21580
|
+
const list = this.#findAll;
|
|
21581
|
+
if (list === void 0 || list.own !== void 0 || list.gone !== void 0) return;
|
|
21582
|
+
if (list.source !== this.#source) this.#findAllGone(list, "sourceChanged");
|
|
21583
|
+
else if (list.sequence !== this.#sequence()) this.#findAllGone(list, "orderChanged");
|
|
21584
|
+
}
|
|
21585
|
+
// The search the panel holds changed: a list of another search goes, so it never lists what the field no longer asks.
|
|
21586
|
+
#findAllHeldChanged() {
|
|
21587
|
+
const list = this.#findAll;
|
|
21588
|
+
if (list === void 0) return;
|
|
21589
|
+
const { text: text3, matchCase, wholeCell } = this.#findHeld;
|
|
21590
|
+
if (list.request.text !== text3 || list.request.matchCase !== matchCase || list.request.wholeCell !== wholeCell) this.#dropFindAll();
|
|
21591
|
+
}
|
|
20553
21592
|
// ---- The clipboard (ADR-0005) ------------------------------------------------------------------------
|
|
20554
21593
|
// A copy the browser's command asked for. Refused, the clipboard stays as it was: the default copy of a
|
|
20555
21594
|
// user-select: none root carries nothing, so the event is left alone. Approved, a Selection the Window
|
|
@@ -21070,6 +22109,7 @@ var GridView = class {
|
|
|
21070
22109
|
if (!dragging) {
|
|
21071
22110
|
this.#forgetHeadingDrag();
|
|
21072
22111
|
this.#endHandleDrag();
|
|
22112
|
+
this.#endGripDrag();
|
|
21073
22113
|
this.#pointDragging = false;
|
|
21074
22114
|
this.#pointedDrag = void 0;
|
|
21075
22115
|
}
|
|
@@ -21694,7 +22734,7 @@ var GridView = class {
|
|
|
21694
22734
|
if (row !== void 0 && column !== void 0) {
|
|
21695
22735
|
const extent = this.#extent;
|
|
21696
22736
|
const current = this.#held.selection;
|
|
21697
|
-
changed = this.#handleDrag !== void 0 ? this.#moveHandlePointer(cell(row, column)) : this.#apply(!this.#headingDrag ? current.extendTo(cell(row, column), extent) : this.#headingAxis === "rows" ? current.extendToRow(row, extent, this.#firstVisibleColumn) : current.extendToColumn(column, extent, this.#firstVisibleRow));
|
|
22737
|
+
changed = this.#gripDrag !== void 0 ? this.#moveGripDrag(cell(row, column)) : this.#handleDrag !== void 0 ? this.#moveHandlePointer(cell(row, column)) : this.#apply(!this.#headingDrag ? current.extendTo(cell(row, column), extent) : this.#headingAxis === "rows" ? current.extendToRow(row, extent, this.#firstVisibleColumn) : current.extendToColumn(column, extent, this.#firstVisibleRow));
|
|
21698
22738
|
}
|
|
21699
22739
|
if (moved || changed) this.#invalidate();
|
|
21700
22740
|
};
|
|
@@ -21951,13 +22991,18 @@ var GridView = class {
|
|
|
21951
22991
|
// A row the source has since taken away has no band; the next movement finds the row there now.
|
|
21952
22992
|
hoverRow: this.#hoverRow !== void 0 && this.#hoverRow < this.#totalRows ? this.#hoverRow : void 0,
|
|
21953
22993
|
focusRow: this.#highlightFocusRow,
|
|
22994
|
+
focusColumn: this.#highlightFocusColumn,
|
|
21954
22995
|
// Each held, so a pass that changed neither text nor columns finds them the same.
|
|
21955
22996
|
colouring: this.#colouring(),
|
|
21956
22997
|
extentRows: this.#totalRows,
|
|
21957
22998
|
extentColumns: this.#columns.length,
|
|
21958
22999
|
pointer: this.#edit === void 0 ? void 0 : this.#pointer,
|
|
21959
23000
|
outlinedColumns: this.#referenceOutlines.columns(this.#outlinedColumnsBoth(), this.#columnNames, this.#totalRows),
|
|
21960
|
-
pointDashes: this.#pointDashesRange()
|
|
23001
|
+
pointDashes: this.#pointDashesRange(),
|
|
23002
|
+
// The grips (ADR-0480): drawn while a Reference can be dragged, held at the edges of what covers them.
|
|
23003
|
+
grips: this.#gripsShown(),
|
|
23004
|
+
pinnedWidthPx: this.#styles.geometry.pinnedWidthPx,
|
|
23005
|
+
leadWidthPx: this.#styles.geometry.leadWidthPx
|
|
21961
23006
|
};
|
|
21962
23007
|
const was = this.#layerInputs;
|
|
21963
23008
|
if (was === void 0 || Object.entries(inputs).some(([name, value]) => was[name] !== value)) {
|
|
@@ -21969,7 +23014,7 @@ var GridView = class {
|
|
|
21969
23014
|
inputs.rowHeightPx,
|
|
21970
23015
|
visible,
|
|
21971
23016
|
{ firstOpenRow, scrollLeftPx: this.#scrollLeftPx, hasHeader: true },
|
|
21972
|
-
{ hoverRow: inputs.hoverRow, focusRow: inputs.focusRow },
|
|
23017
|
+
{ hoverRow: inputs.hoverRow, focusRow: inputs.focusRow, focusColumn: inputs.focusColumn, rowCount: inputs.extentRows },
|
|
21973
23018
|
this.#fillPaint(handle2, readable),
|
|
21974
23019
|
{
|
|
21975
23020
|
references: inputs.colouring.outlines.flatMap(([range, colour]) => {
|
|
@@ -21978,17 +23023,23 @@ var GridView = class {
|
|
|
21978
23023
|
}),
|
|
21979
23024
|
columns: inputs.outlinedColumns,
|
|
21980
23025
|
point: this.#pointPaint(inputs.pointer, inputs.colouring),
|
|
21981
|
-
pointDashes: inputs.pointDashes
|
|
23026
|
+
pointDashes: inputs.pointDashes,
|
|
23027
|
+
grips: inputs.grips ? this.#gripPaint(inputs.colouring, inputs.extentRows, inputs.extentColumns) : void 0
|
|
21982
23028
|
}
|
|
21983
23029
|
);
|
|
21984
23030
|
const signature = JSON.stringify(pieces);
|
|
21985
23031
|
if (signature !== this.#paintedLayers) {
|
|
21986
23032
|
this.#paintedLayers = signature;
|
|
21987
23033
|
const fill = (layer, held2) => {
|
|
21988
|
-
|
|
23034
|
+
const pinned2 = layer !== this.#selectionLayer;
|
|
23035
|
+
layer.replaceChildren(...held2.map(({ className, style, grip }) => {
|
|
21989
23036
|
const made4 = this.#root.ownerDocument.createElement("div");
|
|
21990
23037
|
made4.className = className;
|
|
21991
23038
|
made4.setAttribute("style", style);
|
|
23039
|
+
if (grip !== void 0) {
|
|
23040
|
+
made4.setAttribute("data-ex-grip", grip.kind);
|
|
23041
|
+
this.#gripElements.set(made4, { grip, pinned: pinned2 });
|
|
23042
|
+
}
|
|
21992
23043
|
return made4;
|
|
21993
23044
|
}));
|
|
21994
23045
|
};
|
|
@@ -22099,6 +23150,9 @@ var GridView = class {
|
|
|
22099
23150
|
this.#write(this.#scroller, "scroller", "style", this.#scrollerStyle());
|
|
22100
23151
|
this.#write(this.#spacer, "spacer", "style", `width: ${geometry.totalWidthPx}px; height: ${this.#bandHeightPx + scrollHeightPx}px`);
|
|
22101
23152
|
this.#forgetCurrentMatchOffFocus();
|
|
23153
|
+
this.#forgetFindAllOffSequence();
|
|
23154
|
+
this.#findAllFollowCurrent();
|
|
23155
|
+
if (this.#popover?.kind === "find") this.#popover.panel.offerFindAll(this.#canFindAll);
|
|
22102
23156
|
this.#paintHeader();
|
|
22103
23157
|
this.#paintViewport();
|
|
22104
23158
|
this.#paintStatus();
|
|
@@ -23842,8 +24896,11 @@ function wireFindPanel(contents, context, answered2 = false) {
|
|
|
23842
24896
|
case "replaceAll":
|
|
23843
24897
|
context.replaceAll();
|
|
23844
24898
|
break;
|
|
24899
|
+
case "findAll":
|
|
24900
|
+
context.findAll();
|
|
24901
|
+
break;
|
|
23845
24902
|
default:
|
|
23846
|
-
throw new RangeError(`A find panel's button is marked ${findPanelAttributes.step}="${marked.value}": it is next, previous, replace or
|
|
24903
|
+
throw new RangeError(`A find panel's button is marked ${findPanelAttributes.step}="${marked.value}": it is next, previous, replace, replaceAll or findAll.`);
|
|
23847
24904
|
}
|
|
23848
24905
|
};
|
|
23849
24906
|
contents.addEventListener("input", input);
|
|
@@ -23891,9 +24948,9 @@ var completionAttributes = Object.freeze({
|
|
|
23891
24948
|
candidate: "data-ex-candidate"
|
|
23892
24949
|
});
|
|
23893
24950
|
function wireEditorCompletion(contents, context, current) {
|
|
23894
|
-
const
|
|
23895
|
-
if (
|
|
23896
|
-
const list =
|
|
24951
|
+
const lists2 = contents.querySelectorAll(`[${completionAttributes.list}]`);
|
|
24952
|
+
if (lists2.length > 1) throw new Error(`The completion's contents drew ${lists2.length} lists marked ${completionAttributes.list}: mark the one holding the candidates.`);
|
|
24953
|
+
const list = lists2[0];
|
|
23897
24954
|
if (list !== void 0) {
|
|
23898
24955
|
list.id = context.listId;
|
|
23899
24956
|
list.setAttribute("role", "listbox");
|
|
@@ -23963,6 +25020,14 @@ var japaneseGridWordTable = /* @__PURE__ */ new Map([
|
|
|
23963
25020
|
["find-replace-refused-cell", "{row} \u884C\u76EE\u3001{column}: {reason}\u3002"],
|
|
23964
25021
|
["find-replace-refused-more", "\u307B\u304B {count} \u4EF6\u3002"],
|
|
23965
25022
|
["find-not-editable", "\u3053\u306E\u5217\u306F\u7DE8\u96C6\u3067\u304D\u307E\u305B\u3093"],
|
|
25023
|
+
["find-all", "\u3059\u3079\u3066\u691C\u7D22"],
|
|
25024
|
+
["find-all-list", "\u691C\u7D22\u7D50\u679C"],
|
|
25025
|
+
["find-all-found", "{count} \u500B\u306E\u30BB\u30EB\u304C\u898B\u3064\u304B\u308A\u307E\u3057\u305F"],
|
|
25026
|
+
["find-all-found-one", "1 \u500B\u306E\u30BB\u30EB\u304C\u898B\u3064\u304B\u308A\u307E\u3057\u305F"],
|
|
25027
|
+
["find-all-none", "\u4E00\u81F4\u3059\u308B\u30BB\u30EB\u306F\u3042\u308A\u307E\u305B\u3093"],
|
|
25028
|
+
["find-all-in-row", "{row} \u884C\u76EE\u3001{column}"],
|
|
25029
|
+
["find-all-in-labelled-row", "{row}\u3001{column}"],
|
|
25030
|
+
["find-all-in-header", "\u898B\u51FA\u3057 {column}"],
|
|
23966
25031
|
["filter-ok", "OK"],
|
|
23967
25032
|
["filter-cancel", "\u30AD\u30E3\u30F3\u30BB\u30EB"],
|
|
23968
25033
|
["filter-search", "\u691C\u7D22"],
|
|
@@ -24592,7 +25657,7 @@ var FetchingGridSource = class _FetchingGridSource {
|
|
|
24592
25657
|
#named;
|
|
24593
25658
|
constructor(fetch, options) {
|
|
24594
25659
|
if (typeof fetch !== "function") throw new TypeError("GridSource.fetch takes a function that answers a Query with a page.");
|
|
24595
|
-
const { readAheadRows = defaultReadAheadRows, distinctValues, find, summarize, rowKey, marks: marks2, onFetchFailed, clock = systemClock } = options;
|
|
25660
|
+
const { readAheadRows = defaultReadAheadRows, distinctValues, find, findAll: findAll2, summarize, rowKey, marks: marks2, onFetchFailed, clock = systemClock } = options;
|
|
24596
25661
|
if (!Number.isSafeInteger(readAheadRows) || readAheadRows < 0) {
|
|
24597
25662
|
throw new RangeError(`readAheadRows is a whole number of at least 0, not ${readAheadRows}.`);
|
|
24598
25663
|
}
|
|
@@ -24618,6 +25683,13 @@ var FetchingGridSource = class _FetchingGridSource {
|
|
|
24618
25683
|
return find(request, this.#inForce(), signal);
|
|
24619
25684
|
};
|
|
24620
25685
|
}
|
|
25686
|
+
if (findAll2 !== void 0) {
|
|
25687
|
+
if (find === void 0) throw new TypeError("A Find All is offered beside a Find: give `find` with `findAll` (ADR-0470 \xA71).");
|
|
25688
|
+
this.findAll = async (request, signal) => {
|
|
25689
|
+
this.#requireUndisposed();
|
|
25690
|
+
return findAll2(request, this.#inForce(), signal);
|
|
25691
|
+
};
|
|
25692
|
+
}
|
|
24621
25693
|
if (summarize !== void 0) {
|
|
24622
25694
|
this.summarize = async (request, signal) => {
|
|
24623
25695
|
this.#requireUndisposed();
|
|
@@ -27270,6 +28342,7 @@ export {
|
|
|
27270
28342
|
EditorHint,
|
|
27271
28343
|
FetchingGridSource,
|
|
27272
28344
|
FetchingRowMarks,
|
|
28345
|
+
FindAllMatches,
|
|
27273
28346
|
FormatCode,
|
|
27274
28347
|
GlyphWidthTable,
|
|
27275
28348
|
GridMetrics,
|
|
@@ -27308,6 +28381,8 @@ export {
|
|
|
27308
28381
|
exactDecimalDigits,
|
|
27309
28382
|
filterPanelAttributes,
|
|
27310
28383
|
filterPanelLabelIds,
|
|
28384
|
+
findAll,
|
|
28385
|
+
findAllPage,
|
|
27311
28386
|
findMatches,
|
|
27312
28387
|
findOutcomeText,
|
|
27313
28388
|
findPanelAttributes,
|