@a3s-lab/office 0.2.2 → 0.3.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 +14 -1
- package/dist/0~4595.js +117 -11
- package/dist/0~5050.js +124 -113
- package/dist/0~9512.js +1 -0
- package/dist/0~document-editor.js +2836 -1429
- package/dist/0~work-document-extensions.js +2 -2
- package/dist/internal/design-system/primitives/navigation/tabs.d.ts +3 -1
- package/dist/internal/features/work/editors/document-command-catalog.d.ts +527 -0
- package/dist/internal/features/work/editors/document-editor-support.d.ts +7 -3
- package/dist/internal/features/work/editors/document-editor.d.ts +1 -1
- package/dist/internal/features/work/editors/document-format-clipboard.d.ts +6 -0
- package/dist/internal/features/work/editors/document-format-tools.d.ts +4 -0
- package/dist/internal/features/work/editors/document-layout-panel.d.ts +4 -1
- package/dist/internal/features/work/editors/document-page-chrome-wps-shortcuts.d.ts +2 -0
- package/dist/internal/features/work/editors/document-page-layout-ribbon.d.ts +14 -0
- package/dist/internal/features/work/editors/document-review-navigation.d.ts +9 -0
- package/dist/internal/features/work/editors/document-statistics-dialog.d.ts +7 -0
- package/dist/internal/features/work/editors/document-status-bar.d.ts +2 -1
- package/dist/internal/features/work/editors/document-toolbar.d.ts +12 -42
- package/dist/internal/features/work/editors/document-wps-shortcuts.d.ts +12 -0
- package/dist/internal/features/work/editors/document-zoom.d.ts +17 -0
- package/dist/internal/features/work/editors/work-office-chrome.d.ts +22 -3
- package/dist/internal/features/work/editors/work-office-ribbon-overflow.d.ts +2 -0
- package/dist/office-kernel.wasm +0 -0
- package/dist/styles.css +213 -1
- package/docs/latest/en/browser-editor-architecture.md +33 -0
- package/package.json +11 -1
|
@@ -1,54 +1,20 @@
|
|
|
1
1
|
import type { Editor } from '@tiptap/core';
|
|
2
2
|
import type { WorkDocumentCaptionKind } from '../work-document-captions';
|
|
3
3
|
import type { WorkDocumentFieldKind } from '../work-document-fields';
|
|
4
|
-
import type { WorkDocumentNoteKind } from '../work-document-notes';
|
|
5
4
|
import type { WorkDocumentLayoutFont } from '../work-document-fonts';
|
|
6
|
-
import {
|
|
5
|
+
import type { WorkDocumentNoteKind } from '../work-document-notes';
|
|
6
|
+
import type { WorkDocumentSectionLayout } from '../work-types';
|
|
7
|
+
import { type DocumentRibbonTabId } from './document-command-catalog';
|
|
7
8
|
import type { DocumentFindReplaceMode } from './document-find-replace-panel';
|
|
9
|
+
import type { DocumentLayoutPanelTab } from './document-layout-panel';
|
|
10
|
+
import { type DocumentPageChromeEditingPart } from './document-page-chrome-ribbon';
|
|
11
|
+
import { type DocumentZoomFit } from './document-zoom';
|
|
8
12
|
import { type WorkOfficeFileAction } from './work-office-chrome';
|
|
9
|
-
declare const documentRibbonTabs: readonly [{
|
|
10
|
-
readonly id: "home";
|
|
11
|
-
readonly label: "开始";
|
|
12
|
-
}, {
|
|
13
|
-
readonly id: "insert";
|
|
14
|
-
readonly label: "插入";
|
|
15
|
-
}, {
|
|
16
|
-
readonly id: "page";
|
|
17
|
-
readonly label: "页面布局";
|
|
18
|
-
readonly compactLabel: "布局";
|
|
19
|
-
}, {
|
|
20
|
-
readonly id: "references";
|
|
21
|
-
readonly label: "引用";
|
|
22
|
-
}, {
|
|
23
|
-
readonly id: "review";
|
|
24
|
-
readonly label: "审阅";
|
|
25
|
-
}, {
|
|
26
|
-
readonly id: "view";
|
|
27
|
-
readonly label: "视图";
|
|
28
|
-
}];
|
|
29
|
-
declare const documentPictureRibbonTab: {
|
|
30
|
-
readonly id: "picture";
|
|
31
|
-
readonly label: "图片";
|
|
32
|
-
};
|
|
33
|
-
declare const documentTableRibbonTabs: readonly [{
|
|
34
|
-
readonly id: "tableDesign";
|
|
35
|
-
readonly label: "表格设计";
|
|
36
|
-
readonly compactLabel: "设计";
|
|
37
|
-
}, {
|
|
38
|
-
readonly id: "tableLayout";
|
|
39
|
-
readonly label: "表格布局";
|
|
40
|
-
readonly compactLabel: "布局";
|
|
41
|
-
}];
|
|
42
|
-
declare const documentPageChromeRibbonTab: {
|
|
43
|
-
readonly id: "pageChrome";
|
|
44
|
-
readonly label: "页眉和页脚";
|
|
45
|
-
readonly compactLabel: "页眉页脚";
|
|
46
|
-
};
|
|
47
|
-
type DocumentRibbonTabId = (typeof documentRibbonTabs)[number]['id'] | typeof documentPictureRibbonTab.id | (typeof documentTableRibbonTabs)[number]['id'] | typeof documentPageChromeRibbonTab.id;
|
|
48
13
|
export type DocumentViewMode = 'page' | 'web';
|
|
49
14
|
interface DocumentToolbarProps {
|
|
50
15
|
editor: Editor;
|
|
51
16
|
layoutOpen: boolean;
|
|
17
|
+
layout: WorkDocumentSectionLayout;
|
|
52
18
|
layoutFonts?: readonly WorkDocumentLayoutFont[];
|
|
53
19
|
navigationOpen: boolean;
|
|
54
20
|
pageColor: string;
|
|
@@ -65,6 +31,8 @@ interface DocumentToolbarProps {
|
|
|
65
31
|
onClosePageChrome: () => void;
|
|
66
32
|
onTogglePageChromePageNumber: () => void;
|
|
67
33
|
onToggleLayout: () => void;
|
|
34
|
+
onLayoutChange: (layout: WorkDocumentSectionLayout) => void;
|
|
35
|
+
onOpenLayout: (target: DocumentLayoutPanelTab) => void;
|
|
68
36
|
onToggleNavigation: () => void;
|
|
69
37
|
onTogglePageNumbers: () => void;
|
|
70
38
|
onToggleRulers: () => void;
|
|
@@ -72,6 +40,7 @@ interface DocumentToolbarProps {
|
|
|
72
40
|
onToggleSpellcheck: () => void;
|
|
73
41
|
onViewModeChange: (mode: DocumentViewMode) => void;
|
|
74
42
|
onZoomChange: (zoom: number) => void;
|
|
43
|
+
onZoomFit: (fit: DocumentZoomFit) => void;
|
|
75
44
|
onInsertSection: () => void;
|
|
76
45
|
onInsertNote: (kind: WorkDocumentNoteKind) => void;
|
|
77
46
|
onInsertCaption: (kind: WorkDocumentCaptionKind) => void;
|
|
@@ -94,7 +63,8 @@ interface DocumentToolbarProps {
|
|
|
94
63
|
onRibbonTabChange?: (tab: DocumentRibbonTabId) => boolean | undefined | Promise<boolean | undefined>;
|
|
95
64
|
onToggleTrackChanges: () => void;
|
|
96
65
|
onToggleChanges: () => void;
|
|
66
|
+
onOpenWordCount: () => void;
|
|
97
67
|
onOpenFindReplace: (mode: DocumentFindReplaceMode) => void;
|
|
98
68
|
}
|
|
99
|
-
export declare function DocumentToolbar({ editor, layoutOpen, layoutFonts, navigationOpen, pageColor, showPageNumbers, showRulers, spellcheckEnabled, viewMode, zoom, pageChromeEditor, pageChromeEditingPart, pageChromeShowPageNumber, onRequestImage, onPageChromeEditingPartChange, onClosePageChrome, onTogglePageChromePageNumber, onToggleLayout, onToggleNavigation, onTogglePageNumbers, onToggleRulers, onPageColorChange, onToggleSpellcheck, onViewModeChange, onZoomChange, onInsertSection, onInsertNote, onInsertCaption, onInsertCrossReference, citationsOpen, citationSourceCount, onToggleCitations, onInsertField, onRefreshFields, canInsertComment, onInsertComment, commentsOpen, commentCount, onToggleComments, trackChanges, changesOpen, changeCount, findReplaceMode, fileActions, onRibbonTabChange, onToggleTrackChanges, onToggleChanges, onOpenFindReplace, }: DocumentToolbarProps): import("react").JSX.Element;
|
|
69
|
+
export declare function DocumentToolbar({ editor, layoutOpen, layout, layoutFonts, navigationOpen, pageColor, showPageNumbers, showRulers, spellcheckEnabled, viewMode, zoom, pageChromeEditor, pageChromeEditingPart, pageChromeShowPageNumber, onRequestImage, onPageChromeEditingPartChange, onClosePageChrome, onTogglePageChromePageNumber, onToggleLayout, onLayoutChange, onOpenLayout, onToggleNavigation, onTogglePageNumbers, onToggleRulers, onPageColorChange, onToggleSpellcheck, onViewModeChange, onZoomChange, onZoomFit, onInsertSection, onInsertNote, onInsertCaption, onInsertCrossReference, citationsOpen, citationSourceCount, onToggleCitations, onInsertField, onRefreshFields, canInsertComment, onInsertComment, commentsOpen, commentCount, onToggleComments, trackChanges, changesOpen, changeCount, findReplaceMode, fileActions, onRibbonTabChange, onToggleTrackChanges, onToggleChanges, onOpenWordCount, onOpenFindReplace, }: DocumentToolbarProps): import("react").JSX.Element;
|
|
100
70
|
export {};
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { Editor } from '@tiptap/core';
|
|
2
|
+
export interface DocumentWpsShortcutCallbacks {
|
|
3
|
+
canInsertComment: boolean;
|
|
4
|
+
canRefreshFields: boolean;
|
|
5
|
+
onInsertComment: () => void;
|
|
6
|
+
onOpenWordCount: () => void;
|
|
7
|
+
onRefreshFields: () => void;
|
|
8
|
+
onToggleSpellcheck: () => void;
|
|
9
|
+
onToggleTrackChanges: () => void;
|
|
10
|
+
}
|
|
11
|
+
export type DocumentWpsShortcutEvent = Pick<KeyboardEvent, 'altKey' | 'code' | 'ctrlKey' | 'key' | 'metaKey' | 'shiftKey'>;
|
|
12
|
+
export declare function runDocumentWpsShortcut(editor: Editor, event: DocumentWpsShortcutEvent, callbacks: DocumentWpsShortcutCallbacks): boolean;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
export declare const MIN_DOCUMENT_ZOOM = 50;
|
|
2
|
+
export declare const MAX_DOCUMENT_ZOOM = 200;
|
|
3
|
+
export type DocumentZoomFit = 'page' | 'width';
|
|
4
|
+
export interface DocumentZoomFitMetrics {
|
|
5
|
+
pageHeight: number;
|
|
6
|
+
pageWidth: number;
|
|
7
|
+
viewportHeight: number;
|
|
8
|
+
viewportWidth: number;
|
|
9
|
+
viewportPadding: {
|
|
10
|
+
top: number;
|
|
11
|
+
right: number;
|
|
12
|
+
bottom: number;
|
|
13
|
+
left: number;
|
|
14
|
+
};
|
|
15
|
+
}
|
|
16
|
+
export declare function clampDocumentZoom(zoom: number): number;
|
|
17
|
+
export declare function documentZoomForFit(fit: DocumentZoomFit, metrics: DocumentZoomFitMetrics): number;
|
|
@@ -3,6 +3,7 @@ export interface WorkOfficeRibbonTab<T extends string> {
|
|
|
3
3
|
id: T;
|
|
4
4
|
label: string;
|
|
5
5
|
compactLabel?: string;
|
|
6
|
+
contextual?: boolean;
|
|
6
7
|
}
|
|
7
8
|
export interface WorkOfficeFileAction {
|
|
8
9
|
id: string;
|
|
@@ -13,7 +14,16 @@ export interface WorkOfficeFileAction {
|
|
|
13
14
|
separatorBefore?: boolean;
|
|
14
15
|
onSelect: () => void | Promise<void>;
|
|
15
16
|
}
|
|
16
|
-
export
|
|
17
|
+
export interface WorkOfficeQuickAccessAction {
|
|
18
|
+
id: string;
|
|
19
|
+
label: string;
|
|
20
|
+
icon: ReactNode;
|
|
21
|
+
shortcut?: string;
|
|
22
|
+
ariaKeyShortcuts?: string;
|
|
23
|
+
disabled?: boolean;
|
|
24
|
+
onSelect: () => void | Promise<void>;
|
|
25
|
+
}
|
|
26
|
+
export declare function WorkOfficeRibbon<T extends string>({ ariaLabel, tabs, defaultTab, activeTab, onTabChange, panels, fileActions, quickAccessActions, adaptive, collapsible, collapsed: controlledCollapsed, defaultCollapsed, onCollapsedChange, className, toolbarClassName, }: {
|
|
17
27
|
ariaLabel: string;
|
|
18
28
|
tabs: readonly WorkOfficeRibbonTab<T>[];
|
|
19
29
|
defaultTab: T;
|
|
@@ -21,6 +31,12 @@ export declare function WorkOfficeRibbon<T extends string>({ ariaLabel, tabs, de
|
|
|
21
31
|
onTabChange?: (tab: T) => void;
|
|
22
32
|
panels: Record<T, ReactNode>;
|
|
23
33
|
fileActions?: readonly WorkOfficeFileAction[];
|
|
34
|
+
quickAccessActions?: readonly WorkOfficeQuickAccessAction[];
|
|
35
|
+
adaptive?: boolean;
|
|
36
|
+
collapsible?: boolean;
|
|
37
|
+
collapsed?: boolean;
|
|
38
|
+
defaultCollapsed?: boolean;
|
|
39
|
+
onCollapsedChange?: (collapsed: boolean) => void;
|
|
24
40
|
className?: string;
|
|
25
41
|
toolbarClassName?: string;
|
|
26
42
|
}): import("react").JSX.Element;
|
|
@@ -31,8 +47,9 @@ export declare function WorkOfficePreviewBar({ ariaLabel, label, detail, fileAct
|
|
|
31
47
|
fileActions?: readonly WorkOfficeFileAction[];
|
|
32
48
|
className?: string;
|
|
33
49
|
}): import("react").JSX.Element;
|
|
34
|
-
export declare function WorkOfficeRibbonGroup({ label, children, }: {
|
|
50
|
+
export declare function WorkOfficeRibbonGroup({ label, priority, children, }: {
|
|
35
51
|
label: string;
|
|
52
|
+
priority?: 'high' | 'normal' | 'low';
|
|
36
53
|
children: ReactNode;
|
|
37
54
|
}): import("react").JSX.Element;
|
|
38
55
|
export declare function WorkOfficeRibbonButton({ label, visibleLabel, badge, active, displayLabel, className, title, children, ...props }: Omit<ButtonHTMLAttributes<HTMLButtonElement>, 'aria-label' | 'children'> & {
|
|
@@ -43,9 +60,11 @@ export declare function WorkOfficeRibbonButton({ label, visibleLabel, badge, act
|
|
|
43
60
|
displayLabel?: boolean;
|
|
44
61
|
children: ReactNode;
|
|
45
62
|
}): import("react").JSX.Element;
|
|
46
|
-
export declare function WorkOfficeStatusBar({ children, controls, className, }: {
|
|
63
|
+
export declare function WorkOfficeStatusBar({ ariaLabel, children, controls, controlsLabel, className, }: {
|
|
64
|
+
ariaLabel?: string;
|
|
47
65
|
children: ReactNode;
|
|
48
66
|
controls?: ReactNode;
|
|
67
|
+
controlsLabel?: string;
|
|
49
68
|
className?: string;
|
|
50
69
|
}): import("react").JSX.Element;
|
|
51
70
|
export declare function WorkOfficeZoomControls({ zoom, minimum, maximum, step, decreaseLabel, increaseLabel, outputLabel, sliderLabel, onChange, }: {
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
export declare const WORK_OFFICE_RIBBON_SCROLL_INSET = 34;
|
|
2
|
+
export type WorkOfficeRibbonDensity = 'comfortable' | 'compact-low' | 'compact-normal';
|
|
3
|
+
export declare function calculateRibbonDensity(clientWidth: number): WorkOfficeRibbonDensity;
|
|
2
4
|
export interface WorkOfficeRibbonItemGeometry {
|
|
3
5
|
left: number;
|
|
4
6
|
right: number;
|
package/dist/office-kernel.wasm
CHANGED
|
Binary file
|
package/dist/styles.css
CHANGED
|
@@ -5275,6 +5275,7 @@ html[data-ds-resizing="horizontal"], html[data-ds-resizing="horizontal"] * {
|
|
|
5275
5275
|
flex: none;
|
|
5276
5276
|
min-width: 0;
|
|
5277
5277
|
display: flex;
|
|
5278
|
+
position: relative;
|
|
5278
5279
|
box-shadow: 0 2px 7px #181f2e0a;
|
|
5279
5280
|
}
|
|
5280
5281
|
|
|
@@ -5375,6 +5376,17 @@ html[data-ds-resizing="horizontal"], html[data-ds-resizing="horizontal"] * {
|
|
|
5375
5376
|
font-size: 12px;
|
|
5376
5377
|
}
|
|
5377
5378
|
|
|
5379
|
+
.work-office-ribbon-tabs > button[data-contextual="true"] {
|
|
5380
|
+
background: color-mix(in srgb, var(--work-office-accent) 7%, transparent);
|
|
5381
|
+
box-shadow: inset 0 2px
|
|
5382
|
+
color-mix(in srgb, var(--work-office-accent) 48%, transparent);
|
|
5383
|
+
color: color-mix(in srgb, var(--work-office-accent) 82%, var(--a3s-ink));
|
|
5384
|
+
}
|
|
5385
|
+
|
|
5386
|
+
.work-office-ribbon-tabs > button[data-contextual="true"]:hover:not(:disabled) {
|
|
5387
|
+
background: color-mix(in srgb, var(--work-office-accent) 11%, transparent);
|
|
5388
|
+
}
|
|
5389
|
+
|
|
5378
5390
|
.work-office-ribbon-tabs > button:after {
|
|
5379
5391
|
left: 4px;
|
|
5380
5392
|
right: 4px;
|
|
@@ -5401,6 +5413,11 @@ html[data-ds-resizing="horizontal"], html[data-ds-resizing="horizontal"] * {
|
|
|
5401
5413
|
background: var(--work-office-accent);
|
|
5402
5414
|
}
|
|
5403
5415
|
|
|
5416
|
+
.work-office-ribbon[data-contextual-active="true"] > .work-office-ribbon-panel {
|
|
5417
|
+
box-shadow: inset 0 1px
|
|
5418
|
+
color-mix(in srgb, var(--work-office-accent) 28%, transparent);
|
|
5419
|
+
}
|
|
5420
|
+
|
|
5404
5421
|
.work-office-ribbon-tab-navigation {
|
|
5405
5422
|
border-left: 1px solid var(--a3s-line);
|
|
5406
5423
|
background: var(--a3s-panel);
|
|
@@ -5443,6 +5460,57 @@ html[data-ds-resizing="horizontal"], html[data-ds-resizing="horizontal"] * {
|
|
|
5443
5460
|
opacity: .28;
|
|
5444
5461
|
}
|
|
5445
5462
|
|
|
5463
|
+
.work-office-quick-access {
|
|
5464
|
+
border-right: 1px solid var(--a3s-line);
|
|
5465
|
+
flex: none;
|
|
5466
|
+
align-items: center;
|
|
5467
|
+
gap: 1px;
|
|
5468
|
+
height: 36px;
|
|
5469
|
+
padding: 0 5px;
|
|
5470
|
+
display: flex;
|
|
5471
|
+
}
|
|
5472
|
+
|
|
5473
|
+
.work-office-quick-access > button, .work-office-ribbon-collapse {
|
|
5474
|
+
width: 26px;
|
|
5475
|
+
height: 26px;
|
|
5476
|
+
color: var(--a3s-muted);
|
|
5477
|
+
cursor: pointer;
|
|
5478
|
+
background: none;
|
|
5479
|
+
border: 0;
|
|
5480
|
+
border-radius: 5px;
|
|
5481
|
+
outline: 0;
|
|
5482
|
+
place-items: center;
|
|
5483
|
+
padding: 0;
|
|
5484
|
+
display: grid;
|
|
5485
|
+
}
|
|
5486
|
+
|
|
5487
|
+
.work-office-quick-access > button:hover:not(:disabled), .work-office-quick-access > button:focus-visible, .work-office-ribbon-collapse:hover, .work-office-ribbon-collapse:focus-visible {
|
|
5488
|
+
background: color-mix(in srgb,
|
|
5489
|
+
var(--work-office-accent) 8%,
|
|
5490
|
+
var(--a3s-panel));
|
|
5491
|
+
color: var(--work-office-accent);
|
|
5492
|
+
}
|
|
5493
|
+
|
|
5494
|
+
.work-office-quick-access > button:focus-visible, .work-office-ribbon-collapse:focus-visible {
|
|
5495
|
+
box-shadow: inset 0 0 0 1px var(--work-office-accent);
|
|
5496
|
+
}
|
|
5497
|
+
|
|
5498
|
+
.work-office-quick-access > button:disabled {
|
|
5499
|
+
cursor: default;
|
|
5500
|
+
opacity: .34;
|
|
5501
|
+
}
|
|
5502
|
+
|
|
5503
|
+
.work-office-quick-access > button > span {
|
|
5504
|
+
place-items: center;
|
|
5505
|
+
display: grid;
|
|
5506
|
+
}
|
|
5507
|
+
|
|
5508
|
+
.work-office-ribbon-collapse {
|
|
5509
|
+
flex: 0 0 26px;
|
|
5510
|
+
align-self: center;
|
|
5511
|
+
margin: 0 5px 0 2px;
|
|
5512
|
+
}
|
|
5513
|
+
|
|
5446
5514
|
.work-office-file-menu {
|
|
5447
5515
|
border-right: 1px solid var(--a3s-line);
|
|
5448
5516
|
flex: none;
|
|
@@ -5552,6 +5620,22 @@ html[data-ds-resizing="horizontal"], html[data-ds-resizing="horizontal"] * {
|
|
|
5552
5620
|
position: relative;
|
|
5553
5621
|
}
|
|
5554
5622
|
|
|
5623
|
+
.work-office-ribbon-panel[hidden] {
|
|
5624
|
+
display: none;
|
|
5625
|
+
}
|
|
5626
|
+
|
|
5627
|
+
.work-office-ribbon[data-collapsed="true"] .work-office-ribbon-panel:not([hidden]) {
|
|
5628
|
+
z-index: 10;
|
|
5629
|
+
border-top: 1px solid var(--a3s-line);
|
|
5630
|
+
border-bottom: 1px solid var(--a3s-line);
|
|
5631
|
+
background: var(--a3s-panel);
|
|
5632
|
+
position: absolute;
|
|
5633
|
+
top: 36px;
|
|
5634
|
+
left: 0;
|
|
5635
|
+
right: 0;
|
|
5636
|
+
box-shadow: 0 12px 26px #181f2e26;
|
|
5637
|
+
}
|
|
5638
|
+
|
|
5555
5639
|
.work-office-ribbon-panel[data-empty="true"] {
|
|
5556
5640
|
display: none;
|
|
5557
5641
|
}
|
|
@@ -5664,6 +5748,25 @@ html[data-ds-resizing="horizontal"], html[data-ds-resizing="horizontal"] * {
|
|
|
5664
5748
|
overflow: hidden;
|
|
5665
5749
|
}
|
|
5666
5750
|
|
|
5751
|
+
.work-office-ribbon .work-office-toolbar[data-density="compact-low"] .work-office-ribbon-group[data-priority="low"], .work-office-ribbon .work-office-toolbar[data-density="compact-normal"] .work-office-ribbon-group:not([data-priority="high"]) {
|
|
5752
|
+
padding-left: 4px;
|
|
5753
|
+
padding-right: 4px;
|
|
5754
|
+
}
|
|
5755
|
+
|
|
5756
|
+
.work-office-ribbon .work-office-toolbar[data-density="compact-low"] .work-office-ribbon-group[data-priority="low"] > div, .work-office-ribbon .work-office-toolbar[data-density="compact-normal"] .work-office-ribbon-group:not([data-priority="high"]) > div {
|
|
5757
|
+
gap: 0;
|
|
5758
|
+
}
|
|
5759
|
+
|
|
5760
|
+
.work-office-ribbon .work-office-toolbar[data-density="compact-low"] .work-office-ribbon-group[data-priority="low"] button.with-label, .work-office-ribbon .work-office-toolbar[data-density="compact-normal"] .work-office-ribbon-group:not([data-priority="high"]) button.with-label {
|
|
5761
|
+
width: 38px;
|
|
5762
|
+
min-width: 38px;
|
|
5763
|
+
padding-inline: 4px;
|
|
5764
|
+
}
|
|
5765
|
+
|
|
5766
|
+
.work-office-ribbon .work-office-toolbar[data-density="compact-low"] .work-office-ribbon-group[data-priority="low"] button.with-label > span, .work-office-ribbon .work-office-toolbar[data-density="compact-normal"] .work-office-ribbon-group:not([data-priority="high"]) button.with-label > span {
|
|
5767
|
+
display: none;
|
|
5768
|
+
}
|
|
5769
|
+
|
|
5667
5770
|
.work-office-ribbon .work-office-toolbar button.with-label {
|
|
5668
5771
|
flex-direction: column;
|
|
5669
5772
|
gap: 3px;
|
|
@@ -5757,6 +5860,15 @@ html[data-ds-resizing="horizontal"], html[data-ds-resizing="horizontal"] * {
|
|
|
5757
5860
|
display: grid;
|
|
5758
5861
|
}
|
|
5759
5862
|
|
|
5863
|
+
.work-office-status button.work-office-status-text-button {
|
|
5864
|
+
width: auto;
|
|
5865
|
+
min-width: 0;
|
|
5866
|
+
color: inherit;
|
|
5867
|
+
font: inherit;
|
|
5868
|
+
white-space: nowrap;
|
|
5869
|
+
padding: 0 5px;
|
|
5870
|
+
}
|
|
5871
|
+
|
|
5760
5872
|
.work-office-status button:hover:not(:disabled), .work-office-status button[aria-pressed="true"] {
|
|
5761
5873
|
background: var(--a3s-panel-soft);
|
|
5762
5874
|
color: var(--a3s-ink);
|
|
@@ -6691,6 +6803,31 @@ html[data-ds-resizing="horizontal"], html[data-ds-resizing="horizontal"] * {
|
|
|
6691
6803
|
width: 82px;
|
|
6692
6804
|
}
|
|
6693
6805
|
|
|
6806
|
+
.work-document-ribbon .work-office-ribbon-group > .work-document-page-setup-choice {
|
|
6807
|
+
align-content: center;
|
|
6808
|
+
gap: 2px;
|
|
6809
|
+
width: 84px;
|
|
6810
|
+
padding-inline: 1px;
|
|
6811
|
+
display: grid;
|
|
6812
|
+
}
|
|
6813
|
+
|
|
6814
|
+
.work-document-page-setup-choice > span {
|
|
6815
|
+
color: var(--a3s-faint);
|
|
6816
|
+
text-overflow: ellipsis;
|
|
6817
|
+
white-space: nowrap;
|
|
6818
|
+
padding-inline: 2px;
|
|
6819
|
+
font-size: 8px;
|
|
6820
|
+
line-height: 10px;
|
|
6821
|
+
overflow: hidden;
|
|
6822
|
+
}
|
|
6823
|
+
|
|
6824
|
+
.work-document-ribbon .work-document-page-setup-choice .work-office-select > button[role="combobox"] {
|
|
6825
|
+
gap: 4px;
|
|
6826
|
+
min-width: 0;
|
|
6827
|
+
height: 28px;
|
|
6828
|
+
padding-inline: 6px 5px;
|
|
6829
|
+
}
|
|
6830
|
+
|
|
6694
6831
|
.work-document-selection-toolbar {
|
|
6695
6832
|
z-index: 70;
|
|
6696
6833
|
box-sizing: border-box;
|
|
@@ -8856,6 +8993,14 @@ html[data-ds-resizing="horizontal"], html[data-ds-resizing="horizontal"] * {
|
|
|
8856
8993
|
display: none;
|
|
8857
8994
|
}
|
|
8858
8995
|
|
|
8996
|
+
.work-document-ribbon .work-office-toolbar[data-density="compact-low"] .work-office-ribbon-group[data-priority="low"] .work-document-style-gallery, .work-document-ribbon .work-office-toolbar[data-density="compact-normal"] .work-office-ribbon-group:not([data-priority="high"]) .work-document-style-gallery {
|
|
8997
|
+
display: none;
|
|
8998
|
+
}
|
|
8999
|
+
|
|
9000
|
+
.work-document-ribbon .work-office-toolbar[data-density="compact-low"] .work-office-ribbon-group[data-priority="low"] .work-document-style-select, .work-document-ribbon .work-office-toolbar[data-density="compact-normal"] .work-office-ribbon-group:not([data-priority="high"]) .work-document-style-select {
|
|
9001
|
+
display: block;
|
|
9002
|
+
}
|
|
9003
|
+
|
|
8859
9004
|
@media (width <= 900px) {
|
|
8860
9005
|
.work-document-style-gallery {
|
|
8861
9006
|
display: none;
|
|
@@ -9377,6 +9522,10 @@ html[data-ds-resizing="horizontal"], html[data-ds-resizing="horizontal"] * {
|
|
|
9377
9522
|
position: relative;
|
|
9378
9523
|
}
|
|
9379
9524
|
|
|
9525
|
+
.work-document-editable .ProseMirror[data-document-format-painter="true"] {
|
|
9526
|
+
cursor: copy;
|
|
9527
|
+
}
|
|
9528
|
+
|
|
9380
9529
|
.work-document-page.letter {
|
|
9381
9530
|
width: 816px;
|
|
9382
9531
|
min-height: 1056px;
|
|
@@ -10066,6 +10215,38 @@ html[data-ds-resizing="horizontal"], html[data-ds-resizing="horizontal"] * {
|
|
|
10066
10215
|
box-shadow: 0 8px 30px #1e263712;
|
|
10067
10216
|
}
|
|
10068
10217
|
|
|
10218
|
+
.work-document-statistics {
|
|
10219
|
+
border: 1px solid var(--a3s-line);
|
|
10220
|
+
border-radius: 7px;
|
|
10221
|
+
margin: 0;
|
|
10222
|
+
display: grid;
|
|
10223
|
+
overflow: hidden;
|
|
10224
|
+
}
|
|
10225
|
+
|
|
10226
|
+
.work-document-statistics > div {
|
|
10227
|
+
background: var(--a3s-panel);
|
|
10228
|
+
grid-template-columns: minmax(0, 1fr) auto;
|
|
10229
|
+
gap: 24px;
|
|
10230
|
+
padding: 9px 12px;
|
|
10231
|
+
font-size: 12px;
|
|
10232
|
+
display: grid;
|
|
10233
|
+
}
|
|
10234
|
+
|
|
10235
|
+
.work-document-statistics > div + div {
|
|
10236
|
+
border-top: 1px solid var(--a3s-line);
|
|
10237
|
+
}
|
|
10238
|
+
|
|
10239
|
+
.work-document-statistics dt {
|
|
10240
|
+
color: var(--a3s-muted);
|
|
10241
|
+
}
|
|
10242
|
+
|
|
10243
|
+
.work-document-statistics dd {
|
|
10244
|
+
color: var(--a3s-ink);
|
|
10245
|
+
font-variant-numeric: tabular-nums;
|
|
10246
|
+
margin: 0;
|
|
10247
|
+
font-weight: 620;
|
|
10248
|
+
}
|
|
10249
|
+
|
|
10069
10250
|
@media (width <= 1080px) {
|
|
10070
10251
|
.work-export-button {
|
|
10071
10252
|
padding: 0 9px;
|
|
@@ -10092,7 +10273,7 @@ html[data-ds-resizing="horizontal"], html[data-ds-resizing="horizontal"] * {
|
|
|
10092
10273
|
}
|
|
10093
10274
|
|
|
10094
10275
|
@media (width <= 760px) {
|
|
10095
|
-
.work-document-footer .work-office-status-info [
|
|
10276
|
+
.work-document-footer .work-office-status-info [data-document-status-item="section"], .work-document-footer .work-office-status-info [data-document-status-item="spellcheck"] {
|
|
10096
10277
|
display: none;
|
|
10097
10278
|
}
|
|
10098
10279
|
|
|
@@ -10101,6 +10282,37 @@ html[data-ds-resizing="horizontal"], html[data-ds-resizing="horizontal"] * {
|
|
|
10101
10282
|
}
|
|
10102
10283
|
}
|
|
10103
10284
|
|
|
10285
|
+
@media (width <= 520px) {
|
|
10286
|
+
.work-document-footer.work-office-status {
|
|
10287
|
+
flex-basis: 40px;
|
|
10288
|
+
gap: 6px;
|
|
10289
|
+
height: 40px;
|
|
10290
|
+
padding-inline: 8px;
|
|
10291
|
+
}
|
|
10292
|
+
|
|
10293
|
+
.work-document-footer .work-office-status-info {
|
|
10294
|
+
gap: 8px;
|
|
10295
|
+
}
|
|
10296
|
+
|
|
10297
|
+
.work-document-footer .work-office-status-info [data-document-status-item="word-count"], .work-document-footer .work-office-status-view [data-document-status-control="view-mode"] {
|
|
10298
|
+
display: none;
|
|
10299
|
+
}
|
|
10300
|
+
|
|
10301
|
+
.work-document-footer .work-office-status-view {
|
|
10302
|
+
gap: 2px;
|
|
10303
|
+
}
|
|
10304
|
+
|
|
10305
|
+
.work-document-footer.work-office-status button {
|
|
10306
|
+
width: 36px;
|
|
10307
|
+
height: 36px;
|
|
10308
|
+
}
|
|
10309
|
+
|
|
10310
|
+
.work-document-footer .work-office-status-slider {
|
|
10311
|
+
width: 48px;
|
|
10312
|
+
margin-inline: 0;
|
|
10313
|
+
}
|
|
10314
|
+
}
|
|
10315
|
+
|
|
10104
10316
|
.work-document-layout-panel > legend {
|
|
10105
10317
|
float: none;
|
|
10106
10318
|
color: var(--a3s-ink);
|
|
@@ -32,6 +32,39 @@ model:
|
|
|
32
32
|
from host-page controls while its own shortcuts remain deterministic.
|
|
33
33
|
Successful object and grid commands restore focus to the latest controlled
|
|
34
34
|
selection before the next keystroke.
|
|
35
|
+
Writer keeps tab, group, label, and shortcut metadata in one internal
|
|
36
|
+
command catalog. Undo and redo live in a keyboard-described quick-access
|
|
37
|
+
toolbar. The ribbon measures its own toolbar instead of the browser viewport
|
|
38
|
+
and compacts low-priority, then normal-priority groups before exposing group
|
|
39
|
+
paging. It can remain collapsed; activating a tab temporarily overlays that
|
|
40
|
+
tab's commands without moving the document, and an outside pointer action
|
|
41
|
+
returns to the compact row. Writer routes its catalogued WPS font-size,
|
|
42
|
+
alignment, line-spacing, heading, spelling, field-refresh, comment, and
|
|
43
|
+
track-changes shortcuts only while the document surface owns the event. The
|
|
44
|
+
status route uses the same catalog for WPS word count, opening live page,
|
|
45
|
+
word, character, and paragraph details from either `Ctrl+Shift+G` or the
|
|
46
|
+
visible count. Its local formatting clipboard powers WPS copy-format and
|
|
47
|
+
paste-format shortcuts
|
|
48
|
+
plus a one-shot format painter without requiring browser clipboard access;
|
|
49
|
+
paste replaces only direct character and paragraph formatting, preserving
|
|
50
|
+
links, comments, and revision semantics in one document transaction.
|
|
51
|
+
Header and footer TipTap surfaces register the same WPS alignment and
|
|
52
|
+
copy-format shortcuts. Cross-surface paste retains compatible marks and
|
|
53
|
+
paragraph attributes while falling back from unsupported heading nodes.
|
|
54
|
+
Writer orders Insert commands as Pages, Table, Illustrations, Links, Header
|
|
55
|
+
and Footer, and Text. Page Layout keeps direct margin, orientation, paper,
|
|
56
|
+
and equal-column presets in the ribbon; custom margins and advanced columns
|
|
57
|
+
open the corresponding controlled Page Setup tab instead of duplicating a
|
|
58
|
+
second settings model. References separates footnotes, captions, citations
|
|
59
|
+
and bibliography, and field updates; Review derives previous, next, accept,
|
|
60
|
+
and reject availability from the live revision ranges and moves the
|
|
61
|
+
selection to the next resolvable change. View keeps document modes before
|
|
62
|
+
display controls and calculates One Page and Page Width zoom from the live
|
|
63
|
+
page metrics and scroll viewport. Picture, Table, and Header and Footer tabs
|
|
64
|
+
carry explicit contextual semantics and disappear with their selection. The
|
|
65
|
+
labelled status surface provides arrow-key traversal across view and zoom
|
|
66
|
+
controls; compact Web widths remove secondary section, proofing, citation,
|
|
67
|
+
and save items in stages while retaining physical-page and zoom feedback.
|
|
35
68
|
2. Each editor owns its selection model and exposes typed commands to the
|
|
36
69
|
shell. A command never searches rendered text or infers intent from labels.
|
|
37
70
|
3. Interactive editing stays on the main thread. Presentation keeps object
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@a3s-lab/office",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.0",
|
|
4
4
|
"description": "Open-source browser editors for documents, Markdown, spreadsheets, presentations, and PDFs.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"office",
|
|
@@ -90,6 +90,16 @@
|
|
|
90
90
|
"test:e2e:fixtures": "bun scripts/create-e2e-fixtures.ts",
|
|
91
91
|
"test:e2e:wps-layout": "bun run test:e2e:fixtures && a3s-test run tests/e2e/word-wps-layout-parity.acl --json && a3s-test run tests/e2e/word-wps-font-grid-parity.acl --json",
|
|
92
92
|
"test:e2e:wps-layout:check": "bun run test:e2e:fixtures && a3s-test check tests/e2e/word-wps-layout-parity.acl --json && a3s-test check tests/e2e/word-wps-font-grid-parity.acl --json",
|
|
93
|
+
"test:e2e:writer-ribbon": "a3s-test run tests/e2e/word-ribbon-collapse.acl --json",
|
|
94
|
+
"test:e2e:writer-ribbon:check": "a3s-test check tests/e2e/word-ribbon-collapse.acl --json",
|
|
95
|
+
"test:e2e:writer-shortcuts": "a3s-test run tests/e2e/word-wps-shortcuts.acl --json",
|
|
96
|
+
"test:e2e:writer-shortcuts:check": "a3s-test check tests/e2e/word-wps-shortcuts.acl --json",
|
|
97
|
+
"test:e2e:writer-layout": "a3s-test run tests/e2e/word-insert-page-layout.acl --json",
|
|
98
|
+
"test:e2e:writer-layout:check": "a3s-test check tests/e2e/word-insert-page-layout.acl --json",
|
|
99
|
+
"test:e2e:writer-review-view": "a3s-test run tests/e2e/word-review-view.acl --json",
|
|
100
|
+
"test:e2e:writer-review-view:check": "a3s-test check tests/e2e/word-review-view.acl --json",
|
|
101
|
+
"test:e2e:writer-status": "a3s-test run tests/e2e/word-status-bar.acl --json",
|
|
102
|
+
"test:e2e:writer-status:check": "a3s-test check tests/e2e/word-status-bar.acl --json",
|
|
93
103
|
"test:wps-layout": "powershell -NoProfile -ExecutionPolicy Bypass -File scripts/test-wps-layout-parity.ps1",
|
|
94
104
|
"test:watch": "rstest --watch",
|
|
95
105
|
"typecheck": "tsc --noEmit"
|