@extend-ai/react-xlsx 0.13.4 → 0.14.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/README.md +20 -0
- package/dist/duke_sheets_wasm_bg.wasm +0 -0
- package/dist/index.cjs +871 -79
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +133 -1
- package/dist/index.d.ts +133 -1
- package/dist/index.js +871 -79
- package/dist/index.js.map +1 -1
- package/dist/xlsx-worker.js +128 -0
- package/dist/xlsx-worker.js.map +1 -1
- package/package.json +2 -2
package/dist/index.cjs
CHANGED
|
@@ -3642,7 +3642,6 @@ var SPREADSHEET_NS = "http://schemas.openxmlformats.org/spreadsheetml/2006/main"
|
|
|
3642
3642
|
var CONTENT_TYPES_NS = "http://schemas.openxmlformats.org/package/2006/content-types";
|
|
3643
3643
|
var DRAWING_REL_TYPE = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/drawing";
|
|
3644
3644
|
var VML_DRAWING_REL_TYPE = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/vmlDrawing";
|
|
3645
|
-
var CTRL_PROP_REL_TYPE = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/ctrlProp";
|
|
3646
3645
|
var IMAGE_REL_TYPE = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/image";
|
|
3647
3646
|
var DRAWING_CONTENT_TYPE = "application/vnd.openxmlformats-officedocument.drawing+xml";
|
|
3648
3647
|
var EMU_PER_PIXEL2 = 9525;
|
|
@@ -5085,6 +5084,124 @@ function parseSpreadsheetBooleanNode(node) {
|
|
|
5085
5084
|
}
|
|
5086
5085
|
return parseSpreadsheetBooleanValue(node.getAttribute("val") ?? node.textContent);
|
|
5087
5086
|
}
|
|
5087
|
+
function mapDukeFormControlAnchor(anchor) {
|
|
5088
|
+
return {
|
|
5089
|
+
from: {
|
|
5090
|
+
col: anchor.fromCol,
|
|
5091
|
+
colOffsetEmu: anchor.fromColOffset,
|
|
5092
|
+
row: anchor.fromRow,
|
|
5093
|
+
rowOffsetEmu: anchor.fromRowOffset
|
|
5094
|
+
},
|
|
5095
|
+
kind: "two-cell",
|
|
5096
|
+
to: {
|
|
5097
|
+
col: anchor.toCol,
|
|
5098
|
+
colOffsetEmu: anchor.toColOffset,
|
|
5099
|
+
row: anchor.toRow,
|
|
5100
|
+
rowOffsetEmu: anchor.toRowOffset
|
|
5101
|
+
}
|
|
5102
|
+
};
|
|
5103
|
+
}
|
|
5104
|
+
function mapDukeFormControlKind(kind) {
|
|
5105
|
+
switch (kind.kind) {
|
|
5106
|
+
case "button":
|
|
5107
|
+
return { caption: kind.caption, kind: "button", label: normalizeControlLabel(kind.caption) };
|
|
5108
|
+
case "checkbox":
|
|
5109
|
+
return {
|
|
5110
|
+
caption: kind.caption,
|
|
5111
|
+
checked: kind.state === "checked",
|
|
5112
|
+
kind: "checkbox",
|
|
5113
|
+
label: normalizeControlLabel(kind.caption),
|
|
5114
|
+
linkedCell: kind.cellLink,
|
|
5115
|
+
no3D: kind.no3D,
|
|
5116
|
+
state: kind.state
|
|
5117
|
+
};
|
|
5118
|
+
case "optionButton":
|
|
5119
|
+
return {
|
|
5120
|
+
caption: kind.caption,
|
|
5121
|
+
checked: kind.state === "checked",
|
|
5122
|
+
firstInGroup: kind.firstInGroup,
|
|
5123
|
+
kind: "radio",
|
|
5124
|
+
label: normalizeControlLabel(kind.caption),
|
|
5125
|
+
linkedCell: kind.cellLink,
|
|
5126
|
+
no3D: kind.no3D,
|
|
5127
|
+
state: kind.state
|
|
5128
|
+
};
|
|
5129
|
+
case "label":
|
|
5130
|
+
return { caption: kind.caption, kind: "label", label: normalizeControlLabel(kind.caption) };
|
|
5131
|
+
case "groupBox":
|
|
5132
|
+
return {
|
|
5133
|
+
caption: kind.caption,
|
|
5134
|
+
kind: "group-box",
|
|
5135
|
+
label: normalizeControlLabel(kind.caption),
|
|
5136
|
+
no3D: kind.no3D
|
|
5137
|
+
};
|
|
5138
|
+
case "listBox":
|
|
5139
|
+
return {
|
|
5140
|
+
inputRange: kind.inputRange,
|
|
5141
|
+
kind: "listbox",
|
|
5142
|
+
linkedCell: kind.cellLink,
|
|
5143
|
+
no3D: kind.no3D,
|
|
5144
|
+
selected: [...kind.selected],
|
|
5145
|
+
selection: kind.selection
|
|
5146
|
+
};
|
|
5147
|
+
case "dropdown":
|
|
5148
|
+
return {
|
|
5149
|
+
inputRange: kind.inputRange,
|
|
5150
|
+
kind: "dropdown",
|
|
5151
|
+
lines: kind.lines,
|
|
5152
|
+
linkedCell: kind.cellLink,
|
|
5153
|
+
no3D: kind.no3D,
|
|
5154
|
+
selected: kind.selected
|
|
5155
|
+
};
|
|
5156
|
+
case "scrollbar":
|
|
5157
|
+
return {
|
|
5158
|
+
horizontal: kind.horizontal,
|
|
5159
|
+
increment: kind.increment,
|
|
5160
|
+
kind: "scrollbar",
|
|
5161
|
+
linkedCell: kind.cellLink,
|
|
5162
|
+
max: kind.max,
|
|
5163
|
+
min: kind.min,
|
|
5164
|
+
page: kind.page,
|
|
5165
|
+
value: kind.value
|
|
5166
|
+
};
|
|
5167
|
+
case "spinner":
|
|
5168
|
+
return {
|
|
5169
|
+
increment: kind.increment,
|
|
5170
|
+
kind: "spinner",
|
|
5171
|
+
linkedCell: kind.cellLink,
|
|
5172
|
+
max: kind.max,
|
|
5173
|
+
min: kind.min,
|
|
5174
|
+
value: kind.value
|
|
5175
|
+
};
|
|
5176
|
+
}
|
|
5177
|
+
}
|
|
5178
|
+
function mapDukeFormControl(control, controlIndex, workbookSheetIndex) {
|
|
5179
|
+
return {
|
|
5180
|
+
anchor: mapDukeFormControlAnchor(control.anchor),
|
|
5181
|
+
controlIndex,
|
|
5182
|
+
dukeAnchor: { ...control.anchor },
|
|
5183
|
+
editAs: control.anchor.editAs,
|
|
5184
|
+
hidden: false,
|
|
5185
|
+
id: `form-control-${workbookSheetIndex}-${controlIndex}`,
|
|
5186
|
+
locked: control.locked,
|
|
5187
|
+
name: control.name,
|
|
5188
|
+
printable: control.printable,
|
|
5189
|
+
sheetIndex: workbookSheetIndex,
|
|
5190
|
+
workbookSheetIndex,
|
|
5191
|
+
zIndex: controlIndex + 1,
|
|
5192
|
+
...mapDukeFormControlKind(control.kind)
|
|
5193
|
+
};
|
|
5194
|
+
}
|
|
5195
|
+
function collectWorkbookFormControls(workbook) {
|
|
5196
|
+
return Array.from({ length: workbook.sheetCount }, (_, workbookSheetIndex) => {
|
|
5197
|
+
try {
|
|
5198
|
+
const controls = workbook.getSheet(workbookSheetIndex).formControls;
|
|
5199
|
+
return Array.isArray(controls) ? controls.map((control, controlIndex) => mapDukeFormControl(control, controlIndex, workbookSheetIndex)) : [];
|
|
5200
|
+
} catch {
|
|
5201
|
+
return [];
|
|
5202
|
+
}
|
|
5203
|
+
});
|
|
5204
|
+
}
|
|
5088
5205
|
function parseFormControlKind(rawType) {
|
|
5089
5206
|
const normalized = (rawType ?? "").trim().toLowerCase();
|
|
5090
5207
|
switch (normalized) {
|
|
@@ -5850,27 +5967,10 @@ function parseSheetFormControlNodes(archive, sheetPath) {
|
|
|
5850
5967
|
}
|
|
5851
5968
|
return getLocalElements(sheetDocument, "control").map((controlNode) => ({
|
|
5852
5969
|
anchor: parseAnchor(getFirstDescendant(controlNode, "anchor") ?? controlNode),
|
|
5853
|
-
controlRelationshipId: getRelationshipId(controlNode),
|
|
5854
5970
|
name: controlNode.getAttribute("name") ?? void 0,
|
|
5855
5971
|
shapeId: parseFormControlShapeId(controlNode.getAttribute("shapeId"))
|
|
5856
5972
|
}));
|
|
5857
5973
|
}
|
|
5858
|
-
function parseCtrlPropDocument(archive, ctrlPropPath) {
|
|
5859
|
-
const xml = readArchiveText2(archive, ctrlPropPath);
|
|
5860
|
-
if (!xml) {
|
|
5861
|
-
return null;
|
|
5862
|
-
}
|
|
5863
|
-
const document2 = parseXml2(xml);
|
|
5864
|
-
const root = document2?.documentElement;
|
|
5865
|
-
if (!root) {
|
|
5866
|
-
return null;
|
|
5867
|
-
}
|
|
5868
|
-
return {
|
|
5869
|
-
checked: parseSpreadsheetBooleanValue(root.getAttribute("checked")),
|
|
5870
|
-
linkedCell: root.getAttribute("fmlaLink") ?? void 0,
|
|
5871
|
-
objectType: root.getAttribute("objectType") ?? void 0
|
|
5872
|
-
};
|
|
5873
|
-
}
|
|
5874
5974
|
function parseVmlFormControls(archive, vmlDrawingPath) {
|
|
5875
5975
|
const xml = readArchiveText2(archive, vmlDrawingPath);
|
|
5876
5976
|
if (!xml) {
|
|
@@ -5928,21 +6028,18 @@ function parseSheetFormControls(archive, sheetPath, sheetRelationships, workbook
|
|
|
5928
6028
|
if (!controlNode.anchor) {
|
|
5929
6029
|
return;
|
|
5930
6030
|
}
|
|
5931
|
-
const ctrlPropRelationship = controlNode.controlRelationshipId ? sheetRelationships.get(controlNode.controlRelationshipId) ?? null : null;
|
|
5932
|
-
const ctrlPropPath = ctrlPropRelationship?.type === CTRL_PROP_REL_TYPE ? ctrlPropRelationship.target : null;
|
|
5933
|
-
const ctrlProp = ctrlPropPath ? parseCtrlPropDocument(archive, ctrlPropPath) : null;
|
|
5934
6031
|
const vmlControl = controlNode.shapeId !== null ? vmlControlsByShapeId.get(controlNode.shapeId) ?? null : null;
|
|
5935
|
-
const kind = parseFormControlKind(
|
|
6032
|
+
const kind = parseFormControlKind(vmlControl?.objectType);
|
|
5936
6033
|
parsedControls.push({
|
|
5937
6034
|
anchor: controlNode.anchor,
|
|
5938
|
-
checked:
|
|
6035
|
+
checked: vmlControl?.checked,
|
|
5939
6036
|
fontFamily: vmlControl?.fontFamily,
|
|
5940
6037
|
fontSizePt: vmlControl?.fontSizePt,
|
|
5941
6038
|
hidden: vmlControl?.hidden ?? false,
|
|
5942
6039
|
id: `form-control-${workbookSheetIndex}-${index}`,
|
|
5943
6040
|
kind,
|
|
5944
6041
|
label: vmlControl?.label,
|
|
5945
|
-
linkedCell:
|
|
6042
|
+
linkedCell: vmlControl?.linkedCell,
|
|
5946
6043
|
name: controlNode.name,
|
|
5947
6044
|
sheetIndex: workbookSheetIndex,
|
|
5948
6045
|
textAlign: vmlControl?.textAlign,
|
|
@@ -6028,6 +6125,92 @@ function enrichFormControlsWithHiddenShapes(formControls, shapes, sheetState) {
|
|
|
6028
6125
|
};
|
|
6029
6126
|
});
|
|
6030
6127
|
}
|
|
6128
|
+
function getFormControlAnchorStart(anchor) {
|
|
6129
|
+
return anchor.kind === "absolute" ? null : { col: anchor.from.col, row: anchor.from.row };
|
|
6130
|
+
}
|
|
6131
|
+
function scoreParsedFormControlMatch(dukeControl, parsedControl, parsedIndex) {
|
|
6132
|
+
if (dukeControl.kind !== parsedControl.kind && parsedControl.kind !== "unknown") {
|
|
6133
|
+
return Number.NEGATIVE_INFINITY;
|
|
6134
|
+
}
|
|
6135
|
+
let score = 10;
|
|
6136
|
+
const dukeName = normalizeControlLabel(dukeControl.name)?.toLowerCase();
|
|
6137
|
+
const parsedName = normalizeControlLabel(parsedControl.name)?.toLowerCase();
|
|
6138
|
+
if (dukeName && parsedName) {
|
|
6139
|
+
if (dukeName !== parsedName) {
|
|
6140
|
+
return Number.NEGATIVE_INFINITY;
|
|
6141
|
+
}
|
|
6142
|
+
score += 100;
|
|
6143
|
+
}
|
|
6144
|
+
const dukeStart = getFormControlAnchorStart(dukeControl.anchor);
|
|
6145
|
+
const parsedStart = getFormControlAnchorStart(parsedControl.anchor);
|
|
6146
|
+
if (dukeStart && parsedStart && dukeStart.col === parsedStart.col && dukeStart.row === parsedStart.row) {
|
|
6147
|
+
score += 40;
|
|
6148
|
+
}
|
|
6149
|
+
if (dukeControl.controlIndex === parsedIndex) {
|
|
6150
|
+
score += 5;
|
|
6151
|
+
}
|
|
6152
|
+
return score;
|
|
6153
|
+
}
|
|
6154
|
+
function areDukeFormControlAnchorsEqual(left, right) {
|
|
6155
|
+
if (!left || !right) {
|
|
6156
|
+
return true;
|
|
6157
|
+
}
|
|
6158
|
+
return left.editAs === right.editAs && left.fromCol === right.fromCol && left.fromColOffset === right.fromColOffset && left.fromRow === right.fromRow && left.fromRowOffset === right.fromRowOffset && left.toCol === right.toCol && left.toColOffset === right.toColOffset && left.toRow === right.toRow && left.toRowOffset === right.toRowOffset;
|
|
6159
|
+
}
|
|
6160
|
+
function mergeDukeAndParsedFormControls(dukeControls, parsedControls, keepUnmatchedParsedControl = () => true) {
|
|
6161
|
+
const usedParsedIndexes = /* @__PURE__ */ new Set();
|
|
6162
|
+
const mergedControls = dukeControls.map((dukeControl) => {
|
|
6163
|
+
let bestIndex = -1;
|
|
6164
|
+
let bestScore = Number.NEGATIVE_INFINITY;
|
|
6165
|
+
parsedControls.forEach((parsedControl2, parsedIndex) => {
|
|
6166
|
+
if (usedParsedIndexes.has(parsedIndex)) {
|
|
6167
|
+
return;
|
|
6168
|
+
}
|
|
6169
|
+
const score = scoreParsedFormControlMatch(dukeControl, parsedControl2, parsedIndex);
|
|
6170
|
+
if (score > bestScore) {
|
|
6171
|
+
bestIndex = parsedIndex;
|
|
6172
|
+
bestScore = score;
|
|
6173
|
+
}
|
|
6174
|
+
});
|
|
6175
|
+
const parsedControl = bestIndex >= 0 && bestScore >= 10 ? parsedControls[bestIndex] : null;
|
|
6176
|
+
if (!parsedControl) {
|
|
6177
|
+
return dukeControl;
|
|
6178
|
+
}
|
|
6179
|
+
usedParsedIndexes.add(bestIndex);
|
|
6180
|
+
const dukeAnchorChanged = !areDukeFormControlAnchorsEqual(
|
|
6181
|
+
parsedControl.dukeAnchor,
|
|
6182
|
+
dukeControl.dukeAnchor
|
|
6183
|
+
);
|
|
6184
|
+
return {
|
|
6185
|
+
...parsedControl,
|
|
6186
|
+
...dukeControl,
|
|
6187
|
+
anchor: dukeAnchorChanged ? dukeControl.anchor : parsedControl.anchor,
|
|
6188
|
+
fontFamily: parsedControl.fontFamily,
|
|
6189
|
+
fontSizePt: parsedControl.fontSizePt,
|
|
6190
|
+
hidden: parsedControl.hidden,
|
|
6191
|
+
id: parsedControl.id,
|
|
6192
|
+
label: dukeControl.label ?? parsedControl.label,
|
|
6193
|
+
name: dukeControl.name ?? parsedControl.name,
|
|
6194
|
+
textAlign: parsedControl.textAlign,
|
|
6195
|
+
textColor: parsedControl.textColor,
|
|
6196
|
+
zIndex: parsedControl.zIndex
|
|
6197
|
+
};
|
|
6198
|
+
});
|
|
6199
|
+
parsedControls.forEach((parsedControl, parsedIndex) => {
|
|
6200
|
+
if (!usedParsedIndexes.has(parsedIndex) && keepUnmatchedParsedControl(parsedControl)) {
|
|
6201
|
+
mergedControls.push(parsedControl);
|
|
6202
|
+
}
|
|
6203
|
+
});
|
|
6204
|
+
return mergedControls.sort((left, right) => left.zIndex - right.zIndex);
|
|
6205
|
+
}
|
|
6206
|
+
function refreshWorkbookFormControls(workbook, currentControlsByWorkbookSheetIndex) {
|
|
6207
|
+
const dukeControlsByWorkbookSheetIndex = collectWorkbookFormControls(workbook);
|
|
6208
|
+
return dukeControlsByWorkbookSheetIndex.map((dukeControls, workbookSheetIndex) => mergeDukeAndParsedFormControls(
|
|
6209
|
+
dukeControls,
|
|
6210
|
+
currentControlsByWorkbookSheetIndex[workbookSheetIndex] ?? [],
|
|
6211
|
+
(control) => control.controlIndex === void 0
|
|
6212
|
+
));
|
|
6213
|
+
}
|
|
6031
6214
|
function revokeWorkbookImageAssets(assets) {
|
|
6032
6215
|
if (!assets) {
|
|
6033
6216
|
return;
|
|
@@ -6060,7 +6243,7 @@ function parseWorkbookStructureAssetsFromArchive(archive, options) {
|
|
|
6060
6243
|
workbookSheets
|
|
6061
6244
|
};
|
|
6062
6245
|
}
|
|
6063
|
-
function parseWorkbookImageAssets(bytes) {
|
|
6246
|
+
function parseWorkbookImageAssets(bytes, workbook) {
|
|
6064
6247
|
const archive = (0, import_fflate2.unzipSync)(bytes);
|
|
6065
6248
|
const {
|
|
6066
6249
|
contentTypes,
|
|
@@ -6079,6 +6262,7 @@ function parseWorkbookImageAssets(bytes) {
|
|
|
6079
6262
|
const shapesByWorkbookSheetIndex = [];
|
|
6080
6263
|
const sheetOrigins = [];
|
|
6081
6264
|
const imageOriginsById = /* @__PURE__ */ new Map();
|
|
6265
|
+
const dukeFormControlsByWorkbookSheetIndex = collectWorkbookFormControls(workbook);
|
|
6082
6266
|
workbookSheets.forEach((sheet, workbookSheetIndex) => {
|
|
6083
6267
|
const sheetRelationships = parseRelationships(archive, relsPathForDocument(sheet.path), sheet.path);
|
|
6084
6268
|
const attachments = [];
|
|
@@ -6124,7 +6308,10 @@ function parseWorkbookImageAssets(bytes) {
|
|
|
6124
6308
|
shapeList,
|
|
6125
6309
|
sheetStatesByWorkbookSheetIndex[workbookSheetIndex] ?? null
|
|
6126
6310
|
);
|
|
6127
|
-
formControlsByWorkbookSheetIndex[workbookSheetIndex] =
|
|
6311
|
+
formControlsByWorkbookSheetIndex[workbookSheetIndex] = mergeDukeAndParsedFormControls(
|
|
6312
|
+
dukeFormControlsByWorkbookSheetIndex[workbookSheetIndex] ?? [],
|
|
6313
|
+
enrichedFormControlList
|
|
6314
|
+
);
|
|
6128
6315
|
imagesByWorkbookSheetIndex[workbookSheetIndex] = imageList;
|
|
6129
6316
|
shapesByWorkbookSheetIndex[workbookSheetIndex] = visibleShapeList;
|
|
6130
6317
|
sheetOrigins[workbookSheetIndex] = attachments.length > 0 ? {
|
|
@@ -7199,6 +7386,144 @@ function parseA1RangeReference2(reference) {
|
|
|
7199
7386
|
}
|
|
7200
7387
|
return normalizeRange({ start, end });
|
|
7201
7388
|
}
|
|
7389
|
+
function resolveWorkbookReference(workbook, defaultWorkbookSheetIndex, rawReference, resolvingNamedRange = false) {
|
|
7390
|
+
const reference = rawReference.trim().replace(/^=/, "");
|
|
7391
|
+
if (!reference) {
|
|
7392
|
+
return null;
|
|
7393
|
+
}
|
|
7394
|
+
let workbookSheetIndex = defaultWorkbookSheetIndex;
|
|
7395
|
+
let rangeReference = reference;
|
|
7396
|
+
const bangIndex = reference.lastIndexOf("!");
|
|
7397
|
+
if (bangIndex >= 0) {
|
|
7398
|
+
let sheetName = reference.slice(0, bangIndex).trim();
|
|
7399
|
+
rangeReference = reference.slice(bangIndex + 1).trim();
|
|
7400
|
+
if (sheetName.startsWith("'") && sheetName.endsWith("'")) {
|
|
7401
|
+
sheetName = sheetName.slice(1, -1).replace(/''/g, "'");
|
|
7402
|
+
}
|
|
7403
|
+
const resolvedSheetIndex = workbook.sheetIndex(sheetName);
|
|
7404
|
+
if (resolvedSheetIndex === void 0) {
|
|
7405
|
+
return null;
|
|
7406
|
+
}
|
|
7407
|
+
workbookSheetIndex = resolvedSheetIndex;
|
|
7408
|
+
} else if (!resolvingNamedRange) {
|
|
7409
|
+
const namedRange = workbook.getNamedRange(reference);
|
|
7410
|
+
if (namedRange) {
|
|
7411
|
+
return resolveWorkbookReference(workbook, defaultWorkbookSheetIndex, namedRange, true);
|
|
7412
|
+
}
|
|
7413
|
+
}
|
|
7414
|
+
const range = parseA1RangeReference2(rangeReference.replace(/\$/g, ""));
|
|
7415
|
+
if (!range || workbookSheetIndex < 0 || workbookSheetIndex >= workbook.sheetCount) {
|
|
7416
|
+
return null;
|
|
7417
|
+
}
|
|
7418
|
+
try {
|
|
7419
|
+
return {
|
|
7420
|
+
range,
|
|
7421
|
+
workbookSheetIndex,
|
|
7422
|
+
worksheet: workbook.getSheet(workbookSheetIndex)
|
|
7423
|
+
};
|
|
7424
|
+
} catch {
|
|
7425
|
+
return null;
|
|
7426
|
+
}
|
|
7427
|
+
}
|
|
7428
|
+
function formControlInputFromDukeControl(control) {
|
|
7429
|
+
return {
|
|
7430
|
+
anchor: { ...control.anchor },
|
|
7431
|
+
kind: { ...control.kind },
|
|
7432
|
+
locked: control.locked,
|
|
7433
|
+
name: control.name,
|
|
7434
|
+
printable: control.printable
|
|
7435
|
+
};
|
|
7436
|
+
}
|
|
7437
|
+
function getFormControlCellLink(kind) {
|
|
7438
|
+
return "cellLink" in kind ? kind.cellLink : void 0;
|
|
7439
|
+
}
|
|
7440
|
+
function anchorContainsControl(group, control) {
|
|
7441
|
+
const groupAnchor = group.anchor;
|
|
7442
|
+
const controlAnchor = control.anchor;
|
|
7443
|
+
return controlAnchor.fromCol >= groupAnchor.fromCol && controlAnchor.fromCol <= groupAnchor.toCol && controlAnchor.fromRow >= groupAnchor.fromRow && controlAnchor.fromRow <= groupAnchor.toRow;
|
|
7444
|
+
}
|
|
7445
|
+
function resolveOptionButtonGroupIndexes(controls, targetIndex) {
|
|
7446
|
+
const target = controls[targetIndex];
|
|
7447
|
+
if (!target || target.kind.kind !== "optionButton") {
|
|
7448
|
+
return [];
|
|
7449
|
+
}
|
|
7450
|
+
if (target.kind.cellLink) {
|
|
7451
|
+
const targetCellLink = target.kind.cellLink;
|
|
7452
|
+
return controls.flatMap((control, index) => control.kind.kind === "optionButton" && control.kind.cellLink === targetCellLink ? [index] : []);
|
|
7453
|
+
}
|
|
7454
|
+
const containingGroups = controls.map((control, index) => ({ control, index })).filter(({ control }) => control.kind.kind === "groupBox" && anchorContainsControl(control, target)).sort((left, right) => {
|
|
7455
|
+
const leftArea = (left.control.anchor.toCol - left.control.anchor.fromCol) * (left.control.anchor.toRow - left.control.anchor.fromRow);
|
|
7456
|
+
const rightArea = (right.control.anchor.toCol - right.control.anchor.fromCol) * (right.control.anchor.toRow - right.control.anchor.fromRow);
|
|
7457
|
+
return leftArea - rightArea;
|
|
7458
|
+
});
|
|
7459
|
+
const containingGroup = containingGroups[0]?.control;
|
|
7460
|
+
if (containingGroup) {
|
|
7461
|
+
return controls.flatMap((control, index) => control.kind.kind === "optionButton" && anchorContainsControl(containingGroup, control) ? [index] : []);
|
|
7462
|
+
}
|
|
7463
|
+
const optionIndexes = controls.flatMap((control, index) => control.kind.kind === "optionButton" ? [index] : []);
|
|
7464
|
+
const targetPosition = optionIndexes.indexOf(targetIndex);
|
|
7465
|
+
if (targetPosition < 0) {
|
|
7466
|
+
return [];
|
|
7467
|
+
}
|
|
7468
|
+
let startPosition = targetPosition;
|
|
7469
|
+
while (startPosition > 0) {
|
|
7470
|
+
const control = controls[optionIndexes[startPosition] ?? -1];
|
|
7471
|
+
if (control?.kind.kind === "optionButton" && control.kind.firstInGroup) {
|
|
7472
|
+
break;
|
|
7473
|
+
}
|
|
7474
|
+
startPosition -= 1;
|
|
7475
|
+
}
|
|
7476
|
+
let endPosition = targetPosition + 1;
|
|
7477
|
+
while (endPosition < optionIndexes.length) {
|
|
7478
|
+
const control = controls[optionIndexes[endPosition] ?? -1];
|
|
7479
|
+
if (control?.kind.kind === "optionButton" && control.kind.firstInGroup) {
|
|
7480
|
+
break;
|
|
7481
|
+
}
|
|
7482
|
+
endPosition += 1;
|
|
7483
|
+
}
|
|
7484
|
+
return optionIndexes.slice(startPosition, endPosition);
|
|
7485
|
+
}
|
|
7486
|
+
function resolveLinkedCellValue(controls, controlIndex) {
|
|
7487
|
+
const control = controls[controlIndex];
|
|
7488
|
+
if (!control) {
|
|
7489
|
+
return void 0;
|
|
7490
|
+
}
|
|
7491
|
+
switch (control.kind.kind) {
|
|
7492
|
+
case "checkbox":
|
|
7493
|
+
return control.kind.state === "mixed" ? "#N/A" : control.kind.state === "checked";
|
|
7494
|
+
case "optionButton": {
|
|
7495
|
+
const groupIndexes = resolveOptionButtonGroupIndexes(controls, controlIndex);
|
|
7496
|
+
const checkedIndex = groupIndexes.find((index) => controls[index]?.kind.kind === "optionButton" && controls[index]?.kind.state === "checked");
|
|
7497
|
+
const groupPosition = checkedIndex === void 0 ? -1 : groupIndexes.indexOf(checkedIndex);
|
|
7498
|
+
return groupPosition >= 0 ? groupPosition + 1 : "";
|
|
7499
|
+
}
|
|
7500
|
+
case "dropdown":
|
|
7501
|
+
return control.kind.selected === void 0 ? "" : control.kind.selected + 1;
|
|
7502
|
+
case "listBox":
|
|
7503
|
+
return control.kind.selection === "single" && control.kind.selected.length === 1 ? (control.kind.selected[0] ?? -1) + 1 : "";
|
|
7504
|
+
case "scrollbar":
|
|
7505
|
+
case "spinner":
|
|
7506
|
+
return control.kind.value;
|
|
7507
|
+
default:
|
|
7508
|
+
return void 0;
|
|
7509
|
+
}
|
|
7510
|
+
}
|
|
7511
|
+
function syncFormControlLinkedCell(workbook, workbookSheetIndex, controls, controlIndex) {
|
|
7512
|
+
const control = controls[controlIndex];
|
|
7513
|
+
if (!control) {
|
|
7514
|
+
return;
|
|
7515
|
+
}
|
|
7516
|
+
const cellLink = getFormControlCellLink(control.kind);
|
|
7517
|
+
const value = resolveLinkedCellValue(controls, controlIndex);
|
|
7518
|
+
if (!cellLink || value === void 0) {
|
|
7519
|
+
return;
|
|
7520
|
+
}
|
|
7521
|
+
const target = resolveWorkbookReference(workbook, workbookSheetIndex, cellLink);
|
|
7522
|
+
if (!target || target.range.start.row !== target.range.end.row || target.range.start.col !== target.range.end.col) {
|
|
7523
|
+
return;
|
|
7524
|
+
}
|
|
7525
|
+
target.worksheet.setCell(cellAddressToA1(target.range.start), value);
|
|
7526
|
+
}
|
|
7202
7527
|
function parseWorksheetFreezePanes(worksheet) {
|
|
7203
7528
|
const rawFreezePanes = worksheet.freezePanes;
|
|
7204
7529
|
const row = typeof rawFreezePanes?.row === "number" && rawFreezePanes.row >= 0 ? rawFreezePanes.row : null;
|
|
@@ -7965,7 +8290,7 @@ function createBasicWorkbookAssets(workbook) {
|
|
|
7965
8290
|
const objectUrls = [];
|
|
7966
8291
|
return {
|
|
7967
8292
|
archive: {},
|
|
7968
|
-
formControlsByWorkbookSheetIndex:
|
|
8293
|
+
formControlsByWorkbookSheetIndex: collectWorkbookFormControls(workbook),
|
|
7969
8294
|
imageOriginsById: /* @__PURE__ */ new Map(),
|
|
7970
8295
|
imagesByWorkbookSheetIndex: collectWorksheetApiImages(workbook, objectUrls),
|
|
7971
8296
|
namedCellStyleByName: {},
|
|
@@ -7983,7 +8308,7 @@ function loadWorkbookImageAssets(bytes, workbook, skipXmlParsing = false) {
|
|
|
7983
8308
|
if (shouldSkipXmlParsingForWorkbook(bytes, skipXmlParsing) || !isZipWorkbook(bytes)) {
|
|
7984
8309
|
return createBasicWorkbookAssets(workbook);
|
|
7985
8310
|
}
|
|
7986
|
-
const parsedAssets = parseWorkbookImageAssets(bytes);
|
|
8311
|
+
const parsedAssets = parseWorkbookImageAssets(bytes, workbook);
|
|
7987
8312
|
const apiImagesByWorkbookSheetIndex = collectWorksheetApiImages(workbook, parsedAssets.objectUrls);
|
|
7988
8313
|
const imagesByWorkbookSheetIndex = Array.from(
|
|
7989
8314
|
{ length: Math.max(workbook.sheetCount, parsedAssets.imagesByWorkbookSheetIndex.length, apiImagesByWorkbookSheetIndex.length) },
|
|
@@ -8300,6 +8625,12 @@ function useXlsxViewerController(options) {
|
|
|
8300
8625
|
};
|
|
8301
8626
|
}, [skipXmlParsing]);
|
|
8302
8627
|
const refreshWorkbookState = React.useCallback((targetWorkbook) => {
|
|
8628
|
+
const currentFormControls = imageAssetsRef.current?.formControlsByWorkbookSheetIndex ?? [];
|
|
8629
|
+
const nextFormControls = refreshWorkbookFormControls(targetWorkbook, currentFormControls);
|
|
8630
|
+
if (imageAssetsRef.current) {
|
|
8631
|
+
imageAssetsRef.current.formControlsByWorkbookSheetIndex = nextFormControls;
|
|
8632
|
+
}
|
|
8633
|
+
setFormControlsByWorkbookSheetIndex(nextFormControls);
|
|
8303
8634
|
const nextSheets = buildSheetList(
|
|
8304
8635
|
targetWorkbook,
|
|
8305
8636
|
imageAssetsRef.current?.sheetStatesByWorkbookSheetIndex,
|
|
@@ -8427,6 +8758,7 @@ function useXlsxViewerController(options) {
|
|
|
8427
8758
|
setChartsheets(snapshot.chartsheets);
|
|
8428
8759
|
setTabs(snapshot.tabs);
|
|
8429
8760
|
chartAssetsRef.current = null;
|
|
8761
|
+
setFormControlsByWorkbookSheetIndex(snapshot.formControlsByWorkbookSheetIndex);
|
|
8430
8762
|
setWorkerTablesByWorkbookSheetIndex(snapshot.tablesByWorkbookSheetIndex);
|
|
8431
8763
|
setShouldAutoCalculate(false);
|
|
8432
8764
|
setIsWorkerBacked(true);
|
|
@@ -8646,6 +8978,7 @@ function useXlsxViewerController(options) {
|
|
|
8646
8978
|
setChartsheets(snapshot.chartsheets);
|
|
8647
8979
|
setTabs(snapshot.tabs);
|
|
8648
8980
|
chartAssetsRef.current = null;
|
|
8981
|
+
setFormControlsByWorkbookSheetIndex(snapshot.formControlsByWorkbookSheetIndex);
|
|
8649
8982
|
setWorkerTablesByWorkbookSheetIndex(snapshot.tablesByWorkbookSheetIndex);
|
|
8650
8983
|
setShouldAutoCalculate(false);
|
|
8651
8984
|
setIsWorkerBacked(true);
|
|
@@ -8767,6 +9100,20 @@ function useXlsxViewerController(options) {
|
|
|
8767
9100
|
}
|
|
8768
9101
|
return workbook.getSheet(activeSheet.workbookSheetIndex);
|
|
8769
9102
|
}, [activeSheet, workbook]);
|
|
9103
|
+
const getFormControlWorksheet = React.useCallback((sheetIndex = activeSheetIndex) => {
|
|
9104
|
+
const targetSheet = sheets[sheetIndex];
|
|
9105
|
+
if (!workbook || !targetSheet) {
|
|
9106
|
+
return null;
|
|
9107
|
+
}
|
|
9108
|
+
try {
|
|
9109
|
+
return {
|
|
9110
|
+
workbookSheetIndex: targetSheet.workbookSheetIndex,
|
|
9111
|
+
worksheet: workbook.getSheet(targetSheet.workbookSheetIndex)
|
|
9112
|
+
};
|
|
9113
|
+
} catch {
|
|
9114
|
+
return null;
|
|
9115
|
+
}
|
|
9116
|
+
}, [activeSheetIndex, sheets, workbook]);
|
|
8770
9117
|
const tables = React.useMemo(
|
|
8771
9118
|
() => isWorkerBacked ? workerTablesByWorkbookSheetIndex[activeSheet?.workbookSheetIndex ?? -1] ?? [] : mapWorksheetTables(getActiveWorksheet()),
|
|
8772
9119
|
[activeSheet?.workbookSheetIndex, getActiveWorksheet, isWorkerBacked, revision, workerTablesByWorkbookSheetIndex]
|
|
@@ -8906,6 +9253,28 @@ function useXlsxViewerController(options) {
|
|
|
8906
9253
|
return (formControlsByWorkbookSheetIndex[targetSheet.workbookSheetIndex] ?? []).map(mapPublicFormControl);
|
|
8907
9254
|
}, [activeSheetIndex, formControlsByWorkbookSheetIndex, mapPublicFormControl, sheets]);
|
|
8908
9255
|
const formControls = React.useMemo(() => getSheetFormControls(activeSheetIndex), [activeSheetIndex, getSheetFormControls]);
|
|
9256
|
+
const getFormControlItems = React.useCallback((controlIndex, sheetIndex = activeSheetIndex) => {
|
|
9257
|
+
const target = getFormControlWorksheet(sheetIndex);
|
|
9258
|
+
if (!workbook || !target) {
|
|
9259
|
+
return [];
|
|
9260
|
+
}
|
|
9261
|
+
const control = target.worksheet.formControls[controlIndex];
|
|
9262
|
+
const inputRange = control?.kind.kind === "listBox" || control?.kind.kind === "dropdown" ? control.kind.inputRange : void 0;
|
|
9263
|
+
if (!inputRange) {
|
|
9264
|
+
return [];
|
|
9265
|
+
}
|
|
9266
|
+
const source = resolveWorkbookReference(workbook, target.workbookSheetIndex, inputRange);
|
|
9267
|
+
if (!source) {
|
|
9268
|
+
return [];
|
|
9269
|
+
}
|
|
9270
|
+
const items = [];
|
|
9271
|
+
for (let row = source.range.start.row; row <= source.range.end.row; row += 1) {
|
|
9272
|
+
for (let col = source.range.start.col; col <= source.range.end.col; col += 1) {
|
|
9273
|
+
items.push(source.worksheet.getFormattedValueAt(row, col));
|
|
9274
|
+
}
|
|
9275
|
+
}
|
|
9276
|
+
return items;
|
|
9277
|
+
}, [activeSheetIndex, getFormControlWorksheet, workbook]);
|
|
8909
9278
|
const getSheetShapes = React.useCallback((sheetIndex = activeSheetIndex) => {
|
|
8910
9279
|
const targetSheet = sheets[sheetIndex];
|
|
8911
9280
|
if (!targetSheet) {
|
|
@@ -9303,6 +9672,89 @@ function useXlsxViewerController(options) {
|
|
|
9303
9672
|
redoStackRef.current = [];
|
|
9304
9673
|
setHistoryRevision((current) => current + 1);
|
|
9305
9674
|
}, [createHistoryEntry]);
|
|
9675
|
+
const addFormControl = React.useCallback((input, sheetIndex = activeSheetIndex) => {
|
|
9676
|
+
const target = getFormControlWorksheet(sheetIndex);
|
|
9677
|
+
if (readOnly || !workbook || !target) {
|
|
9678
|
+
return null;
|
|
9679
|
+
}
|
|
9680
|
+
recordHistoryBeforeMutation();
|
|
9681
|
+
const controlIndex = target.worksheet.addFormControl(input);
|
|
9682
|
+
const controls = target.worksheet.formControls;
|
|
9683
|
+
const addedControl = controls[controlIndex];
|
|
9684
|
+
if (addedControl?.kind.kind === "optionButton" && addedControl.kind.state === "checked") {
|
|
9685
|
+
const groupIndexes = resolveOptionButtonGroupIndexes(controls, controlIndex);
|
|
9686
|
+
for (const siblingIndex of groupIndexes) {
|
|
9687
|
+
if (siblingIndex === controlIndex) {
|
|
9688
|
+
continue;
|
|
9689
|
+
}
|
|
9690
|
+
const sibling = target.worksheet.formControls[siblingIndex];
|
|
9691
|
+
if (sibling?.kind.kind === "optionButton" && sibling.kind.state !== "unchecked") {
|
|
9692
|
+
target.worksheet.setFormControl(siblingIndex, {
|
|
9693
|
+
...formControlInputFromDukeControl(sibling),
|
|
9694
|
+
kind: { ...sibling.kind, state: "unchecked" }
|
|
9695
|
+
});
|
|
9696
|
+
}
|
|
9697
|
+
}
|
|
9698
|
+
}
|
|
9699
|
+
syncFormControlLinkedCell(
|
|
9700
|
+
workbook,
|
|
9701
|
+
target.workbookSheetIndex,
|
|
9702
|
+
target.worksheet.formControls,
|
|
9703
|
+
controlIndex
|
|
9704
|
+
);
|
|
9705
|
+
maybeRecalculateWorkbook(workbook);
|
|
9706
|
+
refreshWorkbookState(workbook);
|
|
9707
|
+
return controlIndex;
|
|
9708
|
+
}, [activeSheetIndex, getFormControlWorksheet, maybeRecalculateWorkbook, readOnly, recordHistoryBeforeMutation, refreshWorkbookState, workbook]);
|
|
9709
|
+
const updateFormControl = React.useCallback((controlIndex, patch, sheetIndex = activeSheetIndex) => {
|
|
9710
|
+
const target = getFormControlWorksheet(sheetIndex);
|
|
9711
|
+
const currentControl = target?.worksheet.formControls[controlIndex];
|
|
9712
|
+
if (readOnly || !workbook || !target || !currentControl) {
|
|
9713
|
+
return false;
|
|
9714
|
+
}
|
|
9715
|
+
recordHistoryBeforeMutation();
|
|
9716
|
+
const nextInput = {
|
|
9717
|
+
...formControlInputFromDukeControl(currentControl),
|
|
9718
|
+
...patch,
|
|
9719
|
+
anchor: patch.anchor ? { ...patch.anchor } : { ...currentControl.anchor },
|
|
9720
|
+
kind: patch.kind ? { ...patch.kind } : { ...currentControl.kind }
|
|
9721
|
+
};
|
|
9722
|
+
if (nextInput.kind.kind === "optionButton" && nextInput.kind.state === "checked") {
|
|
9723
|
+
const groupIndexes = resolveOptionButtonGroupIndexes(target.worksheet.formControls, controlIndex);
|
|
9724
|
+
for (const siblingIndex of groupIndexes) {
|
|
9725
|
+
if (siblingIndex === controlIndex) {
|
|
9726
|
+
continue;
|
|
9727
|
+
}
|
|
9728
|
+
const sibling = target.worksheet.formControls[siblingIndex];
|
|
9729
|
+
if (sibling?.kind.kind === "optionButton" && sibling.kind.state !== "unchecked") {
|
|
9730
|
+
target.worksheet.setFormControl(siblingIndex, {
|
|
9731
|
+
...formControlInputFromDukeControl(sibling),
|
|
9732
|
+
kind: { ...sibling.kind, state: "unchecked" }
|
|
9733
|
+
});
|
|
9734
|
+
}
|
|
9735
|
+
}
|
|
9736
|
+
}
|
|
9737
|
+
target.worksheet.setFormControl(controlIndex, nextInput);
|
|
9738
|
+
syncFormControlLinkedCell(
|
|
9739
|
+
workbook,
|
|
9740
|
+
target.workbookSheetIndex,
|
|
9741
|
+
target.worksheet.formControls,
|
|
9742
|
+
controlIndex
|
|
9743
|
+
);
|
|
9744
|
+
maybeRecalculateWorkbook(workbook);
|
|
9745
|
+
refreshWorkbookState(workbook);
|
|
9746
|
+
return true;
|
|
9747
|
+
}, [activeSheetIndex, getFormControlWorksheet, maybeRecalculateWorkbook, readOnly, recordHistoryBeforeMutation, refreshWorkbookState, workbook]);
|
|
9748
|
+
const removeFormControl = React.useCallback((controlIndex, sheetIndex = activeSheetIndex) => {
|
|
9749
|
+
const target = getFormControlWorksheet(sheetIndex);
|
|
9750
|
+
if (readOnly || !workbook || !target || !target.worksheet.formControls[controlIndex]) {
|
|
9751
|
+
return false;
|
|
9752
|
+
}
|
|
9753
|
+
recordHistoryBeforeMutation();
|
|
9754
|
+
target.worksheet.removeFormControl(controlIndex);
|
|
9755
|
+
refreshWorkbookState(workbook);
|
|
9756
|
+
return true;
|
|
9757
|
+
}, [activeSheetIndex, getFormControlWorksheet, readOnly, recordHistoryBeforeMutation, refreshWorkbookState, workbook]);
|
|
9306
9758
|
const recordCellEditHistory = React.useCallback((cell, before, after) => {
|
|
9307
9759
|
if (!activeSheet || isApplyingHistoryRef.current) {
|
|
9308
9760
|
return;
|
|
@@ -10111,8 +10563,15 @@ function useXlsxViewerController(options) {
|
|
|
10111
10563
|
}
|
|
10112
10564
|
workbook.addSheet(candidate);
|
|
10113
10565
|
sheetOriginsRef.current = [...sheetOriginsRef.current, null];
|
|
10566
|
+
setFormControlsByWorkbookSheetIndex((current) => [...current, []]);
|
|
10114
10567
|
setImagesByWorkbookSheetIndex((current) => [...current, []]);
|
|
10115
10568
|
setShapesByWorkbookSheetIndex((current) => [...current, []]);
|
|
10569
|
+
if (imageAssetsRef.current) {
|
|
10570
|
+
imageAssetsRef.current.formControlsByWorkbookSheetIndex = [
|
|
10571
|
+
...imageAssetsRef.current.formControlsByWorkbookSheetIndex,
|
|
10572
|
+
[]
|
|
10573
|
+
];
|
|
10574
|
+
}
|
|
10116
10575
|
const nextSheets = buildSheetList(
|
|
10117
10576
|
workbook,
|
|
10118
10577
|
imageAssetsRef.current?.sheetStatesByWorkbookSheetIndex,
|
|
@@ -10142,9 +10601,13 @@ function useXlsxViewerController(options) {
|
|
|
10142
10601
|
recordHistoryBeforeMutation();
|
|
10143
10602
|
workbook.removeSheet(activeSheet.workbookSheetIndex);
|
|
10144
10603
|
sheetOriginsRef.current = sheetOriginsRef.current.filter((_, index) => index !== activeSheet.workbookSheetIndex);
|
|
10604
|
+
setFormControlsByWorkbookSheetIndex((current) => current.filter((_, index) => index !== activeSheet.workbookSheetIndex));
|
|
10145
10605
|
setImagesByWorkbookSheetIndex((current) => current.filter((_, index) => index !== activeSheet.workbookSheetIndex));
|
|
10146
10606
|
setShapesByWorkbookSheetIndex((current) => current.filter((_, index) => index !== activeSheet.workbookSheetIndex));
|
|
10147
10607
|
if (imageAssetsRef.current) {
|
|
10608
|
+
imageAssetsRef.current.formControlsByWorkbookSheetIndex = imageAssetsRef.current.formControlsByWorkbookSheetIndex.filter(
|
|
10609
|
+
(_, index) => index !== activeSheet.workbookSheetIndex
|
|
10610
|
+
);
|
|
10148
10611
|
imageAssetsRef.current.sheetStatesByWorkbookSheetIndex = imageAssetsRef.current.sheetStatesByWorkbookSheetIndex.filter(
|
|
10149
10612
|
(_, index) => index !== activeSheet.workbookSheetIndex
|
|
10150
10613
|
);
|
|
@@ -10445,6 +10908,7 @@ function useXlsxViewerController(options) {
|
|
|
10445
10908
|
activeSheetIndex,
|
|
10446
10909
|
activeTab,
|
|
10447
10910
|
activeTabIndex,
|
|
10911
|
+
addFormControl,
|
|
10448
10912
|
addSheet,
|
|
10449
10913
|
canRedo,
|
|
10450
10914
|
canDownload: Boolean(file ?? src),
|
|
@@ -10484,6 +10948,7 @@ function useXlsxViewerController(options) {
|
|
|
10484
10948
|
getClipboardData,
|
|
10485
10949
|
getCellDisplayValue: getCellDisplayValue2,
|
|
10486
10950
|
getCellFormula,
|
|
10951
|
+
getFormControlItems,
|
|
10487
10952
|
getCellSnapshotAsync: isWorkerBacked ? getCellSnapshotAsync : void 0,
|
|
10488
10953
|
getActiveWorksheet,
|
|
10489
10954
|
getRowsBatchAsync: isWorkerBacked ? getRowsBatchAsync : void 0,
|
|
@@ -10501,6 +10966,7 @@ function useXlsxViewerController(options) {
|
|
|
10501
10966
|
pasteStructuredClipboardData,
|
|
10502
10967
|
pasteText,
|
|
10503
10968
|
removeActiveSheet,
|
|
10969
|
+
removeFormControl,
|
|
10504
10970
|
readOnly,
|
|
10505
10971
|
recalculate,
|
|
10506
10972
|
redo,
|
|
@@ -10551,6 +11017,7 @@ function useXlsxViewerController(options) {
|
|
|
10551
11017
|
undo,
|
|
10552
11018
|
unmergeSelection,
|
|
10553
11019
|
updateChart,
|
|
11020
|
+
updateFormControl,
|
|
10554
11021
|
workbook,
|
|
10555
11022
|
zoomIn,
|
|
10556
11023
|
zoomOut,
|
|
@@ -10563,6 +11030,7 @@ function useXlsxViewerController(options) {
|
|
|
10563
11030
|
activeSheetIndex,
|
|
10564
11031
|
activeTab,
|
|
10565
11032
|
activeTabIndex,
|
|
11033
|
+
addFormControl,
|
|
10566
11034
|
addSheet,
|
|
10567
11035
|
canLoadDeferred,
|
|
10568
11036
|
canRedo,
|
|
@@ -10599,6 +11067,7 @@ function useXlsxViewerController(options) {
|
|
|
10599
11067
|
getClipboardData,
|
|
10600
11068
|
getCellDisplayValue2,
|
|
10601
11069
|
getCellFormula,
|
|
11070
|
+
getFormControlItems,
|
|
10602
11071
|
getCellSnapshotAsync,
|
|
10603
11072
|
getActiveWorksheet,
|
|
10604
11073
|
historyRevision,
|
|
@@ -10616,6 +11085,7 @@ function useXlsxViewerController(options) {
|
|
|
10616
11085
|
pasteStructuredClipboardData,
|
|
10617
11086
|
pasteText,
|
|
10618
11087
|
removeActiveSheet,
|
|
11088
|
+
removeFormControl,
|
|
10619
11089
|
readOnly,
|
|
10620
11090
|
recalculate,
|
|
10621
11091
|
redo,
|
|
@@ -10666,6 +11136,7 @@ function useXlsxViewerController(options) {
|
|
|
10666
11136
|
undo,
|
|
10667
11137
|
unmergeSelection,
|
|
10668
11138
|
updateChart,
|
|
11139
|
+
updateFormControl,
|
|
10669
11140
|
workbook,
|
|
10670
11141
|
zoomIn,
|
|
10671
11142
|
zoomOut,
|
|
@@ -21637,13 +22108,90 @@ function renderConditionalIcon(icon, scale = 1) {
|
|
|
21637
22108
|
}
|
|
21638
22109
|
);
|
|
21639
22110
|
}
|
|
21640
|
-
function
|
|
22111
|
+
function isFormControlChecked(control) {
|
|
22112
|
+
return control.state ? control.state === "checked" : Boolean(control.checked);
|
|
22113
|
+
}
|
|
22114
|
+
function isFormControlMixed(control) {
|
|
22115
|
+
return control.state === "mixed";
|
|
22116
|
+
}
|
|
22117
|
+
function buildFormControlKindInput(control) {
|
|
22118
|
+
switch (control.kind) {
|
|
22119
|
+
case "button":
|
|
22120
|
+
return { caption: control.caption ?? control.label ?? "", kind: "button" };
|
|
22121
|
+
case "checkbox":
|
|
22122
|
+
return {
|
|
22123
|
+
caption: control.caption ?? control.label ?? "",
|
|
22124
|
+
cellLink: control.linkedCell,
|
|
22125
|
+
kind: "checkbox",
|
|
22126
|
+
no3D: control.no3D ?? false,
|
|
22127
|
+
state: control.state ?? (control.checked ? "checked" : "unchecked")
|
|
22128
|
+
};
|
|
22129
|
+
case "radio":
|
|
22130
|
+
return {
|
|
22131
|
+
caption: control.caption ?? control.label ?? "",
|
|
22132
|
+
cellLink: control.linkedCell,
|
|
22133
|
+
firstInGroup: control.firstInGroup,
|
|
22134
|
+
kind: "optionButton",
|
|
22135
|
+
no3D: control.no3D ?? false,
|
|
22136
|
+
state: control.state === "checked" ? "checked" : "unchecked"
|
|
22137
|
+
};
|
|
22138
|
+
case "label":
|
|
22139
|
+
return { caption: control.caption ?? control.label ?? "", kind: "label" };
|
|
22140
|
+
case "group-box":
|
|
22141
|
+
return {
|
|
22142
|
+
caption: control.caption ?? control.label ?? "",
|
|
22143
|
+
kind: "groupBox",
|
|
22144
|
+
no3D: control.no3D ?? false
|
|
22145
|
+
};
|
|
22146
|
+
case "listbox":
|
|
22147
|
+
return {
|
|
22148
|
+
cellLink: control.linkedCell,
|
|
22149
|
+
inputRange: control.inputRange,
|
|
22150
|
+
kind: "listBox",
|
|
22151
|
+
no3D: control.no3D ?? false,
|
|
22152
|
+
selected: Array.isArray(control.selected) ? control.selected : control.selected === void 0 ? [] : [control.selected],
|
|
22153
|
+
selection: control.selection ?? "single"
|
|
22154
|
+
};
|
|
22155
|
+
case "dropdown":
|
|
22156
|
+
return {
|
|
22157
|
+
cellLink: control.linkedCell,
|
|
22158
|
+
inputRange: control.inputRange,
|
|
22159
|
+
kind: "dropdown",
|
|
22160
|
+
lines: control.lines ?? 8,
|
|
22161
|
+
no3D: control.no3D ?? false,
|
|
22162
|
+
selected: typeof control.selected === "number" ? control.selected : void 0
|
|
22163
|
+
};
|
|
22164
|
+
case "scrollbar":
|
|
22165
|
+
return {
|
|
22166
|
+
cellLink: control.linkedCell,
|
|
22167
|
+
horizontal: control.horizontal ?? true,
|
|
22168
|
+
increment: control.increment ?? 1,
|
|
22169
|
+
kind: "scrollbar",
|
|
22170
|
+
max: control.max ?? 100,
|
|
22171
|
+
min: control.min ?? 0,
|
|
22172
|
+
page: control.page ?? 10,
|
|
22173
|
+
value: control.value ?? control.min ?? 0
|
|
22174
|
+
};
|
|
22175
|
+
case "spinner":
|
|
22176
|
+
return {
|
|
22177
|
+
cellLink: control.linkedCell,
|
|
22178
|
+
increment: control.increment ?? 1,
|
|
22179
|
+
kind: "spinner",
|
|
22180
|
+
max: control.max ?? 100,
|
|
22181
|
+
min: control.min ?? 0,
|
|
22182
|
+
value: control.value ?? control.min ?? 0
|
|
22183
|
+
};
|
|
22184
|
+
default:
|
|
22185
|
+
return null;
|
|
22186
|
+
}
|
|
22187
|
+
}
|
|
22188
|
+
function renderCheckboxControl(checked, palette, scale = 1, mixed = false) {
|
|
21641
22189
|
const stroke = paletteIsDark(palette) ? "#cbd5e1" : "#475569";
|
|
21642
|
-
const fill = checked ? paletteIsDark(palette) ? "#60a5fa" : "#2563eb" : "transparent";
|
|
22190
|
+
const fill = checked || mixed ? paletteIsDark(palette) ? "#60a5fa" : "#2563eb" : "transparent";
|
|
21643
22191
|
const check = paletteIsDark(palette) ? "#020617" : "#ffffff";
|
|
21644
22192
|
return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("svg", { "aria-hidden": "true", height: 14 * scale, style: { display: "block" }, viewBox: "0 0 16 16", width: 14 * scale, children: [
|
|
21645
22193
|
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("rect", { fill, height: 11, rx: 2, ry: 2, stroke, strokeWidth: 1.2, width: 11, x: 2.5, y: 2.5 }),
|
|
21646
|
-
checked ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
22194
|
+
mixed ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("path", { d: "M5 8h6", fill: "none", stroke: check, strokeLinecap: "round", strokeWidth: 1.8 }) : checked ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
21647
22195
|
"path",
|
|
21648
22196
|
{
|
|
21649
22197
|
d: "M5 8.1 7.1 10.2 11.3 5.8",
|
|
@@ -21813,6 +22361,8 @@ function drawStaticFormControl(context, control, rect, palette, zoomFactor, shee
|
|
|
21813
22361
|
const textColor = control.textColor ?? "#000000";
|
|
21814
22362
|
const fontSizePx = Math.max(9 * zoomFactor, (control.fontSizePt ?? 9) * 96 / 72 * zoomFactor);
|
|
21815
22363
|
const iconSize = Math.min(14 * zoomFactor, Math.max(0, rect.height - 4 * zoomFactor));
|
|
22364
|
+
const controlChecked = isFormControlChecked(control);
|
|
22365
|
+
const controlMixed = isFormControlMixed(control);
|
|
21816
22366
|
context.save();
|
|
21817
22367
|
context.font = `400 ${fontSizePx}px ${control.fontFamily ?? "Calibri, sans-serif"}`;
|
|
21818
22368
|
context.textBaseline = "middle";
|
|
@@ -21853,14 +22403,19 @@ function drawStaticFormControl(context, control, rect, palette, zoomFactor, shee
|
|
|
21853
22403
|
const textRightInset = control.kind === "dropdown" ? 18 * zoomFactor : 6 * zoomFactor;
|
|
21854
22404
|
if (control.kind === "checkbox") {
|
|
21855
22405
|
context.strokeRect(rect.left + 2 * zoomFactor, rect.top + (rect.height - iconSize) / 2, iconSize, iconSize);
|
|
21856
|
-
if (
|
|
22406
|
+
if (controlChecked || controlMixed) {
|
|
21857
22407
|
context.fillStyle = paletteIsDark(palette) ? "#60a5fa" : "#2563eb";
|
|
21858
22408
|
context.fillRect(rect.left + 2 * zoomFactor + 1.5, rect.top + (rect.height - iconSize) / 2 + 1.5, Math.max(0, iconSize - 3), Math.max(0, iconSize - 3));
|
|
21859
22409
|
context.strokeStyle = paletteIsDark(palette) ? "#020617" : "#ffffff";
|
|
21860
22410
|
context.beginPath();
|
|
21861
|
-
|
|
21862
|
-
|
|
21863
|
-
|
|
22411
|
+
if (controlMixed) {
|
|
22412
|
+
context.moveTo(rect.left + 2 * zoomFactor + iconSize * 0.25, rect.top + rect.height / 2);
|
|
22413
|
+
context.lineTo(rect.left + 2 * zoomFactor + iconSize * 0.75, rect.top + rect.height / 2);
|
|
22414
|
+
} else {
|
|
22415
|
+
context.moveTo(rect.left + 2 * zoomFactor + iconSize * 0.24, rect.top + rect.height / 2 + iconSize * 0.06);
|
|
22416
|
+
context.lineTo(rect.left + 2 * zoomFactor + iconSize * 0.45, rect.top + rect.height / 2 + iconSize * 0.26);
|
|
22417
|
+
context.lineTo(rect.left + 2 * zoomFactor + iconSize * 0.8, rect.top + rect.height / 2 - iconSize * 0.2);
|
|
22418
|
+
}
|
|
21864
22419
|
context.stroke();
|
|
21865
22420
|
}
|
|
21866
22421
|
textLeft += iconSize + 4 * zoomFactor;
|
|
@@ -21868,7 +22423,7 @@ function drawStaticFormControl(context, control, rect, palette, zoomFactor, shee
|
|
|
21868
22423
|
context.beginPath();
|
|
21869
22424
|
context.arc(rect.left + 2 * zoomFactor + iconSize / 2, rect.top + rect.height / 2, iconSize / 2, 0, Math.PI * 2);
|
|
21870
22425
|
context.stroke();
|
|
21871
|
-
if (
|
|
22426
|
+
if (controlChecked) {
|
|
21872
22427
|
context.fillStyle = paletteIsDark(palette) ? "#60a5fa" : "#2563eb";
|
|
21873
22428
|
context.beginPath();
|
|
21874
22429
|
context.arc(rect.left + 2 * zoomFactor + iconSize / 2, rect.top + rect.height / 2, iconSize * 0.25, 0, Math.PI * 2);
|
|
@@ -22504,6 +23059,8 @@ function XlsxGrid({
|
|
|
22504
23059
|
getCellStyle,
|
|
22505
23060
|
loadingComponent,
|
|
22506
23061
|
loadingState,
|
|
23062
|
+
onFormControlAction,
|
|
23063
|
+
onFormControlChange,
|
|
22507
23064
|
renderChartLoading,
|
|
22508
23065
|
palette,
|
|
22509
23066
|
renderImage,
|
|
@@ -22541,6 +23098,7 @@ function XlsxGrid({
|
|
|
22541
23098
|
getRowsBatchAsync,
|
|
22542
23099
|
getClipboardData,
|
|
22543
23100
|
getCellDisplayValue: getControllerCellDisplayValue,
|
|
23101
|
+
getFormControlItems,
|
|
22544
23102
|
images,
|
|
22545
23103
|
shapes,
|
|
22546
23104
|
isLoadDeferred,
|
|
@@ -22578,9 +23136,13 @@ function XlsxGrid({
|
|
|
22578
23136
|
sortTable,
|
|
22579
23137
|
tables,
|
|
22580
23138
|
undo,
|
|
23139
|
+
updateFormControl,
|
|
22581
23140
|
workbook,
|
|
22582
23141
|
zoomScale
|
|
22583
23142
|
} = controller;
|
|
23143
|
+
const formControlItemsById = React4.useMemo(() => new Map(
|
|
23144
|
+
formControls.flatMap((control) => control.controlIndex !== void 0 && (control.kind === "dropdown" || control.kind === "listbox") ? [[control.id, getFormControlItems(control.controlIndex, control.sheetIndex)]] : [])
|
|
23145
|
+
), [formControls, getFormControlItems]);
|
|
22584
23146
|
const canResizeHeaders = !readOnly || allowResizeInReadOnly;
|
|
22585
23147
|
const scrollRef = React4.useRef(null);
|
|
22586
23148
|
const wrapperRef = React4.useRef(null);
|
|
@@ -25088,7 +25650,7 @@ function XlsxGrid({
|
|
|
25088
25650
|
return "";
|
|
25089
25651
|
}
|
|
25090
25652
|
const shapeSignature = bakedShapeRects.map(({ rect, shape }) => `s:${shape.id}:${shape.zIndex}:${Math.round(rect.left)}:${Math.round(rect.top)}:${Math.round(rect.width)}:${Math.round(rect.height)}`).join("|");
|
|
25091
|
-
const controlSignature = bakedFormControlRects.map(({ control, rect }) => `f:${control.id}:${control.zIndex}:${Boolean(control.checked)}:${Math.round(rect.left)}:${Math.round(rect.top)}:${Math.round(rect.width)}:${Math.round(rect.height)}`).join("|");
|
|
25653
|
+
const controlSignature = bakedFormControlRects.map(({ control, rect }) => `f:${control.id}:${control.zIndex}:${control.state ?? Boolean(control.checked)}:${Math.round(rect.left)}:${Math.round(rect.top)}:${Math.round(rect.width)}:${Math.round(rect.height)}`).join("|");
|
|
25092
25654
|
const imageSignature = bakedImageRects.map(({ image, rect }) => `i:${image.id}:${image.src}:${image.zIndex}:${Math.round(rect.left)}:${Math.round(rect.top)}:${Math.round(rect.width)}:${Math.round(rect.height)}`).join("|");
|
|
25093
25655
|
return `${revision}:${canvasImageLoadVersion}:${shapeSignature}:${controlSignature}:${imageSignature}`;
|
|
25094
25656
|
}, [
|
|
@@ -26789,6 +27351,8 @@ function XlsxGrid({
|
|
|
26789
27351
|
const textColor = control.textColor ?? "#000000";
|
|
26790
27352
|
const fontSizePx = Math.max(9 * zoomFactor, (control.fontSizePt ?? 9) * 96 / 72 * zoomFactor);
|
|
26791
27353
|
const iconSize = Math.min(14 * zoomFactor, Math.max(0, rect.height - 4 * zoomFactor));
|
|
27354
|
+
const controlChecked = isFormControlChecked(control);
|
|
27355
|
+
const controlMixed = isFormControlMixed(control);
|
|
26792
27356
|
context.save();
|
|
26793
27357
|
context.font = `400 ${fontSizePx}px ${control.fontFamily ?? "Calibri, sans-serif"}`;
|
|
26794
27358
|
context.textBaseline = "middle";
|
|
@@ -26829,14 +27393,19 @@ function XlsxGrid({
|
|
|
26829
27393
|
const textRightInset = control.kind === "dropdown" ? 18 * zoomFactor : 6 * zoomFactor;
|
|
26830
27394
|
if (control.kind === "checkbox") {
|
|
26831
27395
|
context.strokeRect(rect.left + 2 * zoomFactor, rect.top + (rect.height - iconSize) / 2, iconSize, iconSize);
|
|
26832
|
-
if (
|
|
27396
|
+
if (controlChecked || controlMixed) {
|
|
26833
27397
|
context.fillStyle = paletteIsDark(palette) ? "#60a5fa" : "#2563eb";
|
|
26834
27398
|
context.fillRect(rect.left + 2 * zoomFactor + 1.5, rect.top + (rect.height - iconSize) / 2 + 1.5, Math.max(0, iconSize - 3), Math.max(0, iconSize - 3));
|
|
26835
27399
|
context.strokeStyle = paletteIsDark(palette) ? "#020617" : "#ffffff";
|
|
26836
27400
|
context.beginPath();
|
|
26837
|
-
|
|
26838
|
-
|
|
26839
|
-
|
|
27401
|
+
if (controlMixed) {
|
|
27402
|
+
context.moveTo(rect.left + 2 * zoomFactor + iconSize * 0.25, rect.top + rect.height / 2);
|
|
27403
|
+
context.lineTo(rect.left + 2 * zoomFactor + iconSize * 0.75, rect.top + rect.height / 2);
|
|
27404
|
+
} else {
|
|
27405
|
+
context.moveTo(rect.left + 2 * zoomFactor + iconSize * 0.24, rect.top + rect.height / 2 + iconSize * 0.06);
|
|
27406
|
+
context.lineTo(rect.left + 2 * zoomFactor + iconSize * 0.45, rect.top + rect.height / 2 + iconSize * 0.26);
|
|
27407
|
+
context.lineTo(rect.left + 2 * zoomFactor + iconSize * 0.8, rect.top + rect.height / 2 - iconSize * 0.2);
|
|
27408
|
+
}
|
|
26840
27409
|
context.stroke();
|
|
26841
27410
|
}
|
|
26842
27411
|
textLeft += iconSize + 4 * zoomFactor;
|
|
@@ -26844,7 +27413,7 @@ function XlsxGrid({
|
|
|
26844
27413
|
context.beginPath();
|
|
26845
27414
|
context.arc(rect.left + 2 * zoomFactor + iconSize / 2, rect.top + rect.height / 2, iconSize / 2, 0, Math.PI * 2);
|
|
26846
27415
|
context.stroke();
|
|
26847
|
-
if (
|
|
27416
|
+
if (controlChecked) {
|
|
26848
27417
|
context.fillStyle = paletteIsDark(palette) ? "#60a5fa" : "#2563eb";
|
|
26849
27418
|
context.beginPath();
|
|
26850
27419
|
context.arc(rect.left + 2 * zoomFactor + iconSize / 2, rect.top + rect.height / 2, iconSize * 0.25, 0, Math.PI * 2);
|
|
@@ -28159,10 +28728,22 @@ function XlsxGrid({
|
|
|
28159
28728
|
const fontSizePx = Math.max(9 * zoomFactor, (control.fontSizePt ?? 9) * 96 / 72 * zoomFactor);
|
|
28160
28729
|
const stroke = paletteIsDark(palette) ? "#cbd5e1" : "#475569";
|
|
28161
28730
|
const textColor = control.textColor ?? "#000000";
|
|
28731
|
+
const canMutateControl = !readOnly && control.controlIndex !== void 0 && [
|
|
28732
|
+
"checkbox",
|
|
28733
|
+
"dropdown",
|
|
28734
|
+
"listbox",
|
|
28735
|
+
"radio",
|
|
28736
|
+
"scrollbar",
|
|
28737
|
+
"spinner"
|
|
28738
|
+
].includes(control.kind);
|
|
28739
|
+
const canActivateButton = !readOnly && control.kind === "button" && Boolean(onFormControlAction);
|
|
28740
|
+
const isInteractiveControl = canMutateControl || canActivateButton;
|
|
28741
|
+
const controlItems = formControlItemsById.get(control.id) ?? [];
|
|
28162
28742
|
const commonStyle = {
|
|
28163
28743
|
alignItems: control.kind === "group-box" ? "stretch" : "center",
|
|
28164
28744
|
color: textColor,
|
|
28165
28745
|
contain: "layout paint",
|
|
28746
|
+
cursor: isInteractiveControl ? "pointer" : void 0,
|
|
28166
28747
|
display: "flex",
|
|
28167
28748
|
fontFamily: control.fontFamily ?? "Calibri, sans-serif",
|
|
28168
28749
|
fontSize: fontSizePx,
|
|
@@ -28173,12 +28754,28 @@ function XlsxGrid({
|
|
|
28173
28754
|
left: rect.left,
|
|
28174
28755
|
lineHeight: 1.2,
|
|
28175
28756
|
overflow: "hidden",
|
|
28176
|
-
pointerEvents: "none",
|
|
28757
|
+
pointerEvents: isInteractiveControl ? "auto" : "none",
|
|
28177
28758
|
position: "absolute",
|
|
28178
28759
|
top: rect.top,
|
|
28179
28760
|
width: rect.width,
|
|
28180
28761
|
zIndex: isFrozenDrawing ? control.zIndex + 20 : control.zIndex
|
|
28181
28762
|
};
|
|
28763
|
+
const stopControlPointerEvent = (event) => {
|
|
28764
|
+
event.stopPropagation();
|
|
28765
|
+
};
|
|
28766
|
+
const commitControlKind = (kind, nextControl) => {
|
|
28767
|
+
if (control.controlIndex === void 0) {
|
|
28768
|
+
return;
|
|
28769
|
+
}
|
|
28770
|
+
const didUpdate = updateFormControl(control.controlIndex, { kind }, control.sheetIndex);
|
|
28771
|
+
if (didUpdate) {
|
|
28772
|
+
onFormControlChange?.({
|
|
28773
|
+
control: { ...control, ...nextControl },
|
|
28774
|
+
previousControl: control,
|
|
28775
|
+
type: "change"
|
|
28776
|
+
});
|
|
28777
|
+
}
|
|
28778
|
+
};
|
|
28182
28779
|
if (control.kind === "group-box") {
|
|
28183
28780
|
const hasLabel = controlLabel.length > 0;
|
|
28184
28781
|
return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
@@ -28220,15 +28817,88 @@ function XlsxGrid({
|
|
|
28220
28817
|
`${pane}-${control.id}`
|
|
28221
28818
|
);
|
|
28222
28819
|
}
|
|
28223
|
-
let content;
|
|
28224
28820
|
if (control.kind === "radio") {
|
|
28225
|
-
|
|
28226
|
-
|
|
28227
|
-
|
|
28228
|
-
|
|
28821
|
+
const checked = isFormControlChecked(control);
|
|
28822
|
+
const kind = buildFormControlKindInput(control);
|
|
28823
|
+
return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
|
|
28824
|
+
"button",
|
|
28825
|
+
{
|
|
28826
|
+
"aria-checked": checked,
|
|
28827
|
+
disabled: readOnly || control.controlIndex === void 0,
|
|
28828
|
+
onClick: (event) => {
|
|
28829
|
+
event.stopPropagation();
|
|
28830
|
+
if (!checked && kind?.kind === "optionButton") {
|
|
28831
|
+
commitControlKind(
|
|
28832
|
+
{ ...kind, state: "checked" },
|
|
28833
|
+
{ checked: true, state: "checked" }
|
|
28834
|
+
);
|
|
28835
|
+
}
|
|
28836
|
+
},
|
|
28837
|
+
onPointerDown: stopControlPointerEvent,
|
|
28838
|
+
role: "radio",
|
|
28839
|
+
style: {
|
|
28840
|
+
...commonStyle,
|
|
28841
|
+
background: "transparent",
|
|
28842
|
+
border: 0,
|
|
28843
|
+
boxSizing: "border-box",
|
|
28844
|
+
padding: `0 ${Math.max(1, zoomFactor)}px`
|
|
28845
|
+
},
|
|
28846
|
+
type: "button",
|
|
28847
|
+
children: [
|
|
28848
|
+
renderRadioControl(checked, palette, zoomFactor),
|
|
28849
|
+
controlLabel ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { style: { overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }, children: controlLabel }) : null
|
|
28850
|
+
]
|
|
28851
|
+
},
|
|
28852
|
+
`${pane}-${control.id}`
|
|
28853
|
+
);
|
|
28854
|
+
}
|
|
28855
|
+
if (control.kind === "checkbox") {
|
|
28856
|
+
const checked = isFormControlChecked(control);
|
|
28857
|
+
const mixed = isFormControlMixed(control);
|
|
28858
|
+
const kind = buildFormControlKindInput(control);
|
|
28859
|
+
return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
|
|
28860
|
+
"button",
|
|
28861
|
+
{
|
|
28862
|
+
"aria-checked": mixed ? "mixed" : checked,
|
|
28863
|
+
disabled: readOnly || control.controlIndex === void 0,
|
|
28864
|
+
onClick: (event) => {
|
|
28865
|
+
event.stopPropagation();
|
|
28866
|
+
if (kind?.kind === "checkbox") {
|
|
28867
|
+
const nextState = checked && !mixed ? "unchecked" : "checked";
|
|
28868
|
+
commitControlKind(
|
|
28869
|
+
{ ...kind, state: nextState },
|
|
28870
|
+
{ checked: nextState === "checked", state: nextState }
|
|
28871
|
+
);
|
|
28872
|
+
}
|
|
28873
|
+
},
|
|
28874
|
+
onPointerDown: stopControlPointerEvent,
|
|
28875
|
+
role: "checkbox",
|
|
28876
|
+
style: {
|
|
28877
|
+
...commonStyle,
|
|
28878
|
+
background: "transparent",
|
|
28879
|
+
border: 0,
|
|
28880
|
+
boxSizing: "border-box",
|
|
28881
|
+
padding: `0 ${Math.max(1, zoomFactor)}px`
|
|
28882
|
+
},
|
|
28883
|
+
type: "button",
|
|
28884
|
+
children: [
|
|
28885
|
+
renderCheckboxControl(checked, palette, zoomFactor, mixed),
|
|
28886
|
+
controlLabel ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { style: { overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }, children: controlLabel }) : null
|
|
28887
|
+
]
|
|
28888
|
+
},
|
|
28889
|
+
`${pane}-${control.id}`
|
|
28890
|
+
);
|
|
28891
|
+
}
|
|
28892
|
+
if (control.kind === "button") {
|
|
28229
28893
|
return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
28230
|
-
"
|
|
28894
|
+
"button",
|
|
28231
28895
|
{
|
|
28896
|
+
disabled: readOnly || !onFormControlAction,
|
|
28897
|
+
onClick: (event) => {
|
|
28898
|
+
event.stopPropagation();
|
|
28899
|
+
onFormControlAction?.({ control, type: "activate" });
|
|
28900
|
+
},
|
|
28901
|
+
onPointerDown: stopControlPointerEvent,
|
|
28232
28902
|
style: {
|
|
28233
28903
|
...commonStyle,
|
|
28234
28904
|
background: "linear-gradient(180deg, #f8fafc 0%, #e2e8f0 100%)",
|
|
@@ -28239,68 +28909,168 @@ function XlsxGrid({
|
|
|
28239
28909
|
padding: `0 ${6 * zoomFactor}px`,
|
|
28240
28910
|
textAlign: "center"
|
|
28241
28911
|
},
|
|
28912
|
+
type: "button",
|
|
28242
28913
|
children: controlLabel
|
|
28243
28914
|
},
|
|
28244
28915
|
`${pane}-${control.id}`
|
|
28245
28916
|
);
|
|
28246
|
-
}
|
|
28917
|
+
}
|
|
28918
|
+
if (control.kind === "dropdown") {
|
|
28919
|
+
const kind = buildFormControlKindInput(control);
|
|
28920
|
+
const selected = typeof control.selected === "number" ? control.selected : void 0;
|
|
28247
28921
|
return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
|
|
28248
|
-
"
|
|
28922
|
+
"select",
|
|
28249
28923
|
{
|
|
28924
|
+
"aria-label": controlLabel || control.name || "Dropdown form control",
|
|
28925
|
+
disabled: readOnly || control.controlIndex === void 0 || controlItems.length === 0,
|
|
28926
|
+
onChange: (event) => {
|
|
28927
|
+
event.stopPropagation();
|
|
28928
|
+
if (kind?.kind === "dropdown") {
|
|
28929
|
+
const nextSelected = event.currentTarget.value === "" ? void 0 : Number(event.currentTarget.value);
|
|
28930
|
+
commitControlKind(
|
|
28931
|
+
{ ...kind, selected: nextSelected },
|
|
28932
|
+
{ selected: nextSelected }
|
|
28933
|
+
);
|
|
28934
|
+
}
|
|
28935
|
+
},
|
|
28936
|
+
onClick: stopControlPointerEvent,
|
|
28937
|
+
onPointerDown: stopControlPointerEvent,
|
|
28250
28938
|
style: {
|
|
28251
28939
|
...commonStyle,
|
|
28940
|
+
backgroundColor: SHEET_SURFACE,
|
|
28252
28941
|
border: `${Math.max(1, zoomFactor)}px solid ${stroke}`,
|
|
28253
28942
|
borderRadius: 2 * zoomFactor,
|
|
28254
28943
|
boxSizing: "border-box",
|
|
28255
|
-
|
|
28256
|
-
padding: `0 ${6 * zoomFactor}px`
|
|
28944
|
+
padding: `0 ${4 * zoomFactor}px`
|
|
28257
28945
|
},
|
|
28946
|
+
value: selected === void 0 ? "" : String(selected),
|
|
28258
28947
|
children: [
|
|
28259
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("
|
|
28260
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("
|
|
28948
|
+
selected === void 0 ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("option", { value: "", children: controlLabel }) : null,
|
|
28949
|
+
controlItems.map((item, index) => /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("option", { value: index, children: item }, index))
|
|
28261
28950
|
]
|
|
28262
28951
|
},
|
|
28263
28952
|
`${pane}-${control.id}`
|
|
28264
28953
|
);
|
|
28265
|
-
}
|
|
28954
|
+
}
|
|
28955
|
+
if (control.kind === "listbox") {
|
|
28956
|
+
const kind = buildFormControlKindInput(control);
|
|
28957
|
+
const selected = Array.isArray(control.selected) ? control.selected : control.selected === void 0 ? [] : [control.selected];
|
|
28958
|
+
const allowsMultipleSelection = (control.selection ?? "single") !== "single";
|
|
28266
28959
|
return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
28267
|
-
"
|
|
28960
|
+
"select",
|
|
28268
28961
|
{
|
|
28962
|
+
"aria-label": controlLabel || control.name || "List box form control",
|
|
28963
|
+
disabled: readOnly || control.controlIndex === void 0 || controlItems.length === 0,
|
|
28964
|
+
multiple: allowsMultipleSelection,
|
|
28965
|
+
onChange: (event) => {
|
|
28966
|
+
event.stopPropagation();
|
|
28967
|
+
if (kind?.kind === "listBox") {
|
|
28968
|
+
const nextSelected = Array.from(event.currentTarget.selectedOptions, (option) => Number(option.value));
|
|
28969
|
+
commitControlKind(
|
|
28970
|
+
{ ...kind, selected: nextSelected },
|
|
28971
|
+
{ selected: nextSelected }
|
|
28972
|
+
);
|
|
28973
|
+
}
|
|
28974
|
+
},
|
|
28975
|
+
onClick: stopControlPointerEvent,
|
|
28976
|
+
onPointerDown: stopControlPointerEvent,
|
|
28977
|
+
size: Math.max(2, Math.min(controlItems.length || 2, Math.floor(rect.height / Math.max(1, fontSizePx * 1.45)))),
|
|
28269
28978
|
style: {
|
|
28270
28979
|
...commonStyle,
|
|
28980
|
+
alignItems: void 0,
|
|
28981
|
+
backgroundColor: SHEET_SURFACE,
|
|
28271
28982
|
border: `${Math.max(1, zoomFactor)}px solid ${stroke}`,
|
|
28272
28983
|
borderRadius: 2 * zoomFactor,
|
|
28273
28984
|
boxSizing: "border-box",
|
|
28274
|
-
|
|
28985
|
+
display: "block",
|
|
28986
|
+
padding: 0
|
|
28275
28987
|
},
|
|
28276
|
-
|
|
28988
|
+
value: allowsMultipleSelection ? selected.map(String) : selected[0] === void 0 ? "" : String(selected[0]),
|
|
28989
|
+
children: controlItems.map((item, index) => /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("option", { value: index, children: item }, index))
|
|
28277
28990
|
},
|
|
28278
28991
|
`${pane}-${control.id}`
|
|
28279
28992
|
);
|
|
28280
|
-
} else {
|
|
28281
|
-
content = null;
|
|
28282
28993
|
}
|
|
28283
|
-
|
|
28994
|
+
if (control.kind === "scrollbar") {
|
|
28995
|
+
const kind = buildFormControlKindInput(control);
|
|
28996
|
+
const min = control.min ?? 0;
|
|
28997
|
+
const max = Math.max(min, control.max ?? 100);
|
|
28998
|
+
return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
28999
|
+
"input",
|
|
29000
|
+
{
|
|
29001
|
+
"aria-label": controlLabel || control.name || "Scrollbar form control",
|
|
29002
|
+
disabled: readOnly || control.controlIndex === void 0,
|
|
29003
|
+
max,
|
|
29004
|
+
min,
|
|
29005
|
+
onChange: (event) => {
|
|
29006
|
+
event.stopPropagation();
|
|
29007
|
+
if (kind?.kind === "scrollbar") {
|
|
29008
|
+
const value = event.currentTarget.valueAsNumber;
|
|
29009
|
+
commitControlKind({ ...kind, value }, { value });
|
|
29010
|
+
}
|
|
29011
|
+
},
|
|
29012
|
+
onClick: stopControlPointerEvent,
|
|
29013
|
+
onPointerDown: stopControlPointerEvent,
|
|
29014
|
+
step: Math.max(1, control.increment ?? 1),
|
|
29015
|
+
style: {
|
|
29016
|
+
...commonStyle,
|
|
29017
|
+
accentColor: paletteIsDark(palette) ? "#60a5fa" : "#2563eb",
|
|
29018
|
+
boxSizing: "border-box",
|
|
29019
|
+
padding: 0,
|
|
29020
|
+
writingMode: control.horizontal === false ? "vertical-lr" : void 0
|
|
29021
|
+
},
|
|
29022
|
+
type: "range",
|
|
29023
|
+
value: Math.max(min, Math.min(max, control.value ?? min))
|
|
29024
|
+
},
|
|
29025
|
+
`${pane}-${control.id}`
|
|
29026
|
+
);
|
|
29027
|
+
}
|
|
29028
|
+
if (control.kind === "spinner") {
|
|
29029
|
+
const kind = buildFormControlKindInput(control);
|
|
29030
|
+
const min = control.min ?? 0;
|
|
29031
|
+
const max = Math.max(min, control.max ?? 100);
|
|
29032
|
+
return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
29033
|
+
"input",
|
|
29034
|
+
{
|
|
29035
|
+
"aria-label": controlLabel || control.name || "Spinner form control",
|
|
29036
|
+
disabled: readOnly || control.controlIndex === void 0,
|
|
29037
|
+
max,
|
|
29038
|
+
min,
|
|
29039
|
+
onChange: (event) => {
|
|
29040
|
+
event.stopPropagation();
|
|
29041
|
+
if (kind?.kind === "spinner" && Number.isFinite(event.currentTarget.valueAsNumber)) {
|
|
29042
|
+
const value = Math.max(min, Math.min(max, event.currentTarget.valueAsNumber));
|
|
29043
|
+
commitControlKind({ ...kind, value }, { value });
|
|
29044
|
+
}
|
|
29045
|
+
},
|
|
29046
|
+
onClick: stopControlPointerEvent,
|
|
29047
|
+
onPointerDown: stopControlPointerEvent,
|
|
29048
|
+
step: Math.max(1, control.increment ?? 1),
|
|
29049
|
+
style: {
|
|
29050
|
+
...commonStyle,
|
|
29051
|
+
backgroundColor: SHEET_SURFACE,
|
|
29052
|
+
border: `${Math.max(1, zoomFactor)}px solid ${stroke}`,
|
|
29053
|
+
borderRadius: 2 * zoomFactor,
|
|
29054
|
+
boxSizing: "border-box",
|
|
29055
|
+
padding: `0 ${4 * zoomFactor}px`
|
|
29056
|
+
},
|
|
29057
|
+
type: "number",
|
|
29058
|
+
value: Math.max(min, Math.min(max, control.value ?? min))
|
|
29059
|
+
},
|
|
29060
|
+
`${pane}-${control.id}`
|
|
29061
|
+
);
|
|
29062
|
+
}
|
|
29063
|
+
return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
28284
29064
|
"div",
|
|
28285
29065
|
{
|
|
28286
29066
|
style: {
|
|
28287
29067
|
...commonStyle,
|
|
29068
|
+
border: control.kind === "editbox" || control.kind === "unknown" ? `${Math.max(1, zoomFactor)}px solid ${stroke}` : void 0,
|
|
29069
|
+
borderRadius: 2 * zoomFactor,
|
|
29070
|
+
boxSizing: "border-box",
|
|
28288
29071
|
padding: `0 ${Math.max(1, zoomFactor)}px`
|
|
28289
29072
|
},
|
|
28290
|
-
children:
|
|
28291
|
-
content,
|
|
28292
|
-
controlLabel ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
28293
|
-
"span",
|
|
28294
|
-
{
|
|
28295
|
-
style: {
|
|
28296
|
-
overflow: "hidden",
|
|
28297
|
-
textOverflow: "ellipsis",
|
|
28298
|
-
whiteSpace: "nowrap"
|
|
28299
|
-
},
|
|
28300
|
-
children: controlLabel
|
|
28301
|
-
}
|
|
28302
|
-
) : null
|
|
28303
|
-
]
|
|
29073
|
+
children: controlLabel ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { style: { overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }, children: controlLabel }) : null
|
|
28304
29074
|
},
|
|
28305
29075
|
`${pane}-${control.id}`
|
|
28306
29076
|
);
|
|
@@ -29863,6 +30633,8 @@ function XlsxViewerInner({
|
|
|
29863
30633
|
isDark = false,
|
|
29864
30634
|
loadingComponent,
|
|
29865
30635
|
loadingState,
|
|
30636
|
+
onFormControlAction,
|
|
30637
|
+
onFormControlChange,
|
|
29866
30638
|
renderChartLoading,
|
|
29867
30639
|
renderImage,
|
|
29868
30640
|
renderImageSelection,
|
|
@@ -29925,6 +30697,8 @@ function XlsxViewerInner({
|
|
|
29925
30697
|
getCellStyle,
|
|
29926
30698
|
loadingComponent,
|
|
29927
30699
|
loadingState,
|
|
30700
|
+
onFormControlAction,
|
|
30701
|
+
onFormControlChange,
|
|
29928
30702
|
palette,
|
|
29929
30703
|
renderChartLoading,
|
|
29930
30704
|
renderImage,
|
|
@@ -30031,6 +30805,7 @@ function useXlsxViewerZoom() {
|
|
|
30031
30805
|
}
|
|
30032
30806
|
function useXlsxViewerEditing() {
|
|
30033
30807
|
const {
|
|
30808
|
+
addFormControl,
|
|
30034
30809
|
addSheet,
|
|
30035
30810
|
canRedo,
|
|
30036
30811
|
canUndo,
|
|
@@ -30038,14 +30813,18 @@ function useXlsxViewerEditing() {
|
|
|
30038
30813
|
copySelectionToClipboard,
|
|
30039
30814
|
defineNamedRange,
|
|
30040
30815
|
fillSelection,
|
|
30816
|
+
formControls,
|
|
30041
30817
|
getClipboardData,
|
|
30042
30818
|
getCellDisplayValue: getCellDisplayValue2,
|
|
30043
30819
|
getCellFormula,
|
|
30820
|
+
getFormControlItems,
|
|
30821
|
+
getSheetFormControls,
|
|
30044
30822
|
mergeSelection,
|
|
30045
30823
|
pasteFromClipboard,
|
|
30046
30824
|
pasteStructuredClipboardData,
|
|
30047
30825
|
pasteText,
|
|
30048
30826
|
removeActiveSheet,
|
|
30827
|
+
removeFormControl,
|
|
30049
30828
|
readOnly,
|
|
30050
30829
|
redo,
|
|
30051
30830
|
selectedCellFormula,
|
|
@@ -30062,10 +30841,12 @@ function useXlsxViewerEditing() {
|
|
|
30062
30841
|
setSelectedCellStyle,
|
|
30063
30842
|
setSelectedCellValue,
|
|
30064
30843
|
undo,
|
|
30065
|
-
unmergeSelection
|
|
30844
|
+
unmergeSelection,
|
|
30845
|
+
updateFormControl
|
|
30066
30846
|
} = useXlsxViewer();
|
|
30067
30847
|
return React4.useMemo(
|
|
30068
30848
|
() => ({
|
|
30849
|
+
addFormControl,
|
|
30069
30850
|
addSheet,
|
|
30070
30851
|
canRedo,
|
|
30071
30852
|
canUndo,
|
|
@@ -30073,14 +30854,18 @@ function useXlsxViewerEditing() {
|
|
|
30073
30854
|
copySelectionToClipboard,
|
|
30074
30855
|
defineNamedRange,
|
|
30075
30856
|
fillSelection,
|
|
30857
|
+
formControls,
|
|
30076
30858
|
getClipboardData,
|
|
30077
30859
|
getCellDisplayValue: getCellDisplayValue2,
|
|
30078
30860
|
getCellFormula,
|
|
30861
|
+
getFormControlItems,
|
|
30862
|
+
getSheetFormControls,
|
|
30079
30863
|
mergeSelection,
|
|
30080
30864
|
pasteFromClipboard,
|
|
30081
30865
|
pasteStructuredClipboardData,
|
|
30082
30866
|
pasteText,
|
|
30083
30867
|
removeActiveSheet,
|
|
30868
|
+
removeFormControl,
|
|
30084
30869
|
readOnly,
|
|
30085
30870
|
redo,
|
|
30086
30871
|
selectedCellFormula,
|
|
@@ -30097,9 +30882,11 @@ function useXlsxViewerEditing() {
|
|
|
30097
30882
|
setSelectedCellStyle,
|
|
30098
30883
|
setSelectedCellValue,
|
|
30099
30884
|
undo,
|
|
30100
|
-
unmergeSelection
|
|
30885
|
+
unmergeSelection,
|
|
30886
|
+
updateFormControl
|
|
30101
30887
|
}),
|
|
30102
30888
|
[
|
|
30889
|
+
addFormControl,
|
|
30103
30890
|
addSheet,
|
|
30104
30891
|
canRedo,
|
|
30105
30892
|
canUndo,
|
|
@@ -30107,14 +30894,18 @@ function useXlsxViewerEditing() {
|
|
|
30107
30894
|
copySelectionToClipboard,
|
|
30108
30895
|
defineNamedRange,
|
|
30109
30896
|
fillSelection,
|
|
30897
|
+
formControls,
|
|
30110
30898
|
getClipboardData,
|
|
30111
30899
|
getCellDisplayValue2,
|
|
30112
30900
|
getCellFormula,
|
|
30901
|
+
getFormControlItems,
|
|
30902
|
+
getSheetFormControls,
|
|
30113
30903
|
mergeSelection,
|
|
30114
30904
|
pasteFromClipboard,
|
|
30115
30905
|
pasteStructuredClipboardData,
|
|
30116
30906
|
pasteText,
|
|
30117
30907
|
removeActiveSheet,
|
|
30908
|
+
removeFormControl,
|
|
30118
30909
|
readOnly,
|
|
30119
30910
|
redo,
|
|
30120
30911
|
selectedCellFormula,
|
|
@@ -30131,7 +30922,8 @@ function useXlsxViewerEditing() {
|
|
|
30131
30922
|
setSelectedCellStyle,
|
|
30132
30923
|
setSelectedCellValue,
|
|
30133
30924
|
undo,
|
|
30134
|
-
unmergeSelection
|
|
30925
|
+
unmergeSelection,
|
|
30926
|
+
updateFormControl
|
|
30135
30927
|
]
|
|
30136
30928
|
);
|
|
30137
30929
|
}
|