@a3s-lab/office 0.34.0 → 0.35.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 -18
- package/dist/0~presentation-editor.js +19 -5
- package/dist/0~spreadsheet-editor.js +166 -18
- package/dist/internal/features/work/editors/presentation-editor-focus.d.ts +2 -0
- package/dist/internal/features/work/editors/presentation-text-editor.d.ts +7 -0
- package/dist/internal/features/work/editors/spreadsheet-command-controller.d.ts +10 -0
- package/dist/internal/features/work/editors/spreadsheet-command-selection.d.ts +22 -1
- package/dist/internal/features/work/editors/use-presentation-selection.d.ts +1 -1
- package/dist/office-kernel.wasm +0 -0
- package/package.json +16 -13
package/README.md
CHANGED
|
@@ -13,13 +13,13 @@
|
|
|
13
13
|
|
|
14
14
|
<p align="center">
|
|
15
15
|
<a href="https://github.com/A3S-Lab/Office/actions/workflows/ci.yml"><img alt="CI status" src="https://img.shields.io/github/actions/workflow/status/A3S-Lab/Office/ci.yml?branch=main&style=flat-square&label=CI"></a>
|
|
16
|
-
<a href="https://a3s-lab.github.io/Office/"><img alt="Open the live Playground" src="https://img.shields.io/badge/Live_Playground-open-2f6fed?style=flat-square"></a>
|
|
16
|
+
<a href="https://a3s-lab.github.io/Office/playground/"><img alt="Open the live Playground" src="https://img.shields.io/badge/Live_Playground-open-2f6fed?style=flat-square"></a>
|
|
17
17
|
<a href="#project-status"><img alt="Project status: pre-1.0" src="https://img.shields.io/badge/status-pre--1.0-7a5bd6?style=flat-square"></a>
|
|
18
18
|
<a href="LICENSE"><img alt="MIT License" src="https://img.shields.io/badge/license-MIT-159469?style=flat-square"></a>
|
|
19
19
|
</p>
|
|
20
20
|
|
|
21
21
|
<p align="center">
|
|
22
|
-
<a href="https://a3s-lab.github.io/Office/">Playground</a> ·
|
|
22
|
+
<a href="https://a3s-lab.github.io/Office/playground/">Playground</a> ·
|
|
23
23
|
<a href="https://a3s-lab.github.io/Office/docs/">Documentation</a> ·
|
|
24
24
|
<a href="#quick-start">Quick start</a> ·
|
|
25
25
|
<a href="#editor-capability-comparison">Editors</a> ·
|
|
@@ -56,7 +56,7 @@ workflows, and a separate Rust automation plane.
|
|
|
56
56
|
|
|
57
57
|
## Latest on `main`
|
|
58
58
|
|
|
59
|
-
The `0.
|
|
59
|
+
The `0.35.0` release plus the current `main` branch expose these capabilities
|
|
60
60
|
as normal user-facing Playground templates, with matching implementation
|
|
61
61
|
detail in the documentation:
|
|
62
62
|
|
|
@@ -71,16 +71,17 @@ detail in the documentation:
|
|
|
71
71
|
| Spreadsheet | Complete common Data Validation input, blank/dropdown, and Stop/Warning/Information error settings with native XLSX round trips | Playground **Latest capabilities → 数据验证** · [Spreadsheet reference](docs/latest/en/components/spreadsheet.mdx#data-validation) |
|
|
72
72
|
| PDF | Insert, delete, rotate, reorder, extract, merge, and split pages through a dedicated Web Worker, with Blob-level Undo/Redo and independent binary reopen verification | Playground **Latest capabilities → 组织 PDF 页面** · [PDF reference](docs/latest/en/components/pdf.mdx#page-organization) |
|
|
73
73
|
|
|
74
|
-
All eight entries are reachable from the first Playground viewport. The
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
74
|
+
All eight entries are reachable from the first Playground viewport. The
|
|
75
|
+
filterable capability gallery groups releases by editor, publishes the source
|
|
76
|
+
release on every card, and grows from one shared metadata list instead of a
|
|
77
|
+
fixed-width strip. The seven content templates also remain under **新建**;
|
|
78
|
+
**组织 PDF 页面** opens the normal PDF file workflow because page organization
|
|
79
|
+
must operate on host-provided source bytes.
|
|
79
80
|
|
|
80
81
|
## See it working
|
|
81
82
|
|
|
82
83
|
The images below are committed visual-regression baselines from the real
|
|
83
|
-
[Playground](https://a3s-lab.github.io/Office/), not conceptual mockups.
|
|
84
|
+
[Playground](https://a3s-lab.github.io/Office/playground/), not conceptual mockups.
|
|
84
85
|
|
|
85
86
|
<p align="center">
|
|
86
87
|
<a href="visual-tests/__snapshots__/linux/desktop-1280/document.png">
|
|
@@ -364,7 +365,7 @@ bun run playground
|
|
|
364
365
|
```
|
|
365
366
|
|
|
366
367
|
Then open the local URL printed by the development server. For a zero-install
|
|
367
|
-
tour, use the [live Playground](https://a3s-lab.github.io/Office/).
|
|
368
|
+
tour, use the [live Playground](https://a3s-lab.github.io/Office/playground/).
|
|
368
369
|
Choose **体验格式修订**, open **审阅**, then **查看修订(2)** to inspect the
|
|
369
370
|
independent Formatting and Paragraph Formatting cards and exercise accept or
|
|
370
371
|
reject semantics.
|
|
@@ -1613,15 +1614,16 @@ committed visual contracts; see [CONTRIBUTING.md](CONTRIBUTING.md).
|
|
|
1613
1614
|
|
|
1614
1615
|
## Documentation
|
|
1615
1616
|
|
|
1616
|
-
The published website
|
|
1617
|
-
|
|
1618
|
-
|
|
1619
|
-
|
|
1620
|
-
|
|
1621
|
-
|
|
1622
|
-
|
|
1617
|
+
The published website follows the A3S UI documentation model: the searchable
|
|
1618
|
+
Rspress documentation center owns the website root, while Playground is a
|
|
1619
|
+
primary top-navigation route under `/playground/`. Simplified Chinese is the
|
|
1620
|
+
stable default, English remains available from the language menu, and the
|
|
1621
|
+
version menu switches between `latest` and frozen release documentation.
|
|
1622
|
+
Search is scoped to the active language and version. Both surfaces derive
|
|
1623
|
+
their paths from one deployment base, so preview, Pages, and fork deployments
|
|
1624
|
+
keep working without hard-coded return URLs.
|
|
1623
1625
|
|
|
1624
|
-
- [Live Playground](https://a3s-lab.github.io/Office/)
|
|
1626
|
+
- [Live Playground](https://a3s-lab.github.io/Office/playground/)
|
|
1625
1627
|
- [Documentation center](https://a3s-lab.github.io/Office/docs/)
|
|
1626
1628
|
- [A3S Office 0.34.0 documentation](https://a3s-lab.github.io/Office/docs/0.34.0/)
|
|
1627
1629
|
- [A3S Office 0.33.0 documentation](https://a3s-lab.github.io/Office/docs/0.33.0/)
|
|
@@ -2425,6 +2425,9 @@ function PlaceholderButtons({ onAdd }) {
|
|
|
2425
2425
|
});
|
|
2426
2426
|
}
|
|
2427
2427
|
const PRESENTATION_WORKSPACE_FOCUS_RETRY_FRAMES = 6;
|
|
2428
|
+
function presentationInitialEditingElementId(elements) {
|
|
2429
|
+
return elements.find((element)=>element.placeholder?.type === 'title' && presentationElementCanEditContent(element) && !element.text.trim() && !element.textRuns?.some((run)=>run.text.trim()))?.id ?? null;
|
|
2430
|
+
}
|
|
2428
2431
|
function restorePresentationWorkspaceFocus(root, getState, focusOrigin = document.activeElement) {
|
|
2429
2432
|
if (!root) return;
|
|
2430
2433
|
const commandTrigger = focusOrigin;
|
|
@@ -4356,6 +4359,7 @@ function PresentationTextEditor({ autoFocus = false, element, onChange, onEditor
|
|
|
4356
4359
|
const onSelectionChangeRef = useRef(onSelectionChange);
|
|
4357
4360
|
const appliedSignatureRef = useRef(presentationTextElementSignature(element));
|
|
4358
4361
|
const initialContentRef = useRef(presentationTextElementHtml(element));
|
|
4362
|
+
const initialFocusTargetRef = useRef("u" > typeof document && document.activeElement instanceof HTMLElement ? document.activeElement : null);
|
|
4359
4363
|
elementRef.current = element;
|
|
4360
4364
|
onChangeRef.current = onChange;
|
|
4361
4365
|
onEditorChangeRef.current = onEditorChange;
|
|
@@ -4410,7 +4414,8 @@ function PresentationTextEditor({ autoFocus = false, element, onChange, onEditor
|
|
|
4410
4414
|
useEffect(()=>{
|
|
4411
4415
|
if (!autoFocus || !editor || editor.isDestroyed) return;
|
|
4412
4416
|
const frame = window.requestAnimationFrame(()=>{
|
|
4413
|
-
if (
|
|
4417
|
+
if (editor.isDestroyed || !presentationFocusOwnerIsUnchanged(initialFocusTargetRef.current)) return;
|
|
4418
|
+
editor.commands.focus('end');
|
|
4414
4419
|
});
|
|
4415
4420
|
return ()=>window.cancelAnimationFrame(frame);
|
|
4416
4421
|
}, [
|
|
@@ -4438,6 +4443,12 @@ function PresentationTextEditor({ autoFocus = false, element, onChange, onEditor
|
|
|
4438
4443
|
style: presentationTextBaseStyle(element)
|
|
4439
4444
|
});
|
|
4440
4445
|
}
|
|
4446
|
+
function presentationFocusOwnerIsUnchanged(initialFocusTarget) {
|
|
4447
|
+
if ("u" < typeof document) return true;
|
|
4448
|
+
const currentFocusTarget = document.activeElement;
|
|
4449
|
+
if (!currentFocusTarget || currentFocusTarget === document.body) return true;
|
|
4450
|
+
return !initialFocusTarget || currentFocusTarget === initialFocusTarget;
|
|
4451
|
+
}
|
|
4441
4452
|
function createPresentationTextEditorExtensions(placeholder = '输入文字') {
|
|
4442
4453
|
return [
|
|
4443
4454
|
starter_kit.configure({
|
|
@@ -7881,9 +7892,12 @@ function usePresentationReviewCommands({ content, onChange, onClearSelection, on
|
|
|
7881
7892
|
function activePresentationReviewInvoker() {
|
|
7882
7893
|
return "u" > typeof document && document.activeElement instanceof HTMLElement ? document.activeElement : null;
|
|
7883
7894
|
}
|
|
7884
|
-
function usePresentationSelection(elements) {
|
|
7885
|
-
const
|
|
7886
|
-
const [
|
|
7895
|
+
function usePresentationSelection(elements, initialEditingElementId = null) {
|
|
7896
|
+
const initialEditingElementExists = Boolean(initialEditingElementId && elements.some((element)=>element.id === initialEditingElementId));
|
|
7897
|
+
const [selectedElementIds, setSelectedElementIds] = useState(()=>initialEditingElementExists && initialEditingElementId ? selectionWithPendingIds(elements, [
|
|
7898
|
+
initialEditingElementId
|
|
7899
|
+
]) : []);
|
|
7900
|
+
const [editingElementId, setEditingElementId] = useState(()=>initialEditingElementExists ? initialEditingElementId : null);
|
|
7887
7901
|
const clear = useCallback(()=>{
|
|
7888
7902
|
setSelectedElementIds([]);
|
|
7889
7903
|
setEditingElementId(null);
|
|
@@ -8482,7 +8496,7 @@ function PresentationEditingSurface({ initialSlide, autoFocus = true, collaborat
|
|
|
8482
8496
|
const selectedLayout = designContent.layouts?.find((layout)=>layout.id === selectedSlide?.layoutId) ?? designContent.layouts?.[0];
|
|
8483
8497
|
const selectedMaster = designContent.masters?.find((master)=>master.id === selectedLayout?.masterId) ?? designContent.masters?.[0];
|
|
8484
8498
|
const activeElements = 'layout' === designMode ? selectedLayout?.elements ?? [] : 'master' === designMode ? selectedMaster?.elements ?? [] : selectedSlide?.elements ?? [];
|
|
8485
|
-
const selection = usePresentationSelection(activeElements);
|
|
8499
|
+
const selection = usePresentationSelection(activeElements, autoFocus ? presentationInitialEditingElementId(activeElements) : null);
|
|
8486
8500
|
const presentationPresenceLocation = useMemo(()=>({
|
|
8487
8501
|
kind: 'presentation',
|
|
8488
8502
|
slideId: selectedSlide.id,
|
|
@@ -5315,6 +5315,70 @@ function spreadsheetCellFillRangeIsSafe(range) {
|
|
|
5315
5315
|
function sameSpreadsheetCellRange(left, right) {
|
|
5316
5316
|
return left.row[0] === right.row[0] && left.row[1] === right.row[1] && left.column[0] === right.column[0] && left.column[1] === right.column[1];
|
|
5317
5317
|
}
|
|
5318
|
+
function canEditSpreadsheetSelection(context) {
|
|
5319
|
+
return Boolean(context.editable && context.workbook && context.targetSheetId);
|
|
5320
|
+
}
|
|
5321
|
+
function spreadsheetLiveCommandRange(context) {
|
|
5322
|
+
const selection = spreadsheetLiveCommandSelection(context);
|
|
5323
|
+
return spreadsheetSingleRange(selection ?? context.fallbackRange);
|
|
5324
|
+
}
|
|
5325
|
+
function spreadsheetLiveCommandSelection(context) {
|
|
5326
|
+
return spreadsheetLiveCommandSelections(context)?.at(-1);
|
|
5327
|
+
}
|
|
5328
|
+
function spreadsheetLiveCommandSelections(context) {
|
|
5329
|
+
const shadow = context.selectionRef?.current;
|
|
5330
|
+
if (shadow?.sheetId === context.targetSheetId) return [
|
|
5331
|
+
shadow.selection
|
|
5332
|
+
];
|
|
5333
|
+
return context.workbook?.getSelection();
|
|
5334
|
+
}
|
|
5335
|
+
function acceptSpreadsheetSelectionChange(selectionRef, sheetId, selection) {
|
|
5336
|
+
const nextSelection = finiteSpreadsheetSelection(selection);
|
|
5337
|
+
const requested = selectionRef.requested;
|
|
5338
|
+
if (requested && (requested.sheetId !== sheetId || !sameSpreadsheetSelectionValue(requested.selection, nextSelection))) return null;
|
|
5339
|
+
const next = {
|
|
5340
|
+
sheetId,
|
|
5341
|
+
selection: nextSelection
|
|
5342
|
+
};
|
|
5343
|
+
selectionRef.current = next;
|
|
5344
|
+
return next;
|
|
5345
|
+
}
|
|
5346
|
+
function rememberSpreadsheetCommandSelection(context, selection) {
|
|
5347
|
+
if (!context.selectionRef || !context.targetSheetId) return;
|
|
5348
|
+
const next = {
|
|
5349
|
+
...selection,
|
|
5350
|
+
row: [
|
|
5351
|
+
...selection.row
|
|
5352
|
+
],
|
|
5353
|
+
column: [
|
|
5354
|
+
...selection.column
|
|
5355
|
+
]
|
|
5356
|
+
};
|
|
5357
|
+
context.selectionRef.current = {
|
|
5358
|
+
sheetId: context.targetSheetId,
|
|
5359
|
+
selection: next
|
|
5360
|
+
};
|
|
5361
|
+
context.selectionRef.requested = {
|
|
5362
|
+
sheetId: context.targetSheetId,
|
|
5363
|
+
selection: {
|
|
5364
|
+
...next,
|
|
5365
|
+
row: [
|
|
5366
|
+
...next.row
|
|
5367
|
+
],
|
|
5368
|
+
column: [
|
|
5369
|
+
...next.column
|
|
5370
|
+
]
|
|
5371
|
+
}
|
|
5372
|
+
};
|
|
5373
|
+
}
|
|
5374
|
+
function releaseSpreadsheetSelectionRequest(selectionRef) {
|
|
5375
|
+
selectionRef.requested = null;
|
|
5376
|
+
}
|
|
5377
|
+
function sameSpreadsheetSelectionValue(left, right) {
|
|
5378
|
+
const normalizedLeft = finiteSpreadsheetSelection(left);
|
|
5379
|
+
const normalizedRight = finiteSpreadsheetSelection(right);
|
|
5380
|
+
return normalizedLeft.row[0] === normalizedRight.row[0] && normalizedLeft.row[1] === normalizedRight.row[1] && normalizedLeft.column[0] === normalizedRight.column[0] && normalizedLeft.column[1] === normalizedRight.column[1] && normalizedLeft.row_focus === normalizedRight.row_focus && normalizedLeft.column_focus === normalizedRight.column_focus;
|
|
5381
|
+
}
|
|
5318
5382
|
function createSpreadsheetCellFillExtension() {
|
|
5319
5383
|
return createOfficeEditorExtension({
|
|
5320
5384
|
name: 'spreadsheetCellFill',
|
|
@@ -5365,9 +5429,11 @@ function materializeSpreadsheetCellFillRows(sheet, plan) {
|
|
|
5365
5429
|
}
|
|
5366
5430
|
function spreadsheetSelectedCellFillPlan(context, direction) {
|
|
5367
5431
|
if (!context.editable || !context.workbook || !context.targetSheetId || context.targetSheetId !== context.activeSheetId) return null;
|
|
5368
|
-
const selections = context
|
|
5432
|
+
const selections = spreadsheetLiveCommandSelections(context);
|
|
5369
5433
|
if (selections?.length !== 1) return null;
|
|
5370
|
-
const
|
|
5434
|
+
const selection = selections[0];
|
|
5435
|
+
if (!selection) return null;
|
|
5436
|
+
const plan = planSpreadsheetCellFill(selection, direction);
|
|
5371
5437
|
if (!plan) return null;
|
|
5372
5438
|
const sheet = context.content.sheets.find((candidate)=>candidate.id === context.targetSheetId);
|
|
5373
5439
|
return canApplySpreadsheetCellFill(sheet, plan) ? plan : null;
|
|
@@ -6323,13 +6389,6 @@ function applySelectedCellStyle(context, preset) {
|
|
|
6323
6389
|
function liveSpreadsheetCellStyleRange(context) {
|
|
6324
6390
|
return spreadsheetSingleRange(context.workbook?.getSelection()?.at(-1) ?? context.fallbackRange);
|
|
6325
6391
|
}
|
|
6326
|
-
function canEditSpreadsheetSelection(context) {
|
|
6327
|
-
return Boolean(context.editable && context.workbook && context.targetSheetId);
|
|
6328
|
-
}
|
|
6329
|
-
function spreadsheetLiveCommandRange(context) {
|
|
6330
|
-
const selection = context.workbook?.getSelection()?.at(-1);
|
|
6331
|
-
return spreadsheetSingleRange(selection ?? context.fallbackRange);
|
|
6332
|
-
}
|
|
6333
6392
|
const MAX_SPREADSHEET_ROWS = 1048576;
|
|
6334
6393
|
const spreadsheetPasteContentOptions = [
|
|
6335
6394
|
{
|
|
@@ -8493,7 +8552,7 @@ function updateSpreadsheetSelection(context, storage, update) {
|
|
|
8493
8552
|
if (!context.workbook || !context.targetSheetId) return false;
|
|
8494
8553
|
const sheet = context.content.sheets.find((candidate)=>candidate.id === context.targetSheetId);
|
|
8495
8554
|
if (!sheet) return false;
|
|
8496
|
-
const liveSelection = context
|
|
8555
|
+
const liveSelection = spreadsheetLiveCommandSelection(context) ?? context.fallbackRange;
|
|
8497
8556
|
const rememberedFocus = storage.focus;
|
|
8498
8557
|
const selection = rememberedFocus && spreadsheetSelectionContainsFocus(liveSelection, rememberedFocus) ? {
|
|
8499
8558
|
...liveSelection,
|
|
@@ -8507,6 +8566,7 @@ function updateSpreadsheetSelection(context, storage, update) {
|
|
|
8507
8566
|
], {
|
|
8508
8567
|
id: context.targetSheetId
|
|
8509
8568
|
});
|
|
8569
|
+
rememberSpreadsheetCommandSelection(context, next);
|
|
8510
8570
|
storage.focus = {
|
|
8511
8571
|
row: next.row_focus ?? next.row[1] ?? next.row[0] ?? 0,
|
|
8512
8572
|
column: next.column_focus ?? next.column[1] ?? next.column[0] ?? 0
|
|
@@ -10010,6 +10070,16 @@ function pasteCells(context, values) {
|
|
|
10010
10070
|
], {
|
|
10011
10071
|
id: context.targetSheetId
|
|
10012
10072
|
});
|
|
10073
|
+
rememberSpreadsheetCommandSelection(context, {
|
|
10074
|
+
row: [
|
|
10075
|
+
...range.row
|
|
10076
|
+
],
|
|
10077
|
+
column: [
|
|
10078
|
+
...range.column
|
|
10079
|
+
],
|
|
10080
|
+
row_focus: range.row[0],
|
|
10081
|
+
column_focus: range.column[0]
|
|
10082
|
+
});
|
|
10013
10083
|
} catch {}
|
|
10014
10084
|
syncSpreadsheetFormulaBar(context, data[0][0]);
|
|
10015
10085
|
return true;
|
|
@@ -25395,6 +25465,60 @@ function SpreadsheetEditorSurface({ autoFocus = true, content, collaborationHist
|
|
|
25395
25465
|
const editorFocusOrigin = useOfficeEditorFocusOrigin();
|
|
25396
25466
|
const workbookRef = useRef(null);
|
|
25397
25467
|
const projectedWorkbookSheetsRef = useRef([]);
|
|
25468
|
+
useLayoutEffect(()=>{
|
|
25469
|
+
const container = spreadsheetCanvasRef.current;
|
|
25470
|
+
if (!container || preview) return;
|
|
25471
|
+
let pendingEditor = null;
|
|
25472
|
+
let pointerEnteredEditor = false;
|
|
25473
|
+
const moveEditorCaretToEnd = (editor)=>{
|
|
25474
|
+
if (document.activeElement !== editor || !editor.isConnected || !editor.textContent) return false;
|
|
25475
|
+
const selection = document.getSelection();
|
|
25476
|
+
if (!selection) return false;
|
|
25477
|
+
const range = document.createRange();
|
|
25478
|
+
range.selectNodeContents(editor);
|
|
25479
|
+
range.collapse(false);
|
|
25480
|
+
selection.removeAllRanges();
|
|
25481
|
+
selection.addRange(range);
|
|
25482
|
+
return true;
|
|
25483
|
+
};
|
|
25484
|
+
const handlePointerDown = (event)=>{
|
|
25485
|
+
pointerEnteredEditor = event.target instanceof Element && Boolean(event.target.closest('.luckysheet-cell-input'));
|
|
25486
|
+
};
|
|
25487
|
+
const handleFocusIn = (event)=>{
|
|
25488
|
+
const target = event.target;
|
|
25489
|
+
const editor = target instanceof Element ? target.closest('.luckysheet-cell-input') : null;
|
|
25490
|
+
if (!editor || pointerEnteredEditor) {
|
|
25491
|
+
pendingEditor = null;
|
|
25492
|
+
pointerEnteredEditor = false;
|
|
25493
|
+
return;
|
|
25494
|
+
}
|
|
25495
|
+
pendingEditor = editor;
|
|
25496
|
+
queueMicrotask(()=>{
|
|
25497
|
+
if (pendingEditor === editor && moveEditorCaretToEnd(editor)) pendingEditor = null;
|
|
25498
|
+
});
|
|
25499
|
+
};
|
|
25500
|
+
const observer = new MutationObserver(()=>{
|
|
25501
|
+
const editor = pendingEditor;
|
|
25502
|
+
if (!editor || document.activeElement !== editor) return;
|
|
25503
|
+
if (!editor.textContent) return;
|
|
25504
|
+
moveEditorCaretToEnd(editor);
|
|
25505
|
+
pendingEditor = null;
|
|
25506
|
+
});
|
|
25507
|
+
container.addEventListener('pointerdown', handlePointerDown, true);
|
|
25508
|
+
container.addEventListener('focusin', handleFocusIn, true);
|
|
25509
|
+
observer.observe(container, {
|
|
25510
|
+
characterData: true,
|
|
25511
|
+
childList: true,
|
|
25512
|
+
subtree: true
|
|
25513
|
+
});
|
|
25514
|
+
return ()=>{
|
|
25515
|
+
container.removeEventListener('pointerdown', handlePointerDown, true);
|
|
25516
|
+
container.removeEventListener('focusin', handleFocusIn, true);
|
|
25517
|
+
observer.disconnect();
|
|
25518
|
+
};
|
|
25519
|
+
}, [
|
|
25520
|
+
preview
|
|
25521
|
+
]);
|
|
25398
25522
|
const spreadsheetZoomRef = useRef(100);
|
|
25399
25523
|
const [workbookInstance, setWorkbookInstance] = useState(null);
|
|
25400
25524
|
const bindWorkbookInstance = useCallback((instance)=>{
|
|
@@ -25413,6 +25537,10 @@ function SpreadsheetEditorSurface({ autoFocus = true, content, collaborationHist
|
|
|
25413
25537
|
const [panel, setPanel] = useState(null);
|
|
25414
25538
|
const panelTriggerRef = useRef(null);
|
|
25415
25539
|
const [selectionState, setSelectionState] = useState(null);
|
|
25540
|
+
const selectionStateRef = useRef({
|
|
25541
|
+
current: null,
|
|
25542
|
+
requested: null
|
|
25543
|
+
});
|
|
25416
25544
|
const formatPainterSelectionHandlerRef = useRef((_sheetId, _selection)=>void 0);
|
|
25417
25545
|
const [contextMenu, setContextMenu] = useState(null);
|
|
25418
25546
|
const [formatCellsDialog, setFormatCellsDialog] = useState(null);
|
|
@@ -25588,15 +25716,16 @@ function SpreadsheetEditorSurface({ autoFocus = true, content, collaborationHist
|
|
|
25588
25716
|
collaborationView?.activateSheet(id);
|
|
25589
25717
|
if (previewRef.current) setPreviewActiveSheetId(id);
|
|
25590
25718
|
else setNavigationActiveSheetId(id);
|
|
25719
|
+
selectionStateRef.current.current = null;
|
|
25720
|
+
releaseSpreadsheetSelectionRequest(selectionStateRef.current);
|
|
25591
25721
|
setSelectionState(null);
|
|
25592
25722
|
},
|
|
25593
25723
|
afterSelectionChange: (sheetId, selection)=>{
|
|
25594
|
-
|
|
25595
|
-
|
|
25596
|
-
|
|
25597
|
-
|
|
25598
|
-
|
|
25599
|
-
formatPainterSelectionHandlerRef.current(sheetId, selection);
|
|
25724
|
+
const next = acceptSpreadsheetSelectionChange(selectionStateRef.current, sheetId, selection);
|
|
25725
|
+
if (!next) return;
|
|
25726
|
+
collaborationView?.select(sheetId, next.selection);
|
|
25727
|
+
setSelectionState(next);
|
|
25728
|
+
formatPainterSelectionHandlerRef.current(sheetId, next.selection);
|
|
25600
25729
|
},
|
|
25601
25730
|
beforeUpdateCell: (row, column)=>{
|
|
25602
25731
|
const sheet = contentRef.current.sheets.find((candidate)=>candidate.id === activeSheetIdRef.current);
|
|
@@ -25876,6 +26005,8 @@ function SpreadsheetEditorSurface({ autoFocus = true, content, collaborationHist
|
|
|
25876
26005
|
if (!sheet) return false;
|
|
25877
26006
|
activeSheetIdRef.current = sheetId;
|
|
25878
26007
|
if (collaborationView && !collaborationView.activateSheet(sheetId)) return false;
|
|
26008
|
+
selectionStateRef.current.current = null;
|
|
26009
|
+
releaseSpreadsheetSelectionRequest(selectionStateRef.current);
|
|
25879
26010
|
setSelectionState(null);
|
|
25880
26011
|
if (previewRef.current) setPreviewActiveSheetId(sheetId);
|
|
25881
26012
|
try {
|
|
@@ -25910,7 +26041,7 @@ function SpreadsheetEditorSurface({ autoFocus = true, content, collaborationHist
|
|
|
25910
26041
|
targetRow: activeCell.row,
|
|
25911
26042
|
targetColumn: activeCell.column
|
|
25912
26043
|
});
|
|
25913
|
-
|
|
26044
|
+
const nextSelection = {
|
|
25914
26045
|
sheetId,
|
|
25915
26046
|
selection: {
|
|
25916
26047
|
row: [
|
|
@@ -25922,7 +26053,21 @@ function SpreadsheetEditorSurface({ autoFocus = true, content, collaborationHist
|
|
|
25922
26053
|
row_focus: activeCell.row,
|
|
25923
26054
|
column_focus: activeCell.column
|
|
25924
26055
|
}
|
|
25925
|
-
}
|
|
26056
|
+
};
|
|
26057
|
+
selectionStateRef.current.current = nextSelection;
|
|
26058
|
+
selectionStateRef.current.requested = {
|
|
26059
|
+
sheetId,
|
|
26060
|
+
selection: {
|
|
26061
|
+
...nextSelection.selection,
|
|
26062
|
+
row: [
|
|
26063
|
+
...nextSelection.selection.row
|
|
26064
|
+
],
|
|
26065
|
+
column: [
|
|
26066
|
+
...nextSelection.selection.column
|
|
26067
|
+
]
|
|
26068
|
+
}
|
|
26069
|
+
};
|
|
26070
|
+
setSelectionState(nextSelection);
|
|
25926
26071
|
} catch {
|
|
25927
26072
|
return false;
|
|
25928
26073
|
}
|
|
@@ -26043,6 +26188,7 @@ function SpreadsheetEditorSurface({ autoFocus = true, content, collaborationHist
|
|
|
26043
26188
|
toggle: (attribute)=>richTextSelectionRef.current?.toggle(contentRef.current, acceptSpreadsheetCommandChange, attribute) ?? false
|
|
26044
26189
|
},
|
|
26045
26190
|
selection: selectionState,
|
|
26191
|
+
selectionRef: selectionStateRef.current,
|
|
26046
26192
|
table: spreadsheetTable.commandPort,
|
|
26047
26193
|
targetSheetGridSize,
|
|
26048
26194
|
targetSheetId: toolbarSheetId,
|
|
@@ -26150,6 +26296,7 @@ function SpreadsheetEditorSurface({ autoFocus = true, content, collaborationHist
|
|
|
26150
26296
|
if ('Escape' === event.key && isSpreadsheetCellEditingTarget(event.target)) requestAnimationFrame(()=>focusSpreadsheetGrid(spreadsheetCanvasRef.current));
|
|
26151
26297
|
};
|
|
26152
26298
|
const handleSpreadsheetKeyDownCapture = (event)=>{
|
|
26299
|
+
releaseSpreadsheetSelectionRequest(selectionStateRef.current);
|
|
26153
26300
|
if ('Alt' === event.key && !event.repeat && event.target instanceof Element && event.target.closest('.fortune-sheet-overlay') && reserveAutoFilterAltKey()) {
|
|
26154
26301
|
event.preventDefault();
|
|
26155
26302
|
event.stopPropagation();
|
|
@@ -26158,6 +26305,7 @@ function SpreadsheetEditorSurface({ autoFocus = true, content, collaborationHist
|
|
|
26158
26305
|
handleSpreadsheetEditingEscape(event);
|
|
26159
26306
|
};
|
|
26160
26307
|
const handleSpreadsheetPointerDownCapture = (event)=>{
|
|
26308
|
+
releaseSpreadsheetSelectionRequest(selectionStateRef.current);
|
|
26161
26309
|
const controller = richTextSelectionRef.current;
|
|
26162
26310
|
if (!controller) return;
|
|
26163
26311
|
if (!isSpreadsheetRichTextFormatPointerTarget(event.target)) return void controller.clear();
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { PresentationEditorCommands } from './presentation-command-types';
|
|
2
|
+
import type { WorkSlideElement } from '../work-types';
|
|
2
3
|
export interface PresentationObjectFocusState {
|
|
3
4
|
editingElementId: string | null;
|
|
4
5
|
selectedElementIds: readonly string[];
|
|
@@ -7,6 +8,7 @@ export interface PresentationWorkspaceFocusState extends PresentationObjectFocus
|
|
|
7
8
|
selectedSlideId: string;
|
|
8
9
|
viewMode: 'normal' | 'sorter';
|
|
9
10
|
}
|
|
11
|
+
export declare function presentationInitialEditingElementId(elements: readonly WorkSlideElement[]): string | null;
|
|
10
12
|
export declare function restorePresentationObjectFocus(container: HTMLElement | null, getState: () => PresentationObjectFocusState, focusOrigin?: Element | null): void;
|
|
11
13
|
export declare function restorePresentationWorkspaceFocus(root: HTMLElement | null, getState: () => PresentationWorkspaceFocusState, focusOrigin?: Element | null): void;
|
|
12
14
|
export declare function presentationWorkspaceFocusTarget(root: HTMLElement, state: PresentationWorkspaceFocusState): HTMLElement | undefined;
|
|
@@ -13,6 +13,13 @@ export interface PresentationTextEditorProps {
|
|
|
13
13
|
onSelectionChange?: () => void;
|
|
14
14
|
}
|
|
15
15
|
export declare function PresentationTextEditor({ autoFocus, element, onChange, onEditorChange, onExitEditing, onSelectionChange, }: PresentationTextEditorProps): import("react").JSX.Element | null;
|
|
16
|
+
/**
|
|
17
|
+
* Keep delayed first-open focus from overriding a deliberate focus move that
|
|
18
|
+
* happened while the rich-text editor was being created. The document body is
|
|
19
|
+
* treated as an unfocused baseline so opening from a non-focusable surface can
|
|
20
|
+
* still enter the editor normally.
|
|
21
|
+
*/
|
|
22
|
+
export declare function presentationFocusOwnerIsUnchanged(initialFocusTarget: HTMLElement | null): boolean;
|
|
16
23
|
export declare function createPresentationTextEditorExtensions(placeholder?: string): Extensions;
|
|
17
24
|
export declare function presentationTextElementHtml(element: WorkSlideElement): string;
|
|
18
25
|
export declare function presentationTextValue(editor: Editor, element: WorkSlideElement): PresentationTextValue;
|
|
@@ -67,6 +67,15 @@ export interface SpreadsheetCommandSelection {
|
|
|
67
67
|
sheetId: string;
|
|
68
68
|
selection: Selection;
|
|
69
69
|
}
|
|
70
|
+
/**
|
|
71
|
+
* Synchronous selection state shared by commands and the Fortune Sheet bridge.
|
|
72
|
+
* Fortune applies API calls through React state, so reading its imperative API
|
|
73
|
+
* twice in the same task can otherwise return the previous selection.
|
|
74
|
+
*/
|
|
75
|
+
export interface SpreadsheetSelectionRef {
|
|
76
|
+
current: SpreadsheetCommandSelection | null;
|
|
77
|
+
requested: SpreadsheetCommandSelection | null;
|
|
78
|
+
}
|
|
70
79
|
export type SpreadsheetStructureAxis = 'row' | 'column';
|
|
71
80
|
export type SpreadsheetStructureInsertPosition = 'before' | 'after';
|
|
72
81
|
export type SpreadsheetSortDirection = 'ascending' | 'descending';
|
|
@@ -238,6 +247,7 @@ export interface SpreadsheetCommandContext {
|
|
|
238
247
|
onChange: (content: WorkSpreadsheetContent) => void;
|
|
239
248
|
richTextFormat?: SpreadsheetRichTextFormatCommandPort | null;
|
|
240
249
|
selection: SpreadsheetCommandSelection | null;
|
|
250
|
+
selectionRef?: SpreadsheetSelectionRef;
|
|
241
251
|
table: SpreadsheetTableCommandPort;
|
|
242
252
|
targetSheetGridSize?: SpreadsheetGridSize | null;
|
|
243
253
|
targetSheetId: string;
|
|
@@ -1,3 +1,24 @@
|
|
|
1
|
-
import type { SpreadsheetCommandContext, SpreadsheetCommandRange } from './spreadsheet-command-controller';
|
|
1
|
+
import type { SpreadsheetCommandContext, SpreadsheetCommandSelection, SpreadsheetCommandRange, SpreadsheetSelectionRef } from './spreadsheet-command-controller';
|
|
2
2
|
export declare function canEditSpreadsheetSelection(context: SpreadsheetCommandContext): boolean;
|
|
3
3
|
export declare function spreadsheetLiveCommandRange(context: SpreadsheetCommandContext): SpreadsheetCommandRange;
|
|
4
|
+
/**
|
|
5
|
+
* Returns the most recent selection known to the Office bridge. The ref is
|
|
6
|
+
* intentionally checked before Fortune's imperative API because that API is
|
|
7
|
+
* backed by React state and can lag behind a just-issued keyboard command.
|
|
8
|
+
*/
|
|
9
|
+
export declare function spreadsheetLiveCommandSelection(context: SpreadsheetCommandContext): SpreadsheetCommandRange | undefined;
|
|
10
|
+
/**
|
|
11
|
+
* Returns all current selections while preserving the workbook's multi-range
|
|
12
|
+
* semantics. A synchronous command selection is represented as one range.
|
|
13
|
+
*/
|
|
14
|
+
export declare function spreadsheetLiveCommandSelections(context: SpreadsheetCommandContext): SpreadsheetCommandRange[] | undefined;
|
|
15
|
+
/**
|
|
16
|
+
* Accept a Fortune selection callback unless it is older than a pending
|
|
17
|
+
* programmatic selection request. The returned value is the normalized state
|
|
18
|
+
* that should be published to React and collaboration consumers.
|
|
19
|
+
*/
|
|
20
|
+
export declare function acceptSpreadsheetSelectionChange(selectionRef: SpreadsheetSelectionRef, sheetId: string, selection: SpreadsheetCommandRange): SpreadsheetCommandSelection | null;
|
|
21
|
+
export declare function rememberSpreadsheetCommandSelection(context: SpreadsheetCommandContext, selection: SpreadsheetCommandRange): void;
|
|
22
|
+
/** Clear a pending programmatic request when a fresh user intent arrives. */
|
|
23
|
+
export declare function releaseSpreadsheetSelectionRequest(selectionRef: SpreadsheetSelectionRef): void;
|
|
24
|
+
export declare function sameSpreadsheetSelectionValue(left: SpreadsheetCommandRange, right: SpreadsheetCommandRange): boolean;
|
|
@@ -8,4 +8,4 @@ export interface PresentationSelectionController {
|
|
|
8
8
|
select: (elementId: string | null, additive?: boolean) => void;
|
|
9
9
|
selectedElementIds: string[];
|
|
10
10
|
}
|
|
11
|
-
export declare function usePresentationSelection(elements: readonly WorkSlideElement[]): PresentationSelectionController;
|
|
11
|
+
export declare function usePresentationSelection(elements: readonly WorkSlideElement[], initialEditingElementId?: string | null): PresentationSelectionController;
|
package/dist/office-kernel.wasm
CHANGED
|
Binary file
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@a3s-lab/office",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.35.0",
|
|
4
4
|
"description": "Open-source collaborative browser editors for documents, Markdown, spreadsheets, presentations, and PDFs.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"office",
|
|
@@ -72,8 +72,8 @@
|
|
|
72
72
|
"build": "bun run kernel:build && rslib",
|
|
73
73
|
"collaboration-server:typecheck": "tsc --noEmit -p examples/collaboration-server/tsconfig.json",
|
|
74
74
|
"dev": "bun run kernel:build && rslib --watch",
|
|
75
|
-
"docs:build": "
|
|
76
|
-
"docs:dev": "rspress -c website/rspress.config.ts",
|
|
75
|
+
"docs:build": "bun scripts/build-docs.ts",
|
|
76
|
+
"docs:dev": "rspress -c website/rspress.docs.config.ts",
|
|
77
77
|
"format": "biome format --write .",
|
|
78
78
|
"format:check": "biome format .",
|
|
79
79
|
"lint": "biome lint .",
|
|
@@ -82,9 +82,9 @@
|
|
|
82
82
|
"kernel:test": "bun run kernel:build && bun scripts/smoke-office-kernel.ts",
|
|
83
83
|
"playground": "bun run playground:assets && rsbuild dev --config playground/rsbuild.config.ts",
|
|
84
84
|
"playground:assets": "bun run build && bash scripts/package-office-skill.sh",
|
|
85
|
-
"playground:build": "bun run playground:assets && rsbuild build --config playground/rsbuild.config.ts
|
|
85
|
+
"playground:build": "bun run playground:assets && bun run docs:build && rsbuild build --config playground/rsbuild.config.ts",
|
|
86
86
|
"playground:bundle-check": "bun scripts/check-playground-bundle.ts",
|
|
87
|
-
"playground:preview": "
|
|
87
|
+
"playground:preview": "rspress preview -c website/rspress.config.ts --host 127.0.0.1 --port 4175",
|
|
88
88
|
"playground:typecheck": "tsc --noEmit -p playground/tsconfig.json",
|
|
89
89
|
"playground:visual": "playwright test --config playwright.config.ts",
|
|
90
90
|
"playground:visual:document-emphasis": "playwright test visual-tests/document-emphasis.functional.spec.ts --config playwright.config.ts",
|
|
@@ -118,12 +118,12 @@
|
|
|
118
118
|
"playground:visual:pdf-page-organization": "playwright test visual-tests/pdf-page-organization.functional.spec.ts --config playwright.config.ts",
|
|
119
119
|
"playground:visual:update": "playwright test --config playwright.config.ts --update-snapshots",
|
|
120
120
|
"performance:fixtures": "bun .a3s-test/performance/generate-fixtures.ts",
|
|
121
|
-
"performance:large-document-edits": "bun .a3s-test/performance/generate-fixtures.ts --documents-only && bun .a3s-test/performance/benchmark-document-edit.ts http://127.0.0.1:4175/ 3",
|
|
122
|
-
"performance:large-documents": "bun .a3s-test/performance/generate-fixtures.ts --documents-only && bun .a3s-test/performance/benchmark.ts --url http://127.0.0.1:4175/ --scenarios document-text,document-table --runs 3 --timeout-ms 180000",
|
|
123
|
-
"performance:large-spreadsheet-edits": "bun .a3s-test/performance/generate-fixtures.ts --spreadsheets-only && bun .a3s-test/performance/benchmark-spreadsheet-edit.ts http://127.0.0.1:4175/ 3",
|
|
124
|
-
"performance:large-spreadsheets": "bun .a3s-test/performance/generate-fixtures.ts --spreadsheets-only && bun .a3s-test/performance/benchmark.ts --url http://127.0.0.1:4175/ --scenarios spreadsheet --runs 5 --timeout-ms 180000",
|
|
125
|
-
"performance:pdf": "bun .a3s-test/performance/generate-fixtures.ts --pdf-only && bun .a3s-test/performance/benchmark-pdf.ts --url http://127.0.0.1:4175/ --runs 3 --timeout-ms 120000",
|
|
126
|
-
"performance:presentation": "bun .a3s-test/performance/generate-fixtures.ts --presentations-only && bun .a3s-test/performance/benchmark-presentation.ts --url http://127.0.0.1:4175/ --runs 3 --timeout-ms 120000 --modes default,content-visibility",
|
|
121
|
+
"performance:large-document-edits": "bun .a3s-test/performance/generate-fixtures.ts --documents-only && bun .a3s-test/performance/benchmark-document-edit.ts http://127.0.0.1:4175/playground/ 3",
|
|
122
|
+
"performance:large-documents": "bun .a3s-test/performance/generate-fixtures.ts --documents-only && bun .a3s-test/performance/benchmark.ts --url http://127.0.0.1:4175/playground/ --scenarios document-text,document-table --runs 3 --timeout-ms 180000",
|
|
123
|
+
"performance:large-spreadsheet-edits": "bun .a3s-test/performance/generate-fixtures.ts --spreadsheets-only && bun .a3s-test/performance/benchmark-spreadsheet-edit.ts http://127.0.0.1:4175/playground/ 3",
|
|
124
|
+
"performance:large-spreadsheets": "bun .a3s-test/performance/generate-fixtures.ts --spreadsheets-only && bun .a3s-test/performance/benchmark.ts --url http://127.0.0.1:4175/playground/ --scenarios spreadsheet --runs 5 --timeout-ms 180000",
|
|
125
|
+
"performance:pdf": "bun .a3s-test/performance/generate-fixtures.ts --pdf-only && bun .a3s-test/performance/benchmark-pdf.ts --url http://127.0.0.1:4175/playground/ --runs 3 --timeout-ms 120000",
|
|
126
|
+
"performance:presentation": "bun .a3s-test/performance/generate-fixtures.ts --presentations-only && bun .a3s-test/performance/benchmark-presentation.ts --url http://127.0.0.1:4175/playground/ --runs 3 --timeout-ms 120000 --modes default,content-visibility",
|
|
127
127
|
"test": "rstest",
|
|
128
128
|
"test:e2e": "bun run test:e2e:fixtures && a3s-test run tests/e2e/word-page-color.acl --json && a3s-test run tests/e2e/word-page-setup-phone.acl --json && a3s-test run tests/e2e/word-paragraph-layout-phone.acl --json && a3s-test run tests/e2e/word-list-formatting-phone.acl --json && a3s-test run tests/e2e/word-font-picker-phone.acl --json && a3s-test run tests/e2e/word-comments-drawer.acl --json && a3s-test run tests/e2e/word-comment-windowing.acl --json && a3s-test run tests/e2e/word-citations-phone.acl --json && a3s-test run tests/e2e/word-navigation-search.acl --json && a3s-test run tests/e2e/word-navigation-windowing.acl --json && a3s-test run tests/e2e/word-find-replace-phone.acl --json && a3s-test run tests/e2e/word-page-navigation.acl --json && a3s-test run tests/e2e/word-page-windowing.acl --json && a3s-test run tests/e2e/word-ai-question.acl --json && a3s-test run tests/e2e/word-picture-insert.acl --json && a3s-test run tests/e2e/word-picture-alt-text-phone.acl --json && a3s-test run tests/e2e/word-track-changes-phone.acl --json && a3s-test run tests/e2e/word-formatting-revision.acl --json && a3s-test run tests/e2e/word-paragraph-formatting-revision.acl --json && a3s-test run tests/e2e/word-document-comparison.acl --json && a3s-test run tests/e2e/word-review-conflict-phone.acl --json && a3s-test run tests/e2e/word-revision-windowing.acl --json && a3s-test run tests/e2e/word-table-phone.acl --json && a3s-test run tests/e2e/word-table-borders.acl --json && a3s-test run tests/e2e/word-theme-table.acl --json && a3s-test run tests/e2e/word-styled-table.acl --json && a3s-test run tests/e2e/word-multi-page-table.acl --json && a3s-test run tests/e2e/word-cross-reference-phone.acl --json && a3s-test run tests/e2e/word-bookmark-links-phone.acl --json && a3s-test run tests/e2e/word-notes-phone.acl --json && a3s-test run tests/e2e/word-fields-phone.acl --json && a3s-test run tests/e2e/spreadsheet-phone-rename.acl --json && a3s-test run tests/e2e/spreadsheet-phone-find.acl --json && a3s-test run tests/e2e/spreadsheet-phone-context-menu.acl --json && a3s-test run tests/e2e/spreadsheet-phone-task-pane.acl --json && a3s-test run tests/e2e/spreadsheet-maximum-sparse.acl --json && a3s-test run tests/e2e/spreadsheet-cell-style.acl --json && a3s-test run tests/e2e/spreadsheet-paste-special.acl --json && a3s-test run tests/e2e/spreadsheet-hyperlink.acl --json && a3s-test run tests/e2e/presentation-cut-paste-focus.acl --json && a3s-test run tests/e2e/presentation-presenter-view.acl --json && a3s-test run tests/e2e/presentation-phone-chart-pane.acl --json && a3s-test run tests/e2e/presentation-phone-comments.acl --json && a3s-test run tests/e2e/pdf-thumbnail-keyboard.acl --json && a3s-test run tests/e2e/pdf-page-drawer-phone.acl --json && a3s-test run tests/e2e/markdown-phone-modes.acl --json && a3s-test run tests/e2e/office-sidebar-breakpoint.acl --json && a3s-test run tests/e2e/office-docs-navigation.acl --json && a3s-test run tests/e2e/collaboration-playground-entry.acl --json && a3s-test run tests/e2e/collaboration-document-comments.acl --command-timeout-ms 120000 --json && a3s-test run tests/e2e/collaboration-document-suggestions.acl --command-timeout-ms 120000 --json && a3s-test run tests/e2e/collaboration-participants.acl --json && a3s-test run tests/e2e/collaboration-pdf-annotations.acl --json && a3s-test run tests/e2e/collaboration-spreadsheet-cells.acl --json && a3s-test run tests/e2e/collaboration-presentation-elements.acl --json",
|
|
129
129
|
"test:e2e:check": "bun run test:e2e:fixtures && a3s-test check tests/e2e/word-page-color.acl --json && a3s-test check tests/e2e/word-page-setup-phone.acl --json && a3s-test check tests/e2e/word-paragraph-layout-phone.acl --json && a3s-test check tests/e2e/word-list-formatting-phone.acl --json && a3s-test check tests/e2e/word-font-picker-phone.acl --json && a3s-test check tests/e2e/word-comments-drawer.acl --json && a3s-test check tests/e2e/word-comment-windowing.acl --json && a3s-test check tests/e2e/word-citations-phone.acl --json && a3s-test check tests/e2e/word-navigation-search.acl --json && a3s-test check tests/e2e/word-navigation-windowing.acl --json && a3s-test check tests/e2e/word-find-replace-phone.acl --json && a3s-test check tests/e2e/word-page-navigation.acl --json && a3s-test check tests/e2e/word-page-windowing.acl --json && a3s-test check tests/e2e/word-ai-question.acl --json && a3s-test check tests/e2e/word-picture-insert.acl --json && a3s-test check tests/e2e/word-picture-alt-text-phone.acl --json && a3s-test check tests/e2e/word-track-changes-phone.acl --json && a3s-test check tests/e2e/word-formatting-revision.acl --json && a3s-test check tests/e2e/word-paragraph-formatting-revision.acl --json && a3s-test check tests/e2e/word-document-comparison.acl --json && a3s-test check tests/e2e/word-review-conflict-phone.acl --json && a3s-test check tests/e2e/word-revision-windowing.acl --json && a3s-test check tests/e2e/word-table-phone.acl --json && a3s-test check tests/e2e/word-table-borders.acl --json && a3s-test check tests/e2e/word-theme-table.acl --json && a3s-test check tests/e2e/word-styled-table.acl --json && a3s-test check tests/e2e/word-multi-page-table.acl --json && a3s-test check tests/e2e/word-cross-reference-phone.acl --json && a3s-test check tests/e2e/word-bookmark-links-phone.acl --json && a3s-test check tests/e2e/word-notes-phone.acl --json && a3s-test check tests/e2e/word-fields-phone.acl --json && a3s-test check tests/e2e/spreadsheet-phone-rename.acl --json && a3s-test check tests/e2e/spreadsheet-phone-find.acl --json && a3s-test check tests/e2e/spreadsheet-phone-context-menu.acl --json && a3s-test check tests/e2e/spreadsheet-phone-task-pane.acl --json && a3s-test check tests/e2e/spreadsheet-maximum-sparse.acl --json && a3s-test check tests/e2e/spreadsheet-cell-style.acl --json && a3s-test check tests/e2e/spreadsheet-paste-special.acl --json && a3s-test check tests/e2e/spreadsheet-hyperlink.acl --json && a3s-test check tests/e2e/presentation-cut-paste-focus.acl --json && a3s-test check tests/e2e/presentation-presenter-view.acl --json && a3s-test check tests/e2e/presentation-phone-chart-pane.acl --json && a3s-test check tests/e2e/presentation-phone-comments.acl --json && a3s-test check tests/e2e/pdf-thumbnail-keyboard.acl --json && a3s-test check tests/e2e/pdf-page-drawer-phone.acl --json && a3s-test check tests/e2e/markdown-phone-modes.acl --json && a3s-test check tests/e2e/office-sidebar-breakpoint.acl --json && a3s-test check tests/e2e/office-docs-navigation.acl --json && a3s-test check tests/e2e/collaboration-playground-entry.acl --json && a3s-test check tests/e2e/collaboration-document-comments.acl --json && a3s-test check tests/e2e/collaboration-document-suggestions.acl --json && a3s-test check tests/e2e/collaboration-participants.acl --json && a3s-test check tests/e2e/collaboration-pdf-annotations.acl --json && a3s-test check tests/e2e/collaboration-spreadsheet-cells.acl --json && a3s-test check tests/e2e/collaboration-presentation-elements.acl --json",
|
|
@@ -142,6 +142,8 @@
|
|
|
142
142
|
"test:e2e:initial-focus:check": "a3s-test check tests/e2e/office-editor-initial-focus.acl --json",
|
|
143
143
|
"test:e2e:docs": "a3s-test run tests/e2e/office-docs-navigation.acl --json",
|
|
144
144
|
"test:e2e:docs:check": "a3s-test check tests/e2e/office-docs-navigation.acl --json",
|
|
145
|
+
"test:e2e:homepage": "A3S_TEST_SUITE=tests/e2e/homepage-editor-demo.acl bash scripts/run-a3s-test-web-gate.sh",
|
|
146
|
+
"test:e2e:homepage:check": "a3s-test check tests/e2e/homepage-editor-demo.acl --json",
|
|
145
147
|
"test:e2e:latest-capabilities": "A3S_TEST_SUITE=tests/e2e/latest-capabilities-discoverability.acl bash scripts/run-a3s-test-web-gate.sh",
|
|
146
148
|
"test:e2e:latest-capabilities:check": "a3s-test check tests/e2e/latest-capabilities-discoverability.acl --json",
|
|
147
149
|
"test:e2e:collaboration-participants": "a3s-test run tests/e2e/collaboration-participants.acl --json",
|
|
@@ -307,15 +309,16 @@
|
|
|
307
309
|
}
|
|
308
310
|
},
|
|
309
311
|
"devDependencies": {
|
|
312
|
+
"@a3s-lab/testkit": "0.6.2",
|
|
310
313
|
"@biomejs/biome": "2.4.15",
|
|
311
314
|
"@fontsource-variable/geist": "^5.3.0",
|
|
312
315
|
"@fontsource-variable/geist-mono": "^5.3.0",
|
|
313
|
-
"@rspress/core": "^2.0.17",
|
|
314
|
-
"@rspress/shared": "2.0.19",
|
|
315
316
|
"@playwright/test": "1.61.1",
|
|
316
317
|
"@rsbuild/core": "^2.1.5",
|
|
317
318
|
"@rsbuild/plugin-react": "^2.1.0",
|
|
318
319
|
"@rslib/core": "^0.23.2",
|
|
320
|
+
"@rspress/core": "^2.0.17",
|
|
321
|
+
"@rspress/shared": "2.0.19",
|
|
319
322
|
"@rstest/adapter-rslib": "^0.10.6",
|
|
320
323
|
"@rstest/core": "^0.10.6",
|
|
321
324
|
"@rstest/coverage-v8": "0.10.6",
|