@a3s-lab/office 0.37.1 → 0.37.3
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 +285 -1549
- package/dist/0~9073.js +2 -2
- package/dist/0~controlled-editor-composition.js +54 -0
- package/dist/0~document-editor.js +60 -10
- package/dist/0~markdown-editor.js +62 -21
- package/dist/0~presentation-editor.js +57 -31
- package/dist/0~spreadsheet-editor.js +556 -71
- package/dist/internal/features/work/editors/controlled-editor-composition.d.ts +20 -0
- package/dist/internal/features/work/editors/spreadsheet-editor-support.d.ts +1 -0
- package/dist/internal/features/work/editors/spreadsheet-editor.d.ts +2 -1
- package/dist/internal/features/work/editors/spreadsheet-sort-custom-list-manager.d.ts +15 -0
- package/dist/internal/features/work/editors/spreadsheet-sort-dialog.d.ts +3 -2
- package/dist/internal/features/work/editors/use-document-review-conflicts.d.ts +3 -1
- package/dist/office-kernel.wasm +0 -0
- package/dist/styles.css +109 -0
- package/docs/latest/en/browser-editor-architecture.md +28 -7
- package/package.json +2 -1
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { Editor } from '@tiptap/core';
|
|
2
|
+
/**
|
|
3
|
+
* Keeps controlled TipTap editors from publishing or reconciling content while
|
|
4
|
+
* the browser and ProseMirror still own an IME composition. The zero-delay
|
|
5
|
+
* settlement lets ProseMirror flush WebKit's pending DOM records first; the
|
|
6
|
+
* bounded retries cover runtimes that keep `view.composing` true briefly after
|
|
7
|
+
* `compositionend` without adding work to ordinary keyboard input.
|
|
8
|
+
*/
|
|
9
|
+
export declare class ControlledEditorComposition {
|
|
10
|
+
private active;
|
|
11
|
+
private generation;
|
|
12
|
+
private settling;
|
|
13
|
+
private timer;
|
|
14
|
+
start(): void;
|
|
15
|
+
end(editor: Editor, onSettled: (editor: Editor) => void): void;
|
|
16
|
+
isBlocking(editor?: Editor | null): boolean;
|
|
17
|
+
destroy(): void;
|
|
18
|
+
private scheduleSettlement;
|
|
19
|
+
private cancelTimer;
|
|
20
|
+
}
|
|
@@ -35,5 +35,6 @@ export declare function spreadsheetContentWithSelection(content: WorkSpreadsheet
|
|
|
35
35
|
export declare function spreadsheetContentWithSelections(content: WorkSpreadsheetContent, sheetId: string, selections: readonly Selection[]): WorkSpreadsheetContent;
|
|
36
36
|
export declare function isSpreadsheetNativeTextUndoTarget(target: EventTarget | null): boolean;
|
|
37
37
|
export declare function isSpreadsheetCellEditingTarget(target: EventTarget | null): boolean;
|
|
38
|
+
export declare function isSpreadsheetCellEditorTarget(target: EventTarget | null): boolean;
|
|
38
39
|
export declare function spreadsheetFormulaBarSelectAllTarget(event: KeyboardEvent): HTMLElement | null;
|
|
39
40
|
export declare function selectSpreadsheetFormulaBarContents(event: KeyboardEvent): boolean;
|
|
@@ -17,8 +17,9 @@ export interface SpreadsheetEditorProps {
|
|
|
17
17
|
onAgentRequest?: (request: WorkEditorAgentRequest) => void | Promise<void>;
|
|
18
18
|
}
|
|
19
19
|
export declare function SpreadsheetEditor(props: SpreadsheetEditorProps): import("react").JSX.Element;
|
|
20
|
-
export declare function focusSpreadsheetGrid(container: HTMLElement | null, { focusOrigin, forceInitial, }?: {
|
|
20
|
+
export declare function focusSpreadsheetGrid(container: HTMLElement | null, { focusOrigin, forceCellEditingExit, forceInitial, }?: {
|
|
21
21
|
focusOrigin?: Element | null;
|
|
22
|
+
forceCellEditingExit?: boolean;
|
|
22
23
|
forceInitial?: boolean;
|
|
23
24
|
}): void;
|
|
24
25
|
export declare function preserveSpreadsheetGridFocus(container: HTMLElement | null, target: EventTarget | null): void;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { type SpreadsheetSortCustomList } from './spreadsheet-sort-custom-list';
|
|
2
|
+
export interface SpreadsheetSortCustomListManagementChange {
|
|
3
|
+
next: readonly string[] | null;
|
|
4
|
+
previous: readonly string[];
|
|
5
|
+
}
|
|
6
|
+
export interface SpreadsheetSortCustomListManagementResult {
|
|
7
|
+
changes: readonly SpreadsheetSortCustomListManagementChange[];
|
|
8
|
+
lists: readonly (readonly string[])[];
|
|
9
|
+
}
|
|
10
|
+
export declare function SpreadsheetSortCustomListManagerDialog({ customLists, restoreFocusTarget, onApply, onClose, }: {
|
|
11
|
+
customLists: readonly SpreadsheetSortCustomList[];
|
|
12
|
+
restoreFocusTarget: () => HTMLElement | null;
|
|
13
|
+
onApply: (value: SpreadsheetSortCustomListManagementResult) => void;
|
|
14
|
+
onClose: () => void;
|
|
15
|
+
}): import("react").JSX.Element;
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import { type SpreadsheetSortDialogSource, type SpreadsheetSortDialogValue } from './spreadsheet-sort';
|
|
2
2
|
import { type SpreadsheetSortCustomList } from './spreadsheet-sort-custom-list';
|
|
3
|
-
export declare function SpreadsheetSortDialog({ source, restoreFocusTarget, onApply, onRememberCustomList, onClose, }: {
|
|
3
|
+
export declare function SpreadsheetSortDialog({ source, restoreFocusTarget, onApply, onRememberCustomList, onUpdateCustomLists, onClose, }: {
|
|
4
4
|
source: SpreadsheetSortDialogSource;
|
|
5
5
|
restoreFocusTarget: () => HTMLElement | null;
|
|
6
6
|
onApply: (value: SpreadsheetSortDialogValue) => boolean;
|
|
7
|
-
onRememberCustomList?: (list: SpreadsheetSortCustomList) => SpreadsheetSortCustomList |
|
|
7
|
+
onRememberCustomList?: (list: SpreadsheetSortCustomList) => SpreadsheetSortCustomList | undefined;
|
|
8
|
+
onUpdateCustomLists?: (lists: readonly (readonly string[])[]) => readonly SpreadsheetSortCustomList[] | undefined;
|
|
8
9
|
onClose: () => void;
|
|
9
10
|
}): import("react").JSX.Element;
|
|
@@ -10,6 +10,8 @@ export interface UseDocumentReviewConflictsOptions {
|
|
|
10
10
|
appliedSourceKeyRef: MutableValue<string>;
|
|
11
11
|
artifactId?: string;
|
|
12
12
|
content: WorkDocumentContent;
|
|
13
|
+
controlledUpdateRevision?: number;
|
|
14
|
+
deferControlledUpdates?: boolean;
|
|
13
15
|
editor: Editor | null;
|
|
14
16
|
editorInput: WorkDocumentEditorInput;
|
|
15
17
|
normalizedContent: string;
|
|
@@ -17,7 +19,7 @@ export interface UseDocumentReviewConflictsOptions {
|
|
|
17
19
|
publishedDocumentRef: MutableValue<Editor['state']['doc'] | null>;
|
|
18
20
|
reconcileControlledUpdates?: boolean;
|
|
19
21
|
}
|
|
20
|
-
export declare function useDocumentReviewConflicts({ activeConflictsRef, appliedSourceKeyRef, artifactId, content, editor, editorInput, normalizedContent, onReviewConflict, publishedDocumentRef, reconcileControlledUpdates, }: UseDocumentReviewConflictsOptions): {
|
|
22
|
+
export declare function useDocumentReviewConflicts({ activeConflictsRef, appliedSourceKeyRef, artifactId, content, controlledUpdateRevision, deferControlledUpdates, editor, editorInput, normalizedContent, onReviewConflict, publishedDocumentRef, reconcileControlledUpdates, }: UseDocumentReviewConflictsOptions): {
|
|
21
23
|
dismiss: () => void;
|
|
22
24
|
visibleConflicts: WorkDocumentReviewConflict[];
|
|
23
25
|
};
|
package/dist/office-kernel.wasm
CHANGED
|
Binary file
|
package/dist/styles.css
CHANGED
|
@@ -18122,6 +18122,13 @@ sub [data-office-character-position-half-points], sup [data-office-character-pos
|
|
|
18122
18122
|
gap: 6px;
|
|
18123
18123
|
}
|
|
18124
18124
|
|
|
18125
|
+
.work-spreadsheet-sort-toolbar-actions {
|
|
18126
|
+
align-items: center;
|
|
18127
|
+
gap: 6px;
|
|
18128
|
+
min-width: 0;
|
|
18129
|
+
display: flex;
|
|
18130
|
+
}
|
|
18131
|
+
|
|
18125
18132
|
.work-spreadsheet-sort-toolbar .work-office-checkbox {
|
|
18126
18133
|
min-height: 34px;
|
|
18127
18134
|
padding: 6px 9px;
|
|
@@ -18314,6 +18321,96 @@ sub [data-office-character-position-half-points], sup [data-office-character-pos
|
|
|
18314
18321
|
line-height: 1.45;
|
|
18315
18322
|
}
|
|
18316
18323
|
|
|
18324
|
+
.work-spreadsheet-sort-custom-list-manager {
|
|
18325
|
+
--work-office-control-accent: var(--work-spreadsheet-accent, #159469);
|
|
18326
|
+
width: min(720px, 100%);
|
|
18327
|
+
}
|
|
18328
|
+
|
|
18329
|
+
.work-spreadsheet-sort-custom-list-manager-layout {
|
|
18330
|
+
grid-template-columns: minmax(220px, .85fr) minmax(280px, 1.15fr);
|
|
18331
|
+
gap: 14px;
|
|
18332
|
+
display: grid;
|
|
18333
|
+
}
|
|
18334
|
+
|
|
18335
|
+
.work-spreadsheet-sort-custom-list-manager-layout > section, .work-spreadsheet-sort-custom-list-manager-layout label {
|
|
18336
|
+
gap: 7px;
|
|
18337
|
+
min-width: 0;
|
|
18338
|
+
display: grid;
|
|
18339
|
+
}
|
|
18340
|
+
|
|
18341
|
+
.work-spreadsheet-sort-custom-list-manager-layout > section {
|
|
18342
|
+
align-content: start;
|
|
18343
|
+
}
|
|
18344
|
+
|
|
18345
|
+
.work-spreadsheet-sort-custom-list-manager-layout label > span {
|
|
18346
|
+
color: var(--a3s-muted);
|
|
18347
|
+
font-size: 10px;
|
|
18348
|
+
font-weight: 650;
|
|
18349
|
+
}
|
|
18350
|
+
|
|
18351
|
+
.work-spreadsheet-sort-custom-list-manager select, .work-spreadsheet-sort-custom-list-manager textarea {
|
|
18352
|
+
box-sizing: border-box;
|
|
18353
|
+
border: 1px solid var(--a3s-line-strong);
|
|
18354
|
+
background: var(--a3s-panel);
|
|
18355
|
+
width: 100%;
|
|
18356
|
+
min-width: 0;
|
|
18357
|
+
min-height: 252px;
|
|
18358
|
+
color: var(--a3s-ink);
|
|
18359
|
+
font: inherit;
|
|
18360
|
+
border-radius: 6px;
|
|
18361
|
+
padding: 8px;
|
|
18362
|
+
font-size: 11px;
|
|
18363
|
+
line-height: 1.5;
|
|
18364
|
+
}
|
|
18365
|
+
|
|
18366
|
+
.work-spreadsheet-sort-custom-list-manager textarea {
|
|
18367
|
+
resize: vertical;
|
|
18368
|
+
}
|
|
18369
|
+
|
|
18370
|
+
.work-spreadsheet-sort-custom-list-manager textarea[readonly] {
|
|
18371
|
+
background: var(--a3s-panel-soft);
|
|
18372
|
+
color: var(--a3s-muted);
|
|
18373
|
+
}
|
|
18374
|
+
|
|
18375
|
+
.work-spreadsheet-sort-custom-list-manager select:focus-visible, .work-spreadsheet-sort-custom-list-manager textarea:focus-visible {
|
|
18376
|
+
border-color: var(--work-spreadsheet-accent, #159469);
|
|
18377
|
+
outline: 2px solid
|
|
18378
|
+
color-mix(in srgb, var(--work-spreadsheet-accent, #159469) 24%, transparent);
|
|
18379
|
+
outline-offset: 1px;
|
|
18380
|
+
}
|
|
18381
|
+
|
|
18382
|
+
.work-spreadsheet-sort-custom-list-manager-layout section > p, .work-spreadsheet-sort-custom-list-manager-note {
|
|
18383
|
+
color: var(--a3s-muted);
|
|
18384
|
+
margin: 0;
|
|
18385
|
+
font-size: 10px;
|
|
18386
|
+
line-height: 1.45;
|
|
18387
|
+
}
|
|
18388
|
+
|
|
18389
|
+
.work-spreadsheet-sort-custom-list-manager-layout section > .work-spreadsheet-sort-custom-list-error {
|
|
18390
|
+
color: var(--a3s-danger, #b42318);
|
|
18391
|
+
}
|
|
18392
|
+
|
|
18393
|
+
.work-spreadsheet-sort-custom-list-manager-actions {
|
|
18394
|
+
justify-content: flex-end;
|
|
18395
|
+
align-items: center;
|
|
18396
|
+
gap: 6px;
|
|
18397
|
+
display: flex;
|
|
18398
|
+
}
|
|
18399
|
+
|
|
18400
|
+
.work-spreadsheet-sort-custom-list-manager-actions .ds-button {
|
|
18401
|
+
gap: 6px;
|
|
18402
|
+
}
|
|
18403
|
+
|
|
18404
|
+
.work-spreadsheet-sort-custom-list-manager-actions .ds-button[aria-label] {
|
|
18405
|
+
width: 34px;
|
|
18406
|
+
min-width: 34px;
|
|
18407
|
+
padding-inline: 0;
|
|
18408
|
+
}
|
|
18409
|
+
|
|
18410
|
+
.work-spreadsheet-sort-custom-list-manager-note {
|
|
18411
|
+
margin-block-start: 12px;
|
|
18412
|
+
}
|
|
18413
|
+
|
|
18317
18414
|
.work-spreadsheet-sort-range-dialog {
|
|
18318
18415
|
--work-office-control-accent: var(--work-spreadsheet-accent, #159469);
|
|
18319
18416
|
width: min(500px, 100%);
|
|
@@ -18395,6 +18492,18 @@ sub [data-office-character-position-half-points], sup [data-office-character-pos
|
|
|
18395
18492
|
align-items: stretch;
|
|
18396
18493
|
}
|
|
18397
18494
|
|
|
18495
|
+
.work-spreadsheet-sort-toolbar-actions {
|
|
18496
|
+
flex-wrap: wrap;
|
|
18497
|
+
}
|
|
18498
|
+
|
|
18499
|
+
.work-spreadsheet-sort-custom-list-manager-layout {
|
|
18500
|
+
grid-template-columns: minmax(0, 1fr);
|
|
18501
|
+
}
|
|
18502
|
+
|
|
18503
|
+
.work-spreadsheet-sort-custom-list-manager select, .work-spreadsheet-sort-custom-list-manager textarea {
|
|
18504
|
+
min-height: 180px;
|
|
18505
|
+
}
|
|
18506
|
+
|
|
18398
18507
|
.work-spreadsheet-sort-level {
|
|
18399
18508
|
grid-template-columns: minmax(0, 1fr);
|
|
18400
18509
|
}
|
|
@@ -644,6 +644,22 @@ The shell never searches visible labels, scrapes rendered text, or synthesizes
|
|
|
644
644
|
clicks to infer product intent. This keeps localized UI copy independent from
|
|
645
645
|
behavior and gives Worker/WASM operations a stable request contract.
|
|
646
646
|
|
|
647
|
+
## Controlled rich-text IME boundary
|
|
648
|
+
|
|
649
|
+
Document body text, visual Markdown, and Presentation text share one internal
|
|
650
|
+
composition coordinator. `compositionstart` blocks host publication and
|
|
651
|
+
controlled-value reconciliation. `compositionend` schedules settlement after
|
|
652
|
+
the current task so ProseMirror can flush WebKit's pending DOM observer records;
|
|
653
|
+
bounded 20 ms retries cover runtimes that briefly retain `view.composing`.
|
|
654
|
+
Only the settled canonical value is published, and an authoritative host value
|
|
655
|
+
received during composition is reconciled afterward.
|
|
656
|
+
|
|
657
|
+
The coordinator creates no timers or extra renders for ordinary keyboard input.
|
|
658
|
+
Focused component tests cover controlled echo and mid-composition host
|
|
659
|
+
replacement. A dedicated Playwright WebKit gate exercises the browser event
|
|
660
|
+
ordering, asserts zero publications for Pinyin pre-edit text, one publication
|
|
661
|
+
for the committed Chinese value, and the same value after a controlled reopen.
|
|
662
|
+
|
|
647
663
|
## Markdown editing flow
|
|
648
664
|
|
|
649
665
|
```text
|
|
@@ -1455,14 +1471,19 @@ first/last placement. The
|
|
|
1455
1471
|
normalization, duplicate and size guards, seven immutable month/weekday lists,
|
|
1456
1472
|
and rank matching; the validated request clones custom entries so command
|
|
1457
1473
|
execution has no dependency on mutable UI state. The browser adapters own a
|
|
1458
|
-
bounded user-list registry and never
|
|
1459
|
-
|
|
1474
|
+
bounded user-list registry and never write preferences into controlled workbook
|
|
1475
|
+
content. A dedicated manager stages create, edit, delete, and reorder operations
|
|
1476
|
+
against stable list identities, then publishes one normalized preference set.
|
|
1477
|
+
Built-ins remain read-only, no-op confirmation skips the storage boundary,
|
|
1478
|
+
edited active keys receive the replacement sequence, and deleted active keys
|
|
1479
|
+
fall back to ascending value order. Without a store the registry remains scoped
|
|
1480
|
+
to the mounted session.
|
|
1460
1481
|
The optional typed `SpreadsheetSortCustomListStore` synchronously loads and
|
|
1461
1482
|
saves canonical lists through a host-selected local backend. The provided
|
|
1462
1483
|
`LocalStorageSpreadsheetSortCustomListStore` accepts an injected Storage
|
|
1463
1484
|
object, uses a versioned key, and validates, deduplicates, and caps reads at 32
|
|
1464
|
-
lists. Corrupt reads fail closed; a rejected write visibly downgrades the
|
|
1465
|
-
|
|
1485
|
+
lists. Corrupt reads fail closed; a rejected write visibly downgrades the
|
|
1486
|
+
complete changed preference set to session scope. A stored list precedes an identical request-carried
|
|
1466
1487
|
session copy so persistence identity remains stable. The separate
|
|
1467
1488
|
`spreadsheet-sort-appearance` model snapshots direct native styles plus
|
|
1468
1489
|
calculated conditional-format output, preserves no-fill/automatic identities,
|
|
@@ -1481,9 +1502,9 @@ One accepted operation crosses the Fortune boundary as one range write and one
|
|
|
1481
1502
|
controlled Undo record. Table, worksheet-AutoFilter, hyperlink-map,
|
|
1482
1503
|
imported-formula-metadata, and border-sidecar intersections fail closed because
|
|
1483
1504
|
those models still own coordinates outside the cell matrix. Moving large sorts,
|
|
1484
|
-
large aggregate/rank scans, remaining advanced filter predicates,
|
|
1485
|
-
|
|
1486
|
-
|
|
1505
|
+
large aggregate/rank scans, remaining advanced filter predicates, and
|
|
1506
|
+
structural sidecar reconciliation into the Worker/WASM kernel remains Stage 3
|
|
1507
|
+
work.
|
|
1487
1508
|
Direct host focus of the native grid now enters the same bounded focus observer
|
|
1488
1509
|
used by ribbon commands. If a controlled workbook update replaces the focused
|
|
1489
1510
|
Fortune overlay, focus transfers to its connected replacement; deliberate
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@a3s-lab/office",
|
|
3
|
-
"version": "0.37.
|
|
3
|
+
"version": "0.37.3",
|
|
4
4
|
"description": "Open-source collaborative browser editors for documents, Markdown, spreadsheets, presentations, and PDFs.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"office",
|
|
@@ -86,6 +86,7 @@
|
|
|
86
86
|
"playground:bundle-check": "bun scripts/check-playground-bundle.ts",
|
|
87
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
|
+
"playground:ime:webkit": "playwright test --config playwright.ime.config.ts",
|
|
89
90
|
"playground:visual": "playwright test --config playwright.config.ts",
|
|
90
91
|
"playground:visual:document-emphasis": "playwright test visual-tests/document-emphasis.functional.spec.ts --config playwright.config.ts",
|
|
91
92
|
"playground:visual:document-index": "playwright test visual-tests/document-index.functional.spec.ts --config playwright.config.ts",
|