@beyondwork/docx-react-component 1.0.1 โ†’ 1.0.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.
Files changed (172) hide show
  1. package/README.md +44 -104
  2. package/package.json +50 -30
  3. package/src/README.md +85 -0
  4. package/src/api/README.md +22 -0
  5. package/src/api/public-types.ts +525 -0
  6. package/src/compare/diff-engine.ts +530 -0
  7. package/src/compare/export-redlines.ts +162 -0
  8. package/src/compare/snapshot.ts +37 -0
  9. package/src/component-inventory.md +99 -0
  10. package/src/core/README.md +10 -0
  11. package/src/core/commands/README.md +3 -0
  12. package/src/core/commands/formatting-commands.ts +161 -0
  13. package/src/core/commands/image-commands.ts +144 -0
  14. package/src/core/commands/index.ts +1013 -0
  15. package/src/core/commands/list-commands.ts +370 -0
  16. package/src/core/commands/review-commands.ts +108 -0
  17. package/src/core/commands/text-commands.ts +119 -0
  18. package/src/core/schema/README.md +3 -0
  19. package/src/core/schema/text-schema.ts +512 -0
  20. package/src/core/selection/README.md +3 -0
  21. package/src/core/selection/mapping.ts +238 -0
  22. package/src/core/selection/review-anchors.ts +94 -0
  23. package/src/core/state/README.md +3 -0
  24. package/src/core/state/editor-state.ts +580 -0
  25. package/src/core/state/text-transaction.ts +276 -0
  26. package/src/formats/xlsx/io/parse-shared-strings.ts +41 -0
  27. package/src/formats/xlsx/io/parse-sheet.ts +289 -0
  28. package/src/formats/xlsx/io/parse-styles.ts +57 -0
  29. package/src/formats/xlsx/io/parse-workbook.ts +75 -0
  30. package/src/formats/xlsx/io/xlsx-session.ts +306 -0
  31. package/src/formats/xlsx/model/cell.ts +189 -0
  32. package/src/formats/xlsx/model/sheet.ts +244 -0
  33. package/src/formats/xlsx/model/styles.ts +118 -0
  34. package/src/formats/xlsx/model/workbook.ts +449 -0
  35. package/src/index.ts +45 -0
  36. package/src/io/README.md +10 -0
  37. package/src/io/docx-session.ts +1763 -0
  38. package/src/io/export/README.md +3 -0
  39. package/src/io/export/export-session.ts +165 -0
  40. package/src/io/export/minimal-docx.ts +115 -0
  41. package/src/io/export/reattach-preserved-parts.ts +54 -0
  42. package/src/io/export/serialize-comments.ts +876 -0
  43. package/src/io/export/serialize-footnotes.ts +217 -0
  44. package/src/io/export/serialize-headers-footers.ts +200 -0
  45. package/src/io/export/serialize-main-document.ts +982 -0
  46. package/src/io/export/serialize-numbering.ts +97 -0
  47. package/src/io/export/serialize-revisions.ts +389 -0
  48. package/src/io/export/serialize-runtime-revisions.ts +265 -0
  49. package/src/io/export/serialize-tables.ts +147 -0
  50. package/src/io/export/split-review-boundaries.ts +194 -0
  51. package/src/io/normalize/README.md +3 -0
  52. package/src/io/normalize/normalize-text.ts +437 -0
  53. package/src/io/ooxml/README.md +3 -0
  54. package/src/io/ooxml/parse-comments.ts +779 -0
  55. package/src/io/ooxml/parse-complex-content.ts +287 -0
  56. package/src/io/ooxml/parse-fields.ts +438 -0
  57. package/src/io/ooxml/parse-footnotes.ts +403 -0
  58. package/src/io/ooxml/parse-headers-footers.ts +483 -0
  59. package/src/io/ooxml/parse-inline-media.ts +431 -0
  60. package/src/io/ooxml/parse-main-document.ts +1846 -0
  61. package/src/io/ooxml/parse-numbering.ts +425 -0
  62. package/src/io/ooxml/parse-revisions.ts +658 -0
  63. package/src/io/ooxml/parse-shapes.ts +271 -0
  64. package/src/io/ooxml/parse-tables.ts +568 -0
  65. package/src/io/ooxml/parse-theme.ts +314 -0
  66. package/src/io/ooxml/part-manifest.ts +136 -0
  67. package/src/io/ooxml/revision-boundaries.ts +351 -0
  68. package/src/io/opc/README.md +3 -0
  69. package/src/io/opc/corrupt-package.ts +166 -0
  70. package/src/io/opc/docx-package.ts +74 -0
  71. package/src/io/opc/package-reader.ts +325 -0
  72. package/src/io/opc/package-writer.ts +273 -0
  73. package/src/legal/bookmarks.ts +196 -0
  74. package/src/legal/cross-references.ts +356 -0
  75. package/src/legal/defined-terms.ts +203 -0
  76. package/src/model/README.md +3 -0
  77. package/src/model/canonical-document.ts +1911 -0
  78. package/src/model/cds-1.0.0.ts +196 -0
  79. package/src/model/snapshot.ts +393 -0
  80. package/src/preservation/README.md +3 -0
  81. package/src/preservation/markup-compatibility.ts +48 -0
  82. package/src/preservation/opaque-fragment-store.ts +89 -0
  83. package/src/preservation/opaque-region.ts +233 -0
  84. package/src/preservation/package-preservation.ts +120 -0
  85. package/src/preservation/preserved-part-manifest.ts +56 -0
  86. package/src/preservation/relationship-retention.ts +57 -0
  87. package/src/preservation/store.ts +185 -0
  88. package/src/review/README.md +16 -0
  89. package/src/review/store/README.md +3 -0
  90. package/src/review/store/comment-anchors.ts +70 -0
  91. package/src/review/store/comment-remapping.ts +154 -0
  92. package/src/review/store/comment-store.ts +331 -0
  93. package/src/review/store/comment-thread.ts +109 -0
  94. package/src/review/store/revision-actions.ts +394 -0
  95. package/src/review/store/revision-store.ts +303 -0
  96. package/src/review/store/revision-types.ts +168 -0
  97. package/src/review/store/runtime-comment-store.ts +43 -0
  98. package/src/runtime/README.md +3 -0
  99. package/src/runtime/ai-action-policy.ts +764 -0
  100. package/src/runtime/document-runtime.ts +967 -0
  101. package/src/runtime/read-only-diagnostics-runtime.ts +232 -0
  102. package/src/runtime/review-runtime.ts +44 -0
  103. package/src/runtime/revision-runtime.ts +107 -0
  104. package/src/runtime/session-capabilities.ts +138 -0
  105. package/src/runtime/surface-projection.ts +570 -0
  106. package/src/runtime/table-commands.ts +87 -0
  107. package/src/runtime/table-schema.ts +140 -0
  108. package/src/runtime/virtualized-rendering.ts +258 -0
  109. package/src/ui/README.md +30 -0
  110. package/src/ui/WordReviewEditor.tsx +1506 -0
  111. package/src/ui/comments/README.md +3 -0
  112. package/src/ui/compatibility/README.md +3 -0
  113. package/src/ui/editor-surface/README.md +3 -0
  114. package/src/ui/headless/comment-decoration-model.ts +124 -0
  115. package/src/ui/headless/revision-decoration-model.ts +128 -0
  116. package/src/ui/headless/selection-helpers.ts +34 -0
  117. package/src/ui/headless/use-editor-keyboard.ts +98 -0
  118. package/src/ui/review/README.md +3 -0
  119. package/src/ui/shared/revision-filters.ts +31 -0
  120. package/src/ui/status/README.md +3 -0
  121. package/src/ui/theme/README.md +3 -0
  122. package/src/ui/toolbar/README.md +3 -0
  123. package/src/ui-tailwind/chrome/tw-alert-banner.tsx +48 -0
  124. package/src/ui-tailwind/chrome/tw-selection-toolbar.tsx +44 -0
  125. package/src/ui-tailwind/chrome/tw-unsaved-modal.tsx +58 -0
  126. package/src/ui-tailwind/chrome/use-before-unload.ts +20 -0
  127. package/src/ui-tailwind/editor-surface/pm-command-bridge.ts +139 -0
  128. package/src/ui-tailwind/editor-surface/pm-decorations.ts +98 -0
  129. package/src/ui-tailwind/editor-surface/pm-position-map.ts +123 -0
  130. package/src/ui-tailwind/editor-surface/pm-schema.ts +452 -0
  131. package/src/ui-tailwind/editor-surface/pm-state-from-snapshot.ts +327 -0
  132. package/src/ui-tailwind/editor-surface/search-plugin.ts +157 -0
  133. package/src/ui-tailwind/editor-surface/tw-caret.tsx +12 -0
  134. package/src/ui-tailwind/editor-surface/tw-editor-surface.tsx +150 -0
  135. package/src/ui-tailwind/editor-surface/tw-inline-token.tsx +118 -0
  136. package/src/ui-tailwind/editor-surface/tw-opaque-block.tsx +52 -0
  137. package/src/ui-tailwind/editor-surface/tw-paragraph-block.tsx +151 -0
  138. package/src/ui-tailwind/editor-surface/tw-prosemirror-surface.tsx +215 -0
  139. package/src/ui-tailwind/editor-surface/tw-segment-view.tsx +111 -0
  140. package/src/ui-tailwind/editor-surface/tw-table-node-view.tsx +122 -0
  141. package/src/ui-tailwind/index.ts +61 -0
  142. package/src/ui-tailwind/review/tw-comment-sidebar.tsx +276 -0
  143. package/src/ui-tailwind/review/tw-health-panel.tsx +120 -0
  144. package/src/ui-tailwind/review/tw-review-rail.tsx +120 -0
  145. package/src/ui-tailwind/review/tw-revision-sidebar.tsx +164 -0
  146. package/src/ui-tailwind/status/tw-status-bar.tsx +58 -0
  147. package/src/ui-tailwind/theme/editor-theme.css +190 -0
  148. package/src/ui-tailwind/toolbar/tw-toolbar-icon-button.tsx +48 -0
  149. package/src/ui-tailwind/toolbar/tw-toolbar.tsx +231 -0
  150. package/src/ui-tailwind/tw-review-workspace.tsx +140 -0
  151. package/src/validation/README.md +3 -0
  152. package/src/validation/compatibility-engine.ts +317 -0
  153. package/src/validation/compatibility-report.ts +160 -0
  154. package/src/validation/diagnostics.ts +203 -0
  155. package/src/validation/import-diagnostics.ts +128 -0
  156. package/src/validation/low-priority-word-surfaces.ts +373 -0
  157. package/dist/chunk-32W6IVQE.js +0 -7725
  158. package/dist/chunk-32W6IVQE.js.map +0 -1
  159. package/dist/index.cjs +0 -23722
  160. package/dist/index.cjs.map +0 -1
  161. package/dist/index.d.cts +0 -7
  162. package/dist/index.d.ts +0 -7
  163. package/dist/index.js +0 -16011
  164. package/dist/index.js.map +0 -1
  165. package/dist/public-types-DqCURAz8.d.cts +0 -1152
  166. package/dist/public-types-DqCURAz8.d.ts +0 -1152
  167. package/dist/tailwind.cjs +0 -8295
  168. package/dist/tailwind.cjs.map +0 -1
  169. package/dist/tailwind.d.cts +0 -323
  170. package/dist/tailwind.d.ts +0 -323
  171. package/dist/tailwind.js +0 -553
  172. package/dist/tailwind.js.map +0 -1
