@particle-academy/fancy-sheets 0.2.0 → 0.3.0
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.cjs +183 -22
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +6 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.js +183 -22
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.d.cts
CHANGED
|
@@ -7,11 +7,15 @@ type CellAddress = string;
|
|
|
7
7
|
type CellValue = string | number | boolean | null;
|
|
8
8
|
/** Text alignment */
|
|
9
9
|
type TextAlign = "left" | "center" | "right";
|
|
10
|
+
/** Display format for cell values */
|
|
11
|
+
type CellDisplayFormat = "auto" | "text" | "number" | "date" | "datetime" | "percentage" | "currency";
|
|
10
12
|
/** Cell formatting */
|
|
11
13
|
interface CellFormat {
|
|
12
14
|
bold?: boolean;
|
|
13
15
|
italic?: boolean;
|
|
14
16
|
textAlign?: TextAlign;
|
|
17
|
+
/** Display format — controls how the value is rendered */
|
|
18
|
+
displayFormat?: CellDisplayFormat;
|
|
15
19
|
}
|
|
16
20
|
/** A single cell's complete data */
|
|
17
21
|
interface CellData {
|
|
@@ -116,6 +120,8 @@ interface SpreadsheetContextValue {
|
|
|
116
120
|
renameSheet: (sheetId: string, name: string) => void;
|
|
117
121
|
deleteSheet: (sheetId: string) => void;
|
|
118
122
|
setActiveSheet: (sheetId: string) => void;
|
|
123
|
+
setFrozenRows: (count: number) => void;
|
|
124
|
+
setFrozenCols: (count: number) => void;
|
|
119
125
|
undo: () => void;
|
|
120
126
|
redo: () => void;
|
|
121
127
|
canUndo: boolean;
|
package/dist/index.d.ts
CHANGED
|
@@ -7,11 +7,15 @@ type CellAddress = string;
|
|
|
7
7
|
type CellValue = string | number | boolean | null;
|
|
8
8
|
/** Text alignment */
|
|
9
9
|
type TextAlign = "left" | "center" | "right";
|
|
10
|
+
/** Display format for cell values */
|
|
11
|
+
type CellDisplayFormat = "auto" | "text" | "number" | "date" | "datetime" | "percentage" | "currency";
|
|
10
12
|
/** Cell formatting */
|
|
11
13
|
interface CellFormat {
|
|
12
14
|
bold?: boolean;
|
|
13
15
|
italic?: boolean;
|
|
14
16
|
textAlign?: TextAlign;
|
|
17
|
+
/** Display format — controls how the value is rendered */
|
|
18
|
+
displayFormat?: CellDisplayFormat;
|
|
15
19
|
}
|
|
16
20
|
/** A single cell's complete data */
|
|
17
21
|
interface CellData {
|
|
@@ -116,6 +120,8 @@ interface SpreadsheetContextValue {
|
|
|
116
120
|
renameSheet: (sheetId: string, name: string) => void;
|
|
117
121
|
deleteSheet: (sheetId: string) => void;
|
|
118
122
|
setActiveSheet: (sheetId: string) => void;
|
|
123
|
+
setFrozenRows: (count: number) => void;
|
|
124
|
+
setFrozenCols: (count: number) => void;
|
|
119
125
|
undo: () => void;
|
|
120
126
|
redo: () => void;
|
|
121
127
|
canUndo: boolean;
|
package/dist/index.js
CHANGED
|
@@ -121,12 +121,41 @@ function lexFormula(input) {
|
|
|
121
121
|
if (ch >= "A" && ch <= "Z" || ch >= "a" && ch <= "z" || ch === "_") {
|
|
122
122
|
const pos = i;
|
|
123
123
|
i++;
|
|
124
|
-
while (i < len && (input[i] >= "A" && input[i] <= "Z" || input[i] >= "a" && input[i] <= "z" || input[i] >= "0" && input[i] <= "9" || input[i] === "_"))
|
|
125
|
-
|
|
124
|
+
while (i < len && (input[i] >= "A" && input[i] <= "Z" || input[i] >= "a" && input[i] <= "z" || input[i] >= "0" && input[i] <= "9" || input[i] === "_" || input[i] === " ")) {
|
|
125
|
+
if (input[i] === " ") {
|
|
126
|
+
let lookAhead = i + 1;
|
|
127
|
+
while (lookAhead < len && input[lookAhead] === " ") lookAhead++;
|
|
128
|
+
if (lookAhead < len && (input[lookAhead] >= "A" && input[lookAhead] <= "Z" || input[lookAhead] >= "a" && input[lookAhead] <= "z" || input[lookAhead] >= "0" && input[lookAhead] <= "9" || input[lookAhead] === "!")) {
|
|
129
|
+
i++;
|
|
130
|
+
continue;
|
|
131
|
+
}
|
|
132
|
+
break;
|
|
133
|
+
}
|
|
134
|
+
i++;
|
|
135
|
+
}
|
|
136
|
+
let word = input.slice(pos, i).trimEnd();
|
|
137
|
+
i = pos + word.length;
|
|
126
138
|
if (word.toUpperCase() === "TRUE" || word.toUpperCase() === "FALSE") {
|
|
127
139
|
tokens.push({ type: "boolean", value: word.toUpperCase(), position: pos });
|
|
128
140
|
continue;
|
|
129
141
|
}
|
|
142
|
+
if (i < len && input[i] === "!") {
|
|
143
|
+
const sheetName = word;
|
|
144
|
+
i++;
|
|
145
|
+
const refStart = i;
|
|
146
|
+
while (i < len && (input[i] >= "A" && input[i] <= "Z" || input[i] >= "a" && input[i] <= "z" || input[i] >= "0" && input[i] <= "9")) i++;
|
|
147
|
+
const ref1 = input.slice(refStart, i);
|
|
148
|
+
if (i < len && input[i] === ":") {
|
|
149
|
+
i++;
|
|
150
|
+
const ref2Start = i;
|
|
151
|
+
while (i < len && (input[i] >= "A" && input[i] <= "Z" || input[i] >= "a" && input[i] <= "z" || input[i] >= "0" && input[i] <= "9")) i++;
|
|
152
|
+
const ref2 = input.slice(ref2Start, i);
|
|
153
|
+
tokens.push({ type: "sheetRangeRef", value: sheetName + "!" + ref1 + ":" + ref2, position: pos });
|
|
154
|
+
} else {
|
|
155
|
+
tokens.push({ type: "sheetCellRef", value: sheetName + "!" + ref1.toUpperCase(), position: pos });
|
|
156
|
+
}
|
|
157
|
+
continue;
|
|
158
|
+
}
|
|
130
159
|
if (i < len && input[i] === ":") {
|
|
131
160
|
const colonPos = i;
|
|
132
161
|
i++;
|
|
@@ -270,6 +299,19 @@ function parseFormula(tokens) {
|
|
|
270
299
|
const parts = t.value.split(":");
|
|
271
300
|
return { type: "rangeRef", start: parts[0], end: parts[1] };
|
|
272
301
|
}
|
|
302
|
+
if (t.type === "sheetCellRef") {
|
|
303
|
+
advance();
|
|
304
|
+
const bangIdx = t.value.indexOf("!");
|
|
305
|
+
return { type: "sheetCellRef", sheet: t.value.slice(0, bangIdx), address: t.value.slice(bangIdx + 1).toUpperCase() };
|
|
306
|
+
}
|
|
307
|
+
if (t.type === "sheetRangeRef") {
|
|
308
|
+
advance();
|
|
309
|
+
const bangIdx = t.value.indexOf("!");
|
|
310
|
+
const sheetName = t.value.slice(0, bangIdx);
|
|
311
|
+
const rangePart = t.value.slice(bangIdx + 1);
|
|
312
|
+
const parts = rangePart.split(":");
|
|
313
|
+
return { type: "sheetRangeRef", sheet: sheetName, start: parts[0].toUpperCase(), end: parts[1].toUpperCase() };
|
|
314
|
+
}
|
|
273
315
|
if (t.type === "function") {
|
|
274
316
|
const name = advance().value;
|
|
275
317
|
expect("paren", "(");
|
|
@@ -1003,7 +1045,7 @@ registerFunction("TYPE", (args) => {
|
|
|
1003
1045
|
});
|
|
1004
1046
|
|
|
1005
1047
|
// src/engine/formula/evaluator.ts
|
|
1006
|
-
function evaluateAST(node, getCellValue, getRangeValues) {
|
|
1048
|
+
function evaluateAST(node, getCellValue, getRangeValues, ctx) {
|
|
1007
1049
|
switch (node.type) {
|
|
1008
1050
|
case "number":
|
|
1009
1051
|
return node.value;
|
|
@@ -1013,9 +1055,19 @@ function evaluateAST(node, getCellValue, getRangeValues) {
|
|
|
1013
1055
|
return node.value;
|
|
1014
1056
|
case "cellRef":
|
|
1015
1057
|
return getCellValue(node.address);
|
|
1016
|
-
case "rangeRef":
|
|
1058
|
+
case "rangeRef": {
|
|
1017
1059
|
const vals = getRangeValues(node.start, node.end);
|
|
1018
1060
|
return vals[0] ?? null;
|
|
1061
|
+
}
|
|
1062
|
+
case "sheetCellRef": {
|
|
1063
|
+
if (!ctx?.getSheetCellValue) return "#REF!";
|
|
1064
|
+
return ctx.getSheetCellValue(node.sheet, node.address);
|
|
1065
|
+
}
|
|
1066
|
+
case "sheetRangeRef": {
|
|
1067
|
+
if (!ctx?.getSheetRangeValues) return "#REF!";
|
|
1068
|
+
const vals = ctx.getSheetRangeValues(node.sheet, node.start, node.end);
|
|
1069
|
+
return vals[0] ?? null;
|
|
1070
|
+
}
|
|
1019
1071
|
case "functionCall": {
|
|
1020
1072
|
const entry = getFunction(node.name);
|
|
1021
1073
|
if (!entry) return `#NAME?`;
|
|
@@ -1023,7 +1075,11 @@ function evaluateAST(node, getCellValue, getRangeValues) {
|
|
|
1023
1075
|
if (arg.type === "rangeRef") {
|
|
1024
1076
|
return getRangeValues(arg.start, arg.end);
|
|
1025
1077
|
}
|
|
1026
|
-
|
|
1078
|
+
if (arg.type === "sheetRangeRef") {
|
|
1079
|
+
if (!ctx?.getSheetRangeValues) return ["#REF!"];
|
|
1080
|
+
return ctx.getSheetRangeValues(arg.sheet, arg.start, arg.end);
|
|
1081
|
+
}
|
|
1082
|
+
const val = evaluateAST(arg, getCellValue, getRangeValues, ctx);
|
|
1027
1083
|
return [val];
|
|
1028
1084
|
});
|
|
1029
1085
|
try {
|
|
@@ -1033,8 +1089,8 @@ function evaluateAST(node, getCellValue, getRangeValues) {
|
|
|
1033
1089
|
}
|
|
1034
1090
|
}
|
|
1035
1091
|
case "binaryOp": {
|
|
1036
|
-
const left = evaluateAST(node.left, getCellValue, getRangeValues);
|
|
1037
|
-
const right = evaluateAST(node.right, getCellValue, getRangeValues);
|
|
1092
|
+
const left = evaluateAST(node.left, getCellValue, getRangeValues, ctx);
|
|
1093
|
+
const right = evaluateAST(node.right, getCellValue, getRangeValues, ctx);
|
|
1038
1094
|
const lNum = typeof left === "number" ? left : Number(left);
|
|
1039
1095
|
const rNum = typeof right === "number" ? right : Number(right);
|
|
1040
1096
|
switch (node.operator) {
|
|
@@ -1067,7 +1123,7 @@ function evaluateAST(node, getCellValue, getRangeValues) {
|
|
|
1067
1123
|
}
|
|
1068
1124
|
}
|
|
1069
1125
|
case "unaryOp": {
|
|
1070
|
-
const operand = evaluateAST(node.operand, getCellValue, getRangeValues);
|
|
1126
|
+
const operand = evaluateAST(node.operand, getCellValue, getRangeValues, ctx);
|
|
1071
1127
|
const num = typeof operand === "number" ? operand : Number(operand);
|
|
1072
1128
|
if (isNaN(num)) return "#VALUE!";
|
|
1073
1129
|
return node.operator === "-" ? -num : num;
|
|
@@ -1181,7 +1237,7 @@ function getRecalculationOrder(graph) {
|
|
|
1181
1237
|
function recalculateWorkbook(workbook) {
|
|
1182
1238
|
return {
|
|
1183
1239
|
...workbook,
|
|
1184
|
-
sheets: workbook.sheets.map(recalculateSheet)
|
|
1240
|
+
sheets: workbook.sheets.map((s) => recalculateSheet(s, workbook.sheets))
|
|
1185
1241
|
};
|
|
1186
1242
|
}
|
|
1187
1243
|
function createInitialState(data) {
|
|
@@ -1211,7 +1267,7 @@ function pushUndo(state) {
|
|
|
1211
1267
|
if (stack.length > 50) stack.shift();
|
|
1212
1268
|
return { undoStack: stack, redoStack: [] };
|
|
1213
1269
|
}
|
|
1214
|
-
function recalculateSheet(sheet) {
|
|
1270
|
+
function recalculateSheet(sheet, allSheets) {
|
|
1215
1271
|
const graph = buildDependencyGraph(sheet.cells);
|
|
1216
1272
|
if (graph.size === 0) return sheet;
|
|
1217
1273
|
const circular = detectCircularRefs(graph);
|
|
@@ -1227,6 +1283,28 @@ function recalculateSheet(sheet) {
|
|
|
1227
1283
|
const addresses = expandRange(startAddr, endAddr);
|
|
1228
1284
|
return addresses.map(getCellValue);
|
|
1229
1285
|
};
|
|
1286
|
+
const getSheetCellValue = (sheetName, addr) => {
|
|
1287
|
+
if (!allSheets) return "#REF!";
|
|
1288
|
+
const target = allSheets.find((s) => s.name === sheetName || s.id === sheetName);
|
|
1289
|
+
if (!target) return "#REF!";
|
|
1290
|
+
const c = target.cells[addr];
|
|
1291
|
+
if (!c) return null;
|
|
1292
|
+
if (c.formula && c.computedValue !== void 0) return c.computedValue;
|
|
1293
|
+
return c.value;
|
|
1294
|
+
};
|
|
1295
|
+
const getSheetRangeValues = (sheetName, startAddr, endAddr) => {
|
|
1296
|
+
if (!allSheets) return [];
|
|
1297
|
+
const target = allSheets.find((s) => s.name === sheetName || s.id === sheetName);
|
|
1298
|
+
if (!target) return [];
|
|
1299
|
+
const addresses = expandRange(startAddr, endAddr);
|
|
1300
|
+
return addresses.map((a) => {
|
|
1301
|
+
const c = target.cells[a];
|
|
1302
|
+
if (!c) return null;
|
|
1303
|
+
if (c.formula && c.computedValue !== void 0) return c.computedValue;
|
|
1304
|
+
return c.value;
|
|
1305
|
+
});
|
|
1306
|
+
};
|
|
1307
|
+
const ctx = { getSheetCellValue, getSheetRangeValues };
|
|
1230
1308
|
for (const addr of order) {
|
|
1231
1309
|
const cell = cells[addr];
|
|
1232
1310
|
if (!cell?.formula) continue;
|
|
@@ -1237,7 +1315,7 @@ function recalculateSheet(sheet) {
|
|
|
1237
1315
|
try {
|
|
1238
1316
|
const tokens = lexFormula(cell.formula);
|
|
1239
1317
|
const ast = parseFormula(tokens);
|
|
1240
|
-
const result = evaluateAST(ast, getCellValue, getRangeValues);
|
|
1318
|
+
const result = evaluateAST(ast, getCellValue, getRangeValues, ctx);
|
|
1241
1319
|
cells[addr] = { ...cell, computedValue: result };
|
|
1242
1320
|
} catch {
|
|
1243
1321
|
cells[addr] = { ...cell, computedValue: "#ERROR!" };
|
|
@@ -1262,7 +1340,7 @@ function reducer(state, action) {
|
|
|
1262
1340
|
if (existing?.format) cellData.format = existing.format;
|
|
1263
1341
|
const workbook = updateActiveSheet(state, (s) => {
|
|
1264
1342
|
const updated = { ...s, cells: { ...s.cells, [action.address]: cellData } };
|
|
1265
|
-
return recalculateSheet(updated);
|
|
1343
|
+
return recalculateSheet(updated, state.workbook.sheets);
|
|
1266
1344
|
});
|
|
1267
1345
|
return { ...state, workbook, ...history };
|
|
1268
1346
|
}
|
|
@@ -1418,6 +1496,20 @@ function reducer(state, action) {
|
|
|
1418
1496
|
selection: { activeCell: "A1", ranges: [{ start: "A1", end: "A1" }] },
|
|
1419
1497
|
editingCell: null
|
|
1420
1498
|
};
|
|
1499
|
+
case "SET_FROZEN_ROWS": {
|
|
1500
|
+
const workbook = updateActiveSheet(state, (s) => ({
|
|
1501
|
+
...s,
|
|
1502
|
+
frozenRows: Math.max(0, action.count)
|
|
1503
|
+
}));
|
|
1504
|
+
return { ...state, workbook };
|
|
1505
|
+
}
|
|
1506
|
+
case "SET_FROZEN_COLS": {
|
|
1507
|
+
const workbook = updateActiveSheet(state, (s) => ({
|
|
1508
|
+
...s,
|
|
1509
|
+
frozenCols: Math.max(0, action.count)
|
|
1510
|
+
}));
|
|
1511
|
+
return { ...state, workbook };
|
|
1512
|
+
}
|
|
1421
1513
|
case "UNDO": {
|
|
1422
1514
|
if (state.undoStack.length === 0) return state;
|
|
1423
1515
|
const prev = state.undoStack[state.undoStack.length - 1];
|
|
@@ -1462,6 +1554,8 @@ function useSpreadsheetStore(initialData) {
|
|
|
1462
1554
|
addSheet: () => dispatch({ type: "ADD_SHEET" }),
|
|
1463
1555
|
renameSheet: (sheetId, name) => dispatch({ type: "RENAME_SHEET", sheetId, name }),
|
|
1464
1556
|
deleteSheet: (sheetId) => dispatch({ type: "DELETE_SHEET", sheetId }),
|
|
1557
|
+
setFrozenRows: (count) => dispatch({ type: "SET_FROZEN_ROWS", count }),
|
|
1558
|
+
setFrozenCols: (count) => dispatch({ type: "SET_FROZEN_COLS", count }),
|
|
1465
1559
|
setActiveSheet: (sheetId) => dispatch({ type: "SET_ACTIVE_SHEET", sheetId }),
|
|
1466
1560
|
undo: () => dispatch({ type: "UNDO" }),
|
|
1467
1561
|
redo: () => dispatch({ type: "REDO" }),
|
|
@@ -1550,11 +1644,49 @@ function RowHeader({ rowIndex }) {
|
|
|
1550
1644
|
);
|
|
1551
1645
|
}
|
|
1552
1646
|
RowHeader.displayName = "RowHeader";
|
|
1647
|
+
var EXCEL_EPOCH2 = new Date(1899, 11, 30).getTime();
|
|
1648
|
+
function serialToDateStr(serial) {
|
|
1649
|
+
const d = new Date(EXCEL_EPOCH2 + Math.floor(serial) * 864e5);
|
|
1650
|
+
const y = d.getFullYear();
|
|
1651
|
+
const m = String(d.getMonth() + 1).padStart(2, "0");
|
|
1652
|
+
const day = String(d.getDate()).padStart(2, "0");
|
|
1653
|
+
return `${y}-${m}-${day}`;
|
|
1654
|
+
}
|
|
1655
|
+
function serialToDateTimeStr(serial) {
|
|
1656
|
+
const date = serialToDateStr(serial);
|
|
1657
|
+
const fraction = serial % 1;
|
|
1658
|
+
const totalSeconds = Math.round(fraction * 86400);
|
|
1659
|
+
const h = String(Math.floor(totalSeconds / 3600)).padStart(2, "0");
|
|
1660
|
+
const min = String(Math.floor(totalSeconds % 3600 / 60)).padStart(2, "0");
|
|
1661
|
+
const s = String(totalSeconds % 60).padStart(2, "0");
|
|
1662
|
+
return `${date} ${h}:${min}:${s}`;
|
|
1663
|
+
}
|
|
1664
|
+
function isDateFormula(formula) {
|
|
1665
|
+
if (!formula) return false;
|
|
1666
|
+
const f = formula.toUpperCase();
|
|
1667
|
+
return /^(TODAY|NOW|DATE|EDATE)\b/.test(f) || /\b(TODAY|NOW|DATE|EDATE)\s*\(/.test(f);
|
|
1668
|
+
}
|
|
1669
|
+
function formatCellValue(val, cell) {
|
|
1670
|
+
if (val === null || val === void 0) return "";
|
|
1671
|
+
const fmt = cell?.format?.displayFormat;
|
|
1672
|
+
if (typeof val === "number") {
|
|
1673
|
+
if (fmt === "date") return serialToDateStr(val);
|
|
1674
|
+
if (fmt === "datetime") return serialToDateTimeStr(val);
|
|
1675
|
+
if (fmt === "percentage") return (val * 100).toFixed(1) + "%";
|
|
1676
|
+
if (fmt === "currency") return "$" + val.toFixed(2);
|
|
1677
|
+
if (fmt === "auto" || !fmt) {
|
|
1678
|
+
if (cell?.formula && isDateFormula(cell.formula)) {
|
|
1679
|
+
return val % 1 === 0 ? serialToDateStr(val) : serialToDateTimeStr(val);
|
|
1680
|
+
}
|
|
1681
|
+
}
|
|
1682
|
+
}
|
|
1683
|
+
if (typeof val === "boolean") return val ? "TRUE" : "FALSE";
|
|
1684
|
+
return String(val);
|
|
1685
|
+
}
|
|
1553
1686
|
function getCellDisplayValue2(cell) {
|
|
1554
1687
|
if (!cell) return "";
|
|
1555
|
-
|
|
1556
|
-
|
|
1557
|
-
return String(cell.value);
|
|
1688
|
+
const val = cell.formula && cell.computedValue !== void 0 ? cell.computedValue : cell.value;
|
|
1689
|
+
return formatCellValue(val, cell);
|
|
1558
1690
|
}
|
|
1559
1691
|
var Cell = memo(function Cell2({ address, row, col }) {
|
|
1560
1692
|
const {
|
|
@@ -1850,13 +1982,42 @@ function SpreadsheetGrid({ className }) {
|
|
|
1850
1982
|
children: [
|
|
1851
1983
|
/* @__PURE__ */ jsx("div", { className: "sticky top-0 z-10", children: /* @__PURE__ */ jsx(ColumnHeaders, {}) }),
|
|
1852
1984
|
/* @__PURE__ */ jsxs("div", { className: "relative", children: [
|
|
1853
|
-
Array.from({ length: rowCount }, (_, rowIdx) =>
|
|
1854
|
-
|
|
1855
|
-
|
|
1856
|
-
|
|
1857
|
-
|
|
1858
|
-
|
|
1859
|
-
|
|
1985
|
+
Array.from({ length: rowCount }, (_, rowIdx) => {
|
|
1986
|
+
const isFrozenRow = rowIdx < activeSheet.frozenRows;
|
|
1987
|
+
return /* @__PURE__ */ jsxs(
|
|
1988
|
+
"div",
|
|
1989
|
+
{
|
|
1990
|
+
className: "flex",
|
|
1991
|
+
style: isFrozenRow ? {
|
|
1992
|
+
position: "sticky",
|
|
1993
|
+
top: rowHeight + rowIdx * rowHeight,
|
|
1994
|
+
zIndex: 8,
|
|
1995
|
+
backgroundColor: "inherit"
|
|
1996
|
+
} : void 0,
|
|
1997
|
+
children: [
|
|
1998
|
+
/* @__PURE__ */ jsx("div", { className: "sticky left-0 z-[5]", children: /* @__PURE__ */ jsx(RowHeader, { rowIndex: rowIdx }) }),
|
|
1999
|
+
Array.from({ length: columnCount }, (_2, colIdx) => {
|
|
2000
|
+
const addr = toAddress(rowIdx, colIdx);
|
|
2001
|
+
const isFrozenCol = colIdx < activeSheet.frozenCols;
|
|
2002
|
+
return /* @__PURE__ */ jsx(
|
|
2003
|
+
"div",
|
|
2004
|
+
{
|
|
2005
|
+
style: isFrozenCol ? {
|
|
2006
|
+
position: "sticky",
|
|
2007
|
+
left: 48 + Array.from({ length: colIdx }, (_3, c) => getColumnWidth(c)).reduce((a, b) => a + b, 0),
|
|
2008
|
+
zIndex: isFrozenRow ? 9 : 6,
|
|
2009
|
+
backgroundColor: "inherit"
|
|
2010
|
+
} : void 0,
|
|
2011
|
+
children: /* @__PURE__ */ jsx(Cell, { address: addr, row: rowIdx, col: colIdx })
|
|
2012
|
+
},
|
|
2013
|
+
addr
|
|
2014
|
+
);
|
|
2015
|
+
})
|
|
2016
|
+
]
|
|
2017
|
+
},
|
|
2018
|
+
rowIdx
|
|
2019
|
+
);
|
|
2020
|
+
}),
|
|
1860
2021
|
/* @__PURE__ */ jsx(SelectionOverlay, {}),
|
|
1861
2022
|
editorPosition && /* @__PURE__ */ jsx(
|
|
1862
2023
|
"div",
|