@beyondwork/docx-react-component 1.0.41 → 1.0.43
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/package.json +38 -37
- package/src/api/awareness-identity-types.ts +35 -0
- package/src/api/comment-negotiation-types.ts +130 -0
- package/src/api/comment-presentation-types.ts +106 -0
- package/src/api/editor-state-types.ts +110 -0
- package/src/api/external-custody-types.ts +74 -0
- package/src/api/participants-types.ts +18 -0
- package/src/api/public-types.ts +541 -5
- package/src/api/scope-metadata-resolver-types.ts +88 -0
- package/src/core/commands/formatting-commands.ts +1 -1
- package/src/core/commands/index.ts +601 -9
- package/src/core/search/search-text.ts +15 -2
- package/src/index.ts +131 -1
- package/src/io/docx-session.ts +672 -2
- package/src/io/export/escape-xml-attribute.ts +26 -0
- package/src/io/export/external-send.ts +188 -0
- package/src/io/export/serialize-comments.ts +13 -16
- package/src/io/export/serialize-footnotes.ts +17 -24
- package/src/io/export/serialize-headers-footers.ts +17 -24
- package/src/io/export/serialize-main-document.ts +59 -62
- package/src/io/export/serialize-numbering.ts +20 -27
- package/src/io/export/serialize-runtime-revisions.ts +2 -9
- package/src/io/export/serialize-tables.ts +8 -15
- package/src/io/export/table-properties-xml.ts +25 -32
- package/src/io/import/external-reimport.ts +40 -0
- package/src/io/load-scheduler.ts +230 -0
- package/src/io/normalize/normalize-text.ts +83 -0
- package/src/io/ooxml/bw-xml.ts +244 -0
- package/src/io/ooxml/canonicalize-payload.ts +301 -0
- package/src/io/ooxml/comment-negotiation-payload.ts +288 -0
- package/src/io/ooxml/comment-presentation-payload.ts +311 -0
- package/src/io/ooxml/external-custody-payload.ts +102 -0
- package/src/io/ooxml/participants-payload.ts +97 -0
- package/src/io/ooxml/payload-signature.ts +112 -0
- package/src/io/ooxml/workflow-payload-validator.ts +367 -0
- package/src/io/ooxml/workflow-payload.ts +317 -7
- package/src/runtime/awareness-identity.ts +173 -0
- package/src/runtime/collab/event-types.ts +27 -0
- package/src/runtime/collab-session-bridge.ts +157 -0
- package/src/runtime/collab-session-facet.ts +193 -0
- package/src/runtime/collab-session.ts +273 -0
- package/src/runtime/comment-negotiation-sync.ts +91 -0
- package/src/runtime/comment-negotiation.ts +158 -0
- package/src/runtime/comment-presentation.ts +223 -0
- package/src/runtime/document-runtime.ts +639 -124
- package/src/runtime/editor-state-channel.ts +544 -0
- package/src/runtime/editor-state-integration.ts +217 -0
- package/src/runtime/external-send-runtime.ts +117 -0
- package/src/runtime/layout/docx-font-loader.ts +11 -30
- package/src/runtime/layout/index.ts +2 -0
- package/src/runtime/layout/inert-layout-facet.ts +4 -0
- package/src/runtime/layout/layout-engine-instance.ts +139 -14
- package/src/runtime/layout/page-graph.ts +79 -7
- package/src/runtime/layout/paginated-layout-engine.ts +441 -48
- package/src/runtime/layout/public-facet.ts +585 -14
- package/src/runtime/layout/table-row-split.ts +316 -0
- package/src/runtime/markdown-sanitizer.ts +132 -0
- package/src/runtime/participants.ts +134 -0
- package/src/runtime/perf-counters.ts +28 -0
- package/src/runtime/render/render-frame-types.ts +17 -0
- package/src/runtime/render/render-kernel.ts +172 -29
- package/src/runtime/resign-payload.ts +120 -0
- package/src/runtime/surface-projection.ts +10 -5
- package/src/runtime/tamper-gate.ts +157 -0
- package/src/runtime/workflow-markup.ts +80 -16
- package/src/runtime/workflow-rail-segments.ts +244 -5
- package/src/ui/WordReviewEditor.tsx +654 -45
- package/src/ui/editor-command-bag.ts +14 -0
- package/src/ui/editor-runtime-boundary.ts +111 -11
- package/src/ui/editor-shell-view.tsx +21 -0
- package/src/ui/editor-surface-controller.tsx +5 -0
- package/src/ui/headless/selection-helpers.ts +10 -0
- package/src/ui-tailwind/chrome/chrome-preset-model.ts +28 -0
- package/src/ui-tailwind/chrome/chrome-preset-toolbar.tsx +62 -2
- package/src/ui-tailwind/chrome/collab-audience-chip.tsx +73 -0
- package/src/ui-tailwind/chrome/collab-negotiation-action-bar.tsx +244 -0
- package/src/ui-tailwind/chrome/collab-presence-strip.tsx +150 -0
- package/src/ui-tailwind/chrome/collab-role-chip.tsx +62 -0
- package/src/ui-tailwind/chrome/collab-send-to-supplier-button.tsx +68 -0
- package/src/ui-tailwind/chrome/collab-send-to-supplier-modal.tsx +149 -0
- package/src/ui-tailwind/chrome/collab-tamper-banner.tsx +68 -0
- package/src/ui-tailwind/chrome/collab-top-nav-container.tsx +281 -0
- package/src/ui-tailwind/chrome/forward-non-drag-click.ts +104 -0
- package/src/ui-tailwind/chrome/tw-mode-dock.tsx +1 -0
- package/src/ui-tailwind/chrome/tw-selection-tool-host.tsx +7 -1
- package/src/ui-tailwind/chrome/tw-table-grip-layer.tsx +1 -38
- package/src/ui-tailwind/chrome-overlay/index.ts +6 -0
- package/src/ui-tailwind/chrome-overlay/scope-card-role-model.ts +78 -0
- package/src/ui-tailwind/chrome-overlay/scope-keyboard-cycle.ts +49 -0
- package/src/ui-tailwind/chrome-overlay/tw-chrome-overlay.tsx +106 -0
- package/src/ui-tailwind/chrome-overlay/tw-page-stack-overlay-layer.tsx +527 -0
- package/src/ui-tailwind/chrome-overlay/tw-scope-card-layer.tsx +120 -22
- package/src/ui-tailwind/chrome-overlay/tw-scope-card.tsx +310 -32
- package/src/ui-tailwind/chrome-overlay/tw-scope-rail-layer.tsx +93 -14
- package/src/ui-tailwind/editor-surface/paste-plain-text.ts +72 -0
- package/src/ui-tailwind/editor-surface/pm-command-bridge.ts +118 -8
- package/src/ui-tailwind/editor-surface/pm-decorations.ts +35 -1
- package/src/ui-tailwind/editor-surface/pm-page-break-decorations.ts +86 -3
- package/src/ui-tailwind/editor-surface/pm-schema.ts +167 -17
- package/src/ui-tailwind/editor-surface/pm-state-from-snapshot.ts +35 -7
- package/src/ui-tailwind/editor-surface/remote-cursor-plugin.ts +20 -3
- package/src/ui-tailwind/editor-surface/tw-page-block-view.helpers.ts +265 -0
- package/src/ui-tailwind/editor-surface/tw-page-block-view.tsx +10 -256
- package/src/ui-tailwind/editor-surface/tw-prosemirror-surface.tsx +9 -0
- package/src/ui-tailwind/editor-surface/tw-table-node-view.tsx +66 -0
- package/src/ui-tailwind/index.ts +37 -1
- package/src/ui-tailwind/page-stack/tw-endnote-area.tsx +57 -0
- package/src/ui-tailwind/page-stack/tw-footnote-area.tsx +71 -0
- package/src/ui-tailwind/page-stack/tw-page-footer-band.tsx +73 -0
- package/src/ui-tailwind/page-stack/tw-page-header-band.tsx +74 -0
- package/src/ui-tailwind/page-stack/tw-page-stack-chrome-layer.tsx +477 -0
- package/src/ui-tailwind/page-stack/tw-region-block-renderer.tsx +374 -0
- package/src/ui-tailwind/review/comment-markdown-renderer.tsx +155 -0
- package/src/ui-tailwind/review/tw-comment-sidebar.tsx +77 -16
- package/src/ui-tailwind/review/tw-review-rail-footer.tsx +29 -3
- package/src/ui-tailwind/status/tw-status-bar.tsx +52 -1
- package/src/ui-tailwind/theme/editor-theme.css +25 -0
- package/src/ui-tailwind/tw-review-workspace.tsx +455 -118
|
@@ -17,11 +17,36 @@ export interface TwReviewRailFooterProps {
|
|
|
17
17
|
const focusRingClass =
|
|
18
18
|
"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-accent focus-visible:ring-offset-1 focus-visible:ring-offset-canvas";
|
|
19
19
|
|
|
20
|
+
/**
|
|
21
|
+
* Accept only http(s) and mailto help links. Rejects javascript:, data:,
|
|
22
|
+
* and any other scheme that could execute code when a reviewer clicks the
|
|
23
|
+
* help button. Host-supplied; treated as untrusted.
|
|
24
|
+
*/
|
|
25
|
+
function safeHelpHref(raw: string | undefined): string | undefined {
|
|
26
|
+
if (typeof raw !== "string") return undefined;
|
|
27
|
+
const value = raw.trim();
|
|
28
|
+
if (value.length === 0) return undefined;
|
|
29
|
+
// Allow relative paths (no scheme) — hosts often use `/docs/help`.
|
|
30
|
+
if (value.startsWith("/") || value.startsWith("#") || value.startsWith("?")) {
|
|
31
|
+
return value;
|
|
32
|
+
}
|
|
33
|
+
try {
|
|
34
|
+
const url = new URL(value, "https://placeholder.invalid/");
|
|
35
|
+
if (url.protocol === "https:" || url.protocol === "http:" || url.protocol === "mailto:") {
|
|
36
|
+
return value;
|
|
37
|
+
}
|
|
38
|
+
} catch {
|
|
39
|
+
// fall through
|
|
40
|
+
}
|
|
41
|
+
return undefined;
|
|
42
|
+
}
|
|
43
|
+
|
|
20
44
|
export function TwReviewRailFooter(props: TwReviewRailFooterProps) {
|
|
21
45
|
const searchLabel = props.searchLabel ?? "SEARCH";
|
|
22
46
|
const helpLabel = props.helpLabel ?? "HELP";
|
|
47
|
+
const helpHref = safeHelpHref(props.helpHref);
|
|
23
48
|
|
|
24
|
-
if (!props.onSearch && !
|
|
49
|
+
if (!props.onSearch && !helpHref) {
|
|
25
50
|
return null;
|
|
26
51
|
}
|
|
27
52
|
|
|
@@ -38,9 +63,10 @@ export function TwReviewRailFooter(props: TwReviewRailFooterProps) {
|
|
|
38
63
|
</button>
|
|
39
64
|
) : null}
|
|
40
65
|
|
|
41
|
-
{
|
|
66
|
+
{helpHref ? (
|
|
42
67
|
<a
|
|
43
|
-
href={
|
|
68
|
+
href={helpHref}
|
|
69
|
+
rel="noopener noreferrer"
|
|
44
70
|
className={`inline-flex items-center gap-1.5 rounded-sm px-2 py-1 text-[10px] font-semibold uppercase tracking-[0.14em] text-tertiary transition-colors hover:text-secondary ${focusRingClass}`}
|
|
45
71
|
>
|
|
46
72
|
<HelpCircle aria-hidden="true" className="h-3 w-3" />
|
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
import React from "react";
|
|
2
2
|
|
|
3
|
-
import type {
|
|
3
|
+
import type {
|
|
4
|
+
PublicMeasurementFidelity,
|
|
5
|
+
RuntimeContextAnalyticsSnapshot,
|
|
6
|
+
} from "../../api/public-types";
|
|
4
7
|
|
|
5
8
|
export interface TwStatusBarProps {
|
|
6
9
|
isDirty: boolean;
|
|
@@ -10,6 +13,26 @@ export interface TwStatusBarProps {
|
|
|
10
13
|
changeCount: number;
|
|
11
14
|
sessionId: string;
|
|
12
15
|
contextAnalytics?: RuntimeContextAnalyticsSnapshot | null;
|
|
16
|
+
/**
|
|
17
|
+
* P5b: **displayed** page number for the selection head. When the
|
|
18
|
+
* active section restarts page numbering (roman front matter → arabic
|
|
19
|
+
* body), this reflects what Word would print on the page — not the
|
|
20
|
+
* raw 0-based document-order index. Pass `null` when the facet has
|
|
21
|
+
* no resolved page (e.g., during initial load).
|
|
22
|
+
*/
|
|
23
|
+
displayPageNumber?: number | null;
|
|
24
|
+
/**
|
|
25
|
+
* P5b: total **content** page count (excludes evenPage / oddPage
|
|
26
|
+
* blank fillers). Matches `facet.getPageCount()` — same quantity a
|
|
27
|
+
* `NUMPAGES` field resolves to on every page.
|
|
28
|
+
*/
|
|
29
|
+
pageCount?: number | null;
|
|
30
|
+
/**
|
|
31
|
+
* P5b: measurement fidelity the layout engine is computing against.
|
|
32
|
+
* Surfaced as a compact badge so harness operators can see when the
|
|
33
|
+
* canvas backend is live vs. the empirical fallback. Absent = skip.
|
|
34
|
+
*/
|
|
35
|
+
measurementFidelity?: PublicMeasurementFidelity;
|
|
13
36
|
}
|
|
14
37
|
|
|
15
38
|
export function TwStatusBar(props: TwStatusBarProps) {
|
|
@@ -56,10 +79,38 @@ export function TwStatusBar(props: TwStatusBarProps) {
|
|
|
56
79
|
{props.commentCount} comment{props.commentCount !== 1 ? "s" : ""} ·{" "}
|
|
57
80
|
{props.changeCount} change{props.changeCount !== 1 ? "s" : ""}
|
|
58
81
|
</span>
|
|
82
|
+
{props.displayPageNumber != null && props.pageCount != null ? (
|
|
83
|
+
<span data-testid="status-bar-page-count">
|
|
84
|
+
Page {props.displayPageNumber} of {props.pageCount}
|
|
85
|
+
</span>
|
|
86
|
+
) : null}
|
|
59
87
|
<span className="flex-1" />
|
|
88
|
+
{props.measurementFidelity ? (
|
|
89
|
+
<span
|
|
90
|
+
data-testid="status-bar-measurement-fidelity"
|
|
91
|
+
data-fidelity={props.measurementFidelity}
|
|
92
|
+
className="uppercase tracking-[0.12em] text-tertiary/70"
|
|
93
|
+
title={`Measurement fidelity: ${props.measurementFidelity}`}
|
|
94
|
+
>
|
|
95
|
+
{formatFidelityBadge(props.measurementFidelity)}
|
|
96
|
+
</span>
|
|
97
|
+
) : null}
|
|
60
98
|
<span className="truncate text-[10px] uppercase tracking-[0.12em] text-tertiary/80">
|
|
61
99
|
Session active
|
|
62
100
|
</span>
|
|
63
101
|
</footer>
|
|
64
102
|
);
|
|
65
103
|
}
|
|
104
|
+
|
|
105
|
+
function formatFidelityBadge(fidelity: PublicMeasurementFidelity): string {
|
|
106
|
+
switch (fidelity) {
|
|
107
|
+
case "empirical":
|
|
108
|
+
return "E";
|
|
109
|
+
case "canvas":
|
|
110
|
+
return "C";
|
|
111
|
+
case "canvas-with-font-loading":
|
|
112
|
+
return "C+F";
|
|
113
|
+
default:
|
|
114
|
+
return String(fidelity);
|
|
115
|
+
}
|
|
116
|
+
}
|
|
@@ -488,6 +488,31 @@
|
|
|
488
488
|
outline-offset: -1px;
|
|
489
489
|
}
|
|
490
490
|
|
|
491
|
+
/*
|
|
492
|
+
* ─── Agent-pending shimmer (K2 / scope-card-overlay P2) ───
|
|
493
|
+
*
|
|
494
|
+
* Painted on every scope tint that overlaps a WorkflowCandidateRange
|
|
495
|
+
* with `source: "ai"`. A soft 1.8s pulse signals the agent is
|
|
496
|
+
* thinking without competing with the active outline. Reduced-
|
|
497
|
+
* motion disables the animation and holds a static 60% opacity
|
|
498
|
+
* border so the posture is still readable.
|
|
499
|
+
*/
|
|
500
|
+
@keyframes wre-agent-pulse {
|
|
501
|
+
0%, 100% { opacity: 0.4; }
|
|
502
|
+
50% { opacity: 0.85; }
|
|
503
|
+
}
|
|
504
|
+
|
|
505
|
+
.wre-scope-rail-tint-agent-pending {
|
|
506
|
+
outline: 1px solid color-mix(in srgb, var(--color-workflow) 70%, transparent);
|
|
507
|
+
outline-offset: -1px;
|
|
508
|
+
animation: wre-agent-pulse 1.8s ease-in-out infinite;
|
|
509
|
+
}
|
|
510
|
+
|
|
511
|
+
[data-reduced-motion="true"] .wre-scope-rail-tint-agent-pending {
|
|
512
|
+
animation: none;
|
|
513
|
+
opacity: 0.6;
|
|
514
|
+
}
|
|
515
|
+
|
|
491
516
|
/*
|
|
492
517
|
* ─── Scope rail stripe ───
|
|
493
518
|
*
|