package/dist/tailwind.js DELETED
@@ -1,553 +0,0 @@
1
- import {
2
- TwAlertBanner,
3
- TwCommentSidebar,
4
- TwHealthPanel,
5
- TwReviewRail,
6
- TwReviewWorkspace,
7
- TwRevisionSidebar,
8
- TwSelectionToolbar,
9
- TwStatusBar,
10
- TwToolbar,
11
- TwToolbarIconButton,
12
- createCommentDecorationModel,
13
- createRevisionDecorationModel,
14
- createSelectionSnapshot,
15
- deriveCapabilities,
16
- getCommentHighlightClass,
17
- getCommentRangeState,
18
- getRevisionHighlightClass,
19
- getRevisionRangeState,
20
- selectionTouchesRange,
21
- shouldHideInCleanMode
22
- } from "./chunk-32W6IVQE.js";
23
-
24
- // src/ui-tailwind/editor-surface/tw-editor-surface.tsx
25
- import { useMemo } from "react";
26
-
27
- // src/ui/headless/use-editor-keyboard.ts
28
- function createEditorKeyboardHandler(context, callbacks) {
29
- return function handleKeyDown(event) {
30
- const { selection, storySize, canEdit } = context;
31
- if (event.key === "ArrowLeft") {
32
- event.preventDefault();
33
- moveSelection(selection.anchor, selection.head - 1, event.shiftKey, storySize, callbacks);
34
- return;
35
- }
36
- if (event.key === "ArrowRight") {
37
- event.preventDefault();
38
- moveSelection(selection.anchor, selection.head + 1, event.shiftKey, storySize, callbacks);
39
- return;
40
- }
41
- if (event.key === "Home") {
42
- event.preventDefault();
43
- moveSelection(selection.anchor, 0, event.shiftKey, storySize, callbacks);
44
- return;
45
- }
46
- if (event.key === "End") {
47
- event.preventDefault();
48
- moveSelection(selection.anchor, storySize, event.shiftKey, storySize, callbacks);
49
- return;
50
- }
51
- if (!canEdit || event.metaKey || event.ctrlKey || event.altKey) {
52
- return;
53
- }
54
- switch (event.key) {
55
- case "Backspace":
56
- event.preventDefault();
57
- callbacks.onDeleteBackward?.();
58
- return;
59
- case "Delete":
60
- event.preventDefault();
61
- callbacks.onDeleteForward?.();
62
- return;
63
- case "Tab":
64
- event.preventDefault();
65
- callbacks.onInsertTab?.();
66
- return;
67
- case "Enter":
68
- event.preventDefault();
69
- if (event.shiftKey) {
70
- callbacks.onInsertHardBreak?.();
71
- } else {
72
- callbacks.onSplitParagraph?.();
73
- }
74
- return;
75
- default:
76
- if (event.key.length === 1) {
77
- event.preventDefault();
78
- callbacks.onInsertText?.(event.key);
79
- }
80
- }
81
- };
82
- }
83
- function moveSelection(anchor, nextHead, extend, storySize, callbacks) {
84
- const clampedHead = Math.max(0, Math.min(storySize, nextHead));
85
- callbacks.onSelectionChange?.(
86
- createSelectionSnapshot(extend ? anchor : clampedHead, clampedHead)
87
- );
88
- }
89
-
90
- // src/ui-tailwind/editor-surface/tw-opaque-block.tsx
91
- import { jsx, jsxs } from "react/jsx-runtime";
92
- var focusRingClass = "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-accent focus-visible:ring-offset-2 focus-visible:ring-offset-canvas";
93
- function TwOpaqueBlock(props) {
94
- const { block, selection } = props;
95
- const selected = selectionTouchesRange(selection, block.from, block.to);
96
- return /* @__PURE__ */ jsxs("div", { className: "group relative", children: [
97
- /* @__PURE__ */ jsx("div", { className: "absolute -left-10 top-1 flex flex-col items-end gap-0 select-none w-8 text-right", children: /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-0.5", children: [
98
- /* @__PURE__ */ jsx("span", { className: "text-[10px] text-tertiary/60 font-medium", children: "Lock" }),
99
- /* @__PURE__ */ jsx("span", { className: "inline-block h-1 w-1 rounded-full", style: { backgroundColor: "var(--color-comment)" } })
100
- ] }) }),
101
- /* @__PURE__ */ jsxs(
102
- "button",
103
- {
104
- type: "button",
105
- tabIndex: -1,
106
- onMouseDown: (e) => {
107
- e.preventDefault();
108
- props.onSelectionChange?.(createSelectionSnapshot(block.from, block.to));
109
- },
110
- className: [
111
- "w-full text-left border-l-2 border-dashed border-warning/30 pl-4 py-2 rounded-r bg-warning-soft/20",
112
- "cursor-pointer transition-colors",
113
- selected ? "ring-1 ring-accent/30 bg-warning-soft/40" : "hover:bg-warning-soft/30",
114
- focusRingClass
115
- ].join(" "),
116
- children: [
117
- /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1.5 text-xs text-tertiary mb-1", children: [
118
- /* @__PURE__ */ jsx("span", { children: "\u{1F512}" }),
119
- /* @__PURE__ */ jsx("span", { children: block.label }),
120
- /* @__PURE__ */ jsx("span", { className: "inline-flex items-center px-1.5 py-0.5 rounded-full text-[10px] font-semibold text-comment bg-warning-soft", children: "preserve-only" })
121
- ] }),
122
- /* @__PURE__ */ jsx("p", { className: "text-sm text-secondary", children: block.detail })
123
- ]
124
- }
125
- )
126
- ] });
127
- }
128
-
129
- // src/ui-tailwind/editor-surface/tw-caret.tsx
130
- import { jsx as jsx2 } from "react/jsx-runtime";
131
- function renderTwCaret(selection, position) {
132
- return selection.isCollapsed && selection.anchor === position ? /* @__PURE__ */ jsx2(
133
- "span",
134
- {
135
- "aria-hidden": "true",
136
- className: "inline-block w-0.5 h-[1.2em] bg-accent rounded-full align-middle animate-wre-blink"
137
- }
138
- ) : null;
139
- }
140
-
141
- // src/ui-tailwind/editor-surface/tw-inline-token.tsx
142
- import { Fragment, jsx as jsx3, jsxs as jsxs2 } from "react/jsx-runtime";
143
- var focusRingClass2 = "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-accent focus-visible:ring-offset-2 focus-visible:ring-offset-canvas";
144
- function TwInlineToken(props) {
145
- const { segment, selection } = props;
146
- const selected = selectionTouchesRange(selection, segment.from, segment.to);
147
- const commentClass = getCommentHighlightClass(
148
- props.commentDecorations,
149
- segment.from,
150
- segment.to,
151
- props.markupDisplay
152
- );
153
- const showSymbols = props.markupDisplay !== "clean";
154
- if (segment.kind === "tab") {
155
- return /* @__PURE__ */ jsxs2(
156
- "button",
157
- {
158
- type: "button",
159
- tabIndex: -1,
160
- onMouseDown: (e) => {
161
- e.preventDefault();
162
- props.onSelectionChange?.(createSelectionSnapshot(segment.from, segment.to));
163
- },
164
- className: `inline-flex items-center border-none bg-transparent cursor-text ${commentClass} ${selected ? "bg-surface-hover" : ""} ${focusRingClass2} ${showSymbols ? "mx-0.5 text-tertiary/50" : "w-8"}`,
165
- title: "Tab character",
166
- children: [
167
- renderTwCaret(selection, segment.from),
168
- showSymbols ? /* @__PURE__ */ jsx3("span", { className: "text-xs", children: "\u2192" }) : /* @__PURE__ */ jsx3("span", { className: "w-8" }),
169
- renderTwCaret(selection, segment.to)
170
- ]
171
- }
172
- );
173
- }
174
- if (segment.kind === "hard_break") {
175
- return /* @__PURE__ */ jsxs2(Fragment, { children: [
176
- /* @__PURE__ */ jsxs2(
177
- "button",
178
- {
179
- type: "button",
180
- tabIndex: -1,
181
- onMouseDown: (e) => {
182
- e.preventDefault();
183
- props.onSelectionChange?.(createSelectionSnapshot(segment.from, segment.to));
184
- },
185
- className: `inline-flex items-center border-none bg-transparent cursor-text ${commentClass} ${selected ? "bg-surface-hover" : ""} ${focusRingClass2} ${showSymbols ? "mx-0.5 text-tertiary/40" : ""}`,
186
- title: "Line break",
187
- children: [
188
- renderTwCaret(selection, segment.from),
189
- showSymbols ? /* @__PURE__ */ jsx3("span", { className: "text-xs", children: "\u21B5" }) : null,
190
- renderTwCaret(selection, segment.to)
191
- ]
192
- }
193
- ),
194
- /* @__PURE__ */ jsx3("br", {})
195
- ] });
196
- }
197
- if (segment.kind === "image") {
198
- const isMissing = segment.state === "missing";
199
- return /* @__PURE__ */ jsxs2(
200
- "button",
201
- {
202
- type: "button",
203
- tabIndex: -1,
204
- onMouseDown: (e) => {
205
- e.preventDefault();
206
- props.onSelectionChange?.(createSelectionSnapshot(segment.from, segment.to));
207
- },
208
- className: `inline-flex items-center gap-1 mx-0.5 px-1.5 py-0.5 rounded text-xs border-none cursor-pointer ${commentClass} ${isMissing ? "text-danger bg-delete-soft" : "text-secondary bg-surface"} ${selected ? "ring-1 ring-accent/30" : ""} ${focusRingClass2}`,
209
- title: segment.detail ?? segment.altText ?? "Inline image",
210
- children: [
211
- renderTwCaret(selection, segment.from),
212
- /* @__PURE__ */ jsx3("span", { children: "\u{1F4F7}" }),
213
- segment.altText ?? (isMissing ? "Missing image" : "Image"),
214
- renderTwCaret(selection, segment.to)
215
- ]
216
- }
217
- );
218
- }
219
- if (segment.kind === "opaque_inline") {
220
- return /* @__PURE__ */ jsxs2(
221
- "button",
222
- {
223
- type: "button",
224
- tabIndex: -1,
225
- onMouseDown: (e) => {
226
- e.preventDefault();
227
- props.onSelectionChange?.(createSelectionSnapshot(segment.from, segment.to));
228
- },
229
- className: `inline-flex items-center gap-1 mx-0.5 px-1.5 py-0.5 rounded text-xs text-comment bg-warning-soft border-none cursor-pointer ${commentClass} ${selected ? "ring-1 ring-accent/30" : ""} ${focusRingClass2}`,
230
- title: segment.detail,
231
- children: [
232
- renderTwCaret(selection, segment.from),
233
- /* @__PURE__ */ jsx3("span", { children: "\u{1F512}" }),
234
- segment.label,
235
- renderTwCaret(selection, segment.to)
236
- ]
237
- }
238
- );
239
- }
240
- return null;
241
- }
242
-
243
- // src/ui-tailwind/editor-surface/tw-segment-view.tsx
244
- import { Fragment as Fragment2, jsx as jsx4, jsxs as jsxs3 } from "react/jsx-runtime";
245
- function TwSegmentView(props) {
246
- const { segment, selection, markupDisplay } = props;
247
- if (segment.kind === "tab" || segment.kind === "hard_break" || segment.kind === "image" || segment.kind === "opaque_inline") {
248
- return /* @__PURE__ */ jsx4(
249
- TwInlineToken,
250
- {
251
- segment,
252
- selection,
253
- markupDisplay,
254
- commentDecorations: props.commentDecorations,
255
- onSelectionChange: props.onSelectionChange
256
- }
257
- );
258
- }
259
- if (segment.kind !== "text") {
260
- return null;
261
- }
262
- const characters = Array.from(segment.text);
263
- return /* @__PURE__ */ jsx4(Fragment2, { children: characters.map((character, index) => {
264
- const from = segment.from + index;
265
- const to = from + 1;
266
- const isSelected = selectionTouchesRange(selection, from, to);
267
- if (shouldHideInCleanMode(props.revisionDecorations, from, to) && markupDisplay === "clean") {
268
- return null;
269
- }
270
- const commentClass = getCommentHighlightClass(props.commentDecorations, from, to, markupDisplay);
271
- const revisionClass = getRevisionHighlightClass(props.revisionDecorations, from, to, markupDisplay);
272
- const commentState = getCommentRangeState(props.commentDecorations, from, to);
273
- const overlappingComment = commentState.overlapping[0];
274
- let markClasses = "";
275
- if (segment.marks) {
276
- if (segment.marks.includes("bold")) markClasses += "font-bold ";
277
- if (segment.marks.includes("italic")) markClasses += "italic ";
278
- if (segment.marks.includes("underline")) markClasses += "underline ";
279
- if (segment.marks.includes("strikethrough")) markClasses += "line-through ";
280
- }
281
- const hyperlinkClass = segment.hyperlinkHref ? "text-accent underline decoration-1 underline-offset-2 " : "";
282
- return /* @__PURE__ */ jsxs3(
283
- "button",
284
- {
285
- type: "button",
286
- tabIndex: -1,
287
- onMouseDown: (event) => {
288
- event.preventDefault();
289
- props.onSelectionChange?.(createSelectionSnapshot(to));
290
- if (overlappingComment) {
291
- props.onCommentActivated?.(overlappingComment.commentId);
292
- }
293
- },
294
- "data-comment-id": overlappingComment?.commentId,
295
- className: [
296
- "relative inline border-none bg-transparent cursor-text whitespace-pre p-0 m-0",
297
- "text-[15px] text-primary leading-normal",
298
- commentClass,
299
- revisionClass,
300
- markClasses,
301
- hyperlinkClass,
302
- isSelected ? "bg-surface-hover rounded-[3px]" : ""
303
- ].filter(Boolean).join(" "),
304
- children: [
305
- character,
306
- selection.isCollapsed && selection.anchor === from ? /* @__PURE__ */ jsx4("span", { "aria-hidden": "true", className: "absolute left-0 top-[0.1em] w-0.5 h-[1em] bg-accent rounded-full animate-wre-blink pointer-events-none" }) : null
307
- ]
308
- },
309
- `${segment.segmentId}-${from}`
310
- );
311
- }) });
312
- }
313
-
314
- // src/ui-tailwind/editor-surface/tw-paragraph-block.tsx
315
- import { Fragment as Fragment3, jsx as jsx5, jsxs as jsxs4 } from "react/jsx-runtime";
316
- function TwParagraphBlock(props) {
317
- const { block, selection, markupDisplay } = props;
318
- const headingLevel = inferHeadingLevel(block.styleId);
319
- const hasComment = getCommentRangeState(props.commentDecorations, block.from, block.to).hasComments;
320
- const hasChange = getRevisionRangeState(props.revisionDecorations, block.from, block.to).hasChanges;
321
- let marginClass = "";
322
- if (markupDisplay === "simple" && (hasComment || hasChange)) {
323
- if (hasComment && hasChange) marginClass = "border-l-2 border-l-comment/50 pl-3 ";
324
- else if (hasComment) marginClass = "border-l-2 border-l-comment/40 pl-3 ";
325
- else marginClass = "border-l-2 border-l-insert/40 pl-3 ";
326
- }
327
- const dots = [];
328
- if (markupDisplay === "clean" && hasComment) {
329
- dots.push("var(--color-comment)");
330
- } else if (markupDisplay !== "simple") {
331
- if (hasComment) dots.push("var(--color-comment)");
332
- if (hasChange) dots.push("var(--color-insert)");
333
- }
334
- const segmentElements = /* @__PURE__ */ jsxs4(Fragment3, { children: [
335
- /* @__PURE__ */ jsx5(
336
- CaretButton,
337
- {
338
- position: block.from,
339
- selection,
340
- onSelectionChange: props.onSelectionChange
341
- }
342
- ),
343
- block.segments.length > 0 ? block.segments.map((segment) => /* @__PURE__ */ jsx5(
344
- TwSegmentView,
345
- {
346
- segment,
347
- selection,
348
- markupDisplay,
349
- commentDecorations: props.commentDecorations,
350
- revisionDecorations: props.revisionDecorations,
351
- onSelectionChange: props.onSelectionChange,
352
- onCommentActivated: props.onCommentActivated,
353
- onRevisionActivated: props.onRevisionActivated
354
- },
355
- segment.segmentId
356
- )) : /* @__PURE__ */ jsx5("span", { className: "text-secondary italic", children: "Empty paragraph" }),
357
- /* @__PURE__ */ jsx5(
358
- CaretButton,
359
- {
360
- position: block.to,
361
- selection,
362
- onSelectionChange: props.onSelectionChange
363
- }
364
- )
365
- ] });
366
- return /* @__PURE__ */ jsxs4("div", { className: "group relative", children: [
367
- /* @__PURE__ */ jsx5(
368
- BlockHint,
369
- {
370
- label: headingLevel ? `H${headingLevel}` : "P",
371
- dots: dots.length > 0 ? dots : void 0
372
- }
373
- ),
374
- headingLevel ? /* @__PURE__ */ jsx5("div", { className: `${marginClass}transition-colors`, children: /* @__PURE__ */ jsx5(HeadingElement, { level: headingLevel, children: segmentElements }) }) : /* @__PURE__ */ jsx5("p", { className: `text-base leading-[1.75] text-primary ${marginClass}transition-colors`, children: segmentElements })
375
- ] });
376
- }
377
- function CaretButton(props) {
378
- const isActive = props.selection.isCollapsed && props.selection.anchor === props.position;
379
- return /* @__PURE__ */ jsx5(
380
- "button",
381
- {
382
- type: "button",
383
- tabIndex: -1,
384
- onMouseDown: (e) => {
385
- e.preventDefault();
386
- props.onSelectionChange?.(createSelectionSnapshot(props.position));
387
- },
388
- "aria-label": `Set caret at ${props.position}`,
389
- className: `p-0 m-0 border-none bg-transparent cursor-text inline-flex items-center ${isActive ? "min-w-[2px] h-[22px]" : "w-0 h-0 overflow-hidden"}`,
390
- children: renderTwCaret(props.selection, props.position)
391
- }
392
- );
393
- }
394
- function BlockHint(props) {
395
- return /* @__PURE__ */ jsx5("div", { className: "absolute -left-10 top-1 flex flex-col items-end gap-0 select-none w-8 text-right", children: /* @__PURE__ */ jsxs4("div", { className: "flex items-center gap-0.5", children: [
396
- /* @__PURE__ */ jsx5("span", { className: "text-[10px] text-tertiary/60 font-medium", children: props.label }),
397
- props.dots?.map((color, i) => /* @__PURE__ */ jsx5(
398
- "span",
399
- {
400
- className: "inline-block h-1 w-1 rounded-full",
401
- style: { backgroundColor: color }
402
- },
403
- i
404
- ))
405
- ] }) });
406
- }
407
- function HeadingElement(props) {
408
- switch (props.level) {
409
- case 1:
410
- return /* @__PURE__ */ jsx5("h2", { className: "text-2xl font-medium text-primary leading-tight", children: props.children });
411
- case 2:
412
- return /* @__PURE__ */ jsx5("h3", { className: "text-xl font-medium text-primary leading-snug", children: props.children });
413
- case 3:
414
- return /* @__PURE__ */ jsx5("h4", { className: "text-lg font-medium text-primary leading-snug", children: props.children });
415
- }
416
- }
417
- function inferHeadingLevel(styleId) {
418
- if (!styleId) return null;
419
- const lower = styleId.toLowerCase();
420
- if (lower === "heading1") return 1;
421
- if (lower === "heading2") return 2;
422
- if (lower === "heading3") return 3;
423
- return null;
424
- }
425
-
426
- // src/ui-tailwind/editor-surface/tw-editor-surface.tsx
427
- import { jsx as jsx6, jsxs as jsxs5 } from "react/jsx-runtime";
428
- function TwEditorSurface(props) {
429
- const { currentUser, markupDisplay, onBlur, onFocus, snapshot } = props;
430
- const surface = snapshot.surface;
431
- const canEdit = Boolean(
432
- surface && snapshot.isReady && !snapshot.readOnly && !snapshot.fatalError
433
- );
434
- const commentDecorations = useMemo(
435
- () => createCommentDecorationModel(snapshot.comments),
436
- [snapshot.comments]
437
- );
438
- const showTrackedChanges = props.showTrackedChanges !== false;
439
- const revisionDecorations = useMemo(
440
- () => showTrackedChanges ? createRevisionDecorationModel(snapshot.trackedChanges, props.activeRevisionId) : void 0,
441
- [snapshot.trackedChanges, props.activeRevisionId, showTrackedChanges]
442
- );
443
- const handleKeyDown = useMemo(() => {
444
- if (!surface) return void 0;
445
- return createEditorKeyboardHandler(
446
- {
447
- selection: snapshot.selection,
448
- storySize: surface.storySize,
449
- canEdit
450
- },
451
- {
452
- onSelectionChange: props.onSelectionChange,
453
- onInsertText: props.onInsertText,
454
- onDeleteBackward: props.onDeleteBackward,
455
- onDeleteForward: props.onDeleteForward,
456
- onInsertTab: props.onInsertTab,
457
- onInsertHardBreak: props.onInsertHardBreak,
458
- onSplitParagraph: props.onSplitParagraph
459
- }
460
- );
461
- }, [surface, snapshot.selection, canEdit, props]);
462
- const fontClass = markupDisplay === "clean" ? "font-[family-name:var(--font-legal-sans)]" : "font-[family-name:var(--font-legal-serif)]";
463
- return /* @__PURE__ */ jsx6("section", { "aria-label": "Document canvas", className: "min-w-0", children: /* @__PURE__ */ jsxs5(
464
- "div",
465
- {
466
- "aria-label": "Document surface",
467
- "aria-multiline": "true",
468
- role: "textbox",
469
- tabIndex: 0,
470
- onFocus,
471
- onBlur,
472
- onKeyDown: handleKeyDown,
473
- className: `bg-transparent border-none px-12 py-10 outline-offset-1 ${fontClass}`,
474
- children: [
475
- /* @__PURE__ */ jsxs5("div", { className: "flex justify-between gap-4 items-start mb-5", children: [
476
- /* @__PURE__ */ jsxs5("div", { children: [
477
- /* @__PURE__ */ jsx6("h1", { className: "font-[family-name:var(--font-legal-serif)] text-2xl leading-tight text-primary", children: snapshot.sourceLabel ?? "Document draft" }),
478
- /* @__PURE__ */ jsxs5("p", { className: "text-xs text-secondary mt-2", children: [
479
- snapshot.sessionId,
480
- " \xB7 ",
481
- snapshot.documentStats.storyLength,
482
- " chars"
483
- ] })
484
- ] }),
485
- /* @__PURE__ */ jsxs5("span", { className: "text-xs text-secondary whitespace-nowrap", children: [
486
- "Reviewer ",
487
- currentUser.displayName
488
- ] })
489
- ] }),
490
- /* @__PURE__ */ jsxs5("div", { className: "space-y-4 pl-10 relative", children: [
491
- surface ? surface.blocks.map(
492
- (block) => block.kind === "paragraph" ? /* @__PURE__ */ jsx6(
493
- TwParagraphBlock,
494
- {
495
- block,
496
- selection: snapshot.selection,
497
- markupDisplay,
498
- commentDecorations,
499
- revisionDecorations,
500
- onSelectionChange: props.onSelectionChange,
501
- onCommentActivated: props.onCommentActivated,
502
- onRevisionActivated: props.onRevisionActivated
503
- },
504
- block.blockId
505
- ) : block.kind === "opaque_block" ? /* @__PURE__ */ jsx6(
506
- TwOpaqueBlock,
507
- {
508
- block,
509
- selection: snapshot.selection,
510
- onSelectionChange: props.onSelectionChange
511
- },
512
- block.blockId
513
- ) : null
514
- ) : /* @__PURE__ */ jsx6("p", { className: "text-sm text-secondary leading-relaxed", children: "Loading the review surface. Compatibility cues and edit actions appear here once the runtime snapshot is ready." }),
515
- snapshot.fatalError ? /* @__PURE__ */ jsxs5("p", { className: "text-sm text-danger", children: [
516
- "Fatal runtime error: ",
517
- snapshot.fatalError.message
518
- ] }) : null
519
- ] })
520
- ]
521
- }
522
- ) });
523
- }
524
- export {
525
- TwAlertBanner,
526
- TwCommentSidebar,
527
- TwEditorSurface,
528
- TwHealthPanel,
529
- TwInlineToken,
530
- TwOpaqueBlock,
531
- TwParagraphBlock,
532
- TwReviewRail,
533
- TwReviewWorkspace,
534
- TwRevisionSidebar,
535
- TwSegmentView,
536
- TwSelectionToolbar,
537
- TwStatusBar,
538
- TwToolbar,
539
- TwToolbarIconButton,
540
- createCommentDecorationModel,
541
- createEditorKeyboardHandler,
542
- createRevisionDecorationModel,
543
- createSelectionSnapshot,
544
- deriveCapabilities,
545
- getCommentHighlightClass,
546
- getCommentRangeState,
547
- getRevisionHighlightClass,
548
- getRevisionRangeState,
549
- renderTwCaret,
550
- selectionTouchesRange,
551
- shouldHideInCleanMode
552
- };
553
- //# sourceMappingURL=tailwind.js.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/ui-tailwind/editor-surface/tw-editor-surface.tsx","../src/ui/headless/use-editor-keyboard.ts","../src/ui-tailwind/editor-surface/tw-opaque-block.tsx","../src/ui-tailwind/editor-surface/tw-caret.tsx","../src/ui-tailwind/editor-surface/tw-inline-token.tsx","../src/ui-tailwind/editor-surface/tw-segment-view.tsx","../src/ui-tailwind/editor-surface/tw-paragraph-block.tsx"],"sourcesContent":["import React, { type FocusEventHandler, useMemo } from \"react\";\n\nimport type {\n EditorUser,\n RuntimeRenderSnapshot,\n SelectionSnapshot,\n} from \"../../api/public-types\";\nimport {\n createCommentDecorationModel,\n type MarkupDisplay,\n} from \"../../ui/headless/comment-decoration-model\";\nimport { createRevisionDecorationModel } from \"../../ui/headless/revision-decoration-model\";\nimport { createEditorKeyboardHandler } from \"../../ui/headless/use-editor-keyboard\";\nimport { TwOpaqueBlock } from \"./tw-opaque-block\";\nimport { TwParagraphBlock } from \"./tw-paragraph-block\";\n\nexport interface TwEditorSurfaceProps {\n currentUser: EditorUser;\n snapshot: RuntimeRenderSnapshot;\n reviewMode: \"editing\" | \"review\";\n markupDisplay: MarkupDisplay;\n activeRevisionId?: string;\n /** When false, revision decorations are suppressed in the document surface. */\n showTrackedChanges?: boolean;\n onFocus: FocusEventHandler<HTMLDivElement>;\n onBlur: FocusEventHandler<HTMLDivElement>;\n onSelectionChange?: (selection: SelectionSnapshot) => void;\n onInsertText?: (text: string) => void;\n onDeleteBackward?: () => void;\n onDeleteForward?: () => void;\n onInsertTab?: () => void;\n onInsertHardBreak?: () => void;\n onSplitParagraph?: () => void;\n onCommentActivated?: (commentId: string) => void;\n onRevisionActivated?: (revisionId: string) => void;\n}\n\nexport function TwEditorSurface(props: TwEditorSurfaceProps) {\n const { currentUser, markupDisplay, onBlur, onFocus, snapshot } = props;\n const surface = snapshot.surface;\n\n const canEdit = Boolean(\n surface && snapshot.isReady && !snapshot.readOnly && !snapshot.fatalError,\n );\n\n const commentDecorations = useMemo(\n () => createCommentDecorationModel(snapshot.comments),\n [snapshot.comments],\n );\n\n const showTrackedChanges = props.showTrackedChanges !== false;\n const revisionDecorations = useMemo(\n () => showTrackedChanges\n ? createRevisionDecorationModel(snapshot.trackedChanges, props.activeRevisionId)\n : undefined,\n [snapshot.trackedChanges, props.activeRevisionId, showTrackedChanges],\n );\n\n const handleKeyDown = useMemo(() => {\n if (!surface) return undefined;\n return createEditorKeyboardHandler(\n {\n selection: snapshot.selection,\n storySize: surface.storySize,\n canEdit,\n },\n {\n onSelectionChange: props.onSelectionChange,\n onInsertText: props.onInsertText,\n onDeleteBackward: props.onDeleteBackward,\n onDeleteForward: props.onDeleteForward,\n onInsertTab: props.onInsertTab,\n onInsertHardBreak: props.onInsertHardBreak,\n onSplitParagraph: props.onSplitParagraph,\n },\n );\n }, [surface, snapshot.selection, canEdit, props]);\n\n const fontClass = markupDisplay === \"clean\"\n ? \"font-[family-name:var(--font-legal-sans)]\"\n : \"font-[family-name:var(--font-legal-serif)]\";\n\n return (\n <section aria-label=\"Document canvas\" className=\"min-w-0\">\n <div\n aria-label=\"Document surface\"\n aria-multiline=\"true\"\n role=\"textbox\"\n tabIndex={0}\n onFocus={onFocus}\n onBlur={onBlur}\n onKeyDown={handleKeyDown}\n className={`bg-transparent border-none px-12 py-10 outline-offset-1 ${fontClass}`}\n >\n {/* Document header */}\n <div className=\"flex justify-between gap-4 items-start mb-5\">\n <div>\n <h1 className=\"font-[family-name:var(--font-legal-serif)] text-2xl leading-tight text-primary\">\n {snapshot.sourceLabel ?? \"Document draft\"}\n </h1>\n <p className=\"text-xs text-secondary mt-2\">\n {snapshot.sessionId} ยท {snapshot.documentStats.storyLength} chars\n </p>\n </div>\n <span className=\"text-xs text-secondary whitespace-nowrap\">\n Reviewer {currentUser.displayName}\n </span>\n </div>\n\n {/* Document blocks */}\n <div className=\"space-y-4 pl-10 relative\">\n {surface ? (\n surface.blocks.map((block) =>\n block.kind === \"paragraph\" ? (\n <TwParagraphBlock\n key={block.blockId}\n block={block}\n selection={snapshot.selection}\n markupDisplay={markupDisplay}\n commentDecorations={commentDecorations}\n revisionDecorations={revisionDecorations}\n onSelectionChange={props.onSelectionChange}\n onCommentActivated={props.onCommentActivated}\n onRevisionActivated={props.onRevisionActivated}\n />\n ) : block.kind === \"opaque_block\" ? (\n <TwOpaqueBlock\n key={block.blockId}\n block={block}\n selection={snapshot.selection}\n onSelectionChange={props.onSelectionChange}\n />\n ) : null,\n )\n ) : (\n <p className=\"text-sm text-secondary leading-relaxed\">\n Loading the review surface. Compatibility cues and edit actions appear here once\n the runtime snapshot is ready.\n </p>\n )}\n {snapshot.fatalError ? (\n <p className=\"text-sm text-danger\">\n Fatal runtime error: {snapshot.fatalError.message}\n </p>\n ) : null}\n </div>\n </div>\n </section>\n );\n}\n","import type { KeyboardEvent } from \"react\";\n\nimport type { SelectionSnapshot } from \"../../api/public-types\";\nimport { createSelectionSnapshot } from \"./selection-helpers\";\n\nexport interface EditorKeyboardCallbacks {\n onSelectionChange?: (selection: SelectionSnapshot) => void;\n onInsertText?: (text: string) => void;\n onDeleteBackward?: () => void;\n onDeleteForward?: () => void;\n onInsertTab?: () => void;\n onInsertHardBreak?: () => void;\n onSplitParagraph?: () => void;\n}\n\nexport interface EditorKeyboardContext {\n selection: SelectionSnapshot;\n storySize: number;\n canEdit: boolean;\n}\n\nexport function createEditorKeyboardHandler(\n context: EditorKeyboardContext,\n callbacks: EditorKeyboardCallbacks,\n): (event: KeyboardEvent<HTMLDivElement>) => void {\n return function handleKeyDown(event: KeyboardEvent<HTMLDivElement>): void {\n const { selection, storySize, canEdit } = context;\n\n if (event.key === \"ArrowLeft\") {\n event.preventDefault();\n moveSelection(selection.anchor, selection.head - 1, event.shiftKey, storySize, callbacks);\n return;\n }\n\n if (event.key === \"ArrowRight\") {\n event.preventDefault();\n moveSelection(selection.anchor, selection.head + 1, event.shiftKey, storySize, callbacks);\n return;\n }\n\n if (event.key === \"Home\") {\n event.preventDefault();\n moveSelection(selection.anchor, 0, event.shiftKey, storySize, callbacks);\n return;\n }\n\n if (event.key === \"End\") {\n event.preventDefault();\n moveSelection(selection.anchor, storySize, event.shiftKey, storySize, callbacks);\n return;\n }\n\n if (!canEdit || event.metaKey || event.ctrlKey || event.altKey) {\n return;\n }\n\n switch (event.key) {\n case \"Backspace\":\n event.preventDefault();\n callbacks.onDeleteBackward?.();\n return;\n case \"Delete\":\n event.preventDefault();\n callbacks.onDeleteForward?.();\n return;\n case \"Tab\":\n event.preventDefault();\n callbacks.onInsertTab?.();\n return;\n case \"Enter\":\n event.preventDefault();\n if (event.shiftKey) {\n callbacks.onInsertHardBreak?.();\n } else {\n callbacks.onSplitParagraph?.();\n }\n return;\n default:\n if (event.key.length === 1) {\n event.preventDefault();\n callbacks.onInsertText?.(event.key);\n }\n }\n };\n}\n\nfunction moveSelection(\n anchor: number,\n nextHead: number,\n extend: boolean,\n storySize: number,\n callbacks: EditorKeyboardCallbacks,\n): void {\n const clampedHead = Math.max(0, Math.min(storySize, nextHead));\n callbacks.onSelectionChange?.(\n createSelectionSnapshot(extend ? anchor : clampedHead, clampedHead),\n );\n}\n","import React from \"react\";\n\nimport type { SelectionSnapshot, SurfaceBlockSnapshot } from \"../../api/public-types\";\nimport { selectionTouchesRange, createSelectionSnapshot } from \"../../ui/headless/selection-helpers\";\n\nexport interface TwOpaqueBlockProps {\n block: Extract<SurfaceBlockSnapshot, { kind: \"opaque_block\" }>;\n selection: SelectionSnapshot;\n onSelectionChange?: (selection: SelectionSnapshot) => void;\n}\n\nconst focusRingClass =\n \"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-accent focus-visible:ring-offset-2 focus-visible:ring-offset-canvas\";\n\nexport function TwOpaqueBlock(props: TwOpaqueBlockProps) {\n const { block, selection } = props;\n const selected = selectionTouchesRange(selection, block.from, block.to);\n\n return (\n <div className=\"group relative\">\n <div className=\"absolute -left-10 top-1 flex flex-col items-end gap-0 select-none w-8 text-right\">\n <div className=\"flex items-center gap-0.5\">\n <span className=\"text-[10px] text-tertiary/60 font-medium\">Lock</span>\n <span className=\"inline-block h-1 w-1 rounded-full\" style={{ backgroundColor: \"var(--color-comment)\" }} />\n </div>\n </div>\n <button\n type=\"button\"\n tabIndex={-1}\n onMouseDown={(e) => {\n e.preventDefault();\n props.onSelectionChange?.(createSelectionSnapshot(block.from, block.to));\n }}\n className={[\n \"w-full text-left border-l-2 border-dashed border-warning/30 pl-4 py-2 rounded-r bg-warning-soft/20\",\n \"cursor-pointer transition-colors\",\n selected ? \"ring-1 ring-accent/30 bg-warning-soft/40\" : \"hover:bg-warning-soft/30\",\n focusRingClass,\n ].join(\" \")}\n >\n <div className=\"flex items-center gap-1.5 text-xs text-tertiary mb-1\">\n <span>๐Ÿ”’</span>\n <span>{block.label}</span>\n <span className=\"inline-flex items-center px-1.5 py-0.5 rounded-full text-[10px] font-semibold text-comment bg-warning-soft\">\n preserve-only\n </span>\n </div>\n <p className=\"text-sm text-secondary\">{block.detail}</p>\n </button>\n </div>\n );\n}\n","import React from \"react\";\n\nimport type { SelectionSnapshot } from \"../../api/public-types\";\n\nexport function renderTwCaret(selection: SelectionSnapshot, position: number) {\n return selection.isCollapsed && selection.anchor === position ? (\n <span\n aria-hidden=\"true\"\n className=\"inline-block w-0.5 h-[1.2em] bg-accent rounded-full align-middle animate-wre-blink\"\n />\n ) : null;\n}\n","import React from \"react\";\n\nimport type { SelectionSnapshot, SurfaceInlineSegment } from \"../../api/public-types\";\nimport type { CommentDecorationModel } from \"../../ui/headless/comment-decoration-model\";\nimport { getCommentHighlightClass, type MarkupDisplay } from \"../../ui/headless/comment-decoration-model\";\nimport { createSelectionSnapshot, selectionTouchesRange } from \"../../ui/headless/selection-helpers\";\nimport { renderTwCaret } from \"./tw-caret\";\n\nexport interface TwInlineTokenProps {\n segment: SurfaceInlineSegment;\n selection: SelectionSnapshot;\n markupDisplay: MarkupDisplay;\n commentDecorations?: CommentDecorationModel;\n onSelectionChange?: (selection: SelectionSnapshot) => void;\n}\n\nconst focusRingClass =\n \"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-accent focus-visible:ring-offset-2 focus-visible:ring-offset-canvas\";\n\nexport function TwInlineToken(props: TwInlineTokenProps) {\n const { segment, selection } = props;\n const selected = selectionTouchesRange(selection, segment.from, segment.to);\n const commentClass = getCommentHighlightClass(\n props.commentDecorations,\n segment.from,\n segment.to,\n props.markupDisplay,\n );\n\n const showSymbols = props.markupDisplay !== \"clean\";\n\n if (segment.kind === \"tab\") {\n return (\n <button\n type=\"button\"\n tabIndex={-1}\n onMouseDown={(e) => {\n e.preventDefault();\n props.onSelectionChange?.(createSelectionSnapshot(segment.from, segment.to));\n }}\n className={`inline-flex items-center border-none bg-transparent cursor-text ${commentClass} ${selected ? \"bg-surface-hover\" : \"\"} ${focusRingClass} ${showSymbols ? \"mx-0.5 text-tertiary/50\" : \"w-8\"}`}\n title=\"Tab character\"\n >\n {renderTwCaret(selection, segment.from)}\n {showSymbols ? <span className=\"text-xs\">โ†’</span> : <span className=\"w-8\" />}\n {renderTwCaret(selection, segment.to)}\n </button>\n );\n }\n\n if (segment.kind === \"hard_break\") {\n return (\n <>\n <button\n type=\"button\"\n tabIndex={-1}\n onMouseDown={(e) => {\n e.preventDefault();\n props.onSelectionChange?.(createSelectionSnapshot(segment.from, segment.to));\n }}\n className={`inline-flex items-center border-none bg-transparent cursor-text ${commentClass} ${selected ? \"bg-surface-hover\" : \"\"} ${focusRingClass} ${showSymbols ? \"mx-0.5 text-tertiary/40\" : \"\"}`}\n title=\"Line break\"\n >\n {renderTwCaret(selection, segment.from)}\n {showSymbols ? <span className=\"text-xs\">โ†ต</span> : null}\n {renderTwCaret(selection, segment.to)}\n </button>\n <br />\n </>\n );\n }\n\n if (segment.kind === \"image\") {\n const isMissing = segment.state === \"missing\";\n return (\n <button\n type=\"button\"\n tabIndex={-1}\n onMouseDown={(e) => {\n e.preventDefault();\n props.onSelectionChange?.(createSelectionSnapshot(segment.from, segment.to));\n }}\n className={`inline-flex items-center gap-1 mx-0.5 px-1.5 py-0.5 rounded text-xs border-none cursor-pointer ${commentClass} ${\n isMissing ? \"text-danger bg-delete-soft\" : \"text-secondary bg-surface\"\n } ${selected ? \"ring-1 ring-accent/30\" : \"\"} ${focusRingClass}`}\n title={segment.detail ?? segment.altText ?? \"Inline image\"}\n >\n {renderTwCaret(selection, segment.from)}\n <span>๐Ÿ“ท</span>\n {segment.altText ?? (isMissing ? \"Missing image\" : \"Image\")}\n {renderTwCaret(selection, segment.to)}\n </button>\n );\n }\n\n // opaque_inline\n if (segment.kind === \"opaque_inline\") {\n return (\n <button\n type=\"button\"\n tabIndex={-1}\n onMouseDown={(e) => {\n e.preventDefault();\n props.onSelectionChange?.(createSelectionSnapshot(segment.from, segment.to));\n }}\n className={`inline-flex items-center gap-1 mx-0.5 px-1.5 py-0.5 rounded text-xs text-comment bg-warning-soft border-none cursor-pointer ${commentClass} ${selected ? \"ring-1 ring-accent/30\" : \"\"} ${focusRingClass}`}\n title={segment.detail}\n >\n {renderTwCaret(selection, segment.from)}\n <span>๐Ÿ”’</span>\n {segment.label}\n {renderTwCaret(selection, segment.to)}\n </button>\n );\n }\n\n return null;\n}\n","import React from \"react\";\n\nimport type { SelectionSnapshot, SurfaceInlineSegment } from \"../../api/public-types\";\nimport type { CommentDecorationModel } from \"../../ui/headless/comment-decoration-model\";\nimport { getCommentHighlightClass, getCommentRangeState, type MarkupDisplay } from \"../../ui/headless/comment-decoration-model\";\nimport type { RevisionDecorationModel } from \"../../ui/headless/revision-decoration-model\";\nimport { getRevisionHighlightClass, shouldHideInCleanMode } from \"../../ui/headless/revision-decoration-model\";\nimport { createSelectionSnapshot, selectionTouchesRange } from \"../../ui/headless/selection-helpers\";\nimport { TwInlineToken } from \"./tw-inline-token\";\n\nexport interface TwSegmentViewProps {\n segment: SurfaceInlineSegment;\n selection: SelectionSnapshot;\n markupDisplay: MarkupDisplay;\n commentDecorations?: CommentDecorationModel;\n revisionDecorations?: RevisionDecorationModel;\n onSelectionChange?: (selection: SelectionSnapshot) => void;\n onCommentActivated?: (commentId: string) => void;\n onRevisionActivated?: (revisionId: string) => void;\n}\n\nexport function TwSegmentView(props: TwSegmentViewProps) {\n const { segment, selection, markupDisplay } = props;\n\n // Non-text segments delegate to TwInlineToken\n if (segment.kind === \"tab\" || segment.kind === \"hard_break\" || segment.kind === \"image\" || segment.kind === \"opaque_inline\") {\n return (\n <TwInlineToken\n segment={segment}\n selection={selection}\n markupDisplay={markupDisplay}\n commentDecorations={props.commentDecorations}\n onSelectionChange={props.onSelectionChange}\n />\n );\n }\n\n if (segment.kind !== \"text\") {\n return null;\n }\n\n // Text segment: render character-by-character for click-to-position editing\n const characters = Array.from(segment.text);\n\n return (\n <>\n {characters.map((character, index) => {\n const from = segment.from + index;\n const to = from + 1;\n const isSelected = selectionTouchesRange(selection, from, to);\n\n // Hide deletions in clean mode\n if (shouldHideInCleanMode(props.revisionDecorations, from, to) && markupDisplay === \"clean\") {\n return null;\n }\n\n const commentClass = getCommentHighlightClass(props.commentDecorations, from, to, markupDisplay);\n const revisionClass = getRevisionHighlightClass(props.revisionDecorations, from, to, markupDisplay);\n\n // Check if clicking this char should activate a comment or revision\n const commentState = getCommentRangeState(props.commentDecorations, from, to);\n const overlappingComment = commentState.overlapping[0];\n\n // Build mark classes\n let markClasses = \"\";\n if (segment.marks) {\n if (segment.marks.includes(\"bold\")) markClasses += \"font-bold \";\n if (segment.marks.includes(\"italic\")) markClasses += \"italic \";\n if (segment.marks.includes(\"underline\")) markClasses += \"underline \";\n if (segment.marks.includes(\"strikethrough\")) markClasses += \"line-through \";\n }\n\n const hyperlinkClass = segment.hyperlinkHref\n ? \"text-accent underline decoration-1 underline-offset-2 \"\n : \"\";\n\n return (\n <button\n key={`${segment.segmentId}-${from}`}\n type=\"button\"\n tabIndex={-1}\n onMouseDown={(event) => {\n event.preventDefault();\n props.onSelectionChange?.(createSelectionSnapshot(to));\n\n // Activate comment/revision on click if decorated\n if (overlappingComment) {\n props.onCommentActivated?.(overlappingComment.commentId);\n }\n }}\n data-comment-id={overlappingComment?.commentId}\n className={[\n \"relative inline border-none bg-transparent cursor-text whitespace-pre p-0 m-0\",\n \"text-[15px] text-primary leading-normal\",\n commentClass,\n revisionClass,\n markClasses,\n hyperlinkClass,\n isSelected ? \"bg-surface-hover rounded-[3px]\" : \"\",\n ].filter(Boolean).join(\" \")}\n >\n {character}\n {selection.isCollapsed && selection.anchor === from ? (\n <span aria-hidden=\"true\" className=\"absolute left-0 top-[0.1em] w-0.5 h-[1em] bg-accent rounded-full animate-wre-blink pointer-events-none\" />\n ) : null}\n </button>\n );\n })}\n </>\n );\n}\n","import React from \"react\";\n\nimport type { SelectionSnapshot, SurfaceBlockSnapshot, SurfaceInlineSegment } from \"../../api/public-types\";\nimport type { CommentDecorationModel } from \"../../ui/headless/comment-decoration-model\";\nimport { getCommentRangeState, type MarkupDisplay } from \"../../ui/headless/comment-decoration-model\";\nimport type { RevisionDecorationModel } from \"../../ui/headless/revision-decoration-model\";\nimport { getRevisionRangeState } from \"../../ui/headless/revision-decoration-model\";\nimport { createSelectionSnapshot } from \"../../ui/headless/selection-helpers\";\nimport { renderTwCaret } from \"./tw-caret\";\nimport { TwSegmentView } from \"./tw-segment-view\";\n\nexport interface TwParagraphBlockProps {\n block: Extract<SurfaceBlockSnapshot, { kind: \"paragraph\" }>;\n selection: SelectionSnapshot;\n markupDisplay: MarkupDisplay;\n commentDecorations?: CommentDecorationModel;\n revisionDecorations?: RevisionDecorationModel;\n onSelectionChange?: (selection: SelectionSnapshot) => void;\n onCommentActivated?: (commentId: string) => void;\n onRevisionActivated?: (revisionId: string) => void;\n}\n\nexport function TwParagraphBlock(props: TwParagraphBlockProps) {\n const { block, selection, markupDisplay } = props;\n const headingLevel = inferHeadingLevel(block.styleId);\n const hasComment = getCommentRangeState(props.commentDecorations, block.from, block.to).hasComments;\n const hasChange = getRevisionRangeState(props.revisionDecorations, block.from, block.to).hasChanges;\n\n // Margin indicator per mode\n let marginClass = \"\";\n if (markupDisplay === \"simple\" && (hasComment || hasChange)) {\n if (hasComment && hasChange) marginClass = \"border-l-2 border-l-comment/50 pl-3 \";\n else if (hasComment) marginClass = \"border-l-2 border-l-comment/40 pl-3 \";\n else marginClass = \"border-l-2 border-l-insert/40 pl-3 \";\n }\n\n // Dot markers for gutter\n const dots: string[] = [];\n if (markupDisplay === \"clean\" && hasComment) {\n dots.push(\"var(--color-comment)\");\n } else if (markupDisplay !== \"simple\") {\n if (hasComment) dots.push(\"var(--color-comment)\");\n if (hasChange) dots.push(\"var(--color-insert)\");\n }\n\n const segmentElements = (\n <>\n <CaretButton\n position={block.from}\n selection={selection}\n onSelectionChange={props.onSelectionChange}\n />\n {block.segments.length > 0 ? (\n block.segments.map((segment) => (\n <TwSegmentView\n key={segment.segmentId}\n segment={segment}\n selection={selection}\n markupDisplay={markupDisplay}\n commentDecorations={props.commentDecorations}\n revisionDecorations={props.revisionDecorations}\n onSelectionChange={props.onSelectionChange}\n onCommentActivated={props.onCommentActivated}\n onRevisionActivated={props.onRevisionActivated}\n />\n ))\n ) : (\n <span className=\"text-secondary italic\">Empty paragraph</span>\n )}\n <CaretButton\n position={block.to}\n selection={selection}\n onSelectionChange={props.onSelectionChange}\n />\n </>\n );\n\n return (\n <div className=\"group relative\">\n <BlockHint\n label={headingLevel ? `H${headingLevel}` : \"P\"}\n dots={dots.length > 0 ? dots : undefined}\n />\n {headingLevel ? (\n <div className={`${marginClass}transition-colors`}>\n <HeadingElement level={headingLevel}>{segmentElements}</HeadingElement>\n </div>\n ) : (\n <p className={`text-base leading-[1.75] text-primary ${marginClass}transition-colors`}>\n {segmentElements}\n </p>\n )}\n </div>\n );\n}\n\nfunction CaretButton(props: {\n position: number;\n selection: SelectionSnapshot;\n onSelectionChange?: (selection: SelectionSnapshot) => void;\n}) {\n const isActive = props.selection.isCollapsed && props.selection.anchor === props.position;\n return (\n <button\n type=\"button\"\n tabIndex={-1}\n onMouseDown={(e) => {\n e.preventDefault();\n props.onSelectionChange?.(createSelectionSnapshot(props.position));\n }}\n aria-label={`Set caret at ${props.position}`}\n className={`p-0 m-0 border-none bg-transparent cursor-text inline-flex items-center ${isActive ? \"min-w-[2px] h-[22px]\" : \"w-0 h-0 overflow-hidden\"}`}\n >\n {renderTwCaret(props.selection, props.position)}\n </button>\n );\n}\n\nfunction BlockHint(props: { label: string; dots?: string[] }) {\n return (\n <div className=\"absolute -left-10 top-1 flex flex-col items-end gap-0 select-none w-8 text-right\">\n <div className=\"flex items-center gap-0.5\">\n <span className=\"text-[10px] text-tertiary/60 font-medium\">{props.label}</span>\n {props.dots?.map((color, i) => (\n <span\n key={i}\n className=\"inline-block h-1 w-1 rounded-full\"\n style={{ backgroundColor: color }}\n />\n ))}\n </div>\n </div>\n );\n}\n\nfunction HeadingElement(props: { level: 1 | 2 | 3; children: React.ReactNode }) {\n switch (props.level) {\n case 1: return <h2 className=\"text-2xl font-medium text-primary leading-tight\">{props.children}</h2>;\n case 2: return <h3 className=\"text-xl font-medium text-primary leading-snug\">{props.children}</h3>;\n case 3: return <h4 className=\"text-lg font-medium text-primary leading-snug\">{props.children}</h4>;\n }\n}\n\nfunction inferHeadingLevel(styleId?: string): 1 | 2 | 3 | null {\n if (!styleId) return null;\n const lower = styleId.toLowerCase();\n if (lower === \"heading1\") return 1;\n if (lower === \"heading2\") return 2;\n if (lower === \"heading3\") return 3;\n return null;\n}\n"],"mappings":"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","names":["jsx","jsx","jsxs","focusRingClass","Fragment","jsx","jsxs","Fragment","jsx","jsxs","jsx","jsxs"]}