@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.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);
|
|
@@ -28125,10 +28694,22 @@ function XlsxGrid({
|
|
|
28125
28694
|
const fontSizePx = Math.max(9 * zoomFactor, (control.fontSizePt ?? 9) * 96 / 72 * zoomFactor);
|
|
28126
28695
|
const stroke = paletteIsDark(palette) ? "#cbd5e1" : "#475569";
|
|
28127
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) ?? [];
|
|
28128
28708
|
const commonStyle = {
|
|
28129
28709
|
alignItems: control.kind === "group-box" ? "stretch" : "center",
|
|
28130
28710
|
color: textColor,
|
|
28131
28711
|
contain: "layout paint",
|
|
28712
|
+
cursor: isInteractiveControl ? "pointer" : void 0,
|
|
28132
28713
|
display: "flex",
|
|
28133
28714
|
fontFamily: control.fontFamily ?? "Calibri, sans-serif",
|
|
28134
28715
|
fontSize: fontSizePx,
|
|
@@ -28139,12 +28720,28 @@ function XlsxGrid({
|
|
|
28139
28720
|
left: rect.left,
|
|
28140
28721
|
lineHeight: 1.2,
|
|
28141
28722
|
overflow: "hidden",
|
|
28142
|
-
pointerEvents: "none",
|
|
28723
|
+
pointerEvents: isInteractiveControl ? "auto" : "none",
|
|
28143
28724
|
position: "absolute",
|
|
28144
28725
|
top: rect.top,
|
|
28145
28726
|
width: rect.width,
|
|
28146
28727
|
zIndex: isFrozenDrawing ? control.zIndex + 20 : control.zIndex
|
|
28147
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
|
+
};
|
|
28148
28745
|
if (control.kind === "group-box") {
|
|
28149
28746
|
const hasLabel = controlLabel.length > 0;
|
|
28150
28747
|
return /* @__PURE__ */ jsx3(
|
|
@@ -28186,15 +28783,88 @@ function XlsxGrid({
|
|
|
28186
28783
|
`${pane}-${control.id}`
|
|
28187
28784
|
);
|
|
28188
28785
|
}
|
|
28189
|
-
let content;
|
|
28190
28786
|
if (control.kind === "radio") {
|
|
28191
|
-
|
|
28192
|
-
|
|
28193
|
-
|
|
28194
|
-
|
|
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") {
|
|
28195
28859
|
return /* @__PURE__ */ jsx3(
|
|
28196
|
-
"
|
|
28860
|
+
"button",
|
|
28197
28861
|
{
|
|
28862
|
+
disabled: readOnly || !onFormControlAction,
|
|
28863
|
+
onClick: (event) => {
|
|
28864
|
+
event.stopPropagation();
|
|
28865
|
+
onFormControlAction?.({ control, type: "activate" });
|
|
28866
|
+
},
|
|
28867
|
+
onPointerDown: stopControlPointerEvent,
|
|
28198
28868
|
style: {
|
|
28199
28869
|
...commonStyle,
|
|
28200
28870
|
background: "linear-gradient(180deg, #f8fafc 0%, #e2e8f0 100%)",
|
|
@@ -28205,68 +28875,168 @@ function XlsxGrid({
|
|
|
28205
28875
|
padding: `0 ${6 * zoomFactor}px`,
|
|
28206
28876
|
textAlign: "center"
|
|
28207
28877
|
},
|
|
28878
|
+
type: "button",
|
|
28208
28879
|
children: controlLabel
|
|
28209
28880
|
},
|
|
28210
28881
|
`${pane}-${control.id}`
|
|
28211
28882
|
);
|
|
28212
|
-
}
|
|
28883
|
+
}
|
|
28884
|
+
if (control.kind === "dropdown") {
|
|
28885
|
+
const kind = buildFormControlKindInput(control);
|
|
28886
|
+
const selected = typeof control.selected === "number" ? control.selected : void 0;
|
|
28213
28887
|
return /* @__PURE__ */ jsxs3(
|
|
28214
|
-
"
|
|
28888
|
+
"select",
|
|
28215
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,
|
|
28216
28904
|
style: {
|
|
28217
28905
|
...commonStyle,
|
|
28906
|
+
backgroundColor: SHEET_SURFACE,
|
|
28218
28907
|
border: `${Math.max(1, zoomFactor)}px solid ${stroke}`,
|
|
28219
28908
|
borderRadius: 2 * zoomFactor,
|
|
28220
28909
|
boxSizing: "border-box",
|
|
28221
|
-
|
|
28222
|
-
padding: `0 ${6 * zoomFactor}px`
|
|
28910
|
+
padding: `0 ${4 * zoomFactor}px`
|
|
28223
28911
|
},
|
|
28912
|
+
value: selected === void 0 ? "" : String(selected),
|
|
28224
28913
|
children: [
|
|
28225
|
-
/* @__PURE__ */ jsx3("
|
|
28226
|
-
/* @__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))
|
|
28227
28916
|
]
|
|
28228
28917
|
},
|
|
28229
28918
|
`${pane}-${control.id}`
|
|
28230
28919
|
);
|
|
28231
|
-
}
|
|
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";
|
|
28232
28925
|
return /* @__PURE__ */ jsx3(
|
|
28233
|
-
"
|
|
28926
|
+
"select",
|
|
28234
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)))),
|
|
28235
28944
|
style: {
|
|
28236
28945
|
...commonStyle,
|
|
28946
|
+
alignItems: void 0,
|
|
28947
|
+
backgroundColor: SHEET_SURFACE,
|
|
28237
28948
|
border: `${Math.max(1, zoomFactor)}px solid ${stroke}`,
|
|
28238
28949
|
borderRadius: 2 * zoomFactor,
|
|
28239
28950
|
boxSizing: "border-box",
|
|
28240
|
-
|
|
28951
|
+
display: "block",
|
|
28952
|
+
padding: 0
|
|
28241
28953
|
},
|
|
28242
|
-
|
|
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))
|
|
28243
28956
|
},
|
|
28244
28957
|
`${pane}-${control.id}`
|
|
28245
28958
|
);
|
|
28246
|
-
} else {
|
|
28247
|
-
content = null;
|
|
28248
28959
|
}
|
|
28249
|
-
|
|
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(
|
|
28250
29030
|
"div",
|
|
28251
29031
|
{
|
|
28252
29032
|
style: {
|
|
28253
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",
|
|
28254
29037
|
padding: `0 ${Math.max(1, zoomFactor)}px`
|
|
28255
29038
|
},
|
|
28256
|
-
children:
|
|
28257
|
-
content,
|
|
28258
|
-
controlLabel ? /* @__PURE__ */ jsx3(
|
|
28259
|
-
"span",
|
|
28260
|
-
{
|
|
28261
|
-
style: {
|
|
28262
|
-
overflow: "hidden",
|
|
28263
|
-
textOverflow: "ellipsis",
|
|
28264
|
-
whiteSpace: "nowrap"
|
|
28265
|
-
},
|
|
28266
|
-
children: controlLabel
|
|
28267
|
-
}
|
|
28268
|
-
) : null
|
|
28269
|
-
]
|
|
29039
|
+
children: controlLabel ? /* @__PURE__ */ jsx3("span", { style: { overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }, children: controlLabel }) : null
|
|
28270
29040
|
},
|
|
28271
29041
|
`${pane}-${control.id}`
|
|
28272
29042
|
);
|
|
@@ -29829,6 +30599,8 @@ function XlsxViewerInner({
|
|
|
29829
30599
|
isDark = false,
|
|
29830
30600
|
loadingComponent,
|
|
29831
30601
|
loadingState,
|
|
30602
|
+
onFormControlAction,
|
|
30603
|
+
onFormControlChange,
|
|
29832
30604
|
renderChartLoading,
|
|
29833
30605
|
renderImage,
|
|
29834
30606
|
renderImageSelection,
|
|
@@ -29891,6 +30663,8 @@ function XlsxViewerInner({
|
|
|
29891
30663
|
getCellStyle,
|
|
29892
30664
|
loadingComponent,
|
|
29893
30665
|
loadingState,
|
|
30666
|
+
onFormControlAction,
|
|
30667
|
+
onFormControlChange,
|
|
29894
30668
|
palette,
|
|
29895
30669
|
renderChartLoading,
|
|
29896
30670
|
renderImage,
|
|
@@ -29997,6 +30771,7 @@ function useXlsxViewerZoom() {
|
|
|
29997
30771
|
}
|
|
29998
30772
|
function useXlsxViewerEditing() {
|
|
29999
30773
|
const {
|
|
30774
|
+
addFormControl,
|
|
30000
30775
|
addSheet,
|
|
30001
30776
|
canRedo,
|
|
30002
30777
|
canUndo,
|
|
@@ -30004,14 +30779,18 @@ function useXlsxViewerEditing() {
|
|
|
30004
30779
|
copySelectionToClipboard,
|
|
30005
30780
|
defineNamedRange,
|
|
30006
30781
|
fillSelection,
|
|
30782
|
+
formControls,
|
|
30007
30783
|
getClipboardData,
|
|
30008
30784
|
getCellDisplayValue: getCellDisplayValue2,
|
|
30009
30785
|
getCellFormula,
|
|
30786
|
+
getFormControlItems,
|
|
30787
|
+
getSheetFormControls,
|
|
30010
30788
|
mergeSelection,
|
|
30011
30789
|
pasteFromClipboard,
|
|
30012
30790
|
pasteStructuredClipboardData,
|
|
30013
30791
|
pasteText,
|
|
30014
30792
|
removeActiveSheet,
|
|
30793
|
+
removeFormControl,
|
|
30015
30794
|
readOnly,
|
|
30016
30795
|
redo,
|
|
30017
30796
|
selectedCellFormula,
|
|
@@ -30028,10 +30807,12 @@ function useXlsxViewerEditing() {
|
|
|
30028
30807
|
setSelectedCellStyle,
|
|
30029
30808
|
setSelectedCellValue,
|
|
30030
30809
|
undo,
|
|
30031
|
-
unmergeSelection
|
|
30810
|
+
unmergeSelection,
|
|
30811
|
+
updateFormControl
|
|
30032
30812
|
} = useXlsxViewer();
|
|
30033
30813
|
return React4.useMemo(
|
|
30034
30814
|
() => ({
|
|
30815
|
+
addFormControl,
|
|
30035
30816
|
addSheet,
|
|
30036
30817
|
canRedo,
|
|
30037
30818
|
canUndo,
|
|
@@ -30039,14 +30820,18 @@ function useXlsxViewerEditing() {
|
|
|
30039
30820
|
copySelectionToClipboard,
|
|
30040
30821
|
defineNamedRange,
|
|
30041
30822
|
fillSelection,
|
|
30823
|
+
formControls,
|
|
30042
30824
|
getClipboardData,
|
|
30043
30825
|
getCellDisplayValue: getCellDisplayValue2,
|
|
30044
30826
|
getCellFormula,
|
|
30827
|
+
getFormControlItems,
|
|
30828
|
+
getSheetFormControls,
|
|
30045
30829
|
mergeSelection,
|
|
30046
30830
|
pasteFromClipboard,
|
|
30047
30831
|
pasteStructuredClipboardData,
|
|
30048
30832
|
pasteText,
|
|
30049
30833
|
removeActiveSheet,
|
|
30834
|
+
removeFormControl,
|
|
30050
30835
|
readOnly,
|
|
30051
30836
|
redo,
|
|
30052
30837
|
selectedCellFormula,
|
|
@@ -30063,9 +30848,11 @@ function useXlsxViewerEditing() {
|
|
|
30063
30848
|
setSelectedCellStyle,
|
|
30064
30849
|
setSelectedCellValue,
|
|
30065
30850
|
undo,
|
|
30066
|
-
unmergeSelection
|
|
30851
|
+
unmergeSelection,
|
|
30852
|
+
updateFormControl
|
|
30067
30853
|
}),
|
|
30068
30854
|
[
|
|
30855
|
+
addFormControl,
|
|
30069
30856
|
addSheet,
|
|
30070
30857
|
canRedo,
|
|
30071
30858
|
canUndo,
|
|
@@ -30073,14 +30860,18 @@ function useXlsxViewerEditing() {
|
|
|
30073
30860
|
copySelectionToClipboard,
|
|
30074
30861
|
defineNamedRange,
|
|
30075
30862
|
fillSelection,
|
|
30863
|
+
formControls,
|
|
30076
30864
|
getClipboardData,
|
|
30077
30865
|
getCellDisplayValue2,
|
|
30078
30866
|
getCellFormula,
|
|
30867
|
+
getFormControlItems,
|
|
30868
|
+
getSheetFormControls,
|
|
30079
30869
|
mergeSelection,
|
|
30080
30870
|
pasteFromClipboard,
|
|
30081
30871
|
pasteStructuredClipboardData,
|
|
30082
30872
|
pasteText,
|
|
30083
30873
|
removeActiveSheet,
|
|
30874
|
+
removeFormControl,
|
|
30084
30875
|
readOnly,
|
|
30085
30876
|
redo,
|
|
30086
30877
|
selectedCellFormula,
|
|
@@ -30097,7 +30888,8 @@ function useXlsxViewerEditing() {
|
|
|
30097
30888
|
setSelectedCellStyle,
|
|
30098
30889
|
setSelectedCellValue,
|
|
30099
30890
|
undo,
|
|
30100
|
-
unmergeSelection
|
|
30891
|
+
unmergeSelection,
|
|
30892
|
+
updateFormControl
|
|
30101
30893
|
]
|
|
30102
30894
|
);
|
|
30103
30895
|
}
|