@extend-ai/react-xlsx 0.13.3 → 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 +874 -84
- 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 +874 -84
- 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.js
CHANGED
|
@@ -3592,7 +3592,6 @@ var SPREADSHEET_NS = "http://schemas.openxmlformats.org/spreadsheetml/2006/main"
|
|
|
3592
3592
|
var CONTENT_TYPES_NS = "http://schemas.openxmlformats.org/package/2006/content-types";
|
|
3593
3593
|
var DRAWING_REL_TYPE = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/drawing";
|
|
3594
3594
|
var VML_DRAWING_REL_TYPE = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/vmlDrawing";
|
|
3595
|
-
var CTRL_PROP_REL_TYPE = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/ctrlProp";
|
|
3596
3595
|
var IMAGE_REL_TYPE = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/image";
|
|
3597
3596
|
var DRAWING_CONTENT_TYPE = "application/vnd.openxmlformats-officedocument.drawing+xml";
|
|
3598
3597
|
var EMU_PER_PIXEL2 = 9525;
|
|
@@ -5035,6 +5034,124 @@ function parseSpreadsheetBooleanNode(node) {
|
|
|
5035
5034
|
}
|
|
5036
5035
|
return parseSpreadsheetBooleanValue(node.getAttribute("val") ?? node.textContent);
|
|
5037
5036
|
}
|
|
5037
|
+
function mapDukeFormControlAnchor(anchor) {
|
|
5038
|
+
return {
|
|
5039
|
+
from: {
|
|
5040
|
+
col: anchor.fromCol,
|
|
5041
|
+
colOffsetEmu: anchor.fromColOffset,
|
|
5042
|
+
row: anchor.fromRow,
|
|
5043
|
+
rowOffsetEmu: anchor.fromRowOffset
|
|
5044
|
+
},
|
|
5045
|
+
kind: "two-cell",
|
|
5046
|
+
to: {
|
|
5047
|
+
col: anchor.toCol,
|
|
5048
|
+
colOffsetEmu: anchor.toColOffset,
|
|
5049
|
+
row: anchor.toRow,
|
|
5050
|
+
rowOffsetEmu: anchor.toRowOffset
|
|
5051
|
+
}
|
|
5052
|
+
};
|
|
5053
|
+
}
|
|
5054
|
+
function mapDukeFormControlKind(kind) {
|
|
5055
|
+
switch (kind.kind) {
|
|
5056
|
+
case "button":
|
|
5057
|
+
return { caption: kind.caption, kind: "button", label: normalizeControlLabel(kind.caption) };
|
|
5058
|
+
case "checkbox":
|
|
5059
|
+
return {
|
|
5060
|
+
caption: kind.caption,
|
|
5061
|
+
checked: kind.state === "checked",
|
|
5062
|
+
kind: "checkbox",
|
|
5063
|
+
label: normalizeControlLabel(kind.caption),
|
|
5064
|
+
linkedCell: kind.cellLink,
|
|
5065
|
+
no3D: kind.no3D,
|
|
5066
|
+
state: kind.state
|
|
5067
|
+
};
|
|
5068
|
+
case "optionButton":
|
|
5069
|
+
return {
|
|
5070
|
+
caption: kind.caption,
|
|
5071
|
+
checked: kind.state === "checked",
|
|
5072
|
+
firstInGroup: kind.firstInGroup,
|
|
5073
|
+
kind: "radio",
|
|
5074
|
+
label: normalizeControlLabel(kind.caption),
|
|
5075
|
+
linkedCell: kind.cellLink,
|
|
5076
|
+
no3D: kind.no3D,
|
|
5077
|
+
state: kind.state
|
|
5078
|
+
};
|
|
5079
|
+
case "label":
|
|
5080
|
+
return { caption: kind.caption, kind: "label", label: normalizeControlLabel(kind.caption) };
|
|
5081
|
+
case "groupBox":
|
|
5082
|
+
return {
|
|
5083
|
+
caption: kind.caption,
|
|
5084
|
+
kind: "group-box",
|
|
5085
|
+
label: normalizeControlLabel(kind.caption),
|
|
5086
|
+
no3D: kind.no3D
|
|
5087
|
+
};
|
|
5088
|
+
case "listBox":
|
|
5089
|
+
return {
|
|
5090
|
+
inputRange: kind.inputRange,
|
|
5091
|
+
kind: "listbox",
|
|
5092
|
+
linkedCell: kind.cellLink,
|
|
5093
|
+
no3D: kind.no3D,
|
|
5094
|
+
selected: [...kind.selected],
|
|
5095
|
+
selection: kind.selection
|
|
5096
|
+
};
|
|
5097
|
+
case "dropdown":
|
|
5098
|
+
return {
|
|
5099
|
+
inputRange: kind.inputRange,
|
|
5100
|
+
kind: "dropdown",
|
|
5101
|
+
lines: kind.lines,
|
|
5102
|
+
linkedCell: kind.cellLink,
|
|
5103
|
+
no3D: kind.no3D,
|
|
5104
|
+
selected: kind.selected
|
|
5105
|
+
};
|
|
5106
|
+
case "scrollbar":
|
|
5107
|
+
return {
|
|
5108
|
+
horizontal: kind.horizontal,
|
|
5109
|
+
increment: kind.increment,
|
|
5110
|
+
kind: "scrollbar",
|
|
5111
|
+
linkedCell: kind.cellLink,
|
|
5112
|
+
max: kind.max,
|
|
5113
|
+
min: kind.min,
|
|
5114
|
+
page: kind.page,
|
|
5115
|
+
value: kind.value
|
|
5116
|
+
};
|
|
5117
|
+
case "spinner":
|
|
5118
|
+
return {
|
|
5119
|
+
increment: kind.increment,
|
|
5120
|
+
kind: "spinner",
|
|
5121
|
+
linkedCell: kind.cellLink,
|
|
5122
|
+
max: kind.max,
|
|
5123
|
+
min: kind.min,
|
|
5124
|
+
value: kind.value
|
|
5125
|
+
};
|
|
5126
|
+
}
|
|
5127
|
+
}
|
|
5128
|
+
function mapDukeFormControl(control, controlIndex, workbookSheetIndex) {
|
|
5129
|
+
return {
|
|
5130
|
+
anchor: mapDukeFormControlAnchor(control.anchor),
|
|
5131
|
+
controlIndex,
|
|
5132
|
+
dukeAnchor: { ...control.anchor },
|
|
5133
|
+
editAs: control.anchor.editAs,
|
|
5134
|
+
hidden: false,
|
|
5135
|
+
id: `form-control-${workbookSheetIndex}-${controlIndex}`,
|
|
5136
|
+
locked: control.locked,
|
|
5137
|
+
name: control.name,
|
|
5138
|
+
printable: control.printable,
|
|
5139
|
+
sheetIndex: workbookSheetIndex,
|
|
5140
|
+
workbookSheetIndex,
|
|
5141
|
+
zIndex: controlIndex + 1,
|
|
5142
|
+
...mapDukeFormControlKind(control.kind)
|
|
5143
|
+
};
|
|
5144
|
+
}
|
|
5145
|
+
function collectWorkbookFormControls(workbook) {
|
|
5146
|
+
return Array.from({ length: workbook.sheetCount }, (_, workbookSheetIndex) => {
|
|
5147
|
+
try {
|
|
5148
|
+
const controls = workbook.getSheet(workbookSheetIndex).formControls;
|
|
5149
|
+
return Array.isArray(controls) ? controls.map((control, controlIndex) => mapDukeFormControl(control, controlIndex, workbookSheetIndex)) : [];
|
|
5150
|
+
} catch {
|
|
5151
|
+
return [];
|
|
5152
|
+
}
|
|
5153
|
+
});
|
|
5154
|
+
}
|
|
5038
5155
|
function parseFormControlKind(rawType) {
|
|
5039
5156
|
const normalized = (rawType ?? "").trim().toLowerCase();
|
|
5040
5157
|
switch (normalized) {
|
|
@@ -5800,27 +5917,10 @@ function parseSheetFormControlNodes(archive, sheetPath) {
|
|
|
5800
5917
|
}
|
|
5801
5918
|
return getLocalElements(sheetDocument, "control").map((controlNode) => ({
|
|
5802
5919
|
anchor: parseAnchor(getFirstDescendant(controlNode, "anchor") ?? controlNode),
|
|
5803
|
-
controlRelationshipId: getRelationshipId(controlNode),
|
|
5804
5920
|
name: controlNode.getAttribute("name") ?? void 0,
|
|
5805
5921
|
shapeId: parseFormControlShapeId(controlNode.getAttribute("shapeId"))
|
|
5806
5922
|
}));
|
|
5807
5923
|
}
|
|
5808
|
-
function parseCtrlPropDocument(archive, ctrlPropPath) {
|
|
5809
|
-
const xml = readArchiveText2(archive, ctrlPropPath);
|
|
5810
|
-
if (!xml) {
|
|
5811
|
-
return null;
|
|
5812
|
-
}
|
|
5813
|
-
const document2 = parseXml2(xml);
|
|
5814
|
-
const root = document2?.documentElement;
|
|
5815
|
-
if (!root) {
|
|
5816
|
-
return null;
|
|
5817
|
-
}
|
|
5818
|
-
return {
|
|
5819
|
-
checked: parseSpreadsheetBooleanValue(root.getAttribute("checked")),
|
|
5820
|
-
linkedCell: root.getAttribute("fmlaLink") ?? void 0,
|
|
5821
|
-
objectType: root.getAttribute("objectType") ?? void 0
|
|
5822
|
-
};
|
|
5823
|
-
}
|
|
5824
5924
|
function parseVmlFormControls(archive, vmlDrawingPath) {
|
|
5825
5925
|
const xml = readArchiveText2(archive, vmlDrawingPath);
|
|
5826
5926
|
if (!xml) {
|
|
@@ -5878,21 +5978,18 @@ function parseSheetFormControls(archive, sheetPath, sheetRelationships, workbook
|
|
|
5878
5978
|
if (!controlNode.anchor) {
|
|
5879
5979
|
return;
|
|
5880
5980
|
}
|
|
5881
|
-
const ctrlPropRelationship = controlNode.controlRelationshipId ? sheetRelationships.get(controlNode.controlRelationshipId) ?? null : null;
|
|
5882
|
-
const ctrlPropPath = ctrlPropRelationship?.type === CTRL_PROP_REL_TYPE ? ctrlPropRelationship.target : null;
|
|
5883
|
-
const ctrlProp = ctrlPropPath ? parseCtrlPropDocument(archive, ctrlPropPath) : null;
|
|
5884
5981
|
const vmlControl = controlNode.shapeId !== null ? vmlControlsByShapeId.get(controlNode.shapeId) ?? null : null;
|
|
5885
|
-
const kind = parseFormControlKind(
|
|
5982
|
+
const kind = parseFormControlKind(vmlControl?.objectType);
|
|
5886
5983
|
parsedControls.push({
|
|
5887
5984
|
anchor: controlNode.anchor,
|
|
5888
|
-
checked:
|
|
5985
|
+
checked: vmlControl?.checked,
|
|
5889
5986
|
fontFamily: vmlControl?.fontFamily,
|
|
5890
5987
|
fontSizePt: vmlControl?.fontSizePt,
|
|
5891
5988
|
hidden: vmlControl?.hidden ?? false,
|
|
5892
5989
|
id: `form-control-${workbookSheetIndex}-${index}`,
|
|
5893
5990
|
kind,
|
|
5894
5991
|
label: vmlControl?.label,
|
|
5895
|
-
linkedCell:
|
|
5992
|
+
linkedCell: vmlControl?.linkedCell,
|
|
5896
5993
|
name: controlNode.name,
|
|
5897
5994
|
sheetIndex: workbookSheetIndex,
|
|
5898
5995
|
textAlign: vmlControl?.textAlign,
|
|
@@ -5978,6 +6075,92 @@ function enrichFormControlsWithHiddenShapes(formControls, shapes, sheetState) {
|
|
|
5978
6075
|
};
|
|
5979
6076
|
});
|
|
5980
6077
|
}
|
|
6078
|
+
function getFormControlAnchorStart(anchor) {
|
|
6079
|
+
return anchor.kind === "absolute" ? null : { col: anchor.from.col, row: anchor.from.row };
|
|
6080
|
+
}
|
|
6081
|
+
function scoreParsedFormControlMatch(dukeControl, parsedControl, parsedIndex) {
|
|
6082
|
+
if (dukeControl.kind !== parsedControl.kind && parsedControl.kind !== "unknown") {
|
|
6083
|
+
return Number.NEGATIVE_INFINITY;
|
|
6084
|
+
}
|
|
6085
|
+
let score = 10;
|
|
6086
|
+
const dukeName = normalizeControlLabel(dukeControl.name)?.toLowerCase();
|
|
6087
|
+
const parsedName = normalizeControlLabel(parsedControl.name)?.toLowerCase();
|
|
6088
|
+
if (dukeName && parsedName) {
|
|
6089
|
+
if (dukeName !== parsedName) {
|
|
6090
|
+
return Number.NEGATIVE_INFINITY;
|
|
6091
|
+
}
|
|
6092
|
+
score += 100;
|
|
6093
|
+
}
|
|
6094
|
+
const dukeStart = getFormControlAnchorStart(dukeControl.anchor);
|
|
6095
|
+
const parsedStart = getFormControlAnchorStart(parsedControl.anchor);
|
|
6096
|
+
if (dukeStart && parsedStart && dukeStart.col === parsedStart.col && dukeStart.row === parsedStart.row) {
|
|
6097
|
+
score += 40;
|
|
6098
|
+
}
|
|
6099
|
+
if (dukeControl.controlIndex === parsedIndex) {
|
|
6100
|
+
score += 5;
|
|
6101
|
+
}
|
|
6102
|
+
return score;
|
|
6103
|
+
}
|
|
6104
|
+
function areDukeFormControlAnchorsEqual(left, right) {
|
|
6105
|
+
if (!left || !right) {
|
|
6106
|
+
return true;
|
|
6107
|
+
}
|
|
6108
|
+
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;
|
|
6109
|
+
}
|
|
6110
|
+
function mergeDukeAndParsedFormControls(dukeControls, parsedControls, keepUnmatchedParsedControl = () => true) {
|
|
6111
|
+
const usedParsedIndexes = /* @__PURE__ */ new Set();
|
|
6112
|
+
const mergedControls = dukeControls.map((dukeControl) => {
|
|
6113
|
+
let bestIndex = -1;
|
|
6114
|
+
let bestScore = Number.NEGATIVE_INFINITY;
|
|
6115
|
+
parsedControls.forEach((parsedControl2, parsedIndex) => {
|
|
6116
|
+
if (usedParsedIndexes.has(parsedIndex)) {
|
|
6117
|
+
return;
|
|
6118
|
+
}
|
|
6119
|
+
const score = scoreParsedFormControlMatch(dukeControl, parsedControl2, parsedIndex);
|
|
6120
|
+
if (score > bestScore) {
|
|
6121
|
+
bestIndex = parsedIndex;
|
|
6122
|
+
bestScore = score;
|
|
6123
|
+
}
|
|
6124
|
+
});
|
|
6125
|
+
const parsedControl = bestIndex >= 0 && bestScore >= 10 ? parsedControls[bestIndex] : null;
|
|
6126
|
+
if (!parsedControl) {
|
|
6127
|
+
return dukeControl;
|
|
6128
|
+
}
|
|
6129
|
+
usedParsedIndexes.add(bestIndex);
|
|
6130
|
+
const dukeAnchorChanged = !areDukeFormControlAnchorsEqual(
|
|
6131
|
+
parsedControl.dukeAnchor,
|
|
6132
|
+
dukeControl.dukeAnchor
|
|
6133
|
+
);
|
|
6134
|
+
return {
|
|
6135
|
+
...parsedControl,
|
|
6136
|
+
...dukeControl,
|
|
6137
|
+
anchor: dukeAnchorChanged ? dukeControl.anchor : parsedControl.anchor,
|
|
6138
|
+
fontFamily: parsedControl.fontFamily,
|
|
6139
|
+
fontSizePt: parsedControl.fontSizePt,
|
|
6140
|
+
hidden: parsedControl.hidden,
|
|
6141
|
+
id: parsedControl.id,
|
|
6142
|
+
label: dukeControl.label ?? parsedControl.label,
|
|
6143
|
+
name: dukeControl.name ?? parsedControl.name,
|
|
6144
|
+
textAlign: parsedControl.textAlign,
|
|
6145
|
+
textColor: parsedControl.textColor,
|
|
6146
|
+
zIndex: parsedControl.zIndex
|
|
6147
|
+
};
|
|
6148
|
+
});
|
|
6149
|
+
parsedControls.forEach((parsedControl, parsedIndex) => {
|
|
6150
|
+
if (!usedParsedIndexes.has(parsedIndex) && keepUnmatchedParsedControl(parsedControl)) {
|
|
6151
|
+
mergedControls.push(parsedControl);
|
|
6152
|
+
}
|
|
6153
|
+
});
|
|
6154
|
+
return mergedControls.sort((left, right) => left.zIndex - right.zIndex);
|
|
6155
|
+
}
|
|
6156
|
+
function refreshWorkbookFormControls(workbook, currentControlsByWorkbookSheetIndex) {
|
|
6157
|
+
const dukeControlsByWorkbookSheetIndex = collectWorkbookFormControls(workbook);
|
|
6158
|
+
return dukeControlsByWorkbookSheetIndex.map((dukeControls, workbookSheetIndex) => mergeDukeAndParsedFormControls(
|
|
6159
|
+
dukeControls,
|
|
6160
|
+
currentControlsByWorkbookSheetIndex[workbookSheetIndex] ?? [],
|
|
6161
|
+
(control) => control.controlIndex === void 0
|
|
6162
|
+
));
|
|
6163
|
+
}
|
|
5981
6164
|
function revokeWorkbookImageAssets(assets) {
|
|
5982
6165
|
if (!assets) {
|
|
5983
6166
|
return;
|
|
@@ -6010,7 +6193,7 @@ function parseWorkbookStructureAssetsFromArchive(archive, options) {
|
|
|
6010
6193
|
workbookSheets
|
|
6011
6194
|
};
|
|
6012
6195
|
}
|
|
6013
|
-
function parseWorkbookImageAssets(bytes) {
|
|
6196
|
+
function parseWorkbookImageAssets(bytes, workbook) {
|
|
6014
6197
|
const archive = unzipSync(bytes);
|
|
6015
6198
|
const {
|
|
6016
6199
|
contentTypes,
|
|
@@ -6029,6 +6212,7 @@ function parseWorkbookImageAssets(bytes) {
|
|
|
6029
6212
|
const shapesByWorkbookSheetIndex = [];
|
|
6030
6213
|
const sheetOrigins = [];
|
|
6031
6214
|
const imageOriginsById = /* @__PURE__ */ new Map();
|
|
6215
|
+
const dukeFormControlsByWorkbookSheetIndex = collectWorkbookFormControls(workbook);
|
|
6032
6216
|
workbookSheets.forEach((sheet, workbookSheetIndex) => {
|
|
6033
6217
|
const sheetRelationships = parseRelationships(archive, relsPathForDocument(sheet.path), sheet.path);
|
|
6034
6218
|
const attachments = [];
|
|
@@ -6074,7 +6258,10 @@ function parseWorkbookImageAssets(bytes) {
|
|
|
6074
6258
|
shapeList,
|
|
6075
6259
|
sheetStatesByWorkbookSheetIndex[workbookSheetIndex] ?? null
|
|
6076
6260
|
);
|
|
6077
|
-
formControlsByWorkbookSheetIndex[workbookSheetIndex] =
|
|
6261
|
+
formControlsByWorkbookSheetIndex[workbookSheetIndex] = mergeDukeAndParsedFormControls(
|
|
6262
|
+
dukeFormControlsByWorkbookSheetIndex[workbookSheetIndex] ?? [],
|
|
6263
|
+
enrichedFormControlList
|
|
6264
|
+
);
|
|
6078
6265
|
imagesByWorkbookSheetIndex[workbookSheetIndex] = imageList;
|
|
6079
6266
|
shapesByWorkbookSheetIndex[workbookSheetIndex] = visibleShapeList;
|
|
6080
6267
|
sheetOrigins[workbookSheetIndex] = attachments.length > 0 ? {
|
|
@@ -7148,6 +7335,144 @@ function parseA1RangeReference2(reference) {
|
|
|
7148
7335
|
}
|
|
7149
7336
|
return normalizeRange({ start, end });
|
|
7150
7337
|
}
|
|
7338
|
+
function resolveWorkbookReference(workbook, defaultWorkbookSheetIndex, rawReference, resolvingNamedRange = false) {
|
|
7339
|
+
const reference = rawReference.trim().replace(/^=/, "");
|
|
7340
|
+
if (!reference) {
|
|
7341
|
+
return null;
|
|
7342
|
+
}
|
|
7343
|
+
let workbookSheetIndex = defaultWorkbookSheetIndex;
|
|
7344
|
+
let rangeReference = reference;
|
|
7345
|
+
const bangIndex = reference.lastIndexOf("!");
|
|
7346
|
+
if (bangIndex >= 0) {
|
|
7347
|
+
let sheetName = reference.slice(0, bangIndex).trim();
|
|
7348
|
+
rangeReference = reference.slice(bangIndex + 1).trim();
|
|
7349
|
+
if (sheetName.startsWith("'") && sheetName.endsWith("'")) {
|
|
7350
|
+
sheetName = sheetName.slice(1, -1).replace(/''/g, "'");
|
|
7351
|
+
}
|
|
7352
|
+
const resolvedSheetIndex = workbook.sheetIndex(sheetName);
|
|
7353
|
+
if (resolvedSheetIndex === void 0) {
|
|
7354
|
+
return null;
|
|
7355
|
+
}
|
|
7356
|
+
workbookSheetIndex = resolvedSheetIndex;
|
|
7357
|
+
} else if (!resolvingNamedRange) {
|
|
7358
|
+
const namedRange = workbook.getNamedRange(reference);
|
|
7359
|
+
if (namedRange) {
|
|
7360
|
+
return resolveWorkbookReference(workbook, defaultWorkbookSheetIndex, namedRange, true);
|
|
7361
|
+
}
|
|
7362
|
+
}
|
|
7363
|
+
const range = parseA1RangeReference2(rangeReference.replace(/\$/g, ""));
|
|
7364
|
+
if (!range || workbookSheetIndex < 0 || workbookSheetIndex >= workbook.sheetCount) {
|
|
7365
|
+
return null;
|
|
7366
|
+
}
|
|
7367
|
+
try {
|
|
7368
|
+
return {
|
|
7369
|
+
range,
|
|
7370
|
+
workbookSheetIndex,
|
|
7371
|
+
worksheet: workbook.getSheet(workbookSheetIndex)
|
|
7372
|
+
};
|
|
7373
|
+
} catch {
|
|
7374
|
+
return null;
|
|
7375
|
+
}
|
|
7376
|
+
}
|
|
7377
|
+
function formControlInputFromDukeControl(control) {
|
|
7378
|
+
return {
|
|
7379
|
+
anchor: { ...control.anchor },
|
|
7380
|
+
kind: { ...control.kind },
|
|
7381
|
+
locked: control.locked,
|
|
7382
|
+
name: control.name,
|
|
7383
|
+
printable: control.printable
|
|
7384
|
+
};
|
|
7385
|
+
}
|
|
7386
|
+
function getFormControlCellLink(kind) {
|
|
7387
|
+
return "cellLink" in kind ? kind.cellLink : void 0;
|
|
7388
|
+
}
|
|
7389
|
+
function anchorContainsControl(group, control) {
|
|
7390
|
+
const groupAnchor = group.anchor;
|
|
7391
|
+
const controlAnchor = control.anchor;
|
|
7392
|
+
return controlAnchor.fromCol >= groupAnchor.fromCol && controlAnchor.fromCol <= groupAnchor.toCol && controlAnchor.fromRow >= groupAnchor.fromRow && controlAnchor.fromRow <= groupAnchor.toRow;
|
|
7393
|
+
}
|
|
7394
|
+
function resolveOptionButtonGroupIndexes(controls, targetIndex) {
|
|
7395
|
+
const target = controls[targetIndex];
|
|
7396
|
+
if (!target || target.kind.kind !== "optionButton") {
|
|
7397
|
+
return [];
|
|
7398
|
+
}
|
|
7399
|
+
if (target.kind.cellLink) {
|
|
7400
|
+
const targetCellLink = target.kind.cellLink;
|
|
7401
|
+
return controls.flatMap((control, index) => control.kind.kind === "optionButton" && control.kind.cellLink === targetCellLink ? [index] : []);
|
|
7402
|
+
}
|
|
7403
|
+
const containingGroups = controls.map((control, index) => ({ control, index })).filter(({ control }) => control.kind.kind === "groupBox" && anchorContainsControl(control, target)).sort((left, right) => {
|
|
7404
|
+
const leftArea = (left.control.anchor.toCol - left.control.anchor.fromCol) * (left.control.anchor.toRow - left.control.anchor.fromRow);
|
|
7405
|
+
const rightArea = (right.control.anchor.toCol - right.control.anchor.fromCol) * (right.control.anchor.toRow - right.control.anchor.fromRow);
|
|
7406
|
+
return leftArea - rightArea;
|
|
7407
|
+
});
|
|
7408
|
+
const containingGroup = containingGroups[0]?.control;
|
|
7409
|
+
if (containingGroup) {
|
|
7410
|
+
return controls.flatMap((control, index) => control.kind.kind === "optionButton" && anchorContainsControl(containingGroup, control) ? [index] : []);
|
|
7411
|
+
}
|
|
7412
|
+
const optionIndexes = controls.flatMap((control, index) => control.kind.kind === "optionButton" ? [index] : []);
|
|
7413
|
+
const targetPosition = optionIndexes.indexOf(targetIndex);
|
|
7414
|
+
if (targetPosition < 0) {
|
|
7415
|
+
return [];
|
|
7416
|
+
}
|
|
7417
|
+
let startPosition = targetPosition;
|
|
7418
|
+
while (startPosition > 0) {
|
|
7419
|
+
const control = controls[optionIndexes[startPosition] ?? -1];
|
|
7420
|
+
if (control?.kind.kind === "optionButton" && control.kind.firstInGroup) {
|
|
7421
|
+
break;
|
|
7422
|
+
}
|
|
7423
|
+
startPosition -= 1;
|
|
7424
|
+
}
|
|
7425
|
+
let endPosition = targetPosition + 1;
|
|
7426
|
+
while (endPosition < optionIndexes.length) {
|
|
7427
|
+
const control = controls[optionIndexes[endPosition] ?? -1];
|
|
7428
|
+
if (control?.kind.kind === "optionButton" && control.kind.firstInGroup) {
|
|
7429
|
+
break;
|
|
7430
|
+
}
|
|
7431
|
+
endPosition += 1;
|
|
7432
|
+
}
|
|
7433
|
+
return optionIndexes.slice(startPosition, endPosition);
|
|
7434
|
+
}
|
|
7435
|
+
function resolveLinkedCellValue(controls, controlIndex) {
|
|
7436
|
+
const control = controls[controlIndex];
|
|
7437
|
+
if (!control) {
|
|
7438
|
+
return void 0;
|
|
7439
|
+
}
|
|
7440
|
+
switch (control.kind.kind) {
|
|
7441
|
+
case "checkbox":
|
|
7442
|
+
return control.kind.state === "mixed" ? "#N/A" : control.kind.state === "checked";
|
|
7443
|
+
case "optionButton": {
|
|
7444
|
+
const groupIndexes = resolveOptionButtonGroupIndexes(controls, controlIndex);
|
|
7445
|
+
const checkedIndex = groupIndexes.find((index) => controls[index]?.kind.kind === "optionButton" && controls[index]?.kind.state === "checked");
|
|
7446
|
+
const groupPosition = checkedIndex === void 0 ? -1 : groupIndexes.indexOf(checkedIndex);
|
|
7447
|
+
return groupPosition >= 0 ? groupPosition + 1 : "";
|
|
7448
|
+
}
|
|
7449
|
+
case "dropdown":
|
|
7450
|
+
return control.kind.selected === void 0 ? "" : control.kind.selected + 1;
|
|
7451
|
+
case "listBox":
|
|
7452
|
+
return control.kind.selection === "single" && control.kind.selected.length === 1 ? (control.kind.selected[0] ?? -1) + 1 : "";
|
|
7453
|
+
case "scrollbar":
|
|
7454
|
+
case "spinner":
|
|
7455
|
+
return control.kind.value;
|
|
7456
|
+
default:
|
|
7457
|
+
return void 0;
|
|
7458
|
+
}
|
|
7459
|
+
}
|
|
7460
|
+
function syncFormControlLinkedCell(workbook, workbookSheetIndex, controls, controlIndex) {
|
|
7461
|
+
const control = controls[controlIndex];
|
|
7462
|
+
if (!control) {
|
|
7463
|
+
return;
|
|
7464
|
+
}
|
|
7465
|
+
const cellLink = getFormControlCellLink(control.kind);
|
|
7466
|
+
const value = resolveLinkedCellValue(controls, controlIndex);
|
|
7467
|
+
if (!cellLink || value === void 0) {
|
|
7468
|
+
return;
|
|
7469
|
+
}
|
|
7470
|
+
const target = resolveWorkbookReference(workbook, workbookSheetIndex, cellLink);
|
|
7471
|
+
if (!target || target.range.start.row !== target.range.end.row || target.range.start.col !== target.range.end.col) {
|
|
7472
|
+
return;
|
|
7473
|
+
}
|
|
7474
|
+
target.worksheet.setCell(cellAddressToA1(target.range.start), value);
|
|
7475
|
+
}
|
|
7151
7476
|
function parseWorksheetFreezePanes(worksheet) {
|
|
7152
7477
|
const rawFreezePanes = worksheet.freezePanes;
|
|
7153
7478
|
const row = typeof rawFreezePanes?.row === "number" && rawFreezePanes.row >= 0 ? rawFreezePanes.row : null;
|
|
@@ -7914,7 +8239,7 @@ function createBasicWorkbookAssets(workbook) {
|
|
|
7914
8239
|
const objectUrls = [];
|
|
7915
8240
|
return {
|
|
7916
8241
|
archive: {},
|
|
7917
|
-
formControlsByWorkbookSheetIndex:
|
|
8242
|
+
formControlsByWorkbookSheetIndex: collectWorkbookFormControls(workbook),
|
|
7918
8243
|
imageOriginsById: /* @__PURE__ */ new Map(),
|
|
7919
8244
|
imagesByWorkbookSheetIndex: collectWorksheetApiImages(workbook, objectUrls),
|
|
7920
8245
|
namedCellStyleByName: {},
|
|
@@ -7932,7 +8257,7 @@ function loadWorkbookImageAssets(bytes, workbook, skipXmlParsing = false) {
|
|
|
7932
8257
|
if (shouldSkipXmlParsingForWorkbook(bytes, skipXmlParsing) || !isZipWorkbook(bytes)) {
|
|
7933
8258
|
return createBasicWorkbookAssets(workbook);
|
|
7934
8259
|
}
|
|
7935
|
-
const parsedAssets = parseWorkbookImageAssets(bytes);
|
|
8260
|
+
const parsedAssets = parseWorkbookImageAssets(bytes, workbook);
|
|
7936
8261
|
const apiImagesByWorkbookSheetIndex = collectWorksheetApiImages(workbook, parsedAssets.objectUrls);
|
|
7937
8262
|
const imagesByWorkbookSheetIndex = Array.from(
|
|
7938
8263
|
{ length: Math.max(workbook.sheetCount, parsedAssets.imagesByWorkbookSheetIndex.length, apiImagesByWorkbookSheetIndex.length) },
|
|
@@ -8249,6 +8574,12 @@ function useXlsxViewerController(options) {
|
|
|
8249
8574
|
};
|
|
8250
8575
|
}, [skipXmlParsing]);
|
|
8251
8576
|
const refreshWorkbookState = React.useCallback((targetWorkbook) => {
|
|
8577
|
+
const currentFormControls = imageAssetsRef.current?.formControlsByWorkbookSheetIndex ?? [];
|
|
8578
|
+
const nextFormControls = refreshWorkbookFormControls(targetWorkbook, currentFormControls);
|
|
8579
|
+
if (imageAssetsRef.current) {
|
|
8580
|
+
imageAssetsRef.current.formControlsByWorkbookSheetIndex = nextFormControls;
|
|
8581
|
+
}
|
|
8582
|
+
setFormControlsByWorkbookSheetIndex(nextFormControls);
|
|
8252
8583
|
const nextSheets = buildSheetList(
|
|
8253
8584
|
targetWorkbook,
|
|
8254
8585
|
imageAssetsRef.current?.sheetStatesByWorkbookSheetIndex,
|
|
@@ -8376,6 +8707,7 @@ function useXlsxViewerController(options) {
|
|
|
8376
8707
|
setChartsheets(snapshot.chartsheets);
|
|
8377
8708
|
setTabs(snapshot.tabs);
|
|
8378
8709
|
chartAssetsRef.current = null;
|
|
8710
|
+
setFormControlsByWorkbookSheetIndex(snapshot.formControlsByWorkbookSheetIndex);
|
|
8379
8711
|
setWorkerTablesByWorkbookSheetIndex(snapshot.tablesByWorkbookSheetIndex);
|
|
8380
8712
|
setShouldAutoCalculate(false);
|
|
8381
8713
|
setIsWorkerBacked(true);
|
|
@@ -8595,6 +8927,7 @@ function useXlsxViewerController(options) {
|
|
|
8595
8927
|
setChartsheets(snapshot.chartsheets);
|
|
8596
8928
|
setTabs(snapshot.tabs);
|
|
8597
8929
|
chartAssetsRef.current = null;
|
|
8930
|
+
setFormControlsByWorkbookSheetIndex(snapshot.formControlsByWorkbookSheetIndex);
|
|
8598
8931
|
setWorkerTablesByWorkbookSheetIndex(snapshot.tablesByWorkbookSheetIndex);
|
|
8599
8932
|
setShouldAutoCalculate(false);
|
|
8600
8933
|
setIsWorkerBacked(true);
|
|
@@ -8716,6 +9049,20 @@ function useXlsxViewerController(options) {
|
|
|
8716
9049
|
}
|
|
8717
9050
|
return workbook.getSheet(activeSheet.workbookSheetIndex);
|
|
8718
9051
|
}, [activeSheet, workbook]);
|
|
9052
|
+
const getFormControlWorksheet = React.useCallback((sheetIndex = activeSheetIndex) => {
|
|
9053
|
+
const targetSheet = sheets[sheetIndex];
|
|
9054
|
+
if (!workbook || !targetSheet) {
|
|
9055
|
+
return null;
|
|
9056
|
+
}
|
|
9057
|
+
try {
|
|
9058
|
+
return {
|
|
9059
|
+
workbookSheetIndex: targetSheet.workbookSheetIndex,
|
|
9060
|
+
worksheet: workbook.getSheet(targetSheet.workbookSheetIndex)
|
|
9061
|
+
};
|
|
9062
|
+
} catch {
|
|
9063
|
+
return null;
|
|
9064
|
+
}
|
|
9065
|
+
}, [activeSheetIndex, sheets, workbook]);
|
|
8719
9066
|
const tables = React.useMemo(
|
|
8720
9067
|
() => isWorkerBacked ? workerTablesByWorkbookSheetIndex[activeSheet?.workbookSheetIndex ?? -1] ?? [] : mapWorksheetTables(getActiveWorksheet()),
|
|
8721
9068
|
[activeSheet?.workbookSheetIndex, getActiveWorksheet, isWorkerBacked, revision, workerTablesByWorkbookSheetIndex]
|
|
@@ -8855,6 +9202,28 @@ function useXlsxViewerController(options) {
|
|
|
8855
9202
|
return (formControlsByWorkbookSheetIndex[targetSheet.workbookSheetIndex] ?? []).map(mapPublicFormControl);
|
|
8856
9203
|
}, [activeSheetIndex, formControlsByWorkbookSheetIndex, mapPublicFormControl, sheets]);
|
|
8857
9204
|
const formControls = React.useMemo(() => getSheetFormControls(activeSheetIndex), [activeSheetIndex, getSheetFormControls]);
|
|
9205
|
+
const getFormControlItems = React.useCallback((controlIndex, sheetIndex = activeSheetIndex) => {
|
|
9206
|
+
const target = getFormControlWorksheet(sheetIndex);
|
|
9207
|
+
if (!workbook || !target) {
|
|
9208
|
+
return [];
|
|
9209
|
+
}
|
|
9210
|
+
const control = target.worksheet.formControls[controlIndex];
|
|
9211
|
+
const inputRange = control?.kind.kind === "listBox" || control?.kind.kind === "dropdown" ? control.kind.inputRange : void 0;
|
|
9212
|
+
if (!inputRange) {
|
|
9213
|
+
return [];
|
|
9214
|
+
}
|
|
9215
|
+
const source = resolveWorkbookReference(workbook, target.workbookSheetIndex, inputRange);
|
|
9216
|
+
if (!source) {
|
|
9217
|
+
return [];
|
|
9218
|
+
}
|
|
9219
|
+
const items = [];
|
|
9220
|
+
for (let row = source.range.start.row; row <= source.range.end.row; row += 1) {
|
|
9221
|
+
for (let col = source.range.start.col; col <= source.range.end.col; col += 1) {
|
|
9222
|
+
items.push(source.worksheet.getFormattedValueAt(row, col));
|
|
9223
|
+
}
|
|
9224
|
+
}
|
|
9225
|
+
return items;
|
|
9226
|
+
}, [activeSheetIndex, getFormControlWorksheet, workbook]);
|
|
8858
9227
|
const getSheetShapes = React.useCallback((sheetIndex = activeSheetIndex) => {
|
|
8859
9228
|
const targetSheet = sheets[sheetIndex];
|
|
8860
9229
|
if (!targetSheet) {
|
|
@@ -9252,6 +9621,89 @@ function useXlsxViewerController(options) {
|
|
|
9252
9621
|
redoStackRef.current = [];
|
|
9253
9622
|
setHistoryRevision((current) => current + 1);
|
|
9254
9623
|
}, [createHistoryEntry]);
|
|
9624
|
+
const addFormControl = React.useCallback((input, sheetIndex = activeSheetIndex) => {
|
|
9625
|
+
const target = getFormControlWorksheet(sheetIndex);
|
|
9626
|
+
if (readOnly || !workbook || !target) {
|
|
9627
|
+
return null;
|
|
9628
|
+
}
|
|
9629
|
+
recordHistoryBeforeMutation();
|
|
9630
|
+
const controlIndex = target.worksheet.addFormControl(input);
|
|
9631
|
+
const controls = target.worksheet.formControls;
|
|
9632
|
+
const addedControl = controls[controlIndex];
|
|
9633
|
+
if (addedControl?.kind.kind === "optionButton" && addedControl.kind.state === "checked") {
|
|
9634
|
+
const groupIndexes = resolveOptionButtonGroupIndexes(controls, controlIndex);
|
|
9635
|
+
for (const siblingIndex of groupIndexes) {
|
|
9636
|
+
if (siblingIndex === controlIndex) {
|
|
9637
|
+
continue;
|
|
9638
|
+
}
|
|
9639
|
+
const sibling = target.worksheet.formControls[siblingIndex];
|
|
9640
|
+
if (sibling?.kind.kind === "optionButton" && sibling.kind.state !== "unchecked") {
|
|
9641
|
+
target.worksheet.setFormControl(siblingIndex, {
|
|
9642
|
+
...formControlInputFromDukeControl(sibling),
|
|
9643
|
+
kind: { ...sibling.kind, state: "unchecked" }
|
|
9644
|
+
});
|
|
9645
|
+
}
|
|
9646
|
+
}
|
|
9647
|
+
}
|
|
9648
|
+
syncFormControlLinkedCell(
|
|
9649
|
+
workbook,
|
|
9650
|
+
target.workbookSheetIndex,
|
|
9651
|
+
target.worksheet.formControls,
|
|
9652
|
+
controlIndex
|
|
9653
|
+
);
|
|
9654
|
+
maybeRecalculateWorkbook(workbook);
|
|
9655
|
+
refreshWorkbookState(workbook);
|
|
9656
|
+
return controlIndex;
|
|
9657
|
+
}, [activeSheetIndex, getFormControlWorksheet, maybeRecalculateWorkbook, readOnly, recordHistoryBeforeMutation, refreshWorkbookState, workbook]);
|
|
9658
|
+
const updateFormControl = React.useCallback((controlIndex, patch, sheetIndex = activeSheetIndex) => {
|
|
9659
|
+
const target = getFormControlWorksheet(sheetIndex);
|
|
9660
|
+
const currentControl = target?.worksheet.formControls[controlIndex];
|
|
9661
|
+
if (readOnly || !workbook || !target || !currentControl) {
|
|
9662
|
+
return false;
|
|
9663
|
+
}
|
|
9664
|
+
recordHistoryBeforeMutation();
|
|
9665
|
+
const nextInput = {
|
|
9666
|
+
...formControlInputFromDukeControl(currentControl),
|
|
9667
|
+
...patch,
|
|
9668
|
+
anchor: patch.anchor ? { ...patch.anchor } : { ...currentControl.anchor },
|
|
9669
|
+
kind: patch.kind ? { ...patch.kind } : { ...currentControl.kind }
|
|
9670
|
+
};
|
|
9671
|
+
if (nextInput.kind.kind === "optionButton" && nextInput.kind.state === "checked") {
|
|
9672
|
+
const groupIndexes = resolveOptionButtonGroupIndexes(target.worksheet.formControls, controlIndex);
|
|
9673
|
+
for (const siblingIndex of groupIndexes) {
|
|
9674
|
+
if (siblingIndex === controlIndex) {
|
|
9675
|
+
continue;
|
|
9676
|
+
}
|
|
9677
|
+
const sibling = target.worksheet.formControls[siblingIndex];
|
|
9678
|
+
if (sibling?.kind.kind === "optionButton" && sibling.kind.state !== "unchecked") {
|
|
9679
|
+
target.worksheet.setFormControl(siblingIndex, {
|
|
9680
|
+
...formControlInputFromDukeControl(sibling),
|
|
9681
|
+
kind: { ...sibling.kind, state: "unchecked" }
|
|
9682
|
+
});
|
|
9683
|
+
}
|
|
9684
|
+
}
|
|
9685
|
+
}
|
|
9686
|
+
target.worksheet.setFormControl(controlIndex, nextInput);
|
|
9687
|
+
syncFormControlLinkedCell(
|
|
9688
|
+
workbook,
|
|
9689
|
+
target.workbookSheetIndex,
|
|
9690
|
+
target.worksheet.formControls,
|
|
9691
|
+
controlIndex
|
|
9692
|
+
);
|
|
9693
|
+
maybeRecalculateWorkbook(workbook);
|
|
9694
|
+
refreshWorkbookState(workbook);
|
|
9695
|
+
return true;
|
|
9696
|
+
}, [activeSheetIndex, getFormControlWorksheet, maybeRecalculateWorkbook, readOnly, recordHistoryBeforeMutation, refreshWorkbookState, workbook]);
|
|
9697
|
+
const removeFormControl = React.useCallback((controlIndex, sheetIndex = activeSheetIndex) => {
|
|
9698
|
+
const target = getFormControlWorksheet(sheetIndex);
|
|
9699
|
+
if (readOnly || !workbook || !target || !target.worksheet.formControls[controlIndex]) {
|
|
9700
|
+
return false;
|
|
9701
|
+
}
|
|
9702
|
+
recordHistoryBeforeMutation();
|
|
9703
|
+
target.worksheet.removeFormControl(controlIndex);
|
|
9704
|
+
refreshWorkbookState(workbook);
|
|
9705
|
+
return true;
|
|
9706
|
+
}, [activeSheetIndex, getFormControlWorksheet, readOnly, recordHistoryBeforeMutation, refreshWorkbookState, workbook]);
|
|
9255
9707
|
const recordCellEditHistory = React.useCallback((cell, before, after) => {
|
|
9256
9708
|
if (!activeSheet || isApplyingHistoryRef.current) {
|
|
9257
9709
|
return;
|
|
@@ -10060,8 +10512,15 @@ function useXlsxViewerController(options) {
|
|
|
10060
10512
|
}
|
|
10061
10513
|
workbook.addSheet(candidate);
|
|
10062
10514
|
sheetOriginsRef.current = [...sheetOriginsRef.current, null];
|
|
10515
|
+
setFormControlsByWorkbookSheetIndex((current) => [...current, []]);
|
|
10063
10516
|
setImagesByWorkbookSheetIndex((current) => [...current, []]);
|
|
10064
10517
|
setShapesByWorkbookSheetIndex((current) => [...current, []]);
|
|
10518
|
+
if (imageAssetsRef.current) {
|
|
10519
|
+
imageAssetsRef.current.formControlsByWorkbookSheetIndex = [
|
|
10520
|
+
...imageAssetsRef.current.formControlsByWorkbookSheetIndex,
|
|
10521
|
+
[]
|
|
10522
|
+
];
|
|
10523
|
+
}
|
|
10065
10524
|
const nextSheets = buildSheetList(
|
|
10066
10525
|
workbook,
|
|
10067
10526
|
imageAssetsRef.current?.sheetStatesByWorkbookSheetIndex,
|
|
@@ -10091,9 +10550,13 @@ function useXlsxViewerController(options) {
|
|
|
10091
10550
|
recordHistoryBeforeMutation();
|
|
10092
10551
|
workbook.removeSheet(activeSheet.workbookSheetIndex);
|
|
10093
10552
|
sheetOriginsRef.current = sheetOriginsRef.current.filter((_, index) => index !== activeSheet.workbookSheetIndex);
|
|
10553
|
+
setFormControlsByWorkbookSheetIndex((current) => current.filter((_, index) => index !== activeSheet.workbookSheetIndex));
|
|
10094
10554
|
setImagesByWorkbookSheetIndex((current) => current.filter((_, index) => index !== activeSheet.workbookSheetIndex));
|
|
10095
10555
|
setShapesByWorkbookSheetIndex((current) => current.filter((_, index) => index !== activeSheet.workbookSheetIndex));
|
|
10096
10556
|
if (imageAssetsRef.current) {
|
|
10557
|
+
imageAssetsRef.current.formControlsByWorkbookSheetIndex = imageAssetsRef.current.formControlsByWorkbookSheetIndex.filter(
|
|
10558
|
+
(_, index) => index !== activeSheet.workbookSheetIndex
|
|
10559
|
+
);
|
|
10097
10560
|
imageAssetsRef.current.sheetStatesByWorkbookSheetIndex = imageAssetsRef.current.sheetStatesByWorkbookSheetIndex.filter(
|
|
10098
10561
|
(_, index) => index !== activeSheet.workbookSheetIndex
|
|
10099
10562
|
);
|
|
@@ -10394,6 +10857,7 @@ function useXlsxViewerController(options) {
|
|
|
10394
10857
|
activeSheetIndex,
|
|
10395
10858
|
activeTab,
|
|
10396
10859
|
activeTabIndex,
|
|
10860
|
+
addFormControl,
|
|
10397
10861
|
addSheet,
|
|
10398
10862
|
canRedo,
|
|
10399
10863
|
canDownload: Boolean(file ?? src),
|
|
@@ -10433,6 +10897,7 @@ function useXlsxViewerController(options) {
|
|
|
10433
10897
|
getClipboardData,
|
|
10434
10898
|
getCellDisplayValue: getCellDisplayValue2,
|
|
10435
10899
|
getCellFormula,
|
|
10900
|
+
getFormControlItems,
|
|
10436
10901
|
getCellSnapshotAsync: isWorkerBacked ? getCellSnapshotAsync : void 0,
|
|
10437
10902
|
getActiveWorksheet,
|
|
10438
10903
|
getRowsBatchAsync: isWorkerBacked ? getRowsBatchAsync : void 0,
|
|
@@ -10450,6 +10915,7 @@ function useXlsxViewerController(options) {
|
|
|
10450
10915
|
pasteStructuredClipboardData,
|
|
10451
10916
|
pasteText,
|
|
10452
10917
|
removeActiveSheet,
|
|
10918
|
+
removeFormControl,
|
|
10453
10919
|
readOnly,
|
|
10454
10920
|
recalculate,
|
|
10455
10921
|
redo,
|
|
@@ -10500,6 +10966,7 @@ function useXlsxViewerController(options) {
|
|
|
10500
10966
|
undo,
|
|
10501
10967
|
unmergeSelection,
|
|
10502
10968
|
updateChart,
|
|
10969
|
+
updateFormControl,
|
|
10503
10970
|
workbook,
|
|
10504
10971
|
zoomIn,
|
|
10505
10972
|
zoomOut,
|
|
@@ -10512,6 +10979,7 @@ function useXlsxViewerController(options) {
|
|
|
10512
10979
|
activeSheetIndex,
|
|
10513
10980
|
activeTab,
|
|
10514
10981
|
activeTabIndex,
|
|
10982
|
+
addFormControl,
|
|
10515
10983
|
addSheet,
|
|
10516
10984
|
canLoadDeferred,
|
|
10517
10985
|
canRedo,
|
|
@@ -10548,6 +11016,7 @@ function useXlsxViewerController(options) {
|
|
|
10548
11016
|
getClipboardData,
|
|
10549
11017
|
getCellDisplayValue2,
|
|
10550
11018
|
getCellFormula,
|
|
11019
|
+
getFormControlItems,
|
|
10551
11020
|
getCellSnapshotAsync,
|
|
10552
11021
|
getActiveWorksheet,
|
|
10553
11022
|
historyRevision,
|
|
@@ -10565,6 +11034,7 @@ function useXlsxViewerController(options) {
|
|
|
10565
11034
|
pasteStructuredClipboardData,
|
|
10566
11035
|
pasteText,
|
|
10567
11036
|
removeActiveSheet,
|
|
11037
|
+
removeFormControl,
|
|
10568
11038
|
readOnly,
|
|
10569
11039
|
recalculate,
|
|
10570
11040
|
redo,
|
|
@@ -10615,6 +11085,7 @@ function useXlsxViewerController(options) {
|
|
|
10615
11085
|
undo,
|
|
10616
11086
|
unmergeSelection,
|
|
10617
11087
|
updateChart,
|
|
11088
|
+
updateFormControl,
|
|
10618
11089
|
workbook,
|
|
10619
11090
|
zoomIn,
|
|
10620
11091
|
zoomOut,
|
|
@@ -21603,13 +22074,90 @@ function renderConditionalIcon(icon, scale = 1) {
|
|
|
21603
22074
|
}
|
|
21604
22075
|
);
|
|
21605
22076
|
}
|
|
21606
|
-
function
|
|
22077
|
+
function isFormControlChecked(control) {
|
|
22078
|
+
return control.state ? control.state === "checked" : Boolean(control.checked);
|
|
22079
|
+
}
|
|
22080
|
+
function isFormControlMixed(control) {
|
|
22081
|
+
return control.state === "mixed";
|
|
22082
|
+
}
|
|
22083
|
+
function buildFormControlKindInput(control) {
|
|
22084
|
+
switch (control.kind) {
|
|
22085
|
+
case "button":
|
|
22086
|
+
return { caption: control.caption ?? control.label ?? "", kind: "button" };
|
|
22087
|
+
case "checkbox":
|
|
22088
|
+
return {
|
|
22089
|
+
caption: control.caption ?? control.label ?? "",
|
|
22090
|
+
cellLink: control.linkedCell,
|
|
22091
|
+
kind: "checkbox",
|
|
22092
|
+
no3D: control.no3D ?? false,
|
|
22093
|
+
state: control.state ?? (control.checked ? "checked" : "unchecked")
|
|
22094
|
+
};
|
|
22095
|
+
case "radio":
|
|
22096
|
+
return {
|
|
22097
|
+
caption: control.caption ?? control.label ?? "",
|
|
22098
|
+
cellLink: control.linkedCell,
|
|
22099
|
+
firstInGroup: control.firstInGroup,
|
|
22100
|
+
kind: "optionButton",
|
|
22101
|
+
no3D: control.no3D ?? false,
|
|
22102
|
+
state: control.state === "checked" ? "checked" : "unchecked"
|
|
22103
|
+
};
|
|
22104
|
+
case "label":
|
|
22105
|
+
return { caption: control.caption ?? control.label ?? "", kind: "label" };
|
|
22106
|
+
case "group-box":
|
|
22107
|
+
return {
|
|
22108
|
+
caption: control.caption ?? control.label ?? "",
|
|
22109
|
+
kind: "groupBox",
|
|
22110
|
+
no3D: control.no3D ?? false
|
|
22111
|
+
};
|
|
22112
|
+
case "listbox":
|
|
22113
|
+
return {
|
|
22114
|
+
cellLink: control.linkedCell,
|
|
22115
|
+
inputRange: control.inputRange,
|
|
22116
|
+
kind: "listBox",
|
|
22117
|
+
no3D: control.no3D ?? false,
|
|
22118
|
+
selected: Array.isArray(control.selected) ? control.selected : control.selected === void 0 ? [] : [control.selected],
|
|
22119
|
+
selection: control.selection ?? "single"
|
|
22120
|
+
};
|
|
22121
|
+
case "dropdown":
|
|
22122
|
+
return {
|
|
22123
|
+
cellLink: control.linkedCell,
|
|
22124
|
+
inputRange: control.inputRange,
|
|
22125
|
+
kind: "dropdown",
|
|
22126
|
+
lines: control.lines ?? 8,
|
|
22127
|
+
no3D: control.no3D ?? false,
|
|
22128
|
+
selected: typeof control.selected === "number" ? control.selected : void 0
|
|
22129
|
+
};
|
|
22130
|
+
case "scrollbar":
|
|
22131
|
+
return {
|
|
22132
|
+
cellLink: control.linkedCell,
|
|
22133
|
+
horizontal: control.horizontal ?? true,
|
|
22134
|
+
increment: control.increment ?? 1,
|
|
22135
|
+
kind: "scrollbar",
|
|
22136
|
+
max: control.max ?? 100,
|
|
22137
|
+
min: control.min ?? 0,
|
|
22138
|
+
page: control.page ?? 10,
|
|
22139
|
+
value: control.value ?? control.min ?? 0
|
|
22140
|
+
};
|
|
22141
|
+
case "spinner":
|
|
22142
|
+
return {
|
|
22143
|
+
cellLink: control.linkedCell,
|
|
22144
|
+
increment: control.increment ?? 1,
|
|
22145
|
+
kind: "spinner",
|
|
22146
|
+
max: control.max ?? 100,
|
|
22147
|
+
min: control.min ?? 0,
|
|
22148
|
+
value: control.value ?? control.min ?? 0
|
|
22149
|
+
};
|
|
22150
|
+
default:
|
|
22151
|
+
return null;
|
|
22152
|
+
}
|
|
22153
|
+
}
|
|
22154
|
+
function renderCheckboxControl(checked, palette, scale = 1, mixed = false) {
|
|
21607
22155
|
const stroke = paletteIsDark(palette) ? "#cbd5e1" : "#475569";
|
|
21608
|
-
const fill = checked ? paletteIsDark(palette) ? "#60a5fa" : "#2563eb" : "transparent";
|
|
22156
|
+
const fill = checked || mixed ? paletteIsDark(palette) ? "#60a5fa" : "#2563eb" : "transparent";
|
|
21609
22157
|
const check = paletteIsDark(palette) ? "#020617" : "#ffffff";
|
|
21610
22158
|
return /* @__PURE__ */ jsxs3("svg", { "aria-hidden": "true", height: 14 * scale, style: { display: "block" }, viewBox: "0 0 16 16", width: 14 * scale, children: [
|
|
21611
22159
|
/* @__PURE__ */ jsx3("rect", { fill, height: 11, rx: 2, ry: 2, stroke, strokeWidth: 1.2, width: 11, x: 2.5, y: 2.5 }),
|
|
21612
|
-
checked ? /* @__PURE__ */ jsx3(
|
|
22160
|
+
mixed ? /* @__PURE__ */ jsx3("path", { d: "M5 8h6", fill: "none", stroke: check, strokeLinecap: "round", strokeWidth: 1.8 }) : checked ? /* @__PURE__ */ jsx3(
|
|
21613
22161
|
"path",
|
|
21614
22162
|
{
|
|
21615
22163
|
d: "M5 8.1 7.1 10.2 11.3 5.8",
|
|
@@ -21779,6 +22327,8 @@ function drawStaticFormControl(context, control, rect, palette, zoomFactor, shee
|
|
|
21779
22327
|
const textColor = control.textColor ?? "#000000";
|
|
21780
22328
|
const fontSizePx = Math.max(9 * zoomFactor, (control.fontSizePt ?? 9) * 96 / 72 * zoomFactor);
|
|
21781
22329
|
const iconSize = Math.min(14 * zoomFactor, Math.max(0, rect.height - 4 * zoomFactor));
|
|
22330
|
+
const controlChecked = isFormControlChecked(control);
|
|
22331
|
+
const controlMixed = isFormControlMixed(control);
|
|
21782
22332
|
context.save();
|
|
21783
22333
|
context.font = `400 ${fontSizePx}px ${control.fontFamily ?? "Calibri, sans-serif"}`;
|
|
21784
22334
|
context.textBaseline = "middle";
|
|
@@ -21819,14 +22369,19 @@ function drawStaticFormControl(context, control, rect, palette, zoomFactor, shee
|
|
|
21819
22369
|
const textRightInset = control.kind === "dropdown" ? 18 * zoomFactor : 6 * zoomFactor;
|
|
21820
22370
|
if (control.kind === "checkbox") {
|
|
21821
22371
|
context.strokeRect(rect.left + 2 * zoomFactor, rect.top + (rect.height - iconSize) / 2, iconSize, iconSize);
|
|
21822
|
-
if (
|
|
22372
|
+
if (controlChecked || controlMixed) {
|
|
21823
22373
|
context.fillStyle = paletteIsDark(palette) ? "#60a5fa" : "#2563eb";
|
|
21824
22374
|
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));
|
|
21825
22375
|
context.strokeStyle = paletteIsDark(palette) ? "#020617" : "#ffffff";
|
|
21826
22376
|
context.beginPath();
|
|
21827
|
-
|
|
21828
|
-
|
|
21829
|
-
|
|
22377
|
+
if (controlMixed) {
|
|
22378
|
+
context.moveTo(rect.left + 2 * zoomFactor + iconSize * 0.25, rect.top + rect.height / 2);
|
|
22379
|
+
context.lineTo(rect.left + 2 * zoomFactor + iconSize * 0.75, rect.top + rect.height / 2);
|
|
22380
|
+
} else {
|
|
22381
|
+
context.moveTo(rect.left + 2 * zoomFactor + iconSize * 0.24, rect.top + rect.height / 2 + iconSize * 0.06);
|
|
22382
|
+
context.lineTo(rect.left + 2 * zoomFactor + iconSize * 0.45, rect.top + rect.height / 2 + iconSize * 0.26);
|
|
22383
|
+
context.lineTo(rect.left + 2 * zoomFactor + iconSize * 0.8, rect.top + rect.height / 2 - iconSize * 0.2);
|
|
22384
|
+
}
|
|
21830
22385
|
context.stroke();
|
|
21831
22386
|
}
|
|
21832
22387
|
textLeft += iconSize + 4 * zoomFactor;
|
|
@@ -21834,7 +22389,7 @@ function drawStaticFormControl(context, control, rect, palette, zoomFactor, shee
|
|
|
21834
22389
|
context.beginPath();
|
|
21835
22390
|
context.arc(rect.left + 2 * zoomFactor + iconSize / 2, rect.top + rect.height / 2, iconSize / 2, 0, Math.PI * 2);
|
|
21836
22391
|
context.stroke();
|
|
21837
|
-
if (
|
|
22392
|
+
if (controlChecked) {
|
|
21838
22393
|
context.fillStyle = paletteIsDark(palette) ? "#60a5fa" : "#2563eb";
|
|
21839
22394
|
context.beginPath();
|
|
21840
22395
|
context.arc(rect.left + 2 * zoomFactor + iconSize / 2, rect.top + rect.height / 2, iconSize * 0.25, 0, Math.PI * 2);
|
|
@@ -22470,6 +23025,8 @@ function XlsxGrid({
|
|
|
22470
23025
|
getCellStyle,
|
|
22471
23026
|
loadingComponent,
|
|
22472
23027
|
loadingState,
|
|
23028
|
+
onFormControlAction,
|
|
23029
|
+
onFormControlChange,
|
|
22473
23030
|
renderChartLoading,
|
|
22474
23031
|
palette,
|
|
22475
23032
|
renderImage,
|
|
@@ -22507,6 +23064,7 @@ function XlsxGrid({
|
|
|
22507
23064
|
getRowsBatchAsync,
|
|
22508
23065
|
getClipboardData,
|
|
22509
23066
|
getCellDisplayValue: getControllerCellDisplayValue,
|
|
23067
|
+
getFormControlItems,
|
|
22510
23068
|
images,
|
|
22511
23069
|
shapes,
|
|
22512
23070
|
isLoadDeferred,
|
|
@@ -22544,9 +23102,13 @@ function XlsxGrid({
|
|
|
22544
23102
|
sortTable,
|
|
22545
23103
|
tables,
|
|
22546
23104
|
undo,
|
|
23105
|
+
updateFormControl,
|
|
22547
23106
|
workbook,
|
|
22548
23107
|
zoomScale
|
|
22549
23108
|
} = controller;
|
|
23109
|
+
const formControlItemsById = React4.useMemo(() => new Map(
|
|
23110
|
+
formControls.flatMap((control) => control.controlIndex !== void 0 && (control.kind === "dropdown" || control.kind === "listbox") ? [[control.id, getFormControlItems(control.controlIndex, control.sheetIndex)]] : [])
|
|
23111
|
+
), [formControls, getFormControlItems]);
|
|
22550
23112
|
const canResizeHeaders = !readOnly || allowResizeInReadOnly;
|
|
22551
23113
|
const scrollRef = React4.useRef(null);
|
|
22552
23114
|
const wrapperRef = React4.useRef(null);
|
|
@@ -25054,7 +25616,7 @@ function XlsxGrid({
|
|
|
25054
25616
|
return "";
|
|
25055
25617
|
}
|
|
25056
25618
|
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("|");
|
|
25057
|
-
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("|");
|
|
25619
|
+
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("|");
|
|
25058
25620
|
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("|");
|
|
25059
25621
|
return `${revision}:${canvasImageLoadVersion}:${shapeSignature}:${controlSignature}:${imageSignature}`;
|
|
25060
25622
|
}, [
|
|
@@ -26755,6 +27317,8 @@ function XlsxGrid({
|
|
|
26755
27317
|
const textColor = control.textColor ?? "#000000";
|
|
26756
27318
|
const fontSizePx = Math.max(9 * zoomFactor, (control.fontSizePt ?? 9) * 96 / 72 * zoomFactor);
|
|
26757
27319
|
const iconSize = Math.min(14 * zoomFactor, Math.max(0, rect.height - 4 * zoomFactor));
|
|
27320
|
+
const controlChecked = isFormControlChecked(control);
|
|
27321
|
+
const controlMixed = isFormControlMixed(control);
|
|
26758
27322
|
context.save();
|
|
26759
27323
|
context.font = `400 ${fontSizePx}px ${control.fontFamily ?? "Calibri, sans-serif"}`;
|
|
26760
27324
|
context.textBaseline = "middle";
|
|
@@ -26795,14 +27359,19 @@ function XlsxGrid({
|
|
|
26795
27359
|
const textRightInset = control.kind === "dropdown" ? 18 * zoomFactor : 6 * zoomFactor;
|
|
26796
27360
|
if (control.kind === "checkbox") {
|
|
26797
27361
|
context.strokeRect(rect.left + 2 * zoomFactor, rect.top + (rect.height - iconSize) / 2, iconSize, iconSize);
|
|
26798
|
-
if (
|
|
27362
|
+
if (controlChecked || controlMixed) {
|
|
26799
27363
|
context.fillStyle = paletteIsDark(palette) ? "#60a5fa" : "#2563eb";
|
|
26800
27364
|
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));
|
|
26801
27365
|
context.strokeStyle = paletteIsDark(palette) ? "#020617" : "#ffffff";
|
|
26802
27366
|
context.beginPath();
|
|
26803
|
-
|
|
26804
|
-
|
|
26805
|
-
|
|
27367
|
+
if (controlMixed) {
|
|
27368
|
+
context.moveTo(rect.left + 2 * zoomFactor + iconSize * 0.25, rect.top + rect.height / 2);
|
|
27369
|
+
context.lineTo(rect.left + 2 * zoomFactor + iconSize * 0.75, rect.top + rect.height / 2);
|
|
27370
|
+
} else {
|
|
27371
|
+
context.moveTo(rect.left + 2 * zoomFactor + iconSize * 0.24, rect.top + rect.height / 2 + iconSize * 0.06);
|
|
27372
|
+
context.lineTo(rect.left + 2 * zoomFactor + iconSize * 0.45, rect.top + rect.height / 2 + iconSize * 0.26);
|
|
27373
|
+
context.lineTo(rect.left + 2 * zoomFactor + iconSize * 0.8, rect.top + rect.height / 2 - iconSize * 0.2);
|
|
27374
|
+
}
|
|
26806
27375
|
context.stroke();
|
|
26807
27376
|
}
|
|
26808
27377
|
textLeft += iconSize + 4 * zoomFactor;
|
|
@@ -26810,7 +27379,7 @@ function XlsxGrid({
|
|
|
26810
27379
|
context.beginPath();
|
|
26811
27380
|
context.arc(rect.left + 2 * zoomFactor + iconSize / 2, rect.top + rect.height / 2, iconSize / 2, 0, Math.PI * 2);
|
|
26812
27381
|
context.stroke();
|
|
26813
|
-
if (
|
|
27382
|
+
if (controlChecked) {
|
|
26814
27383
|
context.fillStyle = paletteIsDark(palette) ? "#60a5fa" : "#2563eb";
|
|
26815
27384
|
context.beginPath();
|
|
26816
27385
|
context.arc(rect.left + 2 * zoomFactor + iconSize / 2, rect.top + rect.height / 2, iconSize * 0.25, 0, Math.PI * 2);
|
|
@@ -26989,8 +27558,7 @@ function XlsxGrid({
|
|
|
26989
27558
|
const canvasCellStyle = cellData.canvas ?? buildCanvasCellStyleCache(cellStyle);
|
|
26990
27559
|
const fillColor = cellData.conditionalColorScale?.color ?? (typeof cellStyle.backgroundColor === "string" ? cellStyle.backgroundColor : sheetSurface);
|
|
26991
27560
|
const gradientFill = !cellData.conditionalColorScale && typeof cellStyle.backgroundImage === "string" ? resolveCanvasGradientFill(paneContext, localRect, cellStyle.backgroundImage) : null;
|
|
26992
|
-
|
|
26993
|
-
if (hasExplicitCellFill || cellData.chartHighlight) {
|
|
27561
|
+
if (cellData.chartHighlight) {
|
|
26994
27562
|
flushPendingGridlines();
|
|
26995
27563
|
}
|
|
26996
27564
|
paneContext.fillStyle = gradientFill ?? fillColor;
|
|
@@ -27038,7 +27606,7 @@ function XlsxGrid({
|
|
|
27038
27606
|
const bottomNeighborTopBorder = bottomNeighborData?.isMergedSecondary ? null : bottomNeighborData?.canvas?.topBorder ?? parseCanvasBorderDeclaration(bottomNeighborData?.style.borderTop);
|
|
27039
27607
|
const resolvedRightBorder = resolveCanvasBoundaryBorder(rightBorder, rightNeighborLeftBorder);
|
|
27040
27608
|
const resolvedBottomBorder = resolveCanvasBoundaryBorder(bottomBorder, bottomNeighborTopBorder);
|
|
27041
|
-
if (showGridLines &&
|
|
27609
|
+
if (showGridLines && (!resolvedRightBorder || !resolvedBottomBorder)) {
|
|
27042
27610
|
enqueueGridlinePath();
|
|
27043
27611
|
if (!resolvedRightBorder) {
|
|
27044
27612
|
paneContext.moveTo(localRect.left + localRect.width - 0.5, localRect.top);
|
|
@@ -28126,10 +28694,22 @@ function XlsxGrid({
|
|
|
28126
28694
|
const fontSizePx = Math.max(9 * zoomFactor, (control.fontSizePt ?? 9) * 96 / 72 * zoomFactor);
|
|
28127
28695
|
const stroke = paletteIsDark(palette) ? "#cbd5e1" : "#475569";
|
|
28128
28696
|
const textColor = control.textColor ?? "#000000";
|
|
28697
|
+
const canMutateControl = !readOnly && control.controlIndex !== void 0 && [
|
|
28698
|
+
"checkbox",
|
|
28699
|
+
"dropdown",
|
|
28700
|
+
"listbox",
|
|
28701
|
+
"radio",
|
|
28702
|
+
"scrollbar",
|
|
28703
|
+
"spinner"
|
|
28704
|
+
].includes(control.kind);
|
|
28705
|
+
const canActivateButton = !readOnly && control.kind === "button" && Boolean(onFormControlAction);
|
|
28706
|
+
const isInteractiveControl = canMutateControl || canActivateButton;
|
|
28707
|
+
const controlItems = formControlItemsById.get(control.id) ?? [];
|
|
28129
28708
|
const commonStyle = {
|
|
28130
28709
|
alignItems: control.kind === "group-box" ? "stretch" : "center",
|
|
28131
28710
|
color: textColor,
|
|
28132
28711
|
contain: "layout paint",
|
|
28712
|
+
cursor: isInteractiveControl ? "pointer" : void 0,
|
|
28133
28713
|
display: "flex",
|
|
28134
28714
|
fontFamily: control.fontFamily ?? "Calibri, sans-serif",
|
|
28135
28715
|
fontSize: fontSizePx,
|
|
@@ -28140,12 +28720,28 @@ function XlsxGrid({
|
|
|
28140
28720
|
left: rect.left,
|
|
28141
28721
|
lineHeight: 1.2,
|
|
28142
28722
|
overflow: "hidden",
|
|
28143
|
-
pointerEvents: "none",
|
|
28723
|
+
pointerEvents: isInteractiveControl ? "auto" : "none",
|
|
28144
28724
|
position: "absolute",
|
|
28145
28725
|
top: rect.top,
|
|
28146
28726
|
width: rect.width,
|
|
28147
28727
|
zIndex: isFrozenDrawing ? control.zIndex + 20 : control.zIndex
|
|
28148
28728
|
};
|
|
28729
|
+
const stopControlPointerEvent = (event) => {
|
|
28730
|
+
event.stopPropagation();
|
|
28731
|
+
};
|
|
28732
|
+
const commitControlKind = (kind, nextControl) => {
|
|
28733
|
+
if (control.controlIndex === void 0) {
|
|
28734
|
+
return;
|
|
28735
|
+
}
|
|
28736
|
+
const didUpdate = updateFormControl(control.controlIndex, { kind }, control.sheetIndex);
|
|
28737
|
+
if (didUpdate) {
|
|
28738
|
+
onFormControlChange?.({
|
|
28739
|
+
control: { ...control, ...nextControl },
|
|
28740
|
+
previousControl: control,
|
|
28741
|
+
type: "change"
|
|
28742
|
+
});
|
|
28743
|
+
}
|
|
28744
|
+
};
|
|
28149
28745
|
if (control.kind === "group-box") {
|
|
28150
28746
|
const hasLabel = controlLabel.length > 0;
|
|
28151
28747
|
return /* @__PURE__ */ jsx3(
|
|
@@ -28187,15 +28783,88 @@ function XlsxGrid({
|
|
|
28187
28783
|
`${pane}-${control.id}`
|
|
28188
28784
|
);
|
|
28189
28785
|
}
|
|
28190
|
-
let content;
|
|
28191
28786
|
if (control.kind === "radio") {
|
|
28192
|
-
|
|
28193
|
-
|
|
28194
|
-
|
|
28195
|
-
|
|
28787
|
+
const checked = isFormControlChecked(control);
|
|
28788
|
+
const kind = buildFormControlKindInput(control);
|
|
28789
|
+
return /* @__PURE__ */ jsxs3(
|
|
28790
|
+
"button",
|
|
28791
|
+
{
|
|
28792
|
+
"aria-checked": checked,
|
|
28793
|
+
disabled: readOnly || control.controlIndex === void 0,
|
|
28794
|
+
onClick: (event) => {
|
|
28795
|
+
event.stopPropagation();
|
|
28796
|
+
if (!checked && kind?.kind === "optionButton") {
|
|
28797
|
+
commitControlKind(
|
|
28798
|
+
{ ...kind, state: "checked" },
|
|
28799
|
+
{ checked: true, state: "checked" }
|
|
28800
|
+
);
|
|
28801
|
+
}
|
|
28802
|
+
},
|
|
28803
|
+
onPointerDown: stopControlPointerEvent,
|
|
28804
|
+
role: "radio",
|
|
28805
|
+
style: {
|
|
28806
|
+
...commonStyle,
|
|
28807
|
+
background: "transparent",
|
|
28808
|
+
border: 0,
|
|
28809
|
+
boxSizing: "border-box",
|
|
28810
|
+
padding: `0 ${Math.max(1, zoomFactor)}px`
|
|
28811
|
+
},
|
|
28812
|
+
type: "button",
|
|
28813
|
+
children: [
|
|
28814
|
+
renderRadioControl(checked, palette, zoomFactor),
|
|
28815
|
+
controlLabel ? /* @__PURE__ */ jsx3("span", { style: { overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }, children: controlLabel }) : null
|
|
28816
|
+
]
|
|
28817
|
+
},
|
|
28818
|
+
`${pane}-${control.id}`
|
|
28819
|
+
);
|
|
28820
|
+
}
|
|
28821
|
+
if (control.kind === "checkbox") {
|
|
28822
|
+
const checked = isFormControlChecked(control);
|
|
28823
|
+
const mixed = isFormControlMixed(control);
|
|
28824
|
+
const kind = buildFormControlKindInput(control);
|
|
28825
|
+
return /* @__PURE__ */ jsxs3(
|
|
28826
|
+
"button",
|
|
28827
|
+
{
|
|
28828
|
+
"aria-checked": mixed ? "mixed" : checked,
|
|
28829
|
+
disabled: readOnly || control.controlIndex === void 0,
|
|
28830
|
+
onClick: (event) => {
|
|
28831
|
+
event.stopPropagation();
|
|
28832
|
+
if (kind?.kind === "checkbox") {
|
|
28833
|
+
const nextState = checked && !mixed ? "unchecked" : "checked";
|
|
28834
|
+
commitControlKind(
|
|
28835
|
+
{ ...kind, state: nextState },
|
|
28836
|
+
{ checked: nextState === "checked", state: nextState }
|
|
28837
|
+
);
|
|
28838
|
+
}
|
|
28839
|
+
},
|
|
28840
|
+
onPointerDown: stopControlPointerEvent,
|
|
28841
|
+
role: "checkbox",
|
|
28842
|
+
style: {
|
|
28843
|
+
...commonStyle,
|
|
28844
|
+
background: "transparent",
|
|
28845
|
+
border: 0,
|
|
28846
|
+
boxSizing: "border-box",
|
|
28847
|
+
padding: `0 ${Math.max(1, zoomFactor)}px`
|
|
28848
|
+
},
|
|
28849
|
+
type: "button",
|
|
28850
|
+
children: [
|
|
28851
|
+
renderCheckboxControl(checked, palette, zoomFactor, mixed),
|
|
28852
|
+
controlLabel ? /* @__PURE__ */ jsx3("span", { style: { overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }, children: controlLabel }) : null
|
|
28853
|
+
]
|
|
28854
|
+
},
|
|
28855
|
+
`${pane}-${control.id}`
|
|
28856
|
+
);
|
|
28857
|
+
}
|
|
28858
|
+
if (control.kind === "button") {
|
|
28196
28859
|
return /* @__PURE__ */ jsx3(
|
|
28197
|
-
"
|
|
28860
|
+
"button",
|
|
28198
28861
|
{
|
|
28862
|
+
disabled: readOnly || !onFormControlAction,
|
|
28863
|
+
onClick: (event) => {
|
|
28864
|
+
event.stopPropagation();
|
|
28865
|
+
onFormControlAction?.({ control, type: "activate" });
|
|
28866
|
+
},
|
|
28867
|
+
onPointerDown: stopControlPointerEvent,
|
|
28199
28868
|
style: {
|
|
28200
28869
|
...commonStyle,
|
|
28201
28870
|
background: "linear-gradient(180deg, #f8fafc 0%, #e2e8f0 100%)",
|
|
@@ -28206,68 +28875,168 @@ function XlsxGrid({
|
|
|
28206
28875
|
padding: `0 ${6 * zoomFactor}px`,
|
|
28207
28876
|
textAlign: "center"
|
|
28208
28877
|
},
|
|
28878
|
+
type: "button",
|
|
28209
28879
|
children: controlLabel
|
|
28210
28880
|
},
|
|
28211
28881
|
`${pane}-${control.id}`
|
|
28212
28882
|
);
|
|
28213
|
-
}
|
|
28883
|
+
}
|
|
28884
|
+
if (control.kind === "dropdown") {
|
|
28885
|
+
const kind = buildFormControlKindInput(control);
|
|
28886
|
+
const selected = typeof control.selected === "number" ? control.selected : void 0;
|
|
28214
28887
|
return /* @__PURE__ */ jsxs3(
|
|
28215
|
-
"
|
|
28888
|
+
"select",
|
|
28216
28889
|
{
|
|
28890
|
+
"aria-label": controlLabel || control.name || "Dropdown form control",
|
|
28891
|
+
disabled: readOnly || control.controlIndex === void 0 || controlItems.length === 0,
|
|
28892
|
+
onChange: (event) => {
|
|
28893
|
+
event.stopPropagation();
|
|
28894
|
+
if (kind?.kind === "dropdown") {
|
|
28895
|
+
const nextSelected = event.currentTarget.value === "" ? void 0 : Number(event.currentTarget.value);
|
|
28896
|
+
commitControlKind(
|
|
28897
|
+
{ ...kind, selected: nextSelected },
|
|
28898
|
+
{ selected: nextSelected }
|
|
28899
|
+
);
|
|
28900
|
+
}
|
|
28901
|
+
},
|
|
28902
|
+
onClick: stopControlPointerEvent,
|
|
28903
|
+
onPointerDown: stopControlPointerEvent,
|
|
28217
28904
|
style: {
|
|
28218
28905
|
...commonStyle,
|
|
28906
|
+
backgroundColor: SHEET_SURFACE,
|
|
28219
28907
|
border: `${Math.max(1, zoomFactor)}px solid ${stroke}`,
|
|
28220
28908
|
borderRadius: 2 * zoomFactor,
|
|
28221
28909
|
boxSizing: "border-box",
|
|
28222
|
-
|
|
28223
|
-
padding: `0 ${6 * zoomFactor}px`
|
|
28910
|
+
padding: `0 ${4 * zoomFactor}px`
|
|
28224
28911
|
},
|
|
28912
|
+
value: selected === void 0 ? "" : String(selected),
|
|
28225
28913
|
children: [
|
|
28226
|
-
/* @__PURE__ */ jsx3("
|
|
28227
|
-
/* @__PURE__ */ jsx3("
|
|
28914
|
+
selected === void 0 ? /* @__PURE__ */ jsx3("option", { value: "", children: controlLabel }) : null,
|
|
28915
|
+
controlItems.map((item, index) => /* @__PURE__ */ jsx3("option", { value: index, children: item }, index))
|
|
28228
28916
|
]
|
|
28229
28917
|
},
|
|
28230
28918
|
`${pane}-${control.id}`
|
|
28231
28919
|
);
|
|
28232
|
-
}
|
|
28920
|
+
}
|
|
28921
|
+
if (control.kind === "listbox") {
|
|
28922
|
+
const kind = buildFormControlKindInput(control);
|
|
28923
|
+
const selected = Array.isArray(control.selected) ? control.selected : control.selected === void 0 ? [] : [control.selected];
|
|
28924
|
+
const allowsMultipleSelection = (control.selection ?? "single") !== "single";
|
|
28233
28925
|
return /* @__PURE__ */ jsx3(
|
|
28234
|
-
"
|
|
28926
|
+
"select",
|
|
28235
28927
|
{
|
|
28928
|
+
"aria-label": controlLabel || control.name || "List box form control",
|
|
28929
|
+
disabled: readOnly || control.controlIndex === void 0 || controlItems.length === 0,
|
|
28930
|
+
multiple: allowsMultipleSelection,
|
|
28931
|
+
onChange: (event) => {
|
|
28932
|
+
event.stopPropagation();
|
|
28933
|
+
if (kind?.kind === "listBox") {
|
|
28934
|
+
const nextSelected = Array.from(event.currentTarget.selectedOptions, (option) => Number(option.value));
|
|
28935
|
+
commitControlKind(
|
|
28936
|
+
{ ...kind, selected: nextSelected },
|
|
28937
|
+
{ selected: nextSelected }
|
|
28938
|
+
);
|
|
28939
|
+
}
|
|
28940
|
+
},
|
|
28941
|
+
onClick: stopControlPointerEvent,
|
|
28942
|
+
onPointerDown: stopControlPointerEvent,
|
|
28943
|
+
size: Math.max(2, Math.min(controlItems.length || 2, Math.floor(rect.height / Math.max(1, fontSizePx * 1.45)))),
|
|
28236
28944
|
style: {
|
|
28237
28945
|
...commonStyle,
|
|
28946
|
+
alignItems: void 0,
|
|
28947
|
+
backgroundColor: SHEET_SURFACE,
|
|
28238
28948
|
border: `${Math.max(1, zoomFactor)}px solid ${stroke}`,
|
|
28239
28949
|
borderRadius: 2 * zoomFactor,
|
|
28240
28950
|
boxSizing: "border-box",
|
|
28241
|
-
|
|
28951
|
+
display: "block",
|
|
28952
|
+
padding: 0
|
|
28242
28953
|
},
|
|
28243
|
-
|
|
28954
|
+
value: allowsMultipleSelection ? selected.map(String) : selected[0] === void 0 ? "" : String(selected[0]),
|
|
28955
|
+
children: controlItems.map((item, index) => /* @__PURE__ */ jsx3("option", { value: index, children: item }, index))
|
|
28244
28956
|
},
|
|
28245
28957
|
`${pane}-${control.id}`
|
|
28246
28958
|
);
|
|
28247
|
-
} else {
|
|
28248
|
-
content = null;
|
|
28249
28959
|
}
|
|
28250
|
-
|
|
28960
|
+
if (control.kind === "scrollbar") {
|
|
28961
|
+
const kind = buildFormControlKindInput(control);
|
|
28962
|
+
const min = control.min ?? 0;
|
|
28963
|
+
const max = Math.max(min, control.max ?? 100);
|
|
28964
|
+
return /* @__PURE__ */ jsx3(
|
|
28965
|
+
"input",
|
|
28966
|
+
{
|
|
28967
|
+
"aria-label": controlLabel || control.name || "Scrollbar form control",
|
|
28968
|
+
disabled: readOnly || control.controlIndex === void 0,
|
|
28969
|
+
max,
|
|
28970
|
+
min,
|
|
28971
|
+
onChange: (event) => {
|
|
28972
|
+
event.stopPropagation();
|
|
28973
|
+
if (kind?.kind === "scrollbar") {
|
|
28974
|
+
const value = event.currentTarget.valueAsNumber;
|
|
28975
|
+
commitControlKind({ ...kind, value }, { value });
|
|
28976
|
+
}
|
|
28977
|
+
},
|
|
28978
|
+
onClick: stopControlPointerEvent,
|
|
28979
|
+
onPointerDown: stopControlPointerEvent,
|
|
28980
|
+
step: Math.max(1, control.increment ?? 1),
|
|
28981
|
+
style: {
|
|
28982
|
+
...commonStyle,
|
|
28983
|
+
accentColor: paletteIsDark(palette) ? "#60a5fa" : "#2563eb",
|
|
28984
|
+
boxSizing: "border-box",
|
|
28985
|
+
padding: 0,
|
|
28986
|
+
writingMode: control.horizontal === false ? "vertical-lr" : void 0
|
|
28987
|
+
},
|
|
28988
|
+
type: "range",
|
|
28989
|
+
value: Math.max(min, Math.min(max, control.value ?? min))
|
|
28990
|
+
},
|
|
28991
|
+
`${pane}-${control.id}`
|
|
28992
|
+
);
|
|
28993
|
+
}
|
|
28994
|
+
if (control.kind === "spinner") {
|
|
28995
|
+
const kind = buildFormControlKindInput(control);
|
|
28996
|
+
const min = control.min ?? 0;
|
|
28997
|
+
const max = Math.max(min, control.max ?? 100);
|
|
28998
|
+
return /* @__PURE__ */ jsx3(
|
|
28999
|
+
"input",
|
|
29000
|
+
{
|
|
29001
|
+
"aria-label": controlLabel || control.name || "Spinner form control",
|
|
29002
|
+
disabled: readOnly || control.controlIndex === void 0,
|
|
29003
|
+
max,
|
|
29004
|
+
min,
|
|
29005
|
+
onChange: (event) => {
|
|
29006
|
+
event.stopPropagation();
|
|
29007
|
+
if (kind?.kind === "spinner" && Number.isFinite(event.currentTarget.valueAsNumber)) {
|
|
29008
|
+
const value = Math.max(min, Math.min(max, 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
|
+
backgroundColor: SHEET_SURFACE,
|
|
29018
|
+
border: `${Math.max(1, zoomFactor)}px solid ${stroke}`,
|
|
29019
|
+
borderRadius: 2 * zoomFactor,
|
|
29020
|
+
boxSizing: "border-box",
|
|
29021
|
+
padding: `0 ${4 * zoomFactor}px`
|
|
29022
|
+
},
|
|
29023
|
+
type: "number",
|
|
29024
|
+
value: Math.max(min, Math.min(max, control.value ?? min))
|
|
29025
|
+
},
|
|
29026
|
+
`${pane}-${control.id}`
|
|
29027
|
+
);
|
|
29028
|
+
}
|
|
29029
|
+
return /* @__PURE__ */ jsx3(
|
|
28251
29030
|
"div",
|
|
28252
29031
|
{
|
|
28253
29032
|
style: {
|
|
28254
29033
|
...commonStyle,
|
|
29034
|
+
border: control.kind === "editbox" || control.kind === "unknown" ? `${Math.max(1, zoomFactor)}px solid ${stroke}` : void 0,
|
|
29035
|
+
borderRadius: 2 * zoomFactor,
|
|
29036
|
+
boxSizing: "border-box",
|
|
28255
29037
|
padding: `0 ${Math.max(1, zoomFactor)}px`
|
|
28256
29038
|
},
|
|
28257
|
-
children:
|
|
28258
|
-
content,
|
|
28259
|
-
controlLabel ? /* @__PURE__ */ jsx3(
|
|
28260
|
-
"span",
|
|
28261
|
-
{
|
|
28262
|
-
style: {
|
|
28263
|
-
overflow: "hidden",
|
|
28264
|
-
textOverflow: "ellipsis",
|
|
28265
|
-
whiteSpace: "nowrap"
|
|
28266
|
-
},
|
|
28267
|
-
children: controlLabel
|
|
28268
|
-
}
|
|
28269
|
-
) : null
|
|
28270
|
-
]
|
|
29039
|
+
children: controlLabel ? /* @__PURE__ */ jsx3("span", { style: { overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }, children: controlLabel }) : null
|
|
28271
29040
|
},
|
|
28272
29041
|
`${pane}-${control.id}`
|
|
28273
29042
|
);
|
|
@@ -29830,6 +30599,8 @@ function XlsxViewerInner({
|
|
|
29830
30599
|
isDark = false,
|
|
29831
30600
|
loadingComponent,
|
|
29832
30601
|
loadingState,
|
|
30602
|
+
onFormControlAction,
|
|
30603
|
+
onFormControlChange,
|
|
29833
30604
|
renderChartLoading,
|
|
29834
30605
|
renderImage,
|
|
29835
30606
|
renderImageSelection,
|
|
@@ -29892,6 +30663,8 @@ function XlsxViewerInner({
|
|
|
29892
30663
|
getCellStyle,
|
|
29893
30664
|
loadingComponent,
|
|
29894
30665
|
loadingState,
|
|
30666
|
+
onFormControlAction,
|
|
30667
|
+
onFormControlChange,
|
|
29895
30668
|
palette,
|
|
29896
30669
|
renderChartLoading,
|
|
29897
30670
|
renderImage,
|
|
@@ -29998,6 +30771,7 @@ function useXlsxViewerZoom() {
|
|
|
29998
30771
|
}
|
|
29999
30772
|
function useXlsxViewerEditing() {
|
|
30000
30773
|
const {
|
|
30774
|
+
addFormControl,
|
|
30001
30775
|
addSheet,
|
|
30002
30776
|
canRedo,
|
|
30003
30777
|
canUndo,
|
|
@@ -30005,14 +30779,18 @@ function useXlsxViewerEditing() {
|
|
|
30005
30779
|
copySelectionToClipboard,
|
|
30006
30780
|
defineNamedRange,
|
|
30007
30781
|
fillSelection,
|
|
30782
|
+
formControls,
|
|
30008
30783
|
getClipboardData,
|
|
30009
30784
|
getCellDisplayValue: getCellDisplayValue2,
|
|
30010
30785
|
getCellFormula,
|
|
30786
|
+
getFormControlItems,
|
|
30787
|
+
getSheetFormControls,
|
|
30011
30788
|
mergeSelection,
|
|
30012
30789
|
pasteFromClipboard,
|
|
30013
30790
|
pasteStructuredClipboardData,
|
|
30014
30791
|
pasteText,
|
|
30015
30792
|
removeActiveSheet,
|
|
30793
|
+
removeFormControl,
|
|
30016
30794
|
readOnly,
|
|
30017
30795
|
redo,
|
|
30018
30796
|
selectedCellFormula,
|
|
@@ -30029,10 +30807,12 @@ function useXlsxViewerEditing() {
|
|
|
30029
30807
|
setSelectedCellStyle,
|
|
30030
30808
|
setSelectedCellValue,
|
|
30031
30809
|
undo,
|
|
30032
|
-
unmergeSelection
|
|
30810
|
+
unmergeSelection,
|
|
30811
|
+
updateFormControl
|
|
30033
30812
|
} = useXlsxViewer();
|
|
30034
30813
|
return React4.useMemo(
|
|
30035
30814
|
() => ({
|
|
30815
|
+
addFormControl,
|
|
30036
30816
|
addSheet,
|
|
30037
30817
|
canRedo,
|
|
30038
30818
|
canUndo,
|
|
@@ -30040,14 +30820,18 @@ function useXlsxViewerEditing() {
|
|
|
30040
30820
|
copySelectionToClipboard,
|
|
30041
30821
|
defineNamedRange,
|
|
30042
30822
|
fillSelection,
|
|
30823
|
+
formControls,
|
|
30043
30824
|
getClipboardData,
|
|
30044
30825
|
getCellDisplayValue: getCellDisplayValue2,
|
|
30045
30826
|
getCellFormula,
|
|
30827
|
+
getFormControlItems,
|
|
30828
|
+
getSheetFormControls,
|
|
30046
30829
|
mergeSelection,
|
|
30047
30830
|
pasteFromClipboard,
|
|
30048
30831
|
pasteStructuredClipboardData,
|
|
30049
30832
|
pasteText,
|
|
30050
30833
|
removeActiveSheet,
|
|
30834
|
+
removeFormControl,
|
|
30051
30835
|
readOnly,
|
|
30052
30836
|
redo,
|
|
30053
30837
|
selectedCellFormula,
|
|
@@ -30064,9 +30848,11 @@ function useXlsxViewerEditing() {
|
|
|
30064
30848
|
setSelectedCellStyle,
|
|
30065
30849
|
setSelectedCellValue,
|
|
30066
30850
|
undo,
|
|
30067
|
-
unmergeSelection
|
|
30851
|
+
unmergeSelection,
|
|
30852
|
+
updateFormControl
|
|
30068
30853
|
}),
|
|
30069
30854
|
[
|
|
30855
|
+
addFormControl,
|
|
30070
30856
|
addSheet,
|
|
30071
30857
|
canRedo,
|
|
30072
30858
|
canUndo,
|
|
@@ -30074,14 +30860,18 @@ function useXlsxViewerEditing() {
|
|
|
30074
30860
|
copySelectionToClipboard,
|
|
30075
30861
|
defineNamedRange,
|
|
30076
30862
|
fillSelection,
|
|
30863
|
+
formControls,
|
|
30077
30864
|
getClipboardData,
|
|
30078
30865
|
getCellDisplayValue2,
|
|
30079
30866
|
getCellFormula,
|
|
30867
|
+
getFormControlItems,
|
|
30868
|
+
getSheetFormControls,
|
|
30080
30869
|
mergeSelection,
|
|
30081
30870
|
pasteFromClipboard,
|
|
30082
30871
|
pasteStructuredClipboardData,
|
|
30083
30872
|
pasteText,
|
|
30084
30873
|
removeActiveSheet,
|
|
30874
|
+
removeFormControl,
|
|
30085
30875
|
readOnly,
|
|
30086
30876
|
redo,
|
|
30087
30877
|
selectedCellFormula,
|
|
@@ -30098,7 +30888,8 @@ function useXlsxViewerEditing() {
|
|
|
30098
30888
|
setSelectedCellStyle,
|
|
30099
30889
|
setSelectedCellValue,
|
|
30100
30890
|
undo,
|
|
30101
|
-
unmergeSelection
|
|
30891
|
+
unmergeSelection,
|
|
30892
|
+
updateFormControl
|
|
30102
30893
|
]
|
|
30103
30894
|
);
|
|
30104
30895
|
}
|
|
@@ -30684,7 +31475,6 @@ function useXlsxViewerThumbnails(options = {}) {
|
|
|
30684
31475
|
const canvasCellStyle = cellData.canvas ?? buildCanvasCellStyleCache(cellData.style);
|
|
30685
31476
|
const gradientFill = typeof cellData.style.backgroundImage === "string" ? resolveCanvasGradientFill(context, rect, cellData.style.backgroundImage) : null;
|
|
30686
31477
|
const fillColor = cellData.conditionalColorScale?.color ?? (typeof cellData.style.backgroundColor === "string" ? cellData.style.backgroundColor : thumbnailSheetSurface);
|
|
30687
|
-
const hasExplicitCellFill = cellData.conditionalColorScale !== null || gradientFill !== null || typeof cellData.style.backgroundColor === "string" && cellData.style.backgroundColor !== thumbnailSheetSurface;
|
|
30688
31478
|
context.fillStyle = gradientFill ?? fillColor;
|
|
30689
31479
|
context.fillRect(rect.left, rect.top, rect.width, rect.height);
|
|
30690
31480
|
if (cellData.conditionalDataBar) {
|
|
@@ -30709,7 +31499,7 @@ function useXlsxViewerThumbnails(options = {}) {
|
|
|
30709
31499
|
}
|
|
30710
31500
|
}
|
|
30711
31501
|
}
|
|
30712
|
-
if (showGridLines
|
|
31502
|
+
if (showGridLines) {
|
|
30713
31503
|
context.strokeStyle = palette.border;
|
|
30714
31504
|
context.lineWidth = 1;
|
|
30715
31505
|
context.beginPath();
|