@a3s-lab/office 0.40.0 → 0.41.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
CHANGED
|
@@ -309,6 +309,17 @@ and [CLI reference](./docs/latest/en/cli-reference.md).
|
|
|
309
309
|
|
|
310
310
|
## Current release
|
|
311
311
|
|
|
312
|
+
Version `0.41.0` aligns Spreadsheet data-validation alerts with the local,
|
|
313
|
+
testable interaction model used by Traditional Office:
|
|
314
|
+
|
|
315
|
+
- Stop blocks an invalid edit with an accessible notice. Warning and
|
|
316
|
+
Information ask whether the invalid value should be kept, using the authored
|
|
317
|
+
title and message plus the current input so the decision is explicit.
|
|
318
|
+
- Keeping a Warning or Information value commits it once through the controlled
|
|
319
|
+
workbook API; cancelling restores the original value. Selection, focus,
|
|
320
|
+
Undo, and collaboration remain on the same bounded edit path, and native
|
|
321
|
+
XLSX `errorStyle` metadata remains lossless on reopen.
|
|
322
|
+
|
|
312
323
|
Version `0.40.0` extends Writer's local, testable review workflow with atomic
|
|
313
324
|
ordered-list numbering revisions:
|
|
314
325
|
|
|
@@ -26838,7 +26838,7 @@ function SpreadsheetDataValidationDialog({ source, restoreFocusTarget, onApply,
|
|
|
26838
26838
|
children: [
|
|
26839
26839
|
/*#__PURE__*/ jsx(field_Field, {
|
|
26840
26840
|
label: "错误警告样式",
|
|
26841
|
-
description: "
|
|
26841
|
+
description: "停止会阻止无效输入;警告和信息会询问是否保留。三种样式都会写入原生文件。",
|
|
26842
26842
|
children: /*#__PURE__*/ jsxs("select", {
|
|
26843
26843
|
"aria-label": "错误警告样式",
|
|
26844
26844
|
value: value.errorStyle,
|
|
@@ -27073,6 +27073,55 @@ function use_spreadsheet_data_validation_spreadsheetDataValidationError(content,
|
|
|
27073
27073
|
value
|
|
27074
27074
|
}) ?? fallback;
|
|
27075
27075
|
}
|
|
27076
|
+
function spreadsheetDataValidationErrorStyle(item) {
|
|
27077
|
+
return 'warning' === item.errorStyle || 'information' === item.errorStyle ? item.errorStyle : 'stop';
|
|
27078
|
+
}
|
|
27079
|
+
function spreadsheetDataValidationInteraction(style) {
|
|
27080
|
+
return 'stop' === style ? 'notice' : 'confirm';
|
|
27081
|
+
}
|
|
27082
|
+
function spreadsheetDataValidationDialogTitle(item) {
|
|
27083
|
+
const customTitle = item.errorTitle?.trim();
|
|
27084
|
+
if (customTitle) return customTitle;
|
|
27085
|
+
switch(spreadsheetDataValidationErrorStyle(item)){
|
|
27086
|
+
case 'warning':
|
|
27087
|
+
return '数据验证警告';
|
|
27088
|
+
case 'information':
|
|
27089
|
+
return '数据验证提示';
|
|
27090
|
+
default:
|
|
27091
|
+
return '数据验证错误';
|
|
27092
|
+
}
|
|
27093
|
+
}
|
|
27094
|
+
function spreadsheetDataValidationDialogDescription(failureText, value, item) {
|
|
27095
|
+
const customTitle = item?.errorTitle?.trim();
|
|
27096
|
+
const customMessage = item?.errorMessage?.trim();
|
|
27097
|
+
let message = customMessage || failureText.trim();
|
|
27098
|
+
if (customTitle && message.startsWith(`${customTitle}\n`)) message = message.slice(customTitle.length + 1).trim();
|
|
27099
|
+
message ||= '当前输入不符合此单元格的数据验证规则。';
|
|
27100
|
+
const valueText = spreadsheetDataValidationValueText(value);
|
|
27101
|
+
return valueText ? `${message}\n\n当前输入:${valueText}` : message;
|
|
27102
|
+
}
|
|
27103
|
+
function spreadsheetDataValidationConfirmLabels(style) {
|
|
27104
|
+
return 'warning' === style ? {
|
|
27105
|
+
cancelLabel: '取消',
|
|
27106
|
+
confirmLabel: '继续输入'
|
|
27107
|
+
} : {
|
|
27108
|
+
cancelLabel: '返回修改',
|
|
27109
|
+
confirmLabel: '保留输入'
|
|
27110
|
+
};
|
|
27111
|
+
}
|
|
27112
|
+
function spreadsheetDataValidationValueText(value) {
|
|
27113
|
+
if ('string' == typeof value) return value.trim();
|
|
27114
|
+
if ('number' == typeof value || 'boolean' == typeof value) return String(value);
|
|
27115
|
+
return '';
|
|
27116
|
+
}
|
|
27117
|
+
function cloneSpreadsheetDataValidationItem(item) {
|
|
27118
|
+
return {
|
|
27119
|
+
...item,
|
|
27120
|
+
errorTitle: item.errorTitle,
|
|
27121
|
+
errorMessage: item.errorMessage,
|
|
27122
|
+
hintTitle: item.hintTitle
|
|
27123
|
+
};
|
|
27124
|
+
}
|
|
27076
27125
|
const spreadsheetCellFormatAttributes = [
|
|
27077
27126
|
'bl',
|
|
27078
27127
|
'it',
|
|
@@ -29935,6 +29984,28 @@ function SpreadsheetEditorSurface({ autoFocus = true, content, collaborationHist
|
|
|
29935
29984
|
const activeSheetId = viewActiveSheetId && content.sheets.some((sheet)=>sheet.id === viewActiveSheetId && 1 !== sheet.hide) ? viewActiveSheetId : contentActiveSheetId;
|
|
29936
29985
|
const activeSheetIdRef = useRef(activeSheetId);
|
|
29937
29986
|
const focusedSheetIdRef = useRef(null);
|
|
29987
|
+
const pendingDataValidationRef = useRef(null);
|
|
29988
|
+
const [pendingDataValidation, setPendingDataValidation] = useState(null);
|
|
29989
|
+
const queueDataValidationEdit = useCallback((row, column, value, item, failureText, sheetId)=>{
|
|
29990
|
+
const requestSheetId = sheetId ?? activeSheetIdRef.current;
|
|
29991
|
+
if (!requestSheetId || !item || 'object' != typeof item || pendingDataValidationRef.current) return pendingDataValidationRef.current ? false : void 0;
|
|
29992
|
+
const validationItem = item;
|
|
29993
|
+
const style = spreadsheetDataValidationErrorStyle(validationItem);
|
|
29994
|
+
const request = {
|
|
29995
|
+
column,
|
|
29996
|
+
failureText,
|
|
29997
|
+
interaction: spreadsheetDataValidationInteraction(style),
|
|
29998
|
+
item: cloneSpreadsheetDataValidationItem(validationItem),
|
|
29999
|
+
row,
|
|
30000
|
+
sheetId: requestSheetId,
|
|
30001
|
+
value
|
|
30002
|
+
};
|
|
30003
|
+
pendingDataValidationRef.current = request;
|
|
30004
|
+
queueMicrotask(()=>{
|
|
30005
|
+
if (pendingDataValidationRef.current === request) setPendingDataValidation(request);
|
|
30006
|
+
});
|
|
30007
|
+
return false;
|
|
30008
|
+
}, []);
|
|
29938
30009
|
contentRef.current = materializedContent;
|
|
29939
30010
|
previewRef.current = preview;
|
|
29940
30011
|
const controlledHistory = useOfficeHistory({
|
|
@@ -29992,6 +30063,100 @@ function SpreadsheetEditorSurface({ autoFocus = true, content, collaborationHist
|
|
|
29992
30063
|
}, [
|
|
29993
30064
|
activeSheetId
|
|
29994
30065
|
]);
|
|
30066
|
+
useEffect(()=>{
|
|
30067
|
+
const request = pendingDataValidation;
|
|
30068
|
+
if (!request) return;
|
|
30069
|
+
let cancelled = false;
|
|
30070
|
+
const style = spreadsheetDataValidationErrorStyle(request.item);
|
|
30071
|
+
const description = spreadsheetDataValidationDialogDescription(request.failureText, request.value, request.item);
|
|
30072
|
+
const restoreValidationSelection = ()=>{
|
|
30073
|
+
const selection = {
|
|
30074
|
+
row: [
|
|
30075
|
+
request.row,
|
|
30076
|
+
request.row
|
|
30077
|
+
],
|
|
30078
|
+
column: [
|
|
30079
|
+
request.column,
|
|
30080
|
+
request.column
|
|
30081
|
+
],
|
|
30082
|
+
row_focus: request.row,
|
|
30083
|
+
column_focus: request.column
|
|
30084
|
+
};
|
|
30085
|
+
const nextSelection = {
|
|
30086
|
+
sheetId: request.sheetId,
|
|
30087
|
+
selection
|
|
30088
|
+
};
|
|
30089
|
+
selectionStateRef.current.current = nextSelection;
|
|
30090
|
+
selectionStateRef.current.requested = {
|
|
30091
|
+
sheetId: request.sheetId,
|
|
30092
|
+
selection: {
|
|
30093
|
+
...selection,
|
|
30094
|
+
row: [
|
|
30095
|
+
...selection.row
|
|
30096
|
+
],
|
|
30097
|
+
column: [
|
|
30098
|
+
...selection.column
|
|
30099
|
+
]
|
|
30100
|
+
}
|
|
30101
|
+
};
|
|
30102
|
+
setSelectionState(nextSelection);
|
|
30103
|
+
try {
|
|
30104
|
+
workbookRef.current?.setSelection([
|
|
30105
|
+
{
|
|
30106
|
+
row: selection.row,
|
|
30107
|
+
column: selection.column
|
|
30108
|
+
}
|
|
30109
|
+
], {
|
|
30110
|
+
id: request.sheetId
|
|
30111
|
+
});
|
|
30112
|
+
} catch {}
|
|
30113
|
+
};
|
|
30114
|
+
const finish = (accepted)=>{
|
|
30115
|
+
if (cancelled || pendingDataValidationRef.current !== request) return;
|
|
30116
|
+
pendingDataValidationRef.current = null;
|
|
30117
|
+
setPendingDataValidation(null);
|
|
30118
|
+
if (accepted) try {
|
|
30119
|
+
workbookRef.current?.setCellValue(request.row, request.column, request.value, {
|
|
30120
|
+
id: request.sheetId,
|
|
30121
|
+
skipDataValidation: true
|
|
30122
|
+
});
|
|
30123
|
+
} catch {
|
|
30124
|
+
showToast('无法保留此输入,请重试。', 'error');
|
|
30125
|
+
}
|
|
30126
|
+
restoreValidationSelection();
|
|
30127
|
+
};
|
|
30128
|
+
const showValidationDialog = async ()=>{
|
|
30129
|
+
if ('notice' === request.interaction) {
|
|
30130
|
+
await officeDialog.notice({
|
|
30131
|
+
title: spreadsheetDataValidationDialogTitle(request.item),
|
|
30132
|
+
description,
|
|
30133
|
+
confirmLabel: '知道了',
|
|
30134
|
+
restoreFocusTarget: getSpreadsheetDialogGridFocusTarget
|
|
30135
|
+
});
|
|
30136
|
+
finish(false);
|
|
30137
|
+
return;
|
|
30138
|
+
}
|
|
30139
|
+
const labels = spreadsheetDataValidationConfirmLabels(style);
|
|
30140
|
+
const accepted = await officeDialog.confirm({
|
|
30141
|
+
title: spreadsheetDataValidationDialogTitle(request.item),
|
|
30142
|
+
description,
|
|
30143
|
+
confirmLabel: labels.confirmLabel,
|
|
30144
|
+
cancelLabel: labels.cancelLabel,
|
|
30145
|
+
confirmTone: 'warning' === style ? 'primary' : 'secondary',
|
|
30146
|
+
restoreFocusTarget: getSpreadsheetDialogGridFocusTarget
|
|
30147
|
+
});
|
|
30148
|
+
finish(accepted);
|
|
30149
|
+
};
|
|
30150
|
+
showValidationDialog();
|
|
30151
|
+
return ()=>{
|
|
30152
|
+
cancelled = true;
|
|
30153
|
+
};
|
|
30154
|
+
}, [
|
|
30155
|
+
getSpreadsheetDialogGridFocusTarget,
|
|
30156
|
+
officeDialog.confirm,
|
|
30157
|
+
officeDialog.notice,
|
|
30158
|
+
pendingDataValidation
|
|
30159
|
+
]);
|
|
29995
30160
|
useEffect(()=>{
|
|
29996
30161
|
if (preview || !activeSheetId || focusedSheetIdRef.current === activeSheetId) return;
|
|
29997
30162
|
const initialFocus = null === focusedSheetIdRef.current;
|
|
@@ -30077,6 +30242,7 @@ function SpreadsheetEditorSurface({ autoFocus = true, content, collaborationHist
|
|
|
30077
30242
|
const sheet = contentRef.current.sheets.find((candidate)=>candidate.id === activeSheetIdRef.current);
|
|
30078
30243
|
return !sheet || !spreadsheetPivotOutputContains(sheet, row, column);
|
|
30079
30244
|
},
|
|
30245
|
+
beforeDataValidation: queueDataValidationEdit,
|
|
30080
30246
|
beforePaste: (selections)=>{
|
|
30081
30247
|
const sheet = contentRef.current.sheets.find((candidate)=>candidate.id === activeSheetIdRef.current);
|
|
30082
30248
|
if (!sheet) return true;
|
|
@@ -30116,7 +30282,8 @@ function SpreadsheetEditorSurface({ autoFocus = true, content, collaborationHist
|
|
|
30116
30282
|
}
|
|
30117
30283
|
}
|
|
30118
30284
|
}), [
|
|
30119
|
-
collaborationView
|
|
30285
|
+
collaborationView,
|
|
30286
|
+
queueDataValidationEdit
|
|
30120
30287
|
]);
|
|
30121
30288
|
const conditionalFormatKey = useMemo(()=>content.sheets.map((sheet)=>`${sheet.id}:${JSON.stringify(sheet.luckysheet_conditionformat_save ?? [])}`).join('|'), [
|
|
30122
30289
|
content.sheets
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import type { WorkSpreadsheetDataValidationErrorStyle, WorkSpreadsheetDataValidationItem } from '../work-types';
|
|
2
|
+
export type SpreadsheetDataValidationInteraction = 'notice' | 'confirm';
|
|
3
|
+
export interface SpreadsheetDataValidationEditRequest {
|
|
4
|
+
column: number;
|
|
5
|
+
failureText: string;
|
|
6
|
+
interaction: SpreadsheetDataValidationInteraction;
|
|
7
|
+
item: WorkSpreadsheetDataValidationItem;
|
|
8
|
+
row: number;
|
|
9
|
+
sheetId: string;
|
|
10
|
+
value: unknown;
|
|
11
|
+
}
|
|
12
|
+
type SpreadsheetDataValidationMessageSource = Pick<WorkSpreadsheetDataValidationItem, 'errorMessage' | 'errorTitle'>;
|
|
13
|
+
export declare function spreadsheetDataValidationErrorStyle(item: Pick<WorkSpreadsheetDataValidationItem, 'errorStyle'>): WorkSpreadsheetDataValidationErrorStyle;
|
|
14
|
+
export declare function spreadsheetDataValidationInteraction(style: WorkSpreadsheetDataValidationErrorStyle): SpreadsheetDataValidationInteraction;
|
|
15
|
+
export declare function spreadsheetDataValidationDialogTitle(item: Pick<WorkSpreadsheetDataValidationItem, 'errorStyle' | 'errorTitle'>): string;
|
|
16
|
+
export declare function spreadsheetDataValidationDialogDescription(failureText: string, value: unknown, item?: SpreadsheetDataValidationMessageSource): string;
|
|
17
|
+
export declare function spreadsheetDataValidationConfirmLabels(style: WorkSpreadsheetDataValidationErrorStyle): {
|
|
18
|
+
cancelLabel: string;
|
|
19
|
+
confirmLabel: string;
|
|
20
|
+
};
|
|
21
|
+
export declare function spreadsheetDataValidationValueText(value: unknown): string;
|
|
22
|
+
export declare function cloneSpreadsheetDataValidationItem(item: WorkSpreadsheetDataValidationItem): WorkSpreadsheetDataValidationItem;
|
|
23
|
+
export {};
|
package/dist/office-kernel.wasm
CHANGED
|
Binary file
|