@beyondwork/docx-react-component 1.0.29 → 1.0.31
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 +65 -96
- package/src/README.md +85 -0
- package/src/api/README.md +26 -0
- package/src/api/public-types.ts +1952 -0
- package/src/api/session-state.ts +62 -0
- package/src/compare/diff-engine.ts +623 -0
- package/src/compare/export-redlines.ts +280 -0
- package/src/compare/index.ts +25 -0
- package/src/compare/snapshot.ts +97 -0
- package/src/component-inventory.md +99 -0
- package/src/core/README.md +10 -0
- package/src/core/commands/README.md +3 -0
- package/{dist/chunk-TJBP2K4T.js → src/core/commands/formatting-commands.ts} +536 -196
- package/src/core/commands/image-commands.ts +373 -0
- package/src/core/commands/index.ts +1879 -0
- package/src/core/commands/list-commands.ts +565 -0
- package/src/core/commands/paragraph-layout-commands.ts +339 -0
- package/src/core/commands/review-commands.ts +108 -0
- package/{dist/core/commands/section-layout-commands.cjs → src/core/commands/section-layout-commands.ts} +340 -137
- package/src/core/commands/structural-helpers.ts +309 -0
- package/{dist/core/commands/style-commands.cjs → src/core/commands/style-commands.ts} +113 -65
- package/src/core/commands/table-structure-commands.ts +854 -0
- package/{dist/chunk-UZXBISGO.js → src/core/commands/text-commands.ts} +142 -86
- package/src/core/schema/README.md +3 -0
- package/src/core/schema/text-schema.ts +516 -0
- package/src/core/search/search-text.ts +357 -0
- package/src/core/selection/README.md +3 -0
- package/src/core/selection/mapping.ts +289 -0
- package/src/core/selection/review-anchors.ts +183 -0
- package/src/core/state/README.md +3 -0
- package/src/core/state/editor-state.ts +892 -0
- package/src/core/state/text-transaction.ts +869 -0
- package/src/formats/xlsx/io/parse-shared-strings.ts +41 -0
- package/src/formats/xlsx/io/parse-sheet.ts +459 -0
- package/src/formats/xlsx/io/parse-styles.ts +59 -0
- package/src/formats/xlsx/io/parse-workbook.ts +75 -0
- package/src/formats/xlsx/io/serialize-shared-strings.ts +72 -0
- package/src/formats/xlsx/io/serialize-sheet.ts +333 -0
- package/src/formats/xlsx/io/serialize-styles.ts +98 -0
- package/src/formats/xlsx/io/serialize-workbook.ts +429 -0
- package/src/formats/xlsx/io/xlsx-session.ts +314 -0
- package/src/formats/xlsx/model/cell.ts +189 -0
- package/src/formats/xlsx/model/sheet.ts +326 -0
- package/src/formats/xlsx/model/styles.ts +118 -0
- package/src/formats/xlsx/model/workbook.ts +453 -0
- package/src/formats/xlsx/runtime/cell-commands.ts +567 -0
- package/src/formats/xlsx/runtime/sheet-commands.ts +206 -0
- package/src/formats/xlsx/runtime/workbook-runtime.ts +177 -0
- package/src/formats/xlsx/runtime/workbook-transaction.ts +822 -0
- package/src/index.ts +142 -0
- package/src/io/README.md +10 -0
- package/src/io/docx-session.ts +3175 -0
- package/src/io/export/README.md +3 -0
- package/src/io/export/export-session.ts +220 -0
- package/src/io/export/minimal-docx.ts +115 -0
- package/src/io/export/reattach-preserved-parts.ts +54 -0
- package/src/io/export/serialize-comments.ts +947 -0
- package/src/io/export/serialize-footnotes.ts +394 -0
- package/src/io/export/serialize-headers-footers.ts +368 -0
- package/src/io/export/serialize-main-document.ts +1342 -0
- package/src/io/export/serialize-numbering.ts +218 -0
- package/src/io/export/serialize-revisions.ts +389 -0
- package/src/io/export/serialize-runtime-revisions.ts +463 -0
- package/src/io/export/serialize-tables.ts +174 -0
- package/src/io/export/split-review-boundaries.ts +356 -0
- package/src/io/export/split-story-blocks-for-runtime-revisions.ts +252 -0
- package/src/io/export/table-properties-xml.ts +318 -0
- package/src/io/normalize/README.md +3 -0
- package/src/io/normalize/normalize-text.ts +670 -0
- package/src/io/ooxml/README.md +3 -0
- package/src/io/ooxml/highlight-colors.ts +39 -0
- package/src/io/ooxml/numbering-sentinels.ts +44 -0
- package/src/io/ooxml/parse-comments.ts +852 -0
- package/src/io/ooxml/parse-complex-content.ts +287 -0
- package/src/io/ooxml/parse-fields.ts +834 -0
- package/src/io/ooxml/parse-footnotes.ts +952 -0
- package/src/io/ooxml/parse-headers-footers.ts +1212 -0
- package/src/io/ooxml/parse-inline-media.ts +461 -0
- package/src/io/ooxml/parse-main-document.ts +2947 -0
- package/src/io/ooxml/parse-numbering.ts +747 -0
- package/src/io/ooxml/parse-revisions.ts +1045 -0
- package/src/io/ooxml/parse-settings.ts +184 -0
- package/src/io/ooxml/parse-shapes.ts +296 -0
- package/src/io/ooxml/parse-styles.ts +639 -0
- package/src/io/ooxml/parse-tables.ts +627 -0
- package/src/io/ooxml/parse-theme.ts +346 -0
- package/src/io/ooxml/part-manifest.ts +136 -0
- package/src/io/ooxml/revision-boundaries.ts +475 -0
- package/src/io/ooxml/workflow-payload.ts +544 -0
- package/src/io/opc/README.md +3 -0
- package/src/io/opc/corrupt-package.ts +166 -0
- package/src/io/opc/docx-package.ts +74 -0
- package/src/io/opc/package-reader.ts +325 -0
- package/src/io/opc/package-writer.ts +273 -0
- package/src/io/source-package-provenance.ts +241 -0
- package/{dist/chunk-RMH72RZI.js → src/legal/bookmarks.ts} +130 -44
- package/src/legal/cross-references.ts +414 -0
- package/src/legal/defined-terms.ts +203 -0
- package/src/legal/index.ts +32 -0
- package/src/legal/signature-blocks.ts +259 -0
- package/src/model/README.md +3 -0
- package/src/model/canonical-document.ts +2722 -0
- package/src/model/cds-1.0.0.ts +212 -0
- package/src/model/snapshot.ts +760 -0
- package/src/preservation/README.md +3 -0
- package/src/preservation/markup-compatibility.ts +48 -0
- package/src/preservation/opaque-fragment-store.ts +89 -0
- package/src/preservation/opaque-region.ts +233 -0
- package/src/preservation/package-preservation.ts +113 -0
- package/src/preservation/preserved-part-manifest.ts +56 -0
- package/src/preservation/relationship-retention.ts +57 -0
- package/src/preservation/store.ts +255 -0
- package/src/review/README.md +16 -0
- package/src/review/store/README.md +3 -0
- package/src/review/store/comment-anchors.ts +70 -0
- package/src/review/store/comment-remapping.ts +154 -0
- package/src/review/store/comment-store.ts +349 -0
- package/src/review/store/comment-thread.ts +109 -0
- package/src/review/store/revision-actions.ts +423 -0
- package/src/review/store/revision-store.ts +323 -0
- package/src/review/store/revision-types.ts +182 -0
- package/src/review/store/runtime-comment-store.ts +43 -0
- package/src/runtime/README.md +3 -0
- package/src/runtime/ai-action-policy.ts +764 -0
- package/src/runtime/context-analytics.ts +824 -0
- package/src/runtime/document-layout.ts +332 -0
- package/src/runtime/document-locations.ts +521 -0
- package/src/runtime/document-navigation.ts +616 -0
- package/src/runtime/document-outline.ts +440 -0
- package/src/runtime/document-runtime.ts +4055 -0
- package/src/runtime/document-search.ts +145 -0
- package/src/runtime/event-refresh-hints.ts +137 -0
- package/src/runtime/numbering-prefix.ts +244 -0
- package/src/runtime/page-layout-estimation.ts +305 -0
- package/src/runtime/read-only-diagnostics-runtime.ts +241 -0
- package/src/runtime/resolved-numbering-geometry.ts +293 -0
- package/src/runtime/review-runtime.ts +44 -0
- package/src/runtime/revision-runtime.ts +107 -0
- package/src/runtime/session-capabilities.ts +192 -0
- package/src/runtime/story-context.ts +164 -0
- package/src/runtime/story-targeting.ts +162 -0
- package/src/runtime/suggestions-snapshot.ts +137 -0
- package/src/runtime/surface-projection.ts +1553 -0
- package/src/runtime/table-commands.ts +173 -0
- package/src/runtime/table-schema.ts +309 -0
- package/src/runtime/table-style-resolver.ts +409 -0
- package/src/runtime/view-state.ts +493 -0
- package/src/runtime/virtualized-rendering.ts +258 -0
- package/src/runtime/workflow-markup.ts +393 -0
- package/src/ui/README.md +30 -0
- package/src/ui/WordReviewEditor.tsx +5268 -0
- package/src/ui/browser-export.ts +52 -0
- package/src/ui/comments/README.md +3 -0
- package/src/ui/compatibility/README.md +3 -0
- package/src/ui/editor-command-bag.ts +127 -0
- package/src/ui/editor-runtime-boundary.ts +1558 -0
- package/src/ui/editor-shell-view.tsx +144 -0
- package/src/ui/editor-surface/README.md +3 -0
- package/src/ui/editor-surface-controller.tsx +66 -0
- package/src/ui/headless/comment-decoration-model.ts +124 -0
- package/src/ui/headless/preserve-editor-selection.ts +5 -0
- package/src/ui/headless/revision-decoration-model.ts +128 -0
- package/src/ui/headless/selection-helpers.ts +54 -0
- package/src/ui/headless/selection-tool-context.ts +19 -0
- package/src/ui/headless/selection-tool-resolver.ts +752 -0
- package/src/ui/headless/selection-tool-types.ts +129 -0
- package/src/ui/headless/selection-toolbar-model.ts +11 -0
- package/src/ui/headless/use-editor-keyboard.ts +103 -0
- package/src/ui/review/README.md +3 -0
- package/src/ui/runtime-shortcut-dispatch.ts +365 -0
- package/src/ui/runtime-snapshot-selectors.ts +197 -0
- package/src/ui/shared/revision-filters.ts +31 -0
- package/src/ui/status/README.md +3 -0
- package/src/ui/theme/README.md +3 -0
- package/src/ui/toolbar/README.md +3 -0
- package/src/ui/workflow-surface-blocked-rails.ts +94 -0
- package/src/ui-tailwind/chrome/chrome-preset-model.ts +107 -0
- package/src/ui-tailwind/chrome/chrome-preset-toolbar.tsx +15 -0
- package/src/ui-tailwind/chrome/responsive-chrome.ts +46 -0
- package/src/ui-tailwind/chrome/review-queue-bar.tsx +97 -0
- package/src/ui-tailwind/chrome/tw-alert-banner.tsx +64 -0
- package/src/ui-tailwind/chrome/tw-context-analytics-summary.tsx +122 -0
- package/src/ui-tailwind/chrome/tw-image-context-toolbar.tsx +121 -0
- package/src/ui-tailwind/chrome/tw-layout-panel.tsx +114 -0
- package/src/ui-tailwind/chrome/tw-object-context-toolbar.tsx +30 -0
- package/src/ui-tailwind/chrome/tw-page-ruler.tsx +365 -0
- package/src/ui-tailwind/chrome/tw-selection-tool-blocked.tsx +23 -0
- package/src/ui-tailwind/chrome/tw-selection-tool-comment.tsx +35 -0
- package/src/ui-tailwind/chrome/tw-selection-tool-formatting.tsx +37 -0
- package/src/ui-tailwind/chrome/tw-selection-tool-host.tsx +303 -0
- package/src/ui-tailwind/chrome/tw-selection-tool-structure.tsx +116 -0
- package/src/ui-tailwind/chrome/tw-selection-tool-suggestion.tsx +29 -0
- package/src/ui-tailwind/chrome/tw-selection-tool-workflow.tsx +27 -0
- package/src/ui-tailwind/chrome/tw-selection-toolbar.tsx +186 -0
- package/src/ui-tailwind/chrome/tw-suggestion-card.tsx +139 -0
- package/src/ui-tailwind/chrome/tw-table-context-toolbar.tsx +250 -0
- package/src/ui-tailwind/chrome/tw-unsaved-modal.tsx +58 -0
- package/src/ui-tailwind/chrome/use-before-unload.ts +20 -0
- package/src/ui-tailwind/editor-surface/perf-probe.ts +179 -0
- package/src/ui-tailwind/editor-surface/pm-command-bridge.ts +189 -0
- package/src/ui-tailwind/editor-surface/pm-contextual-ui.ts +31 -0
- package/src/ui-tailwind/editor-surface/pm-decorations.ts +411 -0
- package/src/ui-tailwind/editor-surface/pm-position-map.ts +123 -0
- package/src/ui-tailwind/editor-surface/pm-schema.ts +927 -0
- package/src/ui-tailwind/editor-surface/pm-state-from-snapshot.ts +567 -0
- package/src/ui-tailwind/editor-surface/search-plugin.ts +168 -0
- package/src/ui-tailwind/editor-surface/surface-build-keys.ts +63 -0
- package/src/ui-tailwind/editor-surface/tw-caret.tsx +12 -0
- package/src/ui-tailwind/editor-surface/tw-editor-surface.tsx +150 -0
- package/src/ui-tailwind/editor-surface/tw-inline-token.tsx +129 -0
- package/src/ui-tailwind/editor-surface/tw-opaque-block.tsx +58 -0
- package/src/ui-tailwind/editor-surface/tw-paragraph-block.tsx +151 -0
- package/src/ui-tailwind/editor-surface/tw-prosemirror-surface.tsx +1047 -0
- package/src/ui-tailwind/editor-surface/tw-segment-view.tsx +111 -0
- package/src/ui-tailwind/editor-surface/tw-table-node-view.tsx +503 -0
- package/src/ui-tailwind/index.ts +62 -0
- package/src/ui-tailwind/page-chrome-model.ts +27 -0
- package/src/ui-tailwind/review/tw-comment-sidebar.tsx +406 -0
- package/src/ui-tailwind/review/tw-health-panel.tsx +149 -0
- package/src/ui-tailwind/review/tw-review-rail.tsx +130 -0
- package/src/ui-tailwind/review/tw-revision-sidebar.tsx +164 -0
- package/src/ui-tailwind/status/tw-status-bar.tsx +65 -0
- package/{dist → src}/ui-tailwind/theme/editor-theme.css +58 -40
- package/src/ui-tailwind/toolbar/toolbar-layout.ts +47 -0
- package/src/ui-tailwind/toolbar/tw-toolbar-icon-button.tsx +52 -0
- package/src/ui-tailwind/toolbar/tw-toolbar.tsx +1478 -0
- package/src/ui-tailwind/tw-review-workspace.tsx +1587 -0
- package/src/validation/README.md +3 -0
- package/src/validation/compatibility-engine.ts +878 -0
- package/src/validation/compatibility-report.ts +161 -0
- package/src/validation/diagnostics.ts +204 -0
- package/src/validation/docx-comment-proof.ts +720 -0
- package/src/validation/import-diagnostics.ts +128 -0
- package/src/validation/low-priority-word-surfaces.ts +373 -0
- package/dist/canonical-document-BLEbzL2J.d.cts +0 -844
- package/dist/canonical-document-BLEbzL2J.d.ts +0 -844
- package/dist/chunk-2FJS5GZM.js +0 -763
- package/dist/chunk-2FJS5GZM.js.map +0 -1
- package/dist/chunk-2OQBZS3F.js +0 -446
- package/dist/chunk-2OQBZS3F.js.map +0 -1
- package/dist/chunk-2S7W4KFO.js +0 -127
- package/dist/chunk-2S7W4KFO.js.map +0 -1
- package/dist/chunk-2TG72QSW.js +0 -3874
- package/dist/chunk-2TG72QSW.js.map +0 -1
- package/dist/chunk-36QNIZBO.js +0 -532
- package/dist/chunk-36QNIZBO.js.map +0 -1
- package/dist/chunk-4AQOYAW4.js +0 -3069
- package/dist/chunk-4AQOYAW4.js.map +0 -1
- package/dist/chunk-4D5EWJ3P.js +0 -77
- package/dist/chunk-4D5EWJ3P.js.map +0 -1
- package/dist/chunk-5FN54NDH.js +0 -2257
- package/dist/chunk-5FN54NDH.js.map +0 -1
- package/dist/chunk-BOYGQYRQ.js +0 -7306
- package/dist/chunk-BOYGQYRQ.js.map +0 -1
- package/dist/chunk-CN3XMECL.js +0 -212
- package/dist/chunk-CN3XMECL.js.map +0 -1
- package/dist/chunk-EBI3BX6U.js +0 -164
- package/dist/chunk-EBI3BX6U.js.map +0 -1
- package/dist/chunk-EILUG3VB.js +0 -1275
- package/dist/chunk-EILUG3VB.js.map +0 -1
- package/dist/chunk-FUDY333O.js +0 -70
- package/dist/chunk-FUDY333O.js.map +0 -1
- package/dist/chunk-GBVOWFIK.js +0 -1237
- package/dist/chunk-GBVOWFIK.js.map +0 -1
- package/dist/chunk-H4TQ3H3Y.js +0 -262
- package/dist/chunk-H4TQ3H3Y.js.map +0 -1
- package/dist/chunk-JGB3IXZO.js +0 -189
- package/dist/chunk-JGB3IXZO.js.map +0 -1
- package/dist/chunk-KD2QRQPY.js +0 -4342
- package/dist/chunk-KD2QRQPY.js.map +0 -1
- package/dist/chunk-KLMXQVYK.js +0 -369
- package/dist/chunk-KLMXQVYK.js.map +0 -1
- package/dist/chunk-KZUG5KFQ.js +0 -214
- package/dist/chunk-KZUG5KFQ.js.map +0 -1
- package/dist/chunk-QDAQ4CJU.js +0 -345
- package/dist/chunk-QDAQ4CJU.js.map +0 -1
- package/dist/chunk-RMH72RZI.js.map +0 -1
- package/dist/chunk-SWKWQZXM.js +0 -117
- package/dist/chunk-SWKWQZXM.js.map +0 -1
- package/dist/chunk-TJBP2K4T.js.map +0 -1
- package/dist/chunk-TLCEAQDQ.js +0 -542
- package/dist/chunk-TLCEAQDQ.js.map +0 -1
- package/dist/chunk-UZXBISGO.js.map +0 -1
- package/dist/chunk-WGBAKP3Q.js +0 -3220
- package/dist/chunk-WGBAKP3Q.js.map +0 -1
- package/dist/compare/index.cjs +0 -5475
- package/dist/compare/index.cjs.map +0 -1
- package/dist/compare/index.d.cts +0 -114
- package/dist/compare/index.d.ts +0 -114
- package/dist/compare/index.js +0 -731
- package/dist/compare/index.js.map +0 -1
- package/dist/core/commands/formatting-commands.cjs +0 -828
- package/dist/core/commands/formatting-commands.cjs.map +0 -1
- package/dist/core/commands/formatting-commands.d.cts +0 -63
- package/dist/core/commands/formatting-commands.d.ts +0 -63
- package/dist/core/commands/formatting-commands.js +0 -37
- package/dist/core/commands/formatting-commands.js.map +0 -1
- package/dist/core/commands/image-commands.cjs +0 -2023
- package/dist/core/commands/image-commands.cjs.map +0 -1
- package/dist/core/commands/image-commands.d.cts +0 -58
- package/dist/core/commands/image-commands.d.ts +0 -58
- package/dist/core/commands/image-commands.js +0 -18
- package/dist/core/commands/image-commands.js.map +0 -1
- package/dist/core/commands/section-layout-commands.cjs.map +0 -1
- package/dist/core/commands/section-layout-commands.d.cts +0 -62
- package/dist/core/commands/section-layout-commands.d.ts +0 -62
- package/dist/core/commands/section-layout-commands.js +0 -21
- package/dist/core/commands/section-layout-commands.js.map +0 -1
- package/dist/core/commands/style-commands.cjs.map +0 -1
- package/dist/core/commands/style-commands.d.cts +0 -13
- package/dist/core/commands/style-commands.d.ts +0 -13
- package/dist/core/commands/style-commands.js +0 -9
- package/dist/core/commands/style-commands.js.map +0 -1
- package/dist/core/commands/table-structure-commands.cjs +0 -1883
- package/dist/core/commands/table-structure-commands.cjs.map +0 -1
- package/dist/core/commands/table-structure-commands.d.cts +0 -59
- package/dist/core/commands/table-structure-commands.d.ts +0 -59
- package/dist/core/commands/table-structure-commands.js +0 -12
- package/dist/core/commands/table-structure-commands.js.map +0 -1
- package/dist/core/commands/text-commands.cjs +0 -2391
- package/dist/core/commands/text-commands.cjs.map +0 -1
- package/dist/core/commands/text-commands.d.cts +0 -24
- package/dist/core/commands/text-commands.d.ts +0 -24
- package/dist/core/commands/text-commands.js +0 -28
- package/dist/core/commands/text-commands.js.map +0 -1
- package/dist/core/selection/mapping.cjs +0 -200
- package/dist/core/selection/mapping.cjs.map +0 -1
- package/dist/core/selection/mapping.d.cts +0 -2
- package/dist/core/selection/mapping.d.ts +0 -2
- package/dist/core/selection/mapping.js +0 -31
- package/dist/core/selection/mapping.js.map +0 -1
- package/dist/core/state/editor-state.cjs +0 -2278
- package/dist/core/state/editor-state.cjs.map +0 -1
- package/dist/core/state/editor-state.d.cts +0 -2
- package/dist/core/state/editor-state.d.ts +0 -2
- package/dist/core/state/editor-state.js +0 -26
- package/dist/core/state/editor-state.js.map +0 -1
- package/dist/index.cjs +0 -38553
- package/dist/index.cjs.map +0 -1
- package/dist/index.d.cts +0 -15
- package/dist/index.d.ts +0 -15
- package/dist/index.js +0 -7856
- package/dist/index.js.map +0 -1
- package/dist/io/docx-session.cjs +0 -16236
- package/dist/io/docx-session.cjs.map +0 -1
- package/dist/io/docx-session.d.cts +0 -21
- package/dist/io/docx-session.d.ts +0 -21
- package/dist/io/docx-session.js +0 -18
- package/dist/io/docx-session.js.map +0 -1
- package/dist/legal/index.cjs +0 -3900
- package/dist/legal/index.cjs.map +0 -1
- package/dist/legal/index.d.cts +0 -86
- package/dist/legal/index.d.ts +0 -86
- package/dist/legal/index.js +0 -616
- package/dist/legal/index.js.map +0 -1
- package/dist/public-types-7ZL_94cz.d.ts +0 -1573
- package/dist/public-types-CeMaDueh.d.cts +0 -1573
- package/dist/public-types.cjs +0 -19
- package/dist/public-types.cjs.map +0 -1
- package/dist/public-types.d.cts +0 -2
- package/dist/public-types.d.ts +0 -2
- package/dist/public-types.js +0 -1
- package/dist/public-types.js.map +0 -1
- package/dist/runtime/document-runtime.cjs +0 -11140
- package/dist/runtime/document-runtime.cjs.map +0 -1
- package/dist/runtime/document-runtime.d.cts +0 -231
- package/dist/runtime/document-runtime.d.ts +0 -231
- package/dist/runtime/document-runtime.js +0 -21
- package/dist/runtime/document-runtime.js.map +0 -1
- package/dist/structural-helpers-CilgOVhh.d.cts +0 -10
- package/dist/structural-helpers-q0Gd-eBN.d.ts +0 -10
- package/dist/ui-tailwind/editor-surface/search-plugin.cjs +0 -313
- package/dist/ui-tailwind/editor-surface/search-plugin.cjs.map +0 -1
- package/dist/ui-tailwind/editor-surface/search-plugin.d.cts +0 -67
- package/dist/ui-tailwind/editor-surface/search-plugin.d.ts +0 -67
- package/dist/ui-tailwind/editor-surface/search-plugin.js +0 -23
- package/dist/ui-tailwind/editor-surface/search-plugin.js.map +0 -1
- package/dist/ui-tailwind/index.cjs +0 -4833
- package/dist/ui-tailwind/index.cjs.map +0 -1
- package/dist/ui-tailwind/index.d.cts +0 -617
- package/dist/ui-tailwind/index.d.ts +0 -617
- package/dist/ui-tailwind/index.js +0 -575
- package/dist/ui-tailwind/index.js.map +0 -1
package/dist/chunk-2TG72QSW.js
DELETED
|
@@ -1,3874 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
DEFAULT_PAGE_ESTIMATE_PX_PER_TWIP,
|
|
3
|
-
canCreateDocxCommentAnchor,
|
|
4
|
-
estimateBlockHeight,
|
|
5
|
-
estimateParagraphLineCount,
|
|
6
|
-
estimateParagraphLineHeight,
|
|
7
|
-
findPageForOffset,
|
|
8
|
-
getUsableColumnWidth,
|
|
9
|
-
incrementInvalidationCounter,
|
|
10
|
-
recordPerfSample
|
|
11
|
-
} from "./chunk-GBVOWFIK.js";
|
|
12
|
-
import {
|
|
13
|
-
createDetachedAnchor,
|
|
14
|
-
createNodeAnchor,
|
|
15
|
-
createRangeAnchor
|
|
16
|
-
} from "./chunk-EBI3BX6U.js";
|
|
17
|
-
|
|
18
|
-
// src/runtime/session-capabilities.ts
|
|
19
|
-
function deriveCapabilities(snapshot, reviewMode, workflowScope) {
|
|
20
|
-
const hasFatalError = Boolean(snapshot.fatalError);
|
|
21
|
-
const isReady = snapshot.isReady;
|
|
22
|
-
const isReadOnly = snapshot.readOnly;
|
|
23
|
-
const exportBlocked = snapshot.compatibility.blockExport;
|
|
24
|
-
const activeStory = snapshot.activeStory ?? { kind: "main" };
|
|
25
|
-
const documentMode = snapshot.documentMode ?? "editing";
|
|
26
|
-
const phase = !isReady ? "loading" : hasFatalError ? "diagnostics" : "ready";
|
|
27
|
-
const mode = phase === "diagnostics" ? "read-only-diagnostics" : reviewMode;
|
|
28
|
-
const canEdit = isReady && !isReadOnly && !hasFatalError && documentMode !== "viewing";
|
|
29
|
-
const canUndo = snapshot.commandState.canUndo && canEdit;
|
|
30
|
-
const canRedo = snapshot.commandState.canRedo && canEdit;
|
|
31
|
-
const canAddComment = canEdit && activeStory.kind === "main" && !snapshot.selection.isCollapsed && Boolean(snapshot.surface) && canCreateDocxCommentAnchor(snapshot.surface, toRuntimeAnchor(snapshot.selection.activeRange));
|
|
32
|
-
const canExport = isReady && !exportBlocked && !hasFatalError;
|
|
33
|
-
const actionableRevisions = snapshot.trackedChanges.revisions.filter(
|
|
34
|
-
(r) => r.status === "active" && r.actionability === "actionable"
|
|
35
|
-
);
|
|
36
|
-
const canAcceptChange = canEdit && actionableRevisions.some((r) => r.canAccept);
|
|
37
|
-
const canRejectChange = canEdit && actionableRevisions.some((r) => r.canReject);
|
|
38
|
-
const canAcceptAll = canEdit && actionableRevisions.length > 0;
|
|
39
|
-
const canRejectAll = canEdit && actionableRevisions.length > 0;
|
|
40
|
-
const preserveOnlyCount = snapshot.compatibility.featureEntries.filter(
|
|
41
|
-
(e) => e.featureClass === "preserve-only"
|
|
42
|
-
).length;
|
|
43
|
-
const unsupportedFatalCount = snapshot.compatibility.featureEntries.filter(
|
|
44
|
-
(e) => e.featureClass === "unsupported-fatal"
|
|
45
|
-
).length;
|
|
46
|
-
const workflowOverlayPresent = workflowScope?.overlayPresent ?? false;
|
|
47
|
-
const workflowBlocked = (workflowScope?.blockedReasons?.length ?? 0) > 0;
|
|
48
|
-
const trackChangesSupported = snapshot.trackedChanges.totalCount > 0;
|
|
49
|
-
const hasTrustConcerns = exportBlocked || preserveOnlyCount > 0 || unsupportedFatalCount > 0 || snapshot.warnings.length > 0 || hasFatalError;
|
|
50
|
-
const reviewRailVisible = workflowOverlayPresent ? false : mode === "review" || mode === "read-only-diagnostics" || mode === "editing" && hasTrustConcerns;
|
|
51
|
-
const healthIssueCount = preserveOnlyCount + unsupportedFatalCount + snapshot.warnings.length;
|
|
52
|
-
const protection = snapshot.protectionSnapshot;
|
|
53
|
-
const hasDocumentProtection = protection?.hasDocumentProtection ?? false;
|
|
54
|
-
const protectedRangeCount = protection?.ranges?.length ?? 0;
|
|
55
|
-
return {
|
|
56
|
-
phase,
|
|
57
|
-
mode,
|
|
58
|
-
documentMode,
|
|
59
|
-
canUndo,
|
|
60
|
-
canRedo,
|
|
61
|
-
canEdit,
|
|
62
|
-
canAddComment,
|
|
63
|
-
canExport,
|
|
64
|
-
canAcceptChange,
|
|
65
|
-
canRejectChange,
|
|
66
|
-
canAcceptAll,
|
|
67
|
-
canRejectAll,
|
|
68
|
-
reviewRailVisible,
|
|
69
|
-
trackChangesSupported,
|
|
70
|
-
exportBlocked,
|
|
71
|
-
preserveOnlyCount,
|
|
72
|
-
unsupportedFatalCount,
|
|
73
|
-
hasDocumentProtection,
|
|
74
|
-
protectedRangeCount,
|
|
75
|
-
healthIssueCount,
|
|
76
|
-
workflowOverlayPresent,
|
|
77
|
-
workflowBlocked,
|
|
78
|
-
isDirty: snapshot.isDirty,
|
|
79
|
-
isReady,
|
|
80
|
-
hasFatalError
|
|
81
|
-
};
|
|
82
|
-
}
|
|
83
|
-
function toRuntimeAnchor(anchor) {
|
|
84
|
-
switch (anchor.kind) {
|
|
85
|
-
case "range":
|
|
86
|
-
return createRangeAnchor(anchor.from, anchor.to, anchor.assoc);
|
|
87
|
-
case "node":
|
|
88
|
-
return createNodeAnchor(anchor.at, anchor.assoc);
|
|
89
|
-
case "detached":
|
|
90
|
-
return createDetachedAnchor(anchor.lastKnownRange, anchor.reason);
|
|
91
|
-
}
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
// src/ui-tailwind/chrome/tw-alert-banner.tsx
|
|
95
|
-
import { AlertTriangle, XCircle } from "lucide-react";
|
|
96
|
-
import { jsx, jsxs } from "react/jsx-runtime";
|
|
97
|
-
function TwAlertBanner(props) {
|
|
98
|
-
const { snapshot, preserveOnlyCount, workflowBlockedReasons = [] } = props;
|
|
99
|
-
if (snapshot.fatalError) {
|
|
100
|
-
return /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 px-3 py-1.5 bg-danger-soft text-danger text-xs", children: [
|
|
101
|
-
/* @__PURE__ */ jsx(XCircle, { className: "h-3.5 w-3.5 shrink-0" }),
|
|
102
|
-
/* @__PURE__ */ jsx("span", { children: snapshot.fatalError.message })
|
|
103
|
-
] });
|
|
104
|
-
}
|
|
105
|
-
if (snapshot.compatibility.blockExport) {
|
|
106
|
-
return /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 px-3 py-1.5 bg-danger-soft text-danger text-xs", children: [
|
|
107
|
-
/* @__PURE__ */ jsx(XCircle, { className: "h-3.5 w-3.5 shrink-0" }),
|
|
108
|
-
/* @__PURE__ */ jsxs("span", { children: [
|
|
109
|
-
"Export blocked \u2014",
|
|
110
|
-
" ",
|
|
111
|
-
snapshot.compatibility.blockExportReasons[0] ?? "unsupported content"
|
|
112
|
-
] })
|
|
113
|
-
] });
|
|
114
|
-
}
|
|
115
|
-
if (preserveOnlyCount > 0) {
|
|
116
|
-
return /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 px-3 py-1.5 bg-warning-soft text-comment text-xs", children: [
|
|
117
|
-
/* @__PURE__ */ jsx(AlertTriangle, { className: "h-3.5 w-3.5 shrink-0" }),
|
|
118
|
-
/* @__PURE__ */ jsxs("span", { children: [
|
|
119
|
-
preserveOnlyCount,
|
|
120
|
-
" preserve-only feature",
|
|
121
|
-
preserveOnlyCount !== 1 ? "s" : "",
|
|
122
|
-
" detected"
|
|
123
|
-
] })
|
|
124
|
-
] });
|
|
125
|
-
}
|
|
126
|
-
if (workflowBlockedReasons.length > 0) {
|
|
127
|
-
const firstReason = workflowBlockedReasons[0];
|
|
128
|
-
return /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 px-3 py-1.5 bg-amber-50 text-amber-700 text-xs", children: [
|
|
129
|
-
/* @__PURE__ */ jsx(AlertTriangle, { className: "h-3.5 w-3.5 shrink-0" }),
|
|
130
|
-
/* @__PURE__ */ jsxs("span", { children: [
|
|
131
|
-
firstReason.message,
|
|
132
|
-
workflowBlockedReasons.length > 1 ? ` (+${workflowBlockedReasons.length - 1} more)` : ""
|
|
133
|
-
] })
|
|
134
|
-
] });
|
|
135
|
-
}
|
|
136
|
-
return null;
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
// src/ui-tailwind/chrome/tw-selection-toolbar.tsx
|
|
140
|
-
import { forwardRef } from "react";
|
|
141
|
-
import * as Tooltip from "@radix-ui/react-tooltip";
|
|
142
|
-
import { Baseline, Bold, Highlighter, Italic, MessageSquare, Underline } from "lucide-react";
|
|
143
|
-
|
|
144
|
-
// src/ui/headless/preserve-editor-selection.ts
|
|
145
|
-
function preserveEditorSelectionMouseDown(event) {
|
|
146
|
-
event.preventDefault();
|
|
147
|
-
}
|
|
148
|
-
|
|
149
|
-
// src/ui-tailwind/chrome/tw-selection-toolbar.tsx
|
|
150
|
-
import { Fragment, jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
151
|
-
var focusRingClass = "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-accent focus-visible:ring-offset-2 focus-visible:ring-offset-canvas";
|
|
152
|
-
var TwSelectionToolbar = forwardRef(function TwSelectionToolbar2(props, ref) {
|
|
153
|
-
const { model } = props;
|
|
154
|
-
const addCommentDisabled = !model.canAddComment;
|
|
155
|
-
const formattingDisabled = !model.canToggleFormatting;
|
|
156
|
-
const contextLabel = summarizeSelectionContext(model);
|
|
157
|
-
const tooltipLabel = addCommentDisabled ? props.disabledReason ?? "Select text within one paragraph to add a DOCX comment" : "Add comment";
|
|
158
|
-
return /* @__PURE__ */ jsxs2(
|
|
159
|
-
"div",
|
|
160
|
-
{
|
|
161
|
-
ref,
|
|
162
|
-
"data-testid": "selection-toolbar",
|
|
163
|
-
className: "inline-flex max-w-[min(24rem,calc(100vw-2rem))] items-center gap-1.5 rounded-xl border border-border/80 bg-canvas px-1.5 py-1.5 shadow-lg ring-1 ring-border/80",
|
|
164
|
-
role: "toolbar",
|
|
165
|
-
"aria-label": "Selection actions",
|
|
166
|
-
onFocusCapture: props.onFocusCapture,
|
|
167
|
-
onBlurCapture: props.onBlurCapture,
|
|
168
|
-
children: [
|
|
169
|
-
/* @__PURE__ */ jsx2(
|
|
170
|
-
ToolbarActionButton,
|
|
171
|
-
{
|
|
172
|
-
icon: /* @__PURE__ */ jsx2(Bold, { className: "h-3.5 w-3.5" }),
|
|
173
|
-
label: "Bold selection",
|
|
174
|
-
pressed: model.boldActive,
|
|
175
|
-
disabled: formattingDisabled,
|
|
176
|
-
onClick: props.onToggleBold
|
|
177
|
-
}
|
|
178
|
-
),
|
|
179
|
-
/* @__PURE__ */ jsx2(
|
|
180
|
-
ToolbarActionButton,
|
|
181
|
-
{
|
|
182
|
-
icon: /* @__PURE__ */ jsx2(Italic, { className: "h-3.5 w-3.5" }),
|
|
183
|
-
label: "Italic selection",
|
|
184
|
-
pressed: model.italicActive,
|
|
185
|
-
disabled: formattingDisabled,
|
|
186
|
-
onClick: props.onToggleItalic
|
|
187
|
-
}
|
|
188
|
-
),
|
|
189
|
-
/* @__PURE__ */ jsx2(
|
|
190
|
-
ToolbarActionButton,
|
|
191
|
-
{
|
|
192
|
-
icon: /* @__PURE__ */ jsx2(Underline, { className: "h-3.5 w-3.5" }),
|
|
193
|
-
label: "Underline selection",
|
|
194
|
-
pressed: model.underlineActive,
|
|
195
|
-
disabled: formattingDisabled,
|
|
196
|
-
onClick: props.onToggleUnderline
|
|
197
|
-
}
|
|
198
|
-
),
|
|
199
|
-
/* @__PURE__ */ jsx2(
|
|
200
|
-
ToolbarActionButton,
|
|
201
|
-
{
|
|
202
|
-
icon: /* @__PURE__ */ jsx2(Baseline, { className: "h-3.5 w-3.5" }),
|
|
203
|
-
label: "Text color blue",
|
|
204
|
-
pressed: false,
|
|
205
|
-
disabled: formattingDisabled,
|
|
206
|
-
onClick: () => props.onSetTextColor?.("#1660a8")
|
|
207
|
-
}
|
|
208
|
-
),
|
|
209
|
-
/* @__PURE__ */ jsx2(
|
|
210
|
-
ToolbarActionButton,
|
|
211
|
-
{
|
|
212
|
-
icon: /* @__PURE__ */ jsx2(Highlighter, { className: "h-3.5 w-3.5" }),
|
|
213
|
-
label: "Highlight yellow",
|
|
214
|
-
pressed: false,
|
|
215
|
-
disabled: formattingDisabled,
|
|
216
|
-
onClick: () => props.onSetHighlightColor?.("#ffff00")
|
|
217
|
-
}
|
|
218
|
-
),
|
|
219
|
-
/* @__PURE__ */ jsx2("div", { className: "mx-0.5 h-4 w-px bg-border" }),
|
|
220
|
-
/* @__PURE__ */ jsxs2(Tooltip.Root, { children: [
|
|
221
|
-
/* @__PURE__ */ jsx2(Tooltip.Trigger, { asChild: true, children: /* @__PURE__ */ jsx2(
|
|
222
|
-
"button",
|
|
223
|
-
{
|
|
224
|
-
type: "button",
|
|
225
|
-
"aria-label": "Add comment from selection",
|
|
226
|
-
disabled: addCommentDisabled,
|
|
227
|
-
onMouseDown: preserveEditorSelectionMouseDown,
|
|
228
|
-
onClick: props.onAddComment,
|
|
229
|
-
className: `inline-flex h-7 w-7 items-center justify-center rounded-md transition-colors text-accent hover:bg-accent-soft disabled:cursor-not-allowed disabled:opacity-30 ${focusRingClass}`,
|
|
230
|
-
children: /* @__PURE__ */ jsx2(MessageSquare, { className: "h-3.5 w-3.5" })
|
|
231
|
-
}
|
|
232
|
-
) }),
|
|
233
|
-
/* @__PURE__ */ jsx2(Tooltip.Portal, { children: /* @__PURE__ */ jsx2(
|
|
234
|
-
Tooltip.Content,
|
|
235
|
-
{
|
|
236
|
-
className: "rounded-md bg-primary px-2 py-1 text-xs text-white shadow-md z-50",
|
|
237
|
-
sideOffset: 6,
|
|
238
|
-
children: tooltipLabel
|
|
239
|
-
}
|
|
240
|
-
) })
|
|
241
|
-
] }),
|
|
242
|
-
model.previewText ? /* @__PURE__ */ jsxs2(Fragment, { children: [
|
|
243
|
-
/* @__PURE__ */ jsx2("div", { className: "mx-0.5 h-4 w-px bg-border" }),
|
|
244
|
-
/* @__PURE__ */ jsx2("span", { className: "max-w-[8rem] truncate text-[11px] text-secondary", children: model.previewText })
|
|
245
|
-
] }) : null,
|
|
246
|
-
contextLabel ? /* @__PURE__ */ jsxs2(Fragment, { children: [
|
|
247
|
-
!model.previewText ? /* @__PURE__ */ jsx2("div", { className: "mx-0.5 h-4 w-px bg-border" }) : null,
|
|
248
|
-
/* @__PURE__ */ jsx2(
|
|
249
|
-
"span",
|
|
250
|
-
{
|
|
251
|
-
className: `min-w-0 max-w-[11rem] truncate rounded-full px-2 py-0.5 text-[10px] font-medium tracking-[0.08em] ${model.badges.some((badge) => badge.tone === "accent") ? "bg-accent-soft text-accent" : "bg-surface text-tertiary"}`,
|
|
252
|
-
children: contextLabel
|
|
253
|
-
}
|
|
254
|
-
)
|
|
255
|
-
] }) : null
|
|
256
|
-
]
|
|
257
|
-
}
|
|
258
|
-
);
|
|
259
|
-
});
|
|
260
|
-
function summarizeSelectionContext(model) {
|
|
261
|
-
if (model.badges.length === 0) {
|
|
262
|
-
return null;
|
|
263
|
-
}
|
|
264
|
-
const accentBadges = model.badges.filter((badge) => badge.tone === "accent");
|
|
265
|
-
const source = accentBadges.length > 0 ? accentBadges : model.badges;
|
|
266
|
-
const labels = source.slice(0, 2).map((badge) => badge.label.trim()).filter(Boolean);
|
|
267
|
-
if (labels.length === 0) {
|
|
268
|
-
return null;
|
|
269
|
-
}
|
|
270
|
-
const summary = labels.join(" \xB7 ");
|
|
271
|
-
return summary.length > 30 ? `${summary.slice(0, 27)}...` : summary;
|
|
272
|
-
}
|
|
273
|
-
function ToolbarActionButton(props) {
|
|
274
|
-
return /* @__PURE__ */ jsxs2(Tooltip.Root, { children: [
|
|
275
|
-
/* @__PURE__ */ jsx2(Tooltip.Trigger, { asChild: true, children: /* @__PURE__ */ jsx2(
|
|
276
|
-
"button",
|
|
277
|
-
{
|
|
278
|
-
type: "button",
|
|
279
|
-
"aria-label": props.label,
|
|
280
|
-
"aria-pressed": props.pressed,
|
|
281
|
-
disabled: props.disabled,
|
|
282
|
-
onMouseDown: preserveEditorSelectionMouseDown,
|
|
283
|
-
onClick: props.onClick,
|
|
284
|
-
className: `inline-flex h-7 w-7 items-center justify-center rounded-md transition-colors disabled:cursor-not-allowed disabled:opacity-30 ${props.pressed ? "bg-accent-soft text-accent" : "text-secondary hover:bg-surface"} ${focusRingClass}`,
|
|
285
|
-
children: props.icon
|
|
286
|
-
}
|
|
287
|
-
) }),
|
|
288
|
-
/* @__PURE__ */ jsx2(Tooltip.Portal, { children: /* @__PURE__ */ jsx2(
|
|
289
|
-
Tooltip.Content,
|
|
290
|
-
{
|
|
291
|
-
className: "rounded-md bg-primary px-2 py-1 text-xs text-white shadow-md z-50",
|
|
292
|
-
sideOffset: 6,
|
|
293
|
-
children: props.label
|
|
294
|
-
}
|
|
295
|
-
) })
|
|
296
|
-
] });
|
|
297
|
-
}
|
|
298
|
-
|
|
299
|
-
// src/ui-tailwind/review/tw-comment-sidebar.tsx
|
|
300
|
-
import { useCallback, useEffect, useRef, useState } from "react";
|
|
301
|
-
import { Check, CornerDownRight, RotateCcw } from "lucide-react";
|
|
302
|
-
import { Fragment as Fragment2, jsx as jsx3, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
303
|
-
var focusRingClass2 = "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-accent focus-visible:ring-offset-2 focus-visible:ring-offset-canvas";
|
|
304
|
-
function TwCommentSidebar(props) {
|
|
305
|
-
const { comments, activeCommentId, currentUserId } = props;
|
|
306
|
-
return /* @__PURE__ */ jsxs3("div", { className: "outline-none", children: [
|
|
307
|
-
/* @__PURE__ */ jsxs3("div", { className: "mb-2 flex items-center gap-2 text-[10px] text-tertiary", children: [
|
|
308
|
-
/* @__PURE__ */ jsxs3("span", { children: [
|
|
309
|
-
comments.openCommentIds.length,
|
|
310
|
-
" open"
|
|
311
|
-
] }),
|
|
312
|
-
/* @__PURE__ */ jsx3("span", { className: "text-border", children: "\xB7" }),
|
|
313
|
-
/* @__PURE__ */ jsxs3("span", { children: [
|
|
314
|
-
comments.resolvedCommentIds.length,
|
|
315
|
-
" resolved"
|
|
316
|
-
] }),
|
|
317
|
-
comments.detachedCommentIds.length > 0 && /* @__PURE__ */ jsxs3(Fragment2, { children: [
|
|
318
|
-
/* @__PURE__ */ jsx3("span", { className: "text-border", children: "\xB7" }),
|
|
319
|
-
/* @__PURE__ */ jsxs3("span", { children: [
|
|
320
|
-
comments.detachedCommentIds.length,
|
|
321
|
-
" detached"
|
|
322
|
-
] })
|
|
323
|
-
] })
|
|
324
|
-
] }),
|
|
325
|
-
comments.threads.length > 0 ? /* @__PURE__ */ jsx3("div", { className: "space-y-1.5", children: comments.threads.map((thread) => /* @__PURE__ */ jsx3(
|
|
326
|
-
CommentThreadCard,
|
|
327
|
-
{
|
|
328
|
-
thread,
|
|
329
|
-
isActive: activeCommentId === thread.commentId,
|
|
330
|
-
currentUserId,
|
|
331
|
-
onOpenComment: props.onOpenComment,
|
|
332
|
-
onResolveComment: props.onResolveComment,
|
|
333
|
-
onReopenComment: props.onReopenComment,
|
|
334
|
-
onAddReply: props.onAddReply,
|
|
335
|
-
onEditBody: props.onEditBody
|
|
336
|
-
},
|
|
337
|
-
thread.commentId
|
|
338
|
-
)) }) : /* @__PURE__ */ jsx3("div", { className: "rounded-lg border border-dashed border-border bg-surface/60 px-2.5 py-3 text-[10px] leading-4 text-tertiary", children: "No comment threads yet. Select text and add one from the toolbar." })
|
|
339
|
-
] });
|
|
340
|
-
}
|
|
341
|
-
function CommentThreadCard(props) {
|
|
342
|
-
const { thread, isActive } = props;
|
|
343
|
-
const leadEntry = thread.entries[0];
|
|
344
|
-
const isDraftThread = thread.status === "open" && thread.entryCount === 1 && isEmptyCommentBody(leadEntry?.body);
|
|
345
|
-
const isOwnComment = props.currentUserId != null && leadEntry?.authorId === props.currentUserId;
|
|
346
|
-
const canEdit = isOwnComment && thread.status === "open" && props.onEditBody != null;
|
|
347
|
-
const hasNoBody = isEmptyCommentBody(leadEntry?.body);
|
|
348
|
-
const showExcerpt = Boolean(thread.excerpt) && !isDraftThread && thread.excerpt !== "Empty thread";
|
|
349
|
-
const scrollRef = useCallback(
|
|
350
|
-
(node) => {
|
|
351
|
-
if (node && isActive && typeof node.scrollIntoView === "function") {
|
|
352
|
-
node.scrollIntoView({ behavior: "smooth", block: "nearest" });
|
|
353
|
-
}
|
|
354
|
-
},
|
|
355
|
-
[isActive]
|
|
356
|
-
);
|
|
357
|
-
return /* @__PURE__ */ jsxs3(
|
|
358
|
-
"div",
|
|
359
|
-
{
|
|
360
|
-
ref: scrollRef,
|
|
361
|
-
"data-comment-thread-id": thread.commentId,
|
|
362
|
-
"data-comment-thread-status": thread.status,
|
|
363
|
-
role: "button",
|
|
364
|
-
tabIndex: 0,
|
|
365
|
-
className: [
|
|
366
|
-
"cursor-pointer rounded-lg border px-2 py-1.5 transition-colors",
|
|
367
|
-
focusRingClass2,
|
|
368
|
-
isActive ? "border-accent/25 bg-accent-soft/35" : "border-border bg-canvas hover:border-border-strong hover:bg-surface/70",
|
|
369
|
-
thread.status === "detached" ? "opacity-70" : ""
|
|
370
|
-
].join(" "),
|
|
371
|
-
onClick: () => props.onOpenComment?.(thread),
|
|
372
|
-
onKeyDown: (event) => {
|
|
373
|
-
if (event.key === "Enter" || event.key === " ") {
|
|
374
|
-
event.preventDefault();
|
|
375
|
-
props.onOpenComment?.(thread);
|
|
376
|
-
}
|
|
377
|
-
},
|
|
378
|
-
children: [
|
|
379
|
-
/* @__PURE__ */ jsxs3("div", { className: "mb-1 flex items-center gap-1.5", children: [
|
|
380
|
-
/* @__PURE__ */ jsx3("span", { className: "inline-flex h-4 w-4 shrink-0 items-center justify-center rounded-full bg-accent/10 text-[8px] font-semibold text-accent", children: thread.createdBy.charAt(0).toUpperCase() }),
|
|
381
|
-
/* @__PURE__ */ jsx3("span", { className: "truncate text-[10px] font-medium text-primary", children: thread.createdBy }),
|
|
382
|
-
/* @__PURE__ */ jsx3("span", { "data-comment-thread-created-at": "true", className: "text-[9px] text-tertiary", children: formatCommentDate(thread.createdAt) }),
|
|
383
|
-
/* @__PURE__ */ jsx3("span", { className: "flex-1" }),
|
|
384
|
-
isDraftThread ? /* @__PURE__ */ jsx3(StatusBadge, { label: "draft", tone: "draft" }) : null,
|
|
385
|
-
thread.status === "resolved" ? /* @__PURE__ */ jsx3(StatusBadge, { label: "resolved", tone: "resolved" }) : null,
|
|
386
|
-
thread.status === "detached" ? /* @__PURE__ */ jsx3(StatusBadge, { label: "detached", tone: "detached" }) : null
|
|
387
|
-
] }),
|
|
388
|
-
showExcerpt ? /* @__PURE__ */ jsx3("p", { className: "mb-1 rounded-md border-l-2 border-comment/25 bg-comment-soft/30 px-2 py-1 text-[9px] leading-4 text-comment/80 italic whitespace-pre-wrap break-words line-clamp-2", children: thread.excerpt }) : null,
|
|
389
|
-
canEdit && (isActive || hasNoBody) ? /* @__PURE__ */ jsx3(
|
|
390
|
-
InlineEditableBody,
|
|
391
|
-
{
|
|
392
|
-
body: leadEntry?.body ?? "",
|
|
393
|
-
autoFocus: isActive && hasNoBody,
|
|
394
|
-
onSave: (newBody) => props.onEditBody?.(thread.commentId, newBody),
|
|
395
|
-
label: isDraftThread ? "New comment" : void 0
|
|
396
|
-
}
|
|
397
|
-
) : leadEntry?.body ? /* @__PURE__ */ jsx3(
|
|
398
|
-
"p",
|
|
399
|
-
{
|
|
400
|
-
className: "text-[10px] leading-[1.1rem] text-secondary whitespace-pre-wrap break-words line-clamp-4",
|
|
401
|
-
"data-comment-thread-body": "true",
|
|
402
|
-
children: leadEntry.body
|
|
403
|
-
}
|
|
404
|
-
) : canEdit ? /* @__PURE__ */ jsx3(
|
|
405
|
-
"p",
|
|
406
|
-
{
|
|
407
|
-
className: "cursor-text text-[10px] italic text-tertiary",
|
|
408
|
-
onClick: (e) => {
|
|
409
|
-
e.stopPropagation();
|
|
410
|
-
props.onOpenComment?.(thread);
|
|
411
|
-
},
|
|
412
|
-
children: "New comment"
|
|
413
|
-
}
|
|
414
|
-
) : null,
|
|
415
|
-
thread.entries.slice(1).map((entry) => /* @__PURE__ */ jsxs3("div", { className: "mt-1.5 ml-4 border-l border-border/50 pl-2.5", children: [
|
|
416
|
-
/* @__PURE__ */ jsxs3("div", { className: "mb-0.5 flex items-center gap-1", children: [
|
|
417
|
-
/* @__PURE__ */ jsx3("span", { className: "text-[9px] font-medium text-secondary", children: entry.authorId }),
|
|
418
|
-
/* @__PURE__ */ jsx3("span", { className: "text-[9px] text-tertiary", children: formatCommentDate(entry.createdAt) })
|
|
419
|
-
] }),
|
|
420
|
-
/* @__PURE__ */ jsx3(
|
|
421
|
-
"p",
|
|
422
|
-
{
|
|
423
|
-
className: "text-[10px] leading-4 text-secondary whitespace-pre-wrap break-words line-clamp-3",
|
|
424
|
-
"data-comment-reply-body": "true",
|
|
425
|
-
children: entry.body
|
|
426
|
-
}
|
|
427
|
-
)
|
|
428
|
-
] }, entry.entryId)),
|
|
429
|
-
thread.entryCount > thread.entries.length ? /* @__PURE__ */ jsxs3("p", { className: "mt-1 text-[9px] text-tertiary", children: [
|
|
430
|
-
"+",
|
|
431
|
-
thread.entryCount - thread.entries.length,
|
|
432
|
-
" more"
|
|
433
|
-
] }) : null,
|
|
434
|
-
/* @__PURE__ */ jsxs3("div", { className: "mt-1 flex items-center gap-0.5", children: [
|
|
435
|
-
thread.status === "open" && /* @__PURE__ */ jsxs3(Fragment2, { children: [
|
|
436
|
-
/* @__PURE__ */ jsxs3(
|
|
437
|
-
"button",
|
|
438
|
-
{
|
|
439
|
-
type: "button",
|
|
440
|
-
className: "inline-flex items-center gap-0.5 rounded px-1 py-0.5 text-[9px] font-medium text-insert hover:bg-insert-soft transition-colors",
|
|
441
|
-
onClick: (e) => {
|
|
442
|
-
e.stopPropagation();
|
|
443
|
-
props.onResolveComment?.(thread.commentId);
|
|
444
|
-
},
|
|
445
|
-
children: [
|
|
446
|
-
/* @__PURE__ */ jsx3(Check, { className: "h-2 w-2" }),
|
|
447
|
-
" Resolve"
|
|
448
|
-
]
|
|
449
|
-
}
|
|
450
|
-
),
|
|
451
|
-
props.onAddReply && /* @__PURE__ */ jsx3(ReplyInput, { commentId: thread.commentId, onAddReply: props.onAddReply })
|
|
452
|
-
] }),
|
|
453
|
-
thread.status === "resolved" && /* @__PURE__ */ jsxs3(
|
|
454
|
-
"button",
|
|
455
|
-
{
|
|
456
|
-
type: "button",
|
|
457
|
-
className: "inline-flex items-center gap-0.5 rounded px-1 py-0.5 text-[9px] font-medium text-secondary hover:bg-surface transition-colors",
|
|
458
|
-
"data-comment-thread-action": "reopen",
|
|
459
|
-
onClick: (e) => {
|
|
460
|
-
e.stopPropagation();
|
|
461
|
-
props.onReopenComment?.(thread.commentId);
|
|
462
|
-
},
|
|
463
|
-
children: [
|
|
464
|
-
/* @__PURE__ */ jsx3(RotateCcw, { className: "h-2 w-2" }),
|
|
465
|
-
" Reopen"
|
|
466
|
-
]
|
|
467
|
-
}
|
|
468
|
-
),
|
|
469
|
-
thread.status === "detached" && /* @__PURE__ */ jsx3("span", { className: "text-[9px] text-comment", children: "Detached" })
|
|
470
|
-
] })
|
|
471
|
-
]
|
|
472
|
-
}
|
|
473
|
-
);
|
|
474
|
-
}
|
|
475
|
-
function InlineEditableBody(props) {
|
|
476
|
-
const [isEditing, setIsEditing] = useState(props.autoFocus || props.body === "");
|
|
477
|
-
const [draft, setDraft] = useState(props.body);
|
|
478
|
-
const textareaRef = useRef(null);
|
|
479
|
-
useEffect(() => {
|
|
480
|
-
if (isEditing && textareaRef.current) {
|
|
481
|
-
textareaRef.current.focus();
|
|
482
|
-
textareaRef.current.setSelectionRange(draft.length, draft.length);
|
|
483
|
-
}
|
|
484
|
-
}, [isEditing]);
|
|
485
|
-
if (!isEditing) {
|
|
486
|
-
return /* @__PURE__ */ jsx3(
|
|
487
|
-
"p",
|
|
488
|
-
{
|
|
489
|
-
className: `cursor-text rounded px-1 text-[10px] leading-[1.15rem] -mx-1 transition-colors hover:bg-surface ${props.body ? "text-secondary" : "text-tertiary italic"}`,
|
|
490
|
-
onClick: (e) => {
|
|
491
|
-
e.stopPropagation();
|
|
492
|
-
setDraft(props.body);
|
|
493
|
-
setIsEditing(true);
|
|
494
|
-
},
|
|
495
|
-
title: "Click to edit",
|
|
496
|
-
children: props.body || "Click to add comment\u2026"
|
|
497
|
-
}
|
|
498
|
-
);
|
|
499
|
-
}
|
|
500
|
-
return /* @__PURE__ */ jsxs3("div", { className: "space-y-1", children: [
|
|
501
|
-
props.label ? /* @__PURE__ */ jsx3("span", { className: "block text-[10px] font-medium uppercase tracking-[0.08em] text-tertiary", children: props.label }) : null,
|
|
502
|
-
/* @__PURE__ */ jsx3(
|
|
503
|
-
"textarea",
|
|
504
|
-
{
|
|
505
|
-
ref: textareaRef,
|
|
506
|
-
className: "w-full resize-none rounded-md border border-border bg-surface px-2 py-1.5 text-[10px] leading-4 text-primary placeholder:text-tertiary focus:outline-none focus:ring-1 focus:ring-accent",
|
|
507
|
-
rows: 2,
|
|
508
|
-
value: draft,
|
|
509
|
-
placeholder: "Type your comment...",
|
|
510
|
-
onClick: (e) => e.stopPropagation(),
|
|
511
|
-
onChange: (e) => setDraft(e.target.value),
|
|
512
|
-
onBlur: () => {
|
|
513
|
-
if (draft.trim() && draft.trim() !== props.body) {
|
|
514
|
-
props.onSave(draft.trim());
|
|
515
|
-
}
|
|
516
|
-
setIsEditing(false);
|
|
517
|
-
},
|
|
518
|
-
onKeyDown: (e) => {
|
|
519
|
-
if (e.key === "Enter" && !e.shiftKey) {
|
|
520
|
-
e.preventDefault();
|
|
521
|
-
if (draft.trim() && draft.trim() !== props.body) {
|
|
522
|
-
props.onSave(draft.trim());
|
|
523
|
-
}
|
|
524
|
-
setIsEditing(false);
|
|
525
|
-
}
|
|
526
|
-
if (e.key === "Escape") {
|
|
527
|
-
setDraft(props.body);
|
|
528
|
-
setIsEditing(false);
|
|
529
|
-
}
|
|
530
|
-
e.stopPropagation();
|
|
531
|
-
}
|
|
532
|
-
}
|
|
533
|
-
)
|
|
534
|
-
] });
|
|
535
|
-
}
|
|
536
|
-
function ReplyInput(props) {
|
|
537
|
-
const [body, setBody] = useState("");
|
|
538
|
-
const [isOpen, setIsOpen] = useState(false);
|
|
539
|
-
const inputRef = useRef(null);
|
|
540
|
-
useEffect(() => {
|
|
541
|
-
if (isOpen && inputRef.current) {
|
|
542
|
-
inputRef.current.focus();
|
|
543
|
-
}
|
|
544
|
-
}, [isOpen]);
|
|
545
|
-
if (!isOpen) {
|
|
546
|
-
return /* @__PURE__ */ jsxs3(
|
|
547
|
-
"button",
|
|
548
|
-
{
|
|
549
|
-
type: "button",
|
|
550
|
-
className: "inline-flex items-center gap-0.5 rounded px-1.5 py-0.5 text-[10px] font-medium text-tertiary hover:text-secondary hover:bg-surface transition-colors",
|
|
551
|
-
onClick: (e) => {
|
|
552
|
-
e.stopPropagation();
|
|
553
|
-
setIsOpen(true);
|
|
554
|
-
},
|
|
555
|
-
children: [
|
|
556
|
-
/* @__PURE__ */ jsx3(CornerDownRight, { className: "h-2.5 w-2.5" }),
|
|
557
|
-
" Reply"
|
|
558
|
-
]
|
|
559
|
-
}
|
|
560
|
-
);
|
|
561
|
-
}
|
|
562
|
-
return /* @__PURE__ */ jsxs3("div", { className: "w-full mt-1.5", onClick: (e) => e.stopPropagation(), children: [
|
|
563
|
-
/* @__PURE__ */ jsx3(
|
|
564
|
-
"textarea",
|
|
565
|
-
{
|
|
566
|
-
ref: inputRef,
|
|
567
|
-
className: "w-full rounded border border-border bg-surface px-2 py-1 text-[11px] text-primary placeholder:text-tertiary resize-none focus:outline-none focus:ring-1 focus:ring-accent",
|
|
568
|
-
rows: 2,
|
|
569
|
-
placeholder: "Reply...",
|
|
570
|
-
value: body,
|
|
571
|
-
onChange: (e) => setBody(e.target.value),
|
|
572
|
-
onKeyDown: (e) => {
|
|
573
|
-
if (e.key === "Enter" && !e.shiftKey && body.trim()) {
|
|
574
|
-
e.preventDefault();
|
|
575
|
-
props.onAddReply(props.commentId, body.trim());
|
|
576
|
-
setBody("");
|
|
577
|
-
setIsOpen(false);
|
|
578
|
-
}
|
|
579
|
-
if (e.key === "Escape") {
|
|
580
|
-
setBody("");
|
|
581
|
-
setIsOpen(false);
|
|
582
|
-
}
|
|
583
|
-
e.stopPropagation();
|
|
584
|
-
}
|
|
585
|
-
}
|
|
586
|
-
),
|
|
587
|
-
/* @__PURE__ */ jsxs3("div", { className: "flex gap-1 mt-0.5", children: [
|
|
588
|
-
/* @__PURE__ */ jsx3(
|
|
589
|
-
"button",
|
|
590
|
-
{
|
|
591
|
-
type: "button",
|
|
592
|
-
disabled: !body.trim(),
|
|
593
|
-
className: "rounded px-1.5 py-0.5 text-[10px] font-medium text-accent hover:bg-accent-soft transition-colors disabled:opacity-40",
|
|
594
|
-
onClick: () => {
|
|
595
|
-
if (body.trim()) {
|
|
596
|
-
props.onAddReply(props.commentId, body.trim());
|
|
597
|
-
setBody("");
|
|
598
|
-
setIsOpen(false);
|
|
599
|
-
}
|
|
600
|
-
},
|
|
601
|
-
children: "Send"
|
|
602
|
-
}
|
|
603
|
-
),
|
|
604
|
-
/* @__PURE__ */ jsx3(
|
|
605
|
-
"button",
|
|
606
|
-
{
|
|
607
|
-
type: "button",
|
|
608
|
-
className: "rounded px-1.5 py-0.5 text-[10px] text-tertiary hover:bg-surface transition-colors",
|
|
609
|
-
onClick: () => {
|
|
610
|
-
setBody("");
|
|
611
|
-
setIsOpen(false);
|
|
612
|
-
},
|
|
613
|
-
children: "Cancel"
|
|
614
|
-
}
|
|
615
|
-
)
|
|
616
|
-
] })
|
|
617
|
-
] });
|
|
618
|
-
}
|
|
619
|
-
function formatCommentDate(raw) {
|
|
620
|
-
try {
|
|
621
|
-
const date = new Date(raw);
|
|
622
|
-
if (Number.isNaN(date.getTime())) return raw;
|
|
623
|
-
const now = /* @__PURE__ */ new Date();
|
|
624
|
-
const diffMs = now.getTime() - date.getTime();
|
|
625
|
-
const diffMin = Math.floor(diffMs / 6e4);
|
|
626
|
-
if (diffMin < 1) return "just now";
|
|
627
|
-
if (diffMin < 60) return `${diffMin}m ago`;
|
|
628
|
-
const diffHours = Math.floor(diffMin / 60);
|
|
629
|
-
if (diffHours < 24) return `${diffHours}h ago`;
|
|
630
|
-
const diffDays = Math.floor(diffHours / 24);
|
|
631
|
-
if (diffDays < 7) return `${diffDays}d ago`;
|
|
632
|
-
return new Intl.DateTimeFormat("en-US", {
|
|
633
|
-
month: "short",
|
|
634
|
-
day: "numeric",
|
|
635
|
-
year: date.getFullYear() !== now.getFullYear() ? "numeric" : void 0
|
|
636
|
-
}).format(date);
|
|
637
|
-
} catch {
|
|
638
|
-
return raw;
|
|
639
|
-
}
|
|
640
|
-
}
|
|
641
|
-
function StatusBadge(props) {
|
|
642
|
-
const styles = {
|
|
643
|
-
resolved: "text-insert bg-insert-soft",
|
|
644
|
-
detached: "text-comment bg-warning-soft",
|
|
645
|
-
draft: "text-secondary bg-subtle"
|
|
646
|
-
};
|
|
647
|
-
return /* @__PURE__ */ jsx3(
|
|
648
|
-
"span",
|
|
649
|
-
{
|
|
650
|
-
className: `shrink-0 rounded px-1 py-px text-[8px] font-medium uppercase tracking-[0.08em] ${styles[props.tone] ?? "text-secondary bg-subtle"}`,
|
|
651
|
-
"data-comment-thread-badge": props.tone,
|
|
652
|
-
children: props.label
|
|
653
|
-
}
|
|
654
|
-
);
|
|
655
|
-
}
|
|
656
|
-
function isEmptyCommentBody(body) {
|
|
657
|
-
return !body || body.trim() === "";
|
|
658
|
-
}
|
|
659
|
-
|
|
660
|
-
// src/ui-tailwind/review/tw-revision-sidebar.tsx
|
|
661
|
-
import { Check as Check2, X } from "lucide-react";
|
|
662
|
-
|
|
663
|
-
// src/ui/shared/revision-filters.ts
|
|
664
|
-
function selectVisibleRevisions(revisions, markupDisplay) {
|
|
665
|
-
switch (markupDisplay) {
|
|
666
|
-
case "clean":
|
|
667
|
-
case "simple":
|
|
668
|
-
return revisions.filter(
|
|
669
|
-
(revision) => revision.status === "active" && revision.actionability === "actionable"
|
|
670
|
-
);
|
|
671
|
-
case "all":
|
|
672
|
-
return [...revisions];
|
|
673
|
-
}
|
|
674
|
-
}
|
|
675
|
-
|
|
676
|
-
// src/ui-tailwind/review/tw-revision-sidebar.tsx
|
|
677
|
-
import { Fragment as Fragment3, jsx as jsx4, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
678
|
-
var focusRingClass3 = "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-accent focus-visible:ring-offset-2 focus-visible:ring-offset-canvas";
|
|
679
|
-
function TwRevisionSidebar(props) {
|
|
680
|
-
const { trackedChanges, markupDisplay, activeRevisionId } = props;
|
|
681
|
-
const visibleRevisions = selectVisibleRevisions(trackedChanges.revisions, markupDisplay);
|
|
682
|
-
const actionablePendingCount = trackedChanges.revisions.filter(
|
|
683
|
-
(r) => r.status === "active" && r.actionability === "actionable"
|
|
684
|
-
).length;
|
|
685
|
-
return /* @__PURE__ */ jsxs4("div", { className: "outline-none", children: [
|
|
686
|
-
/* @__PURE__ */ jsxs4("p", { className: "mb-2 text-[10px] text-tertiary", children: [
|
|
687
|
-
trackedChanges.pendingChangeIds.length,
|
|
688
|
-
" active \xB7 ",
|
|
689
|
-
trackedChanges.acceptedChangeIds.length,
|
|
690
|
-
" accepted \xB7 ",
|
|
691
|
-
trackedChanges.preserveOnlyChangeIds.length,
|
|
692
|
-
" preserve-only"
|
|
693
|
-
] }),
|
|
694
|
-
/* @__PURE__ */ jsxs4("div", { className: "mb-2 flex gap-1", children: [
|
|
695
|
-
/* @__PURE__ */ jsxs4(
|
|
696
|
-
"button",
|
|
697
|
-
{
|
|
698
|
-
type: "button",
|
|
699
|
-
disabled: actionablePendingCount === 0,
|
|
700
|
-
className: "inline-flex items-center gap-1 rounded-md px-2 py-1 text-[10px] font-semibold text-accent hover:bg-accent-soft transition-colors disabled:opacity-30 disabled:cursor-not-allowed",
|
|
701
|
-
onClick: props.onAcceptAllChanges,
|
|
702
|
-
children: [
|
|
703
|
-
"Accept all (",
|
|
704
|
-
actionablePendingCount,
|
|
705
|
-
")"
|
|
706
|
-
]
|
|
707
|
-
}
|
|
708
|
-
),
|
|
709
|
-
/* @__PURE__ */ jsx4(
|
|
710
|
-
"button",
|
|
711
|
-
{
|
|
712
|
-
type: "button",
|
|
713
|
-
disabled: actionablePendingCount === 0,
|
|
714
|
-
className: "inline-flex items-center gap-1 rounded-md px-2 py-1 text-[10px] text-secondary hover:bg-surface transition-colors disabled:opacity-30 disabled:cursor-not-allowed",
|
|
715
|
-
onClick: props.onRejectAllChanges,
|
|
716
|
-
children: "Reject all"
|
|
717
|
-
}
|
|
718
|
-
)
|
|
719
|
-
] }),
|
|
720
|
-
visibleRevisions.length > 0 ? /* @__PURE__ */ jsx4("div", { className: "space-y-1", children: visibleRevisions.map((rev) => {
|
|
721
|
-
const isActive = activeRevisionId === rev.revisionId;
|
|
722
|
-
return /* @__PURE__ */ jsxs4(
|
|
723
|
-
"div",
|
|
724
|
-
{
|
|
725
|
-
role: "button",
|
|
726
|
-
tabIndex: 0,
|
|
727
|
-
className: `flex rounded-lg transition-colors cursor-pointer ${focusRingClass3} ${isActive ? "bg-accent-soft" : "hover:bg-surface"}`,
|
|
728
|
-
onClick: () => props.onOpenRevision?.(rev),
|
|
729
|
-
onKeyDown: (event) => {
|
|
730
|
-
if (event.key === "Enter" || event.key === " ") {
|
|
731
|
-
event.preventDefault();
|
|
732
|
-
props.onOpenRevision?.(rev);
|
|
733
|
-
}
|
|
734
|
-
},
|
|
735
|
-
children: [
|
|
736
|
-
/* @__PURE__ */ jsx4("div", { className: `w-0.5 shrink-0 rounded-l-lg ${rev.kind === "insertion" ? "bg-insert" : rev.kind === "deletion" ? "bg-danger" : "bg-tertiary"}` }),
|
|
737
|
-
/* @__PURE__ */ jsxs4("div", { className: "p-2 flex-1 min-w-0", children: [
|
|
738
|
-
/* @__PURE__ */ jsxs4("div", { className: "mb-0.5 flex items-start justify-between gap-2", children: [
|
|
739
|
-
/* @__PURE__ */ jsx4("span", { className: "text-[11px] font-medium text-primary", children: rev.anchorLabel }),
|
|
740
|
-
/* @__PURE__ */ jsx4(RevisionBadge, { status: rev.status, actionability: rev.actionability })
|
|
741
|
-
] }),
|
|
742
|
-
/* @__PURE__ */ jsxs4("p", { className: "mb-1 text-[10px] text-tertiary", children: [
|
|
743
|
-
rev.authorId,
|
|
744
|
-
" \xB7 ",
|
|
745
|
-
rev.createdAt
|
|
746
|
-
] }),
|
|
747
|
-
rev.excerpt ? /* @__PURE__ */ jsx4("p", { className: `text-[11px] ${rev.kind === "insertion" ? "text-insert" : rev.kind === "deletion" ? "text-danger line-through" : "text-secondary"}`, children: rev.excerpt }) : /* @__PURE__ */ jsx4("p", { className: "text-[11px] text-secondary", children: rev.label }),
|
|
748
|
-
rev.detail ? /* @__PURE__ */ jsx4("p", { className: "mt-1 text-[10px] text-secondary", children: rev.detail }) : null,
|
|
749
|
-
/* @__PURE__ */ jsx4("div", { className: "mt-1.5 flex gap-1", children: rev.actionability === "actionable" ? /* @__PURE__ */ jsxs4(Fragment3, { children: [
|
|
750
|
-
/* @__PURE__ */ jsxs4(
|
|
751
|
-
"button",
|
|
752
|
-
{
|
|
753
|
-
type: "button",
|
|
754
|
-
disabled: !rev.canAccept || rev.status === "accepted",
|
|
755
|
-
className: "inline-flex items-center gap-1 rounded-md px-1.5 py-0.5 text-[10px] text-insert hover:bg-insert-soft transition-colors disabled:opacity-30 disabled:cursor-not-allowed",
|
|
756
|
-
onClick: (e) => {
|
|
757
|
-
e.stopPropagation();
|
|
758
|
-
props.onAcceptRevision?.(rev.revisionId);
|
|
759
|
-
},
|
|
760
|
-
children: [
|
|
761
|
-
/* @__PURE__ */ jsx4(Check2, { className: "h-3 w-3" }),
|
|
762
|
-
" Accept"
|
|
763
|
-
]
|
|
764
|
-
}
|
|
765
|
-
),
|
|
766
|
-
/* @__PURE__ */ jsxs4(
|
|
767
|
-
"button",
|
|
768
|
-
{
|
|
769
|
-
type: "button",
|
|
770
|
-
disabled: !rev.canReject || rev.status === "rejected",
|
|
771
|
-
className: "inline-flex items-center gap-1 rounded-md px-1.5 py-0.5 text-[10px] text-danger hover:bg-delete-soft transition-colors disabled:opacity-30 disabled:cursor-not-allowed",
|
|
772
|
-
onClick: (e) => {
|
|
773
|
-
e.stopPropagation();
|
|
774
|
-
props.onRejectRevision?.(rev.revisionId);
|
|
775
|
-
},
|
|
776
|
-
children: [
|
|
777
|
-
/* @__PURE__ */ jsx4(X, { className: "h-3 w-3" }),
|
|
778
|
-
" Reject"
|
|
779
|
-
]
|
|
780
|
-
}
|
|
781
|
-
)
|
|
782
|
-
] }) : /* @__PURE__ */ jsx4("span", { className: "px-1.5 py-0.5 text-[10px] text-tertiary", children: "Preserve-only" }) })
|
|
783
|
-
] })
|
|
784
|
-
]
|
|
785
|
-
},
|
|
786
|
-
rev.revisionId
|
|
787
|
-
);
|
|
788
|
-
}) }) : /* @__PURE__ */ jsx4("p", { className: "text-xs text-tertiary py-4", children: trackedChanges.totalCount > 0 ? "Switch to Full markup to see all tracked changes." : "Tracked change cards will appear here when present." })
|
|
789
|
-
] });
|
|
790
|
-
}
|
|
791
|
-
function RevisionBadge(props) {
|
|
792
|
-
if (props.actionability === "preserve-only") {
|
|
793
|
-
return /* @__PURE__ */ jsx4("span", { className: "inline-flex items-center rounded px-1.5 py-0.5 text-[10px] font-medium text-comment bg-warning-soft", children: "preserve-only" });
|
|
794
|
-
}
|
|
795
|
-
const styles = {
|
|
796
|
-
active: "text-secondary bg-subtle",
|
|
797
|
-
accepted: "text-insert bg-insert-soft",
|
|
798
|
-
rejected: "text-danger bg-delete-soft",
|
|
799
|
-
detached: "text-comment bg-warning-soft"
|
|
800
|
-
};
|
|
801
|
-
return /* @__PURE__ */ jsx4("span", { className: `inline-flex items-center rounded px-1.5 py-0.5 text-[10px] font-medium ${styles[props.status] ?? "text-secondary bg-subtle"}`, children: props.status });
|
|
802
|
-
}
|
|
803
|
-
|
|
804
|
-
// src/ui-tailwind/review/tw-review-rail.tsx
|
|
805
|
-
import * as Tabs from "@radix-ui/react-tabs";
|
|
806
|
-
import * as ScrollArea from "@radix-ui/react-scroll-area";
|
|
807
|
-
import { jsx as jsx5, jsxs as jsxs5 } from "react/jsx-runtime";
|
|
808
|
-
var focusRingClass4 = "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-accent focus-visible:ring-offset-2 focus-visible:ring-offset-canvas";
|
|
809
|
-
function TwReviewRail(props) {
|
|
810
|
-
const warningCount = props.compatibility.featureEntries.filter(
|
|
811
|
-
(e) => e.featureClass !== "supported-roundtrip"
|
|
812
|
-
).length + props.warnings.length;
|
|
813
|
-
return /* @__PURE__ */ jsx5(
|
|
814
|
-
"aside",
|
|
815
|
-
{
|
|
816
|
-
"aria-label": "Review rail",
|
|
817
|
-
className: "flex w-[304px] shrink-0 flex-col border-l border-border bg-canvas",
|
|
818
|
-
children: /* @__PURE__ */ jsxs5(
|
|
819
|
-
Tabs.Root,
|
|
820
|
-
{
|
|
821
|
-
value: props.activeTab,
|
|
822
|
-
onValueChange: (v) => props.onActiveTabChange(v),
|
|
823
|
-
className: "flex flex-1 flex-col min-h-0",
|
|
824
|
-
children: [
|
|
825
|
-
/* @__PURE__ */ jsxs5(Tabs.List, { className: "flex shrink-0 border-b border-border px-2", children: [
|
|
826
|
-
/* @__PURE__ */ jsxs5(
|
|
827
|
-
Tabs.Trigger,
|
|
828
|
-
{
|
|
829
|
-
value: "comments",
|
|
830
|
-
className: `flex-1 py-2 text-xs text-tertiary font-medium transition-colors data-[state=active]:text-primary data-[state=active]:font-semibold data-[state=active]:shadow-[inset_0_-2px_0_var(--color-accent)] outline-none ${focusRingClass4}`,
|
|
831
|
-
children: [
|
|
832
|
-
"Comments",
|
|
833
|
-
" ",
|
|
834
|
-
/* @__PURE__ */ jsx5("span", { className: "ml-1 inline-flex min-w-[14px] items-center justify-center rounded-full bg-subtle px-1.5 py-px text-[10px] font-medium text-tertiary", children: props.comments.totalCount })
|
|
835
|
-
]
|
|
836
|
-
}
|
|
837
|
-
),
|
|
838
|
-
/* @__PURE__ */ jsxs5(
|
|
839
|
-
Tabs.Trigger,
|
|
840
|
-
{
|
|
841
|
-
value: "changes",
|
|
842
|
-
className: `flex-1 py-2 text-xs text-tertiary font-medium transition-colors data-[state=active]:text-primary data-[state=active]:font-semibold data-[state=active]:shadow-[inset_0_-2px_0_var(--color-accent)] outline-none ${focusRingClass4}`,
|
|
843
|
-
children: [
|
|
844
|
-
"Changes",
|
|
845
|
-
" ",
|
|
846
|
-
/* @__PURE__ */ jsx5("span", { className: "ml-1 inline-flex min-w-[14px] items-center justify-center rounded-full bg-subtle px-1.5 py-px text-[10px] font-medium text-tertiary", children: props.trackedChanges.totalCount })
|
|
847
|
-
]
|
|
848
|
-
}
|
|
849
|
-
)
|
|
850
|
-
] }),
|
|
851
|
-
/* @__PURE__ */ jsxs5(ScrollArea.Root, { className: "flex-1 min-h-0", children: [
|
|
852
|
-
/* @__PURE__ */ jsxs5(ScrollArea.Viewport, { className: "h-full w-full", children: [
|
|
853
|
-
/* @__PURE__ */ jsx5(Tabs.Content, { value: "comments", className: "p-2.5 outline-none", children: /* @__PURE__ */ jsx5(
|
|
854
|
-
TwCommentSidebar,
|
|
855
|
-
{
|
|
856
|
-
currentUserId: props.currentUserId,
|
|
857
|
-
comments: props.comments,
|
|
858
|
-
activeCommentId: props.activeCommentId,
|
|
859
|
-
onOpenComment: props.onOpenComment,
|
|
860
|
-
onResolveComment: props.onResolveComment,
|
|
861
|
-
onReopenComment: props.onReopenComment,
|
|
862
|
-
onAddReply: props.onAddReply,
|
|
863
|
-
onEditBody: props.onEditBody
|
|
864
|
-
}
|
|
865
|
-
) }),
|
|
866
|
-
/* @__PURE__ */ jsx5(Tabs.Content, { value: "changes", className: "p-2.5 outline-none", children: /* @__PURE__ */ jsx5(
|
|
867
|
-
TwRevisionSidebar,
|
|
868
|
-
{
|
|
869
|
-
trackedChanges: props.trackedChanges,
|
|
870
|
-
markupDisplay: props.markupDisplay,
|
|
871
|
-
activeRevisionId: props.activeRevisionId,
|
|
872
|
-
onOpenRevision: props.onOpenRevision,
|
|
873
|
-
onAcceptRevision: props.onAcceptRevision,
|
|
874
|
-
onRejectRevision: props.onRejectRevision,
|
|
875
|
-
onAcceptAllChanges: props.onAcceptAllChanges,
|
|
876
|
-
onRejectAllChanges: props.onRejectAllChanges
|
|
877
|
-
}
|
|
878
|
-
) })
|
|
879
|
-
] }),
|
|
880
|
-
/* @__PURE__ */ jsx5(
|
|
881
|
-
ScrollArea.Scrollbar,
|
|
882
|
-
{
|
|
883
|
-
orientation: "vertical",
|
|
884
|
-
className: "flex w-1.5 touch-none select-none p-0.5",
|
|
885
|
-
children: /* @__PURE__ */ jsx5(ScrollArea.Thumb, { className: "relative flex-1 rounded-full bg-black/[0.12]" })
|
|
886
|
-
}
|
|
887
|
-
)
|
|
888
|
-
] })
|
|
889
|
-
]
|
|
890
|
-
}
|
|
891
|
-
)
|
|
892
|
-
}
|
|
893
|
-
);
|
|
894
|
-
}
|
|
895
|
-
|
|
896
|
-
// src/ui-tailwind/status/tw-status-bar.tsx
|
|
897
|
-
import { jsx as jsx6, jsxs as jsxs6 } from "react/jsx-runtime";
|
|
898
|
-
function TwStatusBar(props) {
|
|
899
|
-
const saveState = props.isExportBlocked ? "Read-only" : props.isDirty ? "Unsaved" : "Ready";
|
|
900
|
-
const exportState = props.isExportBlocked ? "Blocked" : props.preserveOnlyCount > 0 ? "Warnings" : "Ready";
|
|
901
|
-
return /* @__PURE__ */ jsxs6(
|
|
902
|
-
"footer",
|
|
903
|
-
{
|
|
904
|
-
"data-testid": "status-bar",
|
|
905
|
-
className: "flex h-7 shrink-0 items-center gap-4 border-t border-border px-3 text-xs text-tertiary",
|
|
906
|
-
children: [
|
|
907
|
-
/* @__PURE__ */ jsxs6("span", { className: "flex items-center gap-1.5", children: [
|
|
908
|
-
/* @__PURE__ */ jsx6(
|
|
909
|
-
"span",
|
|
910
|
-
{
|
|
911
|
-
className: `inline-block h-1.5 w-1.5 rounded-full ${props.isExportBlocked ? "bg-danger" : props.isDirty ? "bg-comment" : "bg-insert"}`
|
|
912
|
-
}
|
|
913
|
-
),
|
|
914
|
-
saveState
|
|
915
|
-
] }),
|
|
916
|
-
/* @__PURE__ */ jsxs6("span", { className: "flex items-center gap-1.5", children: [
|
|
917
|
-
/* @__PURE__ */ jsx6(
|
|
918
|
-
"span",
|
|
919
|
-
{
|
|
920
|
-
className: `inline-block h-1.5 w-1.5 rounded-full ${props.isExportBlocked ? "bg-danger" : props.preserveOnlyCount > 0 ? "bg-comment" : "bg-insert"}`
|
|
921
|
-
}
|
|
922
|
-
),
|
|
923
|
-
"Export ",
|
|
924
|
-
exportState.toLowerCase()
|
|
925
|
-
] }),
|
|
926
|
-
/* @__PURE__ */ jsxs6("span", { children: [
|
|
927
|
-
props.commentCount,
|
|
928
|
-
" comment",
|
|
929
|
-
props.commentCount !== 1 ? "s" : "",
|
|
930
|
-
" \xB7",
|
|
931
|
-
" ",
|
|
932
|
-
props.changeCount,
|
|
933
|
-
" change",
|
|
934
|
-
props.changeCount !== 1 ? "s" : ""
|
|
935
|
-
] }),
|
|
936
|
-
/* @__PURE__ */ jsx6("span", { className: "flex-1" }),
|
|
937
|
-
/* @__PURE__ */ jsx6("span", { children: props.sessionId })
|
|
938
|
-
]
|
|
939
|
-
}
|
|
940
|
-
);
|
|
941
|
-
}
|
|
942
|
-
|
|
943
|
-
// src/ui-tailwind/review/tw-health-panel.tsx
|
|
944
|
-
import { AlertTriangle as AlertTriangle2, Info, Shield, ShieldAlert, ShieldCheck } from "lucide-react";
|
|
945
|
-
import { Fragment as Fragment4, jsx as jsx7, jsxs as jsxs7 } from "react/jsx-runtime";
|
|
946
|
-
function TwHealthPanel(props) {
|
|
947
|
-
const { compatibility, warnings, blockedReasons = [] } = props;
|
|
948
|
-
const supportedCount = compatibility.featureEntries.filter(
|
|
949
|
-
(e) => e.featureClass === "supported-roundtrip"
|
|
950
|
-
).length;
|
|
951
|
-
const preserveOnlyCount = compatibility.featureEntries.filter(
|
|
952
|
-
(e) => e.featureClass === "preserve-only"
|
|
953
|
-
).length;
|
|
954
|
-
const blockedCount = compatibility.featureEntries.filter(
|
|
955
|
-
(e) => e.featureClass === "unsupported-fatal"
|
|
956
|
-
).length;
|
|
957
|
-
return /* @__PURE__ */ jsxs7("div", { className: "outline-none", children: [
|
|
958
|
-
/* @__PURE__ */ jsxs7("p", { className: "text-xs text-tertiary mb-3", children: [
|
|
959
|
-
supportedCount,
|
|
960
|
-
" supported \xB7 ",
|
|
961
|
-
preserveOnlyCount,
|
|
962
|
-
" preserve-only \xB7 ",
|
|
963
|
-
blockedCount,
|
|
964
|
-
" blocked",
|
|
965
|
-
warnings.length > 0 ? ` \xB7 ${warnings.length} warning${warnings.length !== 1 ? "s" : ""}` : ""
|
|
966
|
-
] }),
|
|
967
|
-
/* @__PURE__ */ jsxs7("div", { className: "space-y-1", children: [
|
|
968
|
-
compatibility.featureEntries.map((entry) => /* @__PURE__ */ jsxs7("div", { className: "flex rounded-lg transition-colors hover:bg-surface", children: [
|
|
969
|
-
entry.featureClass !== "supported-roundtrip" ? /* @__PURE__ */ jsx7("div", { className: `w-0.5 shrink-0 rounded-l-lg ${entry.featureClass === "unsupported-fatal" ? "bg-danger" : "bg-comment"}` }) : null,
|
|
970
|
-
/* @__PURE__ */ jsxs7("div", { className: "flex items-start gap-2 p-2.5 flex-1", children: [
|
|
971
|
-
/* @__PURE__ */ jsx7(HealthIcon, { featureClass: entry.featureClass }),
|
|
972
|
-
/* @__PURE__ */ jsxs7("div", { className: "flex-1 min-w-0", children: [
|
|
973
|
-
/* @__PURE__ */ jsxs7("div", { className: "flex items-start justify-between gap-2", children: [
|
|
974
|
-
/* @__PURE__ */ jsx7("span", { className: "text-sm font-medium text-primary", children: entry.message }),
|
|
975
|
-
/* @__PURE__ */ jsx7(FeatureClassBadge, { featureClass: entry.featureClass })
|
|
976
|
-
] }),
|
|
977
|
-
/* @__PURE__ */ jsx7("p", { className: "text-xs text-tertiary mt-0.5", children: entry.featureKey })
|
|
978
|
-
] })
|
|
979
|
-
] })
|
|
980
|
-
] }, entry.featureEntryId)),
|
|
981
|
-
warnings.map((warning) => /* @__PURE__ */ jsxs7("div", { className: "flex rounded-lg transition-colors hover:bg-surface", children: [
|
|
982
|
-
/* @__PURE__ */ jsx7("div", { className: `w-0.5 shrink-0 rounded-l-lg ${warning.severity === "warning" ? "bg-comment" : "bg-accent"}` }),
|
|
983
|
-
/* @__PURE__ */ jsxs7("div", { className: "flex items-start gap-2 p-2.5 flex-1", children: [
|
|
984
|
-
warning.severity === "warning" ? /* @__PURE__ */ jsx7(AlertTriangle2, { className: "h-4 w-4 text-comment shrink-0 mt-0.5" }) : /* @__PURE__ */ jsx7(Info, { className: "h-4 w-4 text-accent shrink-0 mt-0.5" }),
|
|
985
|
-
/* @__PURE__ */ jsxs7("div", { className: "flex-1 min-w-0", children: [
|
|
986
|
-
/* @__PURE__ */ jsxs7("div", { className: "flex items-start justify-between gap-2", children: [
|
|
987
|
-
/* @__PURE__ */ jsx7("span", { className: "text-sm font-medium text-primary", children: warning.message }),
|
|
988
|
-
/* @__PURE__ */ jsx7("span", { className: `inline-flex items-center rounded px-1.5 py-0.5 text-[10px] font-medium ${warning.severity === "warning" ? "text-comment bg-warning-soft" : "text-accent bg-accent-soft"}`, children: warning.code.replace(/_/g, " ") })
|
|
989
|
-
] }),
|
|
990
|
-
/* @__PURE__ */ jsx7("p", { className: "text-xs text-tertiary mt-0.5", children: warning.source })
|
|
991
|
-
] })
|
|
992
|
-
] })
|
|
993
|
-
] }, warning.warningId)),
|
|
994
|
-
blockedReasons.length > 0 ? /* @__PURE__ */ jsxs7(Fragment4, { children: [
|
|
995
|
-
/* @__PURE__ */ jsx7("div", { className: "border-t border-border mt-2 pt-2", children: /* @__PURE__ */ jsx7("p", { className: "text-xs font-medium text-tertiary mb-1", children: "Workflow blocked reasons" }) }),
|
|
996
|
-
blockedReasons.map((reason, index) => /* @__PURE__ */ jsxs7("div", { className: "flex rounded-lg transition-colors hover:bg-surface", children: [
|
|
997
|
-
/* @__PURE__ */ jsx7("div", { className: "w-0.5 shrink-0 rounded-l-lg bg-amber-400" }),
|
|
998
|
-
/* @__PURE__ */ jsxs7("div", { className: "flex items-start gap-2 p-2.5 flex-1", children: [
|
|
999
|
-
/* @__PURE__ */ jsx7(ShieldAlert, { className: "h-4 w-4 text-amber-500 shrink-0 mt-0.5" }),
|
|
1000
|
-
/* @__PURE__ */ jsxs7("div", { className: "flex-1 min-w-0", children: [
|
|
1001
|
-
/* @__PURE__ */ jsxs7("div", { className: "flex items-start justify-between gap-2", children: [
|
|
1002
|
-
/* @__PURE__ */ jsx7("span", { className: "text-sm font-medium text-primary", children: reason.message }),
|
|
1003
|
-
/* @__PURE__ */ jsx7("span", { className: "inline-flex items-center rounded px-1.5 py-0.5 text-[10px] font-medium text-amber-700 bg-amber-100", children: reason.code.replace(/_/g, " ") })
|
|
1004
|
-
] }),
|
|
1005
|
-
reason.scopeId ? /* @__PURE__ */ jsxs7("p", { className: "text-xs text-tertiary mt-0.5", children: [
|
|
1006
|
-
"scope: ",
|
|
1007
|
-
reason.scopeId
|
|
1008
|
-
] }) : null
|
|
1009
|
-
] })
|
|
1010
|
-
] })
|
|
1011
|
-
] }, `blocked-${index}`))
|
|
1012
|
-
] }) : null,
|
|
1013
|
-
compatibility.featureEntries.length === 0 && warnings.length === 0 && blockedReasons.length === 0 ? /* @__PURE__ */ jsx7("p", { className: "text-xs text-tertiary py-4", children: "No compatibility entries or warnings to display." }) : null
|
|
1014
|
-
] })
|
|
1015
|
-
] });
|
|
1016
|
-
}
|
|
1017
|
-
function HealthIcon(props) {
|
|
1018
|
-
switch (props.featureClass) {
|
|
1019
|
-
case "supported-roundtrip":
|
|
1020
|
-
return /* @__PURE__ */ jsx7(ShieldCheck, { className: "h-4 w-4 text-insert shrink-0 mt-0.5" });
|
|
1021
|
-
case "preserve-only":
|
|
1022
|
-
return /* @__PURE__ */ jsx7(Shield, { className: "h-4 w-4 text-comment shrink-0 mt-0.5" });
|
|
1023
|
-
case "unsupported-fatal":
|
|
1024
|
-
return /* @__PURE__ */ jsx7(ShieldAlert, { className: "h-4 w-4 text-danger shrink-0 mt-0.5" });
|
|
1025
|
-
}
|
|
1026
|
-
}
|
|
1027
|
-
function FeatureClassBadge(props) {
|
|
1028
|
-
const styles = {
|
|
1029
|
-
"supported-roundtrip": "text-insert bg-insert-soft",
|
|
1030
|
-
"preserve-only": "text-comment bg-warning-soft",
|
|
1031
|
-
"unsupported-fatal": "text-danger bg-delete-soft"
|
|
1032
|
-
};
|
|
1033
|
-
const labels = {
|
|
1034
|
-
"supported-roundtrip": "supported",
|
|
1035
|
-
"preserve-only": "preserve-only",
|
|
1036
|
-
"unsupported-fatal": "blocked"
|
|
1037
|
-
};
|
|
1038
|
-
return /* @__PURE__ */ jsx7("span", { className: `inline-flex items-center rounded px-1.5 py-0.5 text-[10px] font-medium ${styles[props.featureClass]}`, children: labels[props.featureClass] });
|
|
1039
|
-
}
|
|
1040
|
-
|
|
1041
|
-
// src/ui-tailwind/toolbar/tw-toolbar-icon-button.tsx
|
|
1042
|
-
import * as Tooltip2 from "@radix-ui/react-tooltip";
|
|
1043
|
-
import { jsx as jsx8, jsxs as jsxs8 } from "react/jsx-runtime";
|
|
1044
|
-
var focusRingClass5 = "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-accent focus-visible:ring-offset-2 focus-visible:ring-offset-canvas";
|
|
1045
|
-
function TwToolbarIconButton(props) {
|
|
1046
|
-
return /* @__PURE__ */ jsxs8(Tooltip2.Root, { children: [
|
|
1047
|
-
/* @__PURE__ */ jsx8(Tooltip2.Trigger, { asChild: true, children: /* @__PURE__ */ jsx8(
|
|
1048
|
-
"button",
|
|
1049
|
-
{
|
|
1050
|
-
type: "button",
|
|
1051
|
-
"aria-label": props.label,
|
|
1052
|
-
disabled: props.disabled,
|
|
1053
|
-
onMouseDown: preserveEditorSelectionMouseDown,
|
|
1054
|
-
onClick: props.onClick,
|
|
1055
|
-
className: [
|
|
1056
|
-
"inline-flex h-7 w-7 items-center justify-center rounded-md transition-colors outline-none",
|
|
1057
|
-
"disabled:opacity-30 disabled:cursor-not-allowed",
|
|
1058
|
-
props.emphasis ? "text-accent hover:bg-accent-soft" : props.active ? "bg-accent-soft text-accent" : "text-secondary hover:bg-surface hover:text-primary",
|
|
1059
|
-
focusRingClass5
|
|
1060
|
-
].join(" "),
|
|
1061
|
-
children: /* @__PURE__ */ jsx8(props.icon, { className: "h-4 w-4" })
|
|
1062
|
-
}
|
|
1063
|
-
) }),
|
|
1064
|
-
/* @__PURE__ */ jsx8(Tooltip2.Portal, { children: /* @__PURE__ */ jsx8(
|
|
1065
|
-
Tooltip2.Content,
|
|
1066
|
-
{
|
|
1067
|
-
className: "rounded-md bg-primary px-2 py-1 text-xs text-white shadow-md z-50",
|
|
1068
|
-
sideOffset: 6,
|
|
1069
|
-
children: props.label
|
|
1070
|
-
}
|
|
1071
|
-
) })
|
|
1072
|
-
] });
|
|
1073
|
-
}
|
|
1074
|
-
|
|
1075
|
-
// src/ui-tailwind/toolbar/tw-toolbar.tsx
|
|
1076
|
-
import React3 from "react";
|
|
1077
|
-
import * as Popover from "@radix-ui/react-popover";
|
|
1078
|
-
import * as Select from "@radix-ui/react-select";
|
|
1079
|
-
import * as Toggle from "@radix-ui/react-toggle";
|
|
1080
|
-
import * as ToggleGroup from "@radix-ui/react-toggle-group";
|
|
1081
|
-
import * as Tooltip3 from "@radix-ui/react-tooltip";
|
|
1082
|
-
import {
|
|
1083
|
-
AlignCenter,
|
|
1084
|
-
AlignJustify,
|
|
1085
|
-
AlignLeft,
|
|
1086
|
-
AlignRight,
|
|
1087
|
-
Baseline as Baseline2,
|
|
1088
|
-
Bold as Bold2,
|
|
1089
|
-
ChevronDown,
|
|
1090
|
-
Download,
|
|
1091
|
-
Eye,
|
|
1092
|
-
EyeOff,
|
|
1093
|
-
FileText,
|
|
1094
|
-
Highlighter as Highlighter2,
|
|
1095
|
-
ImagePlus,
|
|
1096
|
-
Indent,
|
|
1097
|
-
Italic as Italic2,
|
|
1098
|
-
MessageSquare as MessageSquare2,
|
|
1099
|
-
Minus,
|
|
1100
|
-
Monitor,
|
|
1101
|
-
MoreHorizontal,
|
|
1102
|
-
Outdent,
|
|
1103
|
-
Plus,
|
|
1104
|
-
Redo2,
|
|
1105
|
-
Rows3,
|
|
1106
|
-
Strikethrough,
|
|
1107
|
-
Subscript,
|
|
1108
|
-
Superscript,
|
|
1109
|
-
ShieldAlert as ShieldAlert2,
|
|
1110
|
-
ShieldCheck as ShieldCheck2,
|
|
1111
|
-
Underline as Underline2,
|
|
1112
|
-
Undo2
|
|
1113
|
-
} from "lucide-react";
|
|
1114
|
-
import { Fragment as Fragment5, jsx as jsx9, jsxs as jsxs9 } from "react/jsx-runtime";
|
|
1115
|
-
function getSupportedZoomPresets() {
|
|
1116
|
-
return [75, 100, 125, 150];
|
|
1117
|
-
}
|
|
1118
|
-
var focusRingClass6 = "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-accent focus-visible:ring-offset-2 focus-visible:ring-offset-canvas";
|
|
1119
|
-
var FONT_FAMILIES = ["Arial", "Times New Roman", "Calibri", "Cambria", "Georgia", "Verdana"];
|
|
1120
|
-
var FONT_SIZES = [8, 9, 10, 11, 12, 14, 16, 18, 20, 24, 28, 36];
|
|
1121
|
-
var TEXT_COLORS = ["#000000", "#434343", "#1660a8", "#1a7f37", "#cf222e", "#7a4f00"];
|
|
1122
|
-
var HIGHLIGHT_COLORS = [
|
|
1123
|
-
{ value: "#ffff00", label: "Yellow" },
|
|
1124
|
-
{ value: "#00ff00", label: "Green" },
|
|
1125
|
-
{ value: "#00ffff", label: "Cyan" },
|
|
1126
|
-
{ value: "#ff69b4", label: "Pink" },
|
|
1127
|
-
{ value: null, label: "None" }
|
|
1128
|
-
];
|
|
1129
|
-
function TwToolbar(props) {
|
|
1130
|
-
const caps = props.capabilities;
|
|
1131
|
-
const workspaceMode = props.workspaceMode;
|
|
1132
|
-
const isPageMode = workspaceMode === "page";
|
|
1133
|
-
const paragraphStyles = props.styleCatalog?.paragraphs ?? [];
|
|
1134
|
-
const zoomLevel = props.zoomLevel ?? 100;
|
|
1135
|
-
const canEdit = props.interactionPolicy?.canFormatText ?? (caps ? caps.canEdit : false);
|
|
1136
|
-
const canInsertStructural = props.interactionPolicy?.canInsertStructural ?? canEdit;
|
|
1137
|
-
const canAddComment = props.interactionPolicy?.canAddComment ?? (caps ? caps.canAddComment : false);
|
|
1138
|
-
const zoomLabel = typeof zoomLevel === "number" ? `${zoomLevel}%` : zoomLevel === "pageWidth" ? "Fit width" : "Fit page";
|
|
1139
|
-
return /* @__PURE__ */ jsxs9("header", { className: "flex h-10 shrink-0 items-center gap-1 border-b border-border px-2", children: [
|
|
1140
|
-
/* @__PURE__ */ jsxs9("div", { className: "flex items-center gap-0.5", children: [
|
|
1141
|
-
/* @__PURE__ */ jsx9(
|
|
1142
|
-
TwToolbarIconButton,
|
|
1143
|
-
{
|
|
1144
|
-
icon: Undo2,
|
|
1145
|
-
label: "Undo",
|
|
1146
|
-
disabled: caps ? !caps.canUndo : true,
|
|
1147
|
-
onClick: props.onUndo
|
|
1148
|
-
}
|
|
1149
|
-
),
|
|
1150
|
-
/* @__PURE__ */ jsx9(
|
|
1151
|
-
TwToolbarIconButton,
|
|
1152
|
-
{
|
|
1153
|
-
icon: Redo2,
|
|
1154
|
-
label: "Redo",
|
|
1155
|
-
disabled: caps ? !caps.canRedo : true,
|
|
1156
|
-
onClick: props.onRedo
|
|
1157
|
-
}
|
|
1158
|
-
),
|
|
1159
|
-
/* @__PURE__ */ jsx9("div", { className: "mx-1 h-4 w-px bg-border" }),
|
|
1160
|
-
/* @__PURE__ */ jsx9(
|
|
1161
|
-
ToolbarParagraphStyleSelect,
|
|
1162
|
-
{
|
|
1163
|
-
disabled: !canEdit || paragraphStyles.length === 0 || !props.onSetParagraphStyle,
|
|
1164
|
-
styles: paragraphStyles,
|
|
1165
|
-
value: props.formattingState?.paragraphStyleId,
|
|
1166
|
-
onValueChange: props.onSetParagraphStyle
|
|
1167
|
-
}
|
|
1168
|
-
),
|
|
1169
|
-
/* @__PURE__ */ jsx9(
|
|
1170
|
-
ToolbarFontFamilySelect,
|
|
1171
|
-
{
|
|
1172
|
-
disabled: !canEdit || !props.onSetFontFamily,
|
|
1173
|
-
value: props.formattingState?.fontFamily,
|
|
1174
|
-
onValueChange: props.onSetFontFamily
|
|
1175
|
-
}
|
|
1176
|
-
),
|
|
1177
|
-
/* @__PURE__ */ jsx9(
|
|
1178
|
-
ToolbarFontSizeSelect,
|
|
1179
|
-
{
|
|
1180
|
-
disabled: !canEdit || !props.onSetFontSize,
|
|
1181
|
-
value: props.formattingState?.fontSize,
|
|
1182
|
-
onValueChange: props.onSetFontSize
|
|
1183
|
-
}
|
|
1184
|
-
),
|
|
1185
|
-
/* @__PURE__ */ jsx9("div", { className: "mx-1 h-4 w-px bg-border" }),
|
|
1186
|
-
/* @__PURE__ */ jsx9(
|
|
1187
|
-
TwToolbarIconButton,
|
|
1188
|
-
{
|
|
1189
|
-
icon: Bold2,
|
|
1190
|
-
label: "Bold",
|
|
1191
|
-
active: props.formattingState?.bold ?? false,
|
|
1192
|
-
disabled: !canEdit,
|
|
1193
|
-
onClick: props.onToggleBold
|
|
1194
|
-
}
|
|
1195
|
-
),
|
|
1196
|
-
/* @__PURE__ */ jsx9(
|
|
1197
|
-
TwToolbarIconButton,
|
|
1198
|
-
{
|
|
1199
|
-
icon: Italic2,
|
|
1200
|
-
label: "Italic",
|
|
1201
|
-
active: props.formattingState?.italic ?? false,
|
|
1202
|
-
disabled: !canEdit,
|
|
1203
|
-
onClick: props.onToggleItalic
|
|
1204
|
-
}
|
|
1205
|
-
),
|
|
1206
|
-
/* @__PURE__ */ jsx9(
|
|
1207
|
-
TwToolbarIconButton,
|
|
1208
|
-
{
|
|
1209
|
-
icon: Underline2,
|
|
1210
|
-
label: "Underline",
|
|
1211
|
-
active: props.formattingState?.underline ?? false,
|
|
1212
|
-
disabled: !canEdit,
|
|
1213
|
-
onClick: props.onToggleUnderline
|
|
1214
|
-
}
|
|
1215
|
-
),
|
|
1216
|
-
/* @__PURE__ */ jsx9(
|
|
1217
|
-
ToolbarFormattingOverflow,
|
|
1218
|
-
{
|
|
1219
|
-
disabled: !canEdit,
|
|
1220
|
-
formattingState: props.formattingState,
|
|
1221
|
-
onToggleStrikethrough: props.onToggleStrikethrough,
|
|
1222
|
-
onToggleSuperscript: props.onToggleSuperscript,
|
|
1223
|
-
onToggleSubscript: props.onToggleSubscript
|
|
1224
|
-
}
|
|
1225
|
-
),
|
|
1226
|
-
/* @__PURE__ */ jsx9(
|
|
1227
|
-
ToolbarColorPopover,
|
|
1228
|
-
{
|
|
1229
|
-
ariaLabel: "Text color",
|
|
1230
|
-
colors: TEXT_COLORS.map((value) => ({ value, label: value })),
|
|
1231
|
-
disabled: !canEdit || !props.onSetTextColor,
|
|
1232
|
-
icon: /* @__PURE__ */ jsx9(Baseline2, { className: "h-3.5 w-3.5" }),
|
|
1233
|
-
onSelect: (value) => {
|
|
1234
|
-
if (value) {
|
|
1235
|
-
props.onSetTextColor?.(value);
|
|
1236
|
-
}
|
|
1237
|
-
},
|
|
1238
|
-
title: "Text color"
|
|
1239
|
-
}
|
|
1240
|
-
),
|
|
1241
|
-
/* @__PURE__ */ jsx9(
|
|
1242
|
-
ToolbarColorPopover,
|
|
1243
|
-
{
|
|
1244
|
-
ariaLabel: "Highlight color",
|
|
1245
|
-
colors: HIGHLIGHT_COLORS.map((entry) => ({ value: entry.value, label: entry.label })),
|
|
1246
|
-
disabled: !canEdit || !props.onSetHighlightColor,
|
|
1247
|
-
icon: /* @__PURE__ */ jsx9(Highlighter2, { className: "h-3.5 w-3.5" }),
|
|
1248
|
-
onSelect: (value) => props.onSetHighlightColor?.(value),
|
|
1249
|
-
title: "Highlight color"
|
|
1250
|
-
}
|
|
1251
|
-
),
|
|
1252
|
-
/* @__PURE__ */ jsx9(
|
|
1253
|
-
ToolbarAlignmentPopover,
|
|
1254
|
-
{
|
|
1255
|
-
activeAlignment: props.formattingState?.alignment,
|
|
1256
|
-
disabled: !canEdit || !props.onSetAlignment,
|
|
1257
|
-
onSelect: (alignment) => props.onSetAlignment?.(alignment)
|
|
1258
|
-
}
|
|
1259
|
-
),
|
|
1260
|
-
/* @__PURE__ */ jsx9("div", { className: "mx-1 h-4 w-px bg-border" }),
|
|
1261
|
-
/* @__PURE__ */ jsx9(
|
|
1262
|
-
TwToolbarIconButton,
|
|
1263
|
-
{
|
|
1264
|
-
icon: Outdent,
|
|
1265
|
-
label: "Outdent",
|
|
1266
|
-
disabled: !canEdit,
|
|
1267
|
-
onClick: props.onOutdent
|
|
1268
|
-
}
|
|
1269
|
-
),
|
|
1270
|
-
/* @__PURE__ */ jsx9(
|
|
1271
|
-
TwToolbarIconButton,
|
|
1272
|
-
{
|
|
1273
|
-
icon: Indent,
|
|
1274
|
-
label: "Indent",
|
|
1275
|
-
disabled: !canEdit,
|
|
1276
|
-
onClick: props.onIndent
|
|
1277
|
-
}
|
|
1278
|
-
),
|
|
1279
|
-
/* @__PURE__ */ jsx9(
|
|
1280
|
-
ToolbarInsertMenu,
|
|
1281
|
-
{
|
|
1282
|
-
disabled: !canInsertStructural,
|
|
1283
|
-
onInsertImage: props.onInsertImage,
|
|
1284
|
-
onInsertPageBreak: props.onInsertPageBreak,
|
|
1285
|
-
onInsertSectionBreak: props.onInsertSectionBreak,
|
|
1286
|
-
onInsertTable: props.onInsertTable
|
|
1287
|
-
}
|
|
1288
|
-
),
|
|
1289
|
-
props.activeStory && props.activeStory.kind !== "main" ? /* @__PURE__ */ jsxs9(Fragment5, { children: [
|
|
1290
|
-
/* @__PURE__ */ jsx9("div", { className: "mx-1 h-4 w-px bg-border" }),
|
|
1291
|
-
/* @__PURE__ */ jsxs9(
|
|
1292
|
-
"button",
|
|
1293
|
-
{
|
|
1294
|
-
type: "button",
|
|
1295
|
-
onClick: props.onCloseStory,
|
|
1296
|
-
onMouseDown: preserveEditorSelectionMouseDown,
|
|
1297
|
-
className: `inline-flex items-center gap-1 rounded-md px-1.5 py-0.5 text-xs font-medium text-accent hover:bg-accent-soft transition-colors outline-none ${focusRingClass6}`,
|
|
1298
|
-
"aria-label": `Editing ${storyLabel(props.activeStory)} \u2014 click to return to main body`,
|
|
1299
|
-
children: [
|
|
1300
|
-
/* @__PURE__ */ jsx9("span", { className: "text-secondary", children: "\u2190" }),
|
|
1301
|
-
storyLabel(props.activeStory)
|
|
1302
|
-
]
|
|
1303
|
-
}
|
|
1304
|
-
)
|
|
1305
|
-
] }) : null
|
|
1306
|
-
] }),
|
|
1307
|
-
/* @__PURE__ */ jsx9("div", { className: "flex-1 text-center min-w-0", children: /* @__PURE__ */ jsx9("span", { className: "text-sm font-medium truncate block", children: props.sourceLabel ?? "Untitled" }) }),
|
|
1308
|
-
/* @__PURE__ */ jsxs9("div", { className: "flex items-center gap-0.5", children: [
|
|
1309
|
-
/* @__PURE__ */ jsx9(
|
|
1310
|
-
TwToolbarIconButton,
|
|
1311
|
-
{
|
|
1312
|
-
icon: MessageSquare2,
|
|
1313
|
-
label: "Add comment",
|
|
1314
|
-
disabled: !canAddComment,
|
|
1315
|
-
emphasis: true,
|
|
1316
|
-
onClick: props.onAddComment
|
|
1317
|
-
}
|
|
1318
|
-
),
|
|
1319
|
-
/* @__PURE__ */ jsxs9(Tooltip3.Root, { children: [
|
|
1320
|
-
/* @__PURE__ */ jsx9(Tooltip3.Trigger, { asChild: true, children: /* @__PURE__ */ jsx9(
|
|
1321
|
-
Toggle.Root,
|
|
1322
|
-
{
|
|
1323
|
-
pressed: props.showTrackedChanges,
|
|
1324
|
-
onPressedChange: props.onShowTrackedChangesChange,
|
|
1325
|
-
disabled: caps ? !caps.trackChangesSupported : false,
|
|
1326
|
-
onMouseDown: preserveEditorSelectionMouseDown,
|
|
1327
|
-
className: `inline-flex h-7 w-7 items-center justify-center rounded-md text-secondary transition-colors hover:bg-surface data-[state=on]:bg-accent-soft data-[state=on]:text-accent outline-none disabled:opacity-40 ${focusRingClass6}`,
|
|
1328
|
-
children: props.showTrackedChanges ? /* @__PURE__ */ jsx9(Eye, { className: "h-4 w-4" }) : /* @__PURE__ */ jsx9(EyeOff, { className: "h-4 w-4" })
|
|
1329
|
-
}
|
|
1330
|
-
) }),
|
|
1331
|
-
/* @__PURE__ */ jsx9(Tooltip3.Portal, { children: /* @__PURE__ */ jsx9(
|
|
1332
|
-
Tooltip3.Content,
|
|
1333
|
-
{
|
|
1334
|
-
className: "rounded-md bg-primary px-2 py-1 text-xs text-white shadow-md z-50",
|
|
1335
|
-
sideOffset: 6,
|
|
1336
|
-
children: props.showTrackedChanges ? "Hide tracked changes" : "Show tracked changes"
|
|
1337
|
-
}
|
|
1338
|
-
) })
|
|
1339
|
-
] }),
|
|
1340
|
-
/* @__PURE__ */ jsx9("div", { className: "mx-1 h-4 w-px bg-border" }),
|
|
1341
|
-
/* @__PURE__ */ jsxs9(
|
|
1342
|
-
ToggleGroup.Root,
|
|
1343
|
-
{
|
|
1344
|
-
type: "single",
|
|
1345
|
-
value: workspaceMode,
|
|
1346
|
-
onValueChange: (v) => {
|
|
1347
|
-
if (v) props.onWorkspaceModeChange(v);
|
|
1348
|
-
},
|
|
1349
|
-
className: "flex items-center gap-0.5",
|
|
1350
|
-
children: [
|
|
1351
|
-
/* @__PURE__ */ jsxs9(Tooltip3.Root, { children: [
|
|
1352
|
-
/* @__PURE__ */ jsx9(Tooltip3.Trigger, { asChild: true, children: /* @__PURE__ */ jsx9(
|
|
1353
|
-
ToggleGroup.Item,
|
|
1354
|
-
{
|
|
1355
|
-
value: "canvas",
|
|
1356
|
-
"aria-label": "Canvas workspace",
|
|
1357
|
-
onMouseDown: preserveEditorSelectionMouseDown,
|
|
1358
|
-
className: `inline-flex h-7 w-7 items-center justify-center rounded-md text-secondary transition-colors hover:bg-surface data-[state=on]:bg-accent-soft data-[state=on]:text-accent outline-none ${focusRingClass6}`,
|
|
1359
|
-
children: /* @__PURE__ */ jsx9(Monitor, { className: "h-3.5 w-3.5" })
|
|
1360
|
-
}
|
|
1361
|
-
) }),
|
|
1362
|
-
/* @__PURE__ */ jsx9(Tooltip3.Portal, { children: /* @__PURE__ */ jsx9(Tooltip3.Content, { className: "rounded-md bg-primary px-2 py-1 text-xs text-white shadow-md z-50", sideOffset: 6, children: "Canvas \u2014 clean flowing text" }) })
|
|
1363
|
-
] }),
|
|
1364
|
-
/* @__PURE__ */ jsxs9(Tooltip3.Root, { children: [
|
|
1365
|
-
/* @__PURE__ */ jsx9(Tooltip3.Trigger, { asChild: true, children: /* @__PURE__ */ jsx9(
|
|
1366
|
-
ToggleGroup.Item,
|
|
1367
|
-
{
|
|
1368
|
-
value: "page",
|
|
1369
|
-
"aria-label": "Page workspace",
|
|
1370
|
-
onMouseDown: preserveEditorSelectionMouseDown,
|
|
1371
|
-
className: `inline-flex h-7 w-7 items-center justify-center rounded-md text-secondary transition-colors hover:bg-surface data-[state=on]:bg-accent-soft data-[state=on]:text-accent outline-none ${focusRingClass6}`,
|
|
1372
|
-
children: /* @__PURE__ */ jsx9(FileText, { className: "h-3.5 w-3.5" })
|
|
1373
|
-
}
|
|
1374
|
-
) }),
|
|
1375
|
-
/* @__PURE__ */ jsx9(Tooltip3.Portal, { children: /* @__PURE__ */ jsx9(Tooltip3.Content, { className: "rounded-md bg-primary px-2 py-1 text-xs text-white shadow-md z-50", sideOffset: 6, children: "Page \u2014 layout-sensitive view" }) })
|
|
1376
|
-
] })
|
|
1377
|
-
]
|
|
1378
|
-
}
|
|
1379
|
-
),
|
|
1380
|
-
isPageMode && props.onZoomChange ? /* @__PURE__ */ jsxs9(Fragment5, { children: [
|
|
1381
|
-
/* @__PURE__ */ jsx9("div", { className: "mx-1 h-4 w-px bg-border" }),
|
|
1382
|
-
/* @__PURE__ */ jsxs9("div", { className: "flex items-center gap-0.5", children: [
|
|
1383
|
-
/* @__PURE__ */ jsxs9(Tooltip3.Root, { children: [
|
|
1384
|
-
/* @__PURE__ */ jsx9(Tooltip3.Trigger, { asChild: true, children: /* @__PURE__ */ jsx9(
|
|
1385
|
-
"button",
|
|
1386
|
-
{
|
|
1387
|
-
type: "button",
|
|
1388
|
-
"aria-label": "Zoom out",
|
|
1389
|
-
className: `inline-flex h-7 w-7 items-center justify-center rounded-md text-secondary transition-colors hover:bg-surface outline-none ${focusRingClass6}`,
|
|
1390
|
-
disabled: typeof zoomLevel === "number" && zoomLevel <= 50,
|
|
1391
|
-
onMouseDown: preserveEditorSelectionMouseDown,
|
|
1392
|
-
onClick: () => {
|
|
1393
|
-
const current = typeof zoomLevel === "number" ? zoomLevel : 100;
|
|
1394
|
-
props.onZoomChange(Math.max(50, current - 10));
|
|
1395
|
-
},
|
|
1396
|
-
children: /* @__PURE__ */ jsx9(Minus, { className: "h-3 w-3" })
|
|
1397
|
-
}
|
|
1398
|
-
) }),
|
|
1399
|
-
/* @__PURE__ */ jsx9(Tooltip3.Portal, { children: /* @__PURE__ */ jsx9(Tooltip3.Content, { className: "rounded-md bg-primary px-2 py-1 text-xs text-white shadow-md z-50", sideOffset: 6, children: "Zoom out" }) })
|
|
1400
|
-
] }),
|
|
1401
|
-
/* @__PURE__ */ jsxs9(Popover.Root, { children: [
|
|
1402
|
-
/* @__PURE__ */ jsxs9(Tooltip3.Root, { children: [
|
|
1403
|
-
/* @__PURE__ */ jsx9(Tooltip3.Trigger, { asChild: true, children: /* @__PURE__ */ jsx9(Popover.Trigger, { asChild: true, children: /* @__PURE__ */ jsx9(
|
|
1404
|
-
"button",
|
|
1405
|
-
{
|
|
1406
|
-
type: "button",
|
|
1407
|
-
"aria-label": `Zoom: ${zoomLabel}`,
|
|
1408
|
-
onMouseDown: preserveEditorSelectionMouseDown,
|
|
1409
|
-
className: `inline-flex h-7 items-center justify-center rounded-md px-1.5 text-[11px] font-medium text-secondary transition-colors hover:bg-surface outline-none ${focusRingClass6}`,
|
|
1410
|
-
children: zoomLabel
|
|
1411
|
-
}
|
|
1412
|
-
) }) }),
|
|
1413
|
-
/* @__PURE__ */ jsx9(Tooltip3.Portal, { children: /* @__PURE__ */ jsx9(Tooltip3.Content, { className: "rounded-md bg-primary px-2 py-1 text-xs text-white shadow-md z-50", sideOffset: 6, children: "Zoom level" }) })
|
|
1414
|
-
] }),
|
|
1415
|
-
/* @__PURE__ */ jsx9(Popover.Portal, { children: /* @__PURE__ */ jsx9(
|
|
1416
|
-
Popover.Content,
|
|
1417
|
-
{
|
|
1418
|
-
className: "w-[140px] rounded-lg bg-canvas shadow-lg ring-1 ring-border p-1 z-50",
|
|
1419
|
-
sideOffset: 8,
|
|
1420
|
-
align: "center",
|
|
1421
|
-
children: getSupportedZoomPresets().map((preset) => {
|
|
1422
|
-
const label = `${preset}%`;
|
|
1423
|
-
return /* @__PURE__ */ jsx9(Popover.Close, { asChild: true, children: /* @__PURE__ */ jsx9(
|
|
1424
|
-
"button",
|
|
1425
|
-
{
|
|
1426
|
-
type: "button",
|
|
1427
|
-
onMouseDown: preserveEditorSelectionMouseDown,
|
|
1428
|
-
className: `w-full rounded-md px-3 py-1.5 text-left text-xs transition-colors hover:bg-surface ${zoomLevel === preset ? "font-semibold text-accent" : "text-primary"}`,
|
|
1429
|
-
onClick: () => props.onZoomChange(preset),
|
|
1430
|
-
children: label
|
|
1431
|
-
}
|
|
1432
|
-
) }, preset);
|
|
1433
|
-
})
|
|
1434
|
-
}
|
|
1435
|
-
) })
|
|
1436
|
-
] }),
|
|
1437
|
-
/* @__PURE__ */ jsxs9(Tooltip3.Root, { children: [
|
|
1438
|
-
/* @__PURE__ */ jsx9(Tooltip3.Trigger, { asChild: true, children: /* @__PURE__ */ jsx9(
|
|
1439
|
-
"button",
|
|
1440
|
-
{
|
|
1441
|
-
type: "button",
|
|
1442
|
-
"aria-label": "Zoom in",
|
|
1443
|
-
className: `inline-flex h-7 w-7 items-center justify-center rounded-md text-secondary transition-colors hover:bg-surface outline-none ${focusRingClass6}`,
|
|
1444
|
-
disabled: typeof zoomLevel === "number" && zoomLevel >= 200,
|
|
1445
|
-
onMouseDown: preserveEditorSelectionMouseDown,
|
|
1446
|
-
onClick: () => {
|
|
1447
|
-
const current = typeof zoomLevel === "number" ? zoomLevel : 100;
|
|
1448
|
-
props.onZoomChange(Math.min(200, current + 10));
|
|
1449
|
-
},
|
|
1450
|
-
children: /* @__PURE__ */ jsx9(Plus, { className: "h-3 w-3" })
|
|
1451
|
-
}
|
|
1452
|
-
) }),
|
|
1453
|
-
/* @__PURE__ */ jsx9(Tooltip3.Portal, { children: /* @__PURE__ */ jsx9(Tooltip3.Content, { className: "rounded-md bg-primary px-2 py-1 text-xs text-white shadow-md z-50", sideOffset: 6, children: "Zoom in" }) })
|
|
1454
|
-
] })
|
|
1455
|
-
] })
|
|
1456
|
-
] }) : null,
|
|
1457
|
-
props.compatibility && props.warnings ? /* @__PURE__ */ jsxs9(Popover.Root, { children: [
|
|
1458
|
-
/* @__PURE__ */ jsxs9(Tooltip3.Root, { children: [
|
|
1459
|
-
/* @__PURE__ */ jsx9(Tooltip3.Trigger, { asChild: true, children: /* @__PURE__ */ jsx9(Popover.Trigger, { asChild: true, children: /* @__PURE__ */ jsxs9(
|
|
1460
|
-
"button",
|
|
1461
|
-
{
|
|
1462
|
-
type: "button",
|
|
1463
|
-
onMouseDown: preserveEditorSelectionMouseDown,
|
|
1464
|
-
className: `relative inline-flex h-7 w-7 items-center justify-center rounded-md transition-colors hover:bg-surface hover:text-primary outline-none ${focusRingClass6} ${(caps?.healthIssueCount ?? 0) > 0 ? "text-secondary" : "text-secondary"}`,
|
|
1465
|
-
children: [
|
|
1466
|
-
(caps?.healthIssueCount ?? 0) > 0 ? /* @__PURE__ */ jsx9(ShieldAlert2, { className: "h-4 w-4" }) : /* @__PURE__ */ jsx9(ShieldCheck2, { className: "h-4 w-4" }),
|
|
1467
|
-
(caps?.healthIssueCount ?? 0) > 0 ? /* @__PURE__ */ jsx9("span", { className: "absolute -top-0.5 -right-0.5 flex h-3 min-w-[12px] items-center justify-center rounded-full bg-tertiary text-[8px] font-medium text-white", children: caps?.healthIssueCount }) : null
|
|
1468
|
-
]
|
|
1469
|
-
}
|
|
1470
|
-
) }) }),
|
|
1471
|
-
/* @__PURE__ */ jsx9(Tooltip3.Portal, { children: /* @__PURE__ */ jsx9(Tooltip3.Content, { className: "rounded-md bg-primary px-2 py-1 text-xs text-white shadow-md z-50", sideOffset: 6, children: (caps?.healthIssueCount ?? 0) > 0 ? `Document health \u2014 ${caps?.healthIssueCount} issue${(caps?.healthIssueCount ?? 0) !== 1 ? "s" : ""}` : "Document health \u2014 no issues" }) })
|
|
1472
|
-
] }),
|
|
1473
|
-
/* @__PURE__ */ jsx9(Popover.Portal, { children: /* @__PURE__ */ jsx9(
|
|
1474
|
-
Popover.Content,
|
|
1475
|
-
{
|
|
1476
|
-
className: "w-[360px] max-h-[480px] overflow-y-auto rounded-lg bg-canvas shadow-lg ring-1 ring-border p-3 z-50",
|
|
1477
|
-
sideOffset: 8,
|
|
1478
|
-
align: "end",
|
|
1479
|
-
children: /* @__PURE__ */ jsx9(
|
|
1480
|
-
TwHealthPanel,
|
|
1481
|
-
{
|
|
1482
|
-
blockedReasons: props.blockedReasons,
|
|
1483
|
-
compatibility: props.compatibility,
|
|
1484
|
-
warnings: props.warnings
|
|
1485
|
-
}
|
|
1486
|
-
)
|
|
1487
|
-
}
|
|
1488
|
-
) })
|
|
1489
|
-
] }) : null,
|
|
1490
|
-
/* @__PURE__ */ jsx9("div", { className: "mx-1 h-4 w-px bg-border" }),
|
|
1491
|
-
/* @__PURE__ */ jsxs9(Tooltip3.Root, { children: [
|
|
1492
|
-
/* @__PURE__ */ jsx9(Tooltip3.Trigger, { asChild: true, children: /* @__PURE__ */ jsxs9(
|
|
1493
|
-
"button",
|
|
1494
|
-
{
|
|
1495
|
-
type: "button",
|
|
1496
|
-
disabled: caps ? !caps.canExport : true,
|
|
1497
|
-
onMouseDown: preserveEditorSelectionMouseDown,
|
|
1498
|
-
className: [
|
|
1499
|
-
"inline-flex h-7 items-center gap-1.5 rounded-md px-2.5 text-xs font-semibold transition-colors outline-none",
|
|
1500
|
-
focusRingClass6,
|
|
1501
|
-
caps?.exportBlocked ? "cursor-not-allowed text-danger opacity-50" : "text-accent hover:bg-accent-soft"
|
|
1502
|
-
].join(" "),
|
|
1503
|
-
onClick: props.onExport,
|
|
1504
|
-
children: [
|
|
1505
|
-
/* @__PURE__ */ jsx9(Download, { className: "h-3.5 w-3.5" }),
|
|
1506
|
-
"Export .docx"
|
|
1507
|
-
]
|
|
1508
|
-
}
|
|
1509
|
-
) }),
|
|
1510
|
-
/* @__PURE__ */ jsx9(Tooltip3.Portal, { children: /* @__PURE__ */ jsx9(Tooltip3.Content, { className: "rounded-md bg-primary px-2 py-1 text-xs text-white shadow-md z-50", sideOffset: 6, children: caps?.exportBlocked ? "Export blocked by unsupported content" : "Export document" }) })
|
|
1511
|
-
] })
|
|
1512
|
-
] })
|
|
1513
|
-
] });
|
|
1514
|
-
}
|
|
1515
|
-
function ToolbarParagraphStyleSelect(props) {
|
|
1516
|
-
const resolvedValue = props.value && props.styles.some((style) => style.styleId === props.value) ? props.value : "";
|
|
1517
|
-
return /* @__PURE__ */ jsxs9(
|
|
1518
|
-
Select.Root,
|
|
1519
|
-
{
|
|
1520
|
-
disabled: props.disabled,
|
|
1521
|
-
onValueChange: (value) => props.onValueChange?.(value),
|
|
1522
|
-
value: resolvedValue,
|
|
1523
|
-
children: [
|
|
1524
|
-
/* @__PURE__ */ jsxs9(
|
|
1525
|
-
Select.Trigger,
|
|
1526
|
-
{
|
|
1527
|
-
"aria-label": "Paragraph style",
|
|
1528
|
-
"aria-disabled": props.disabled || void 0,
|
|
1529
|
-
"data-disabled": props.disabled ? "" : void 0,
|
|
1530
|
-
onMouseDown: preserveEditorSelectionMouseDown,
|
|
1531
|
-
className: `inline-flex h-7 min-w-[8.5rem] items-center justify-between gap-2 rounded-md border border-border bg-canvas px-2.5 text-xs font-medium text-primary transition-colors hover:bg-surface outline-none disabled:cursor-not-allowed disabled:opacity-40 ${focusRingClass6}`,
|
|
1532
|
-
children: [
|
|
1533
|
-
/* @__PURE__ */ jsx9(Select.Value, { placeholder: "Style" }),
|
|
1534
|
-
/* @__PURE__ */ jsx9(Select.Icon, { children: /* @__PURE__ */ jsx9(ChevronDown, { className: "h-3.5 w-3.5 text-tertiary" }) })
|
|
1535
|
-
]
|
|
1536
|
-
}
|
|
1537
|
-
),
|
|
1538
|
-
/* @__PURE__ */ jsx9(Select.Portal, { children: /* @__PURE__ */ jsx9(
|
|
1539
|
-
Select.Content,
|
|
1540
|
-
{
|
|
1541
|
-
align: "start",
|
|
1542
|
-
className: "z-50 overflow-hidden rounded-lg bg-canvas shadow-lg ring-1 ring-border",
|
|
1543
|
-
position: "popper",
|
|
1544
|
-
sideOffset: 8,
|
|
1545
|
-
children: /* @__PURE__ */ jsx9(Select.Viewport, { className: "p-1", children: props.styles.map((style) => /* @__PURE__ */ jsx9(
|
|
1546
|
-
Select.Item,
|
|
1547
|
-
{
|
|
1548
|
-
className: `flex cursor-pointer items-center rounded-md px-2.5 py-1.5 text-xs text-primary outline-none data-[highlighted]:bg-surface data-[state=checked]:bg-accent-soft data-[state=checked]:text-accent ${focusRingClass6}`,
|
|
1549
|
-
value: style.styleId,
|
|
1550
|
-
children: /* @__PURE__ */ jsx9(Select.ItemText, { children: style.displayName })
|
|
1551
|
-
},
|
|
1552
|
-
style.styleId
|
|
1553
|
-
)) })
|
|
1554
|
-
}
|
|
1555
|
-
) })
|
|
1556
|
-
]
|
|
1557
|
-
}
|
|
1558
|
-
);
|
|
1559
|
-
}
|
|
1560
|
-
function ToolbarFontFamilySelect(props) {
|
|
1561
|
-
const resolvedValue = props.value && FONT_FAMILIES.includes(props.value) ? props.value : "";
|
|
1562
|
-
return /* @__PURE__ */ jsxs9(
|
|
1563
|
-
Select.Root,
|
|
1564
|
-
{
|
|
1565
|
-
disabled: props.disabled,
|
|
1566
|
-
onValueChange: (value) => props.onValueChange?.(value),
|
|
1567
|
-
value: resolvedValue,
|
|
1568
|
-
children: [
|
|
1569
|
-
/* @__PURE__ */ jsxs9(
|
|
1570
|
-
Select.Trigger,
|
|
1571
|
-
{
|
|
1572
|
-
"aria-label": "Font family",
|
|
1573
|
-
"aria-disabled": props.disabled || void 0,
|
|
1574
|
-
"data-disabled": props.disabled ? "" : void 0,
|
|
1575
|
-
onMouseDown: preserveEditorSelectionMouseDown,
|
|
1576
|
-
className: `inline-flex h-7 min-w-[7rem] items-center justify-between gap-2 rounded-md border border-border bg-canvas px-2 text-xs font-medium text-primary transition-colors hover:bg-surface outline-none disabled:cursor-not-allowed disabled:opacity-40 ${focusRingClass6}`,
|
|
1577
|
-
children: [
|
|
1578
|
-
/* @__PURE__ */ jsx9(Select.Value, { placeholder: "Font" }),
|
|
1579
|
-
/* @__PURE__ */ jsx9(Select.Icon, { children: /* @__PURE__ */ jsx9(ChevronDown, { className: "h-3.5 w-3.5 text-tertiary" }) })
|
|
1580
|
-
]
|
|
1581
|
-
}
|
|
1582
|
-
),
|
|
1583
|
-
/* @__PURE__ */ jsx9(Select.Portal, { children: /* @__PURE__ */ jsx9(
|
|
1584
|
-
Select.Content,
|
|
1585
|
-
{
|
|
1586
|
-
align: "start",
|
|
1587
|
-
className: "z-50 overflow-hidden rounded-lg bg-canvas shadow-lg ring-1 ring-border",
|
|
1588
|
-
position: "popper",
|
|
1589
|
-
sideOffset: 8,
|
|
1590
|
-
children: /* @__PURE__ */ jsx9(Select.Viewport, { className: "p-1", children: FONT_FAMILIES.map((font) => /* @__PURE__ */ jsx9(
|
|
1591
|
-
Select.Item,
|
|
1592
|
-
{
|
|
1593
|
-
className: `flex cursor-pointer items-center rounded-md px-2.5 py-1.5 text-xs text-primary outline-none data-[highlighted]:bg-surface data-[state=checked]:bg-accent-soft data-[state=checked]:text-accent ${focusRingClass6}`,
|
|
1594
|
-
value: font,
|
|
1595
|
-
children: /* @__PURE__ */ jsx9(Select.ItemText, { children: font })
|
|
1596
|
-
},
|
|
1597
|
-
font
|
|
1598
|
-
)) })
|
|
1599
|
-
}
|
|
1600
|
-
) })
|
|
1601
|
-
]
|
|
1602
|
-
}
|
|
1603
|
-
);
|
|
1604
|
-
}
|
|
1605
|
-
function ToolbarFontSizeSelect(props) {
|
|
1606
|
-
const resolvedValue = typeof props.value === "number" && FONT_SIZES.includes(props.value) ? String(props.value) : "";
|
|
1607
|
-
return /* @__PURE__ */ jsxs9(
|
|
1608
|
-
Select.Root,
|
|
1609
|
-
{
|
|
1610
|
-
disabled: props.disabled,
|
|
1611
|
-
onValueChange: (value) => props.onValueChange?.(Number(value)),
|
|
1612
|
-
value: resolvedValue,
|
|
1613
|
-
children: [
|
|
1614
|
-
/* @__PURE__ */ jsxs9(
|
|
1615
|
-
Select.Trigger,
|
|
1616
|
-
{
|
|
1617
|
-
"aria-label": "Font size",
|
|
1618
|
-
"aria-disabled": props.disabled || void 0,
|
|
1619
|
-
"data-disabled": props.disabled ? "" : void 0,
|
|
1620
|
-
onMouseDown: preserveEditorSelectionMouseDown,
|
|
1621
|
-
className: `inline-flex h-7 min-w-[4rem] items-center justify-between gap-2 rounded-md border border-border bg-canvas px-2 text-xs font-medium text-primary transition-colors hover:bg-surface outline-none disabled:cursor-not-allowed disabled:opacity-40 ${focusRingClass6}`,
|
|
1622
|
-
children: [
|
|
1623
|
-
/* @__PURE__ */ jsx9(Select.Value, { placeholder: "Size" }),
|
|
1624
|
-
/* @__PURE__ */ jsx9(Select.Icon, { children: /* @__PURE__ */ jsx9(ChevronDown, { className: "h-3.5 w-3.5 text-tertiary" }) })
|
|
1625
|
-
]
|
|
1626
|
-
}
|
|
1627
|
-
),
|
|
1628
|
-
/* @__PURE__ */ jsx9(Select.Portal, { children: /* @__PURE__ */ jsx9(
|
|
1629
|
-
Select.Content,
|
|
1630
|
-
{
|
|
1631
|
-
align: "start",
|
|
1632
|
-
className: "z-50 overflow-hidden rounded-lg bg-canvas shadow-lg ring-1 ring-border",
|
|
1633
|
-
position: "popper",
|
|
1634
|
-
sideOffset: 8,
|
|
1635
|
-
children: /* @__PURE__ */ jsx9(Select.Viewport, { className: "p-1", children: FONT_SIZES.map((size) => /* @__PURE__ */ jsx9(
|
|
1636
|
-
Select.Item,
|
|
1637
|
-
{
|
|
1638
|
-
className: `flex cursor-pointer items-center rounded-md px-2.5 py-1.5 text-xs text-primary outline-none data-[highlighted]:bg-surface data-[state=checked]:bg-accent-soft data-[state=checked]:text-accent ${focusRingClass6}`,
|
|
1639
|
-
value: String(size),
|
|
1640
|
-
children: /* @__PURE__ */ jsx9(Select.ItemText, { children: size })
|
|
1641
|
-
},
|
|
1642
|
-
size
|
|
1643
|
-
)) })
|
|
1644
|
-
}
|
|
1645
|
-
) })
|
|
1646
|
-
]
|
|
1647
|
-
}
|
|
1648
|
-
);
|
|
1649
|
-
}
|
|
1650
|
-
function ToolbarFormattingOverflow(props) {
|
|
1651
|
-
const [open, setOpen] = React3.useState(false);
|
|
1652
|
-
return /* @__PURE__ */ jsxs9("div", { className: "relative", children: [
|
|
1653
|
-
/* @__PURE__ */ jsxs9(Tooltip3.Root, { children: [
|
|
1654
|
-
/* @__PURE__ */ jsx9(Tooltip3.Trigger, { asChild: true, children: /* @__PURE__ */ jsx9(
|
|
1655
|
-
"button",
|
|
1656
|
-
{
|
|
1657
|
-
type: "button",
|
|
1658
|
-
"aria-label": "More text formatting",
|
|
1659
|
-
"aria-expanded": open,
|
|
1660
|
-
disabled: props.disabled,
|
|
1661
|
-
onMouseDown: preserveEditorSelectionMouseDown,
|
|
1662
|
-
onClick: () => setOpen((value) => !value),
|
|
1663
|
-
className: `inline-flex h-7 w-7 items-center justify-center rounded-md text-secondary transition-colors hover:bg-surface outline-none disabled:cursor-not-allowed disabled:opacity-40 ${focusRingClass6}`,
|
|
1664
|
-
children: /* @__PURE__ */ jsx9(MoreHorizontal, { className: "h-3.5 w-3.5" })
|
|
1665
|
-
}
|
|
1666
|
-
) }),
|
|
1667
|
-
/* @__PURE__ */ jsx9(Tooltip3.Portal, { children: /* @__PURE__ */ jsx9(Tooltip3.Content, { className: "rounded-md bg-primary px-2 py-1 text-xs text-white shadow-md z-50", sideOffset: 6, children: "More text formatting" }) })
|
|
1668
|
-
] }),
|
|
1669
|
-
open ? /* @__PURE__ */ jsxs9("div", { className: "absolute left-0 top-9 z-50 w-[220px] rounded-lg bg-canvas p-2 shadow-lg ring-1 ring-border", children: [
|
|
1670
|
-
/* @__PURE__ */ jsx9("div", { className: "mb-1 px-1 text-[10px] font-semibold uppercase tracking-[0.12em] text-tertiary", children: "Text styling" }),
|
|
1671
|
-
/* @__PURE__ */ jsxs9("div", { className: "grid grid-cols-3 gap-1", children: [
|
|
1672
|
-
/* @__PURE__ */ jsx9(
|
|
1673
|
-
ToolbarPopoverActionButton,
|
|
1674
|
-
{
|
|
1675
|
-
active: props.formattingState?.strikethrough ?? false,
|
|
1676
|
-
ariaLabel: "Strikethrough",
|
|
1677
|
-
disabled: props.disabled,
|
|
1678
|
-
icon: /* @__PURE__ */ jsx9(Strikethrough, { className: "h-3.5 w-3.5" }),
|
|
1679
|
-
onClick: () => {
|
|
1680
|
-
props.onToggleStrikethrough?.();
|
|
1681
|
-
setOpen(false);
|
|
1682
|
-
}
|
|
1683
|
-
}
|
|
1684
|
-
),
|
|
1685
|
-
/* @__PURE__ */ jsx9(
|
|
1686
|
-
ToolbarPopoverActionButton,
|
|
1687
|
-
{
|
|
1688
|
-
active: props.formattingState?.superscript ?? false,
|
|
1689
|
-
ariaLabel: "Superscript",
|
|
1690
|
-
disabled: props.disabled,
|
|
1691
|
-
icon: /* @__PURE__ */ jsx9(Superscript, { className: "h-3.5 w-3.5" }),
|
|
1692
|
-
onClick: () => {
|
|
1693
|
-
props.onToggleSuperscript?.();
|
|
1694
|
-
setOpen(false);
|
|
1695
|
-
}
|
|
1696
|
-
}
|
|
1697
|
-
),
|
|
1698
|
-
/* @__PURE__ */ jsx9(
|
|
1699
|
-
ToolbarPopoverActionButton,
|
|
1700
|
-
{
|
|
1701
|
-
active: props.formattingState?.subscript ?? false,
|
|
1702
|
-
ariaLabel: "Subscript",
|
|
1703
|
-
disabled: props.disabled,
|
|
1704
|
-
icon: /* @__PURE__ */ jsx9(Subscript, { className: "h-3.5 w-3.5" }),
|
|
1705
|
-
onClick: () => {
|
|
1706
|
-
props.onToggleSubscript?.();
|
|
1707
|
-
setOpen(false);
|
|
1708
|
-
}
|
|
1709
|
-
}
|
|
1710
|
-
)
|
|
1711
|
-
] })
|
|
1712
|
-
] }) : null
|
|
1713
|
-
] });
|
|
1714
|
-
}
|
|
1715
|
-
function ToolbarColorPopover(props) {
|
|
1716
|
-
const [open, setOpen] = React3.useState(false);
|
|
1717
|
-
return /* @__PURE__ */ jsxs9("div", { className: "relative", children: [
|
|
1718
|
-
/* @__PURE__ */ jsxs9(Tooltip3.Root, { children: [
|
|
1719
|
-
/* @__PURE__ */ jsx9(Tooltip3.Trigger, { asChild: true, children: /* @__PURE__ */ jsx9(
|
|
1720
|
-
"button",
|
|
1721
|
-
{
|
|
1722
|
-
type: "button",
|
|
1723
|
-
"aria-label": props.ariaLabel,
|
|
1724
|
-
"aria-expanded": open,
|
|
1725
|
-
disabled: props.disabled,
|
|
1726
|
-
onMouseDown: preserveEditorSelectionMouseDown,
|
|
1727
|
-
onClick: () => setOpen((value) => !value),
|
|
1728
|
-
className: `inline-flex h-7 w-7 items-center justify-center rounded-md text-secondary transition-colors hover:bg-surface outline-none disabled:cursor-not-allowed disabled:opacity-40 ${focusRingClass6}`,
|
|
1729
|
-
children: props.icon
|
|
1730
|
-
}
|
|
1731
|
-
) }),
|
|
1732
|
-
/* @__PURE__ */ jsx9(Tooltip3.Portal, { children: /* @__PURE__ */ jsx9(Tooltip3.Content, { className: "rounded-md bg-primary px-2 py-1 text-xs text-white shadow-md z-50", sideOffset: 6, children: props.title }) })
|
|
1733
|
-
] }),
|
|
1734
|
-
open ? /* @__PURE__ */ jsxs9("div", { className: "absolute left-0 top-9 z-50 w-[180px] rounded-lg bg-canvas p-2 shadow-lg ring-1 ring-border", children: [
|
|
1735
|
-
/* @__PURE__ */ jsx9("div", { className: "mb-1 px-1 text-[10px] font-semibold uppercase tracking-[0.12em] text-tertiary", children: props.title }),
|
|
1736
|
-
/* @__PURE__ */ jsx9("div", { className: "grid grid-cols-3 gap-1", children: props.colors.map((color) => /* @__PURE__ */ jsx9(
|
|
1737
|
-
"button",
|
|
1738
|
-
{
|
|
1739
|
-
type: "button",
|
|
1740
|
-
"aria-label": `${props.title} ${color.label}`,
|
|
1741
|
-
disabled: props.disabled,
|
|
1742
|
-
onMouseDown: preserveEditorSelectionMouseDown,
|
|
1743
|
-
onClick: () => {
|
|
1744
|
-
props.onSelect(color.value);
|
|
1745
|
-
setOpen(false);
|
|
1746
|
-
},
|
|
1747
|
-
className: `inline-flex h-8 items-center justify-center rounded-md border border-border text-[10px] font-medium text-primary transition-transform hover:scale-[1.04] disabled:cursor-not-allowed disabled:opacity-40 ${color.value ? "" : "bg-surface"} ${focusRingClass6}`,
|
|
1748
|
-
style: color.value ? { backgroundColor: color.value } : void 0,
|
|
1749
|
-
children: color.value ? /* @__PURE__ */ jsx9("span", { className: "sr-only", children: color.label }) : "None"
|
|
1750
|
-
},
|
|
1751
|
-
`${props.ariaLabel}-${color.label}`
|
|
1752
|
-
)) })
|
|
1753
|
-
] }) : null
|
|
1754
|
-
] });
|
|
1755
|
-
}
|
|
1756
|
-
function ToolbarAlignmentPopover(props) {
|
|
1757
|
-
const [open, setOpen] = React3.useState(false);
|
|
1758
|
-
const alignments = [
|
|
1759
|
-
{ value: "left", label: "Align left", icon: /* @__PURE__ */ jsx9(AlignLeft, { className: "h-3.5 w-3.5" }) },
|
|
1760
|
-
{ value: "center", label: "Align center", icon: /* @__PURE__ */ jsx9(AlignCenter, { className: "h-3.5 w-3.5" }) },
|
|
1761
|
-
{ value: "right", label: "Align right", icon: /* @__PURE__ */ jsx9(AlignRight, { className: "h-3.5 w-3.5" }) },
|
|
1762
|
-
{ value: "justify", label: "Align justify", icon: /* @__PURE__ */ jsx9(AlignJustify, { className: "h-3.5 w-3.5" }) }
|
|
1763
|
-
];
|
|
1764
|
-
return /* @__PURE__ */ jsxs9("div", { className: "relative", children: [
|
|
1765
|
-
/* @__PURE__ */ jsxs9(Tooltip3.Root, { children: [
|
|
1766
|
-
/* @__PURE__ */ jsx9(Tooltip3.Trigger, { asChild: true, children: /* @__PURE__ */ jsx9(
|
|
1767
|
-
"button",
|
|
1768
|
-
{
|
|
1769
|
-
type: "button",
|
|
1770
|
-
"aria-label": "Paragraph alignment",
|
|
1771
|
-
"aria-expanded": open,
|
|
1772
|
-
disabled: props.disabled,
|
|
1773
|
-
onMouseDown: preserveEditorSelectionMouseDown,
|
|
1774
|
-
onClick: () => setOpen((value) => !value),
|
|
1775
|
-
className: `inline-flex h-7 w-7 items-center justify-center rounded-md text-secondary transition-colors hover:bg-surface outline-none disabled:cursor-not-allowed disabled:opacity-40 ${focusRingClass6}`,
|
|
1776
|
-
children: (alignments.find((entry) => entry.value === props.activeAlignment) ?? alignments[0])?.icon
|
|
1777
|
-
}
|
|
1778
|
-
) }),
|
|
1779
|
-
/* @__PURE__ */ jsx9(Tooltip3.Portal, { children: /* @__PURE__ */ jsx9(Tooltip3.Content, { className: "rounded-md bg-primary px-2 py-1 text-xs text-white shadow-md z-50", sideOffset: 6, children: "Paragraph alignment" }) })
|
|
1780
|
-
] }),
|
|
1781
|
-
open ? /* @__PURE__ */ jsxs9("div", { className: "absolute left-0 top-9 z-50 w-[220px] rounded-lg bg-canvas p-2 shadow-lg ring-1 ring-border", children: [
|
|
1782
|
-
/* @__PURE__ */ jsx9("div", { className: "mb-1 px-1 text-[10px] font-semibold uppercase tracking-[0.12em] text-tertiary", children: "Paragraph alignment" }),
|
|
1783
|
-
/* @__PURE__ */ jsx9("div", { className: "grid grid-cols-2 gap-1", children: alignments.map((entry) => /* @__PURE__ */ jsx9(
|
|
1784
|
-
ToolbarPopoverActionButton,
|
|
1785
|
-
{
|
|
1786
|
-
active: props.activeAlignment === entry.value,
|
|
1787
|
-
ariaLabel: entry.label,
|
|
1788
|
-
disabled: props.disabled,
|
|
1789
|
-
icon: entry.icon,
|
|
1790
|
-
onClick: () => {
|
|
1791
|
-
props.onSelect(entry.value);
|
|
1792
|
-
setOpen(false);
|
|
1793
|
-
}
|
|
1794
|
-
},
|
|
1795
|
-
entry.value
|
|
1796
|
-
)) })
|
|
1797
|
-
] }) : null
|
|
1798
|
-
] });
|
|
1799
|
-
}
|
|
1800
|
-
function ToolbarInsertMenu(props) {
|
|
1801
|
-
const [open, setOpen] = React3.useState(false);
|
|
1802
|
-
async function handleImageChange(event) {
|
|
1803
|
-
const file = event.target.files?.[0];
|
|
1804
|
-
if (!file || props.disabled || !props.onInsertImage) {
|
|
1805
|
-
event.target.value = "";
|
|
1806
|
-
return;
|
|
1807
|
-
}
|
|
1808
|
-
const data = new Uint8Array(await file.arrayBuffer());
|
|
1809
|
-
props.onInsertImage({
|
|
1810
|
-
data,
|
|
1811
|
-
mimeType: file.type || "image/png",
|
|
1812
|
-
altText: file.name
|
|
1813
|
-
});
|
|
1814
|
-
setOpen(false);
|
|
1815
|
-
event.target.value = "";
|
|
1816
|
-
}
|
|
1817
|
-
return /* @__PURE__ */ jsxs9("div", { className: "relative", children: [
|
|
1818
|
-
/* @__PURE__ */ jsxs9(Tooltip3.Root, { children: [
|
|
1819
|
-
/* @__PURE__ */ jsx9(Tooltip3.Trigger, { asChild: true, children: /* @__PURE__ */ jsxs9(
|
|
1820
|
-
"button",
|
|
1821
|
-
{
|
|
1822
|
-
type: "button",
|
|
1823
|
-
"aria-label": "Insert",
|
|
1824
|
-
"aria-expanded": open,
|
|
1825
|
-
disabled: props.disabled,
|
|
1826
|
-
onMouseDown: preserveEditorSelectionMouseDown,
|
|
1827
|
-
onClick: () => setOpen((value) => !value),
|
|
1828
|
-
className: `inline-flex h-7 items-center gap-1 rounded-md border border-border bg-canvas px-2 text-xs font-medium text-primary transition-colors hover:bg-surface outline-none disabled:cursor-not-allowed disabled:opacity-40 ${focusRingClass6}`,
|
|
1829
|
-
children: [
|
|
1830
|
-
"Insert",
|
|
1831
|
-
/* @__PURE__ */ jsx9(ChevronDown, { className: "h-3.5 w-3.5 text-tertiary" })
|
|
1832
|
-
]
|
|
1833
|
-
}
|
|
1834
|
-
) }),
|
|
1835
|
-
/* @__PURE__ */ jsx9(Tooltip3.Portal, { children: /* @__PURE__ */ jsx9(Tooltip3.Content, { className: "rounded-md bg-primary px-2 py-1 text-xs text-white shadow-md z-50", sideOffset: 6, children: "Insert" }) })
|
|
1836
|
-
] }),
|
|
1837
|
-
open ? /* @__PURE__ */ jsx9("div", { className: "absolute left-0 top-9 z-50 w-[220px] rounded-lg bg-canvas p-2 shadow-lg ring-1 ring-border", children: /* @__PURE__ */ jsxs9("div", { className: "space-y-1", children: [
|
|
1838
|
-
/* @__PURE__ */ jsx9(
|
|
1839
|
-
ToolbarMenuButton,
|
|
1840
|
-
{
|
|
1841
|
-
ariaLabel: "Insert page break",
|
|
1842
|
-
disabled: props.disabled || !props.onInsertPageBreak,
|
|
1843
|
-
icon: /* @__PURE__ */ jsx9(Minus, { className: "h-3.5 w-3.5" }),
|
|
1844
|
-
label: "Page break",
|
|
1845
|
-
onClick: () => {
|
|
1846
|
-
props.onInsertPageBreak?.();
|
|
1847
|
-
setOpen(false);
|
|
1848
|
-
}
|
|
1849
|
-
}
|
|
1850
|
-
),
|
|
1851
|
-
/* @__PURE__ */ jsx9(
|
|
1852
|
-
ToolbarMenuButton,
|
|
1853
|
-
{
|
|
1854
|
-
ariaLabel: "Insert table",
|
|
1855
|
-
disabled: props.disabled || !props.onInsertTable,
|
|
1856
|
-
icon: /* @__PURE__ */ jsx9(Rows3, { className: "h-3.5 w-3.5" }),
|
|
1857
|
-
label: "Table",
|
|
1858
|
-
onClick: () => {
|
|
1859
|
-
props.onInsertTable?.();
|
|
1860
|
-
setOpen(false);
|
|
1861
|
-
}
|
|
1862
|
-
}
|
|
1863
|
-
),
|
|
1864
|
-
/* @__PURE__ */ jsxs9(
|
|
1865
|
-
"label",
|
|
1866
|
-
{
|
|
1867
|
-
className: `flex h-8 cursor-pointer items-center gap-2 rounded-md px-2 text-xs font-medium text-primary transition-colors hover:bg-surface ${props.disabled || !props.onInsertImage ? "pointer-events-none opacity-40" : ""}`,
|
|
1868
|
-
children: [
|
|
1869
|
-
/* @__PURE__ */ jsx9(ImagePlus, { className: "h-3.5 w-3.5 text-secondary" }),
|
|
1870
|
-
/* @__PURE__ */ jsx9("span", { children: "Image" }),
|
|
1871
|
-
/* @__PURE__ */ jsx9(
|
|
1872
|
-
"input",
|
|
1873
|
-
{
|
|
1874
|
-
accept: "image/png,image/jpeg,image/gif",
|
|
1875
|
-
"aria-label": "Insert image",
|
|
1876
|
-
className: "sr-only",
|
|
1877
|
-
disabled: props.disabled || !props.onInsertImage,
|
|
1878
|
-
type: "file",
|
|
1879
|
-
onChange: (event) => {
|
|
1880
|
-
void handleImageChange(event);
|
|
1881
|
-
}
|
|
1882
|
-
}
|
|
1883
|
-
)
|
|
1884
|
-
]
|
|
1885
|
-
}
|
|
1886
|
-
),
|
|
1887
|
-
/* @__PURE__ */ jsx9(
|
|
1888
|
-
ToolbarMenuButton,
|
|
1889
|
-
{
|
|
1890
|
-
ariaLabel: "Insert next-page section break",
|
|
1891
|
-
disabled: props.disabled || !props.onInsertSectionBreak,
|
|
1892
|
-
icon: /* @__PURE__ */ jsx9(FileText, { className: "h-3.5 w-3.5" }),
|
|
1893
|
-
label: "Next-page section break",
|
|
1894
|
-
onClick: () => {
|
|
1895
|
-
props.onInsertSectionBreak?.("nextPage");
|
|
1896
|
-
setOpen(false);
|
|
1897
|
-
}
|
|
1898
|
-
}
|
|
1899
|
-
)
|
|
1900
|
-
] }) }) : null
|
|
1901
|
-
] });
|
|
1902
|
-
}
|
|
1903
|
-
function ToolbarPopoverActionButton(props) {
|
|
1904
|
-
return /* @__PURE__ */ jsx9(
|
|
1905
|
-
"button",
|
|
1906
|
-
{
|
|
1907
|
-
type: "button",
|
|
1908
|
-
"aria-label": props.ariaLabel,
|
|
1909
|
-
"aria-pressed": props.active,
|
|
1910
|
-
disabled: props.disabled,
|
|
1911
|
-
onMouseDown: preserveEditorSelectionMouseDown,
|
|
1912
|
-
onClick: props.onClick,
|
|
1913
|
-
className: `inline-flex h-8 items-center justify-center rounded-md border border-border transition-colors disabled:cursor-not-allowed disabled:opacity-40 ${props.active ? "bg-accent-soft text-accent" : "bg-canvas text-secondary hover:bg-surface"} ${focusRingClass6}`,
|
|
1914
|
-
children: props.icon
|
|
1915
|
-
}
|
|
1916
|
-
);
|
|
1917
|
-
}
|
|
1918
|
-
function ToolbarMenuButton(props) {
|
|
1919
|
-
return /* @__PURE__ */ jsxs9(
|
|
1920
|
-
"button",
|
|
1921
|
-
{
|
|
1922
|
-
type: "button",
|
|
1923
|
-
"aria-label": props.ariaLabel,
|
|
1924
|
-
disabled: props.disabled,
|
|
1925
|
-
onMouseDown: preserveEditorSelectionMouseDown,
|
|
1926
|
-
onClick: props.onClick,
|
|
1927
|
-
className: `flex h-8 w-full items-center gap-2 rounded-md px-2 text-left text-xs font-medium text-primary transition-colors hover:bg-surface disabled:cursor-not-allowed disabled:opacity-40 ${focusRingClass6}`,
|
|
1928
|
-
children: [
|
|
1929
|
-
/* @__PURE__ */ jsx9("span", { className: "text-secondary", children: props.icon }),
|
|
1930
|
-
/* @__PURE__ */ jsx9("span", { children: props.label })
|
|
1931
|
-
]
|
|
1932
|
-
}
|
|
1933
|
-
);
|
|
1934
|
-
}
|
|
1935
|
-
function storyLabel(target) {
|
|
1936
|
-
switch (target.kind) {
|
|
1937
|
-
case "header":
|
|
1938
|
-
return `Header (${target.variant})`;
|
|
1939
|
-
case "footer":
|
|
1940
|
-
return `Footer (${target.variant})`;
|
|
1941
|
-
case "footnote":
|
|
1942
|
-
return "Footnote";
|
|
1943
|
-
case "endnote":
|
|
1944
|
-
return "Endnote";
|
|
1945
|
-
default:
|
|
1946
|
-
return "Document";
|
|
1947
|
-
}
|
|
1948
|
-
}
|
|
1949
|
-
|
|
1950
|
-
// src/ui-tailwind/tw-review-workspace.tsx
|
|
1951
|
-
import {
|
|
1952
|
-
useCallback as useCallback2,
|
|
1953
|
-
useEffect as useEffect3,
|
|
1954
|
-
useMemo as useMemo2,
|
|
1955
|
-
useRef as useRef3,
|
|
1956
|
-
useState as useState3
|
|
1957
|
-
} from "react";
|
|
1958
|
-
import * as Tooltip5 from "@radix-ui/react-tooltip";
|
|
1959
|
-
import { ChevronLeft, ChevronRight, List as List2 } from "lucide-react";
|
|
1960
|
-
|
|
1961
|
-
// src/ui-tailwind/page-chrome-model.ts
|
|
1962
|
-
function computeLineMarkersIfEnabled(input) {
|
|
1963
|
-
if (!input.pageLayout?.lineNumbering) {
|
|
1964
|
-
return [];
|
|
1965
|
-
}
|
|
1966
|
-
return input.buildLineNumberMarkers(input.surfaceBlocks, input.pages);
|
|
1967
|
-
}
|
|
1968
|
-
|
|
1969
|
-
// src/ui-tailwind/chrome/tw-image-context-toolbar.tsx
|
|
1970
|
-
import { Fragment as Fragment6, jsx as jsx10, jsxs as jsxs10 } from "react/jsx-runtime";
|
|
1971
|
-
var IMAGE_SIZE_PRESETS = [
|
|
1972
|
-
{ label: "Small image", widthEmu: 1828800, heightEmu: 914400 },
|
|
1973
|
-
{ label: "Medium image", widthEmu: 2743200, heightEmu: 1371600 },
|
|
1974
|
-
{ label: "Large image", widthEmu: 3657600, heightEmu: 1828800 }
|
|
1975
|
-
];
|
|
1976
|
-
var NUDGE_EMU = 228600;
|
|
1977
|
-
function TwImageContextToolbar(props) {
|
|
1978
|
-
const { activeImage } = props;
|
|
1979
|
-
return /* @__PURE__ */ jsxs10(
|
|
1980
|
-
"div",
|
|
1981
|
-
{
|
|
1982
|
-
"data-testid": "image-context-toolbar",
|
|
1983
|
-
className: "flex flex-wrap items-center gap-2 rounded-xl border border-border bg-canvas px-3 py-2 shadow-sm",
|
|
1984
|
-
children: [
|
|
1985
|
-
/* @__PURE__ */ jsx10("span", { className: "text-[10px] font-semibold uppercase tracking-[0.12em] text-tertiary", children: "Image" }),
|
|
1986
|
-
/* @__PURE__ */ jsx10("span", { className: "rounded-full bg-surface px-2 py-1 text-[10px] font-medium uppercase tracking-[0.1em] text-secondary", children: activeImage.display }),
|
|
1987
|
-
IMAGE_SIZE_PRESETS.map((preset) => /* @__PURE__ */ jsx10(
|
|
1988
|
-
ToolbarButton,
|
|
1989
|
-
{
|
|
1990
|
-
ariaLabel: preset.label,
|
|
1991
|
-
disabled: props.disabled || !props.onSetImageLayout,
|
|
1992
|
-
onClick: () => props.onSetImageLayout?.(activeImage.mediaId, {
|
|
1993
|
-
widthEmu: preset.widthEmu,
|
|
1994
|
-
heightEmu: preset.heightEmu
|
|
1995
|
-
}),
|
|
1996
|
-
children: preset.label.replace(" image", "")
|
|
1997
|
-
},
|
|
1998
|
-
preset.label
|
|
1999
|
-
)),
|
|
2000
|
-
activeImage.display === "floating" ? /* @__PURE__ */ jsxs10(Fragment6, { children: [
|
|
2001
|
-
/* @__PURE__ */ jsx10(
|
|
2002
|
-
ToolbarButton,
|
|
2003
|
-
{
|
|
2004
|
-
ariaLabel: "Nudge image left",
|
|
2005
|
-
disabled: props.disabled || !props.onSetImageFrame,
|
|
2006
|
-
onClick: () => props.onSetImageFrame?.(activeImage.mediaId, {
|
|
2007
|
-
horizontalOffsetEmu: (activeImage.horizontalOffsetEmu ?? 0) - NUDGE_EMU
|
|
2008
|
-
}),
|
|
2009
|
-
children: "Left"
|
|
2010
|
-
}
|
|
2011
|
-
),
|
|
2012
|
-
/* @__PURE__ */ jsx10(
|
|
2013
|
-
ToolbarButton,
|
|
2014
|
-
{
|
|
2015
|
-
ariaLabel: "Nudge image right",
|
|
2016
|
-
disabled: props.disabled || !props.onSetImageFrame,
|
|
2017
|
-
onClick: () => props.onSetImageFrame?.(activeImage.mediaId, {
|
|
2018
|
-
horizontalOffsetEmu: (activeImage.horizontalOffsetEmu ?? 0) + NUDGE_EMU
|
|
2019
|
-
}),
|
|
2020
|
-
children: "Right"
|
|
2021
|
-
}
|
|
2022
|
-
),
|
|
2023
|
-
/* @__PURE__ */ jsx10(
|
|
2024
|
-
ToolbarButton,
|
|
2025
|
-
{
|
|
2026
|
-
ariaLabel: "Nudge image up",
|
|
2027
|
-
disabled: props.disabled || !props.onSetImageFrame,
|
|
2028
|
-
onClick: () => props.onSetImageFrame?.(activeImage.mediaId, {
|
|
2029
|
-
verticalOffsetEmu: (activeImage.verticalOffsetEmu ?? 0) - NUDGE_EMU
|
|
2030
|
-
}),
|
|
2031
|
-
children: "Up"
|
|
2032
|
-
}
|
|
2033
|
-
),
|
|
2034
|
-
/* @__PURE__ */ jsx10(
|
|
2035
|
-
ToolbarButton,
|
|
2036
|
-
{
|
|
2037
|
-
ariaLabel: "Nudge image down",
|
|
2038
|
-
disabled: props.disabled || !props.onSetImageFrame,
|
|
2039
|
-
onClick: () => props.onSetImageFrame?.(activeImage.mediaId, {
|
|
2040
|
-
verticalOffsetEmu: (activeImage.verticalOffsetEmu ?? 0) + NUDGE_EMU
|
|
2041
|
-
}),
|
|
2042
|
-
children: "Down"
|
|
2043
|
-
}
|
|
2044
|
-
)
|
|
2045
|
-
] }) : null
|
|
2046
|
-
]
|
|
2047
|
-
}
|
|
2048
|
-
);
|
|
2049
|
-
}
|
|
2050
|
-
function ToolbarButton(props) {
|
|
2051
|
-
return /* @__PURE__ */ jsx10(
|
|
2052
|
-
"button",
|
|
2053
|
-
{
|
|
2054
|
-
type: "button",
|
|
2055
|
-
"aria-label": props.ariaLabel,
|
|
2056
|
-
disabled: props.disabled,
|
|
2057
|
-
onMouseDown: preserveEditorSelectionMouseDown,
|
|
2058
|
-
onClick: props.onClick,
|
|
2059
|
-
className: "inline-flex h-8 items-center rounded-md px-2 text-xs font-medium text-primary transition-colors hover:bg-surface disabled:cursor-not-allowed disabled:opacity-40",
|
|
2060
|
-
children: props.children
|
|
2061
|
-
}
|
|
2062
|
-
);
|
|
2063
|
-
}
|
|
2064
|
-
|
|
2065
|
-
// src/ui-tailwind/chrome/tw-layout-panel.tsx
|
|
2066
|
-
import { jsx as jsx11, jsxs as jsxs11 } from "react/jsx-runtime";
|
|
2067
|
-
function TwLayoutPanel(props) {
|
|
2068
|
-
const nextOrientation = props.pageLayout.orientation === "portrait" ? "landscape" : "portrait";
|
|
2069
|
-
const titlePageEnabled = props.pageLayout.differentFirstPage;
|
|
2070
|
-
return /* @__PURE__ */ jsxs11("div", { className: "mt-3 flex flex-wrap items-center gap-2 rounded-xl border border-border bg-canvas px-3 py-2 shadow-sm", children: [
|
|
2071
|
-
/* @__PURE__ */ jsx11("span", { className: "text-[10px] font-semibold uppercase tracking-[0.12em] text-tertiary", children: "Section" }),
|
|
2072
|
-
/* @__PURE__ */ jsx11(
|
|
2073
|
-
ToolbarButton2,
|
|
2074
|
-
{
|
|
2075
|
-
ariaLabel: "Insert next-page section break",
|
|
2076
|
-
disabled: props.readOnly || !props.onInsertSectionBreak,
|
|
2077
|
-
onClick: () => props.onInsertSectionBreak?.("nextPage"),
|
|
2078
|
-
children: "Next-page break"
|
|
2079
|
-
}
|
|
2080
|
-
),
|
|
2081
|
-
/* @__PURE__ */ jsx11(
|
|
2082
|
-
ToolbarButton2,
|
|
2083
|
-
{
|
|
2084
|
-
ariaLabel: `Switch section to ${nextOrientation}`,
|
|
2085
|
-
disabled: props.readOnly || !props.onUpdateSectionLayout,
|
|
2086
|
-
onClick: () => props.onUpdateSectionLayout?.(props.pageLayout.sectionIndex, {
|
|
2087
|
-
pageSize: {
|
|
2088
|
-
orientation: nextOrientation,
|
|
2089
|
-
width: props.pageLayout.pageHeight,
|
|
2090
|
-
height: props.pageLayout.pageWidth
|
|
2091
|
-
}
|
|
2092
|
-
}),
|
|
2093
|
-
children: nextOrientation === "landscape" ? "Landscape" : "Portrait"
|
|
2094
|
-
}
|
|
2095
|
-
),
|
|
2096
|
-
/* @__PURE__ */ jsx11(
|
|
2097
|
-
ToolbarButton2,
|
|
2098
|
-
{
|
|
2099
|
-
ariaLabel: "Delete current section break",
|
|
2100
|
-
disabled: props.readOnly || props.pageLayout.sectionIndex === 0 || !props.onDeleteSectionBreak,
|
|
2101
|
-
onClick: () => props.onDeleteSectionBreak?.(props.pageLayout.sectionIndex),
|
|
2102
|
-
children: "Delete break"
|
|
2103
|
-
}
|
|
2104
|
-
),
|
|
2105
|
-
/* @__PURE__ */ jsx11(
|
|
2106
|
-
ToolbarButton2,
|
|
2107
|
-
{
|
|
2108
|
-
ariaLabel: "Restart page numbering at 1",
|
|
2109
|
-
disabled: props.readOnly || !props.onSetSectionPageNumbering,
|
|
2110
|
-
onClick: () => props.onSetSectionPageNumbering?.(props.pageLayout.sectionIndex, {
|
|
2111
|
-
...props.pageLayout.pageNumbering ?? {},
|
|
2112
|
-
start: 1
|
|
2113
|
-
}),
|
|
2114
|
-
children: "Restart numbering"
|
|
2115
|
-
}
|
|
2116
|
-
),
|
|
2117
|
-
/* @__PURE__ */ jsx11(
|
|
2118
|
-
ToolbarButton2,
|
|
2119
|
-
{
|
|
2120
|
-
ariaLabel: "Use roman page numbering",
|
|
2121
|
-
disabled: props.readOnly || !props.onSetSectionPageNumbering,
|
|
2122
|
-
onClick: () => props.onSetSectionPageNumbering?.(props.pageLayout.sectionIndex, {
|
|
2123
|
-
...props.pageLayout.pageNumbering ?? {},
|
|
2124
|
-
format: "roman"
|
|
2125
|
-
}),
|
|
2126
|
-
children: "Roman numerals"
|
|
2127
|
-
}
|
|
2128
|
-
),
|
|
2129
|
-
/* @__PURE__ */ jsx11(
|
|
2130
|
-
ToolbarButton2,
|
|
2131
|
-
{
|
|
2132
|
-
ariaLabel: "Toggle different first page",
|
|
2133
|
-
disabled: props.readOnly || !props.onUpdateSectionLayout,
|
|
2134
|
-
onClick: () => props.onUpdateSectionLayout?.(props.pageLayout.sectionIndex, {
|
|
2135
|
-
titlePage: !titlePageEnabled
|
|
2136
|
-
}),
|
|
2137
|
-
children: titlePageEnabled ? "Same first page" : "Different first page"
|
|
2138
|
-
}
|
|
2139
|
-
)
|
|
2140
|
-
] });
|
|
2141
|
-
}
|
|
2142
|
-
function ToolbarButton2(props) {
|
|
2143
|
-
return /* @__PURE__ */ jsx11(
|
|
2144
|
-
"button",
|
|
2145
|
-
{
|
|
2146
|
-
type: "button",
|
|
2147
|
-
"aria-label": props.ariaLabel,
|
|
2148
|
-
disabled: props.disabled,
|
|
2149
|
-
onMouseDown: preserveEditorSelectionMouseDown,
|
|
2150
|
-
onClick: props.onClick,
|
|
2151
|
-
className: "inline-flex h-8 items-center rounded-md px-2 text-xs font-medium text-primary transition-colors hover:bg-surface disabled:cursor-not-allowed disabled:opacity-40",
|
|
2152
|
-
children: props.children
|
|
2153
|
-
}
|
|
2154
|
-
);
|
|
2155
|
-
}
|
|
2156
|
-
|
|
2157
|
-
// src/ui-tailwind/chrome/tw-object-context-toolbar.tsx
|
|
2158
|
-
import { jsx as jsx12, jsxs as jsxs12 } from "react/jsx-runtime";
|
|
2159
|
-
function TwObjectContextToolbar(props) {
|
|
2160
|
-
const label = props.activeObject.kind === "textbox" ? "Text box" : "Shape";
|
|
2161
|
-
return /* @__PURE__ */ jsxs12(
|
|
2162
|
-
"div",
|
|
2163
|
-
{
|
|
2164
|
-
"data-testid": "object-context-toolbar",
|
|
2165
|
-
className: "flex flex-wrap items-center gap-2 rounded-xl border border-border bg-canvas px-3 py-2 shadow-sm",
|
|
2166
|
-
children: [
|
|
2167
|
-
/* @__PURE__ */ jsx12("span", { className: "text-[10px] font-semibold uppercase tracking-[0.12em] text-tertiary", children: "Object" }),
|
|
2168
|
-
/* @__PURE__ */ jsx12("span", { className: "rounded-full bg-surface px-2 py-1 text-[10px] font-medium uppercase tracking-[0.1em] text-secondary", children: label }),
|
|
2169
|
-
/* @__PURE__ */ jsx12("span", { className: "rounded-full bg-surface px-2 py-1 text-[10px] font-medium uppercase tracking-[0.1em] text-secondary", children: props.activeObject.display }),
|
|
2170
|
-
/* @__PURE__ */ jsx12("span", { className: "text-xs text-secondary", children: "Object selection is active." })
|
|
2171
|
-
]
|
|
2172
|
-
}
|
|
2173
|
-
);
|
|
2174
|
-
}
|
|
2175
|
-
|
|
2176
|
-
// src/ui-tailwind/chrome/tw-page-ruler.tsx
|
|
2177
|
-
import { useEffect as useEffect2, useMemo, useRef as useRef2, useState as useState2 } from "react";
|
|
2178
|
-
import { Fragment as Fragment7, jsx as jsx13, jsxs as jsxs13 } from "react/jsx-runtime";
|
|
2179
|
-
var MIN_HANDLE_TWIPS = 0;
|
|
2180
|
-
var HANDLE_OVERLAP_THRESHOLD_PERCENT = 1.4;
|
|
2181
|
-
var HANDLE_OFFSET_PERCENT = 0.9;
|
|
2182
|
-
var MARKER_HALF_PX = 8;
|
|
2183
|
-
function TwPageRuler(props) {
|
|
2184
|
-
const trackRef = useRef2(null);
|
|
2185
|
-
const dragCleanupRef = useRef2(null);
|
|
2186
|
-
const [, setDragState] = useState2(null);
|
|
2187
|
-
const [previewLayout, setPreviewLayout] = useState2(null);
|
|
2188
|
-
const effectiveLayout = previewLayout ?? props.paragraphLayout;
|
|
2189
|
-
const activeRegion = props.viewState.activePageRegion?.region ?? "body";
|
|
2190
|
-
const isBodyParagraphContext = activeRegion === "body" && Boolean(props.paragraphLayout);
|
|
2191
|
-
const availableHeader = props.pageLayout.headerVariants[0];
|
|
2192
|
-
const availableFooter = props.pageLayout.footerVariants[0];
|
|
2193
|
-
const usablePageWidth = Math.max(
|
|
2194
|
-
1440,
|
|
2195
|
-
props.pageLayout.pageWidth - props.pageLayout.marginLeft - props.pageLayout.marginRight
|
|
2196
|
-
);
|
|
2197
|
-
useEffect2(() => {
|
|
2198
|
-
return () => {
|
|
2199
|
-
dragCleanupRef.current?.();
|
|
2200
|
-
};
|
|
2201
|
-
}, []);
|
|
2202
|
-
function beginDrag(kind, clientX) {
|
|
2203
|
-
if (!isBodyParagraphContext || !props.paragraphLayout || props.readOnly) {
|
|
2204
|
-
return;
|
|
2205
|
-
}
|
|
2206
|
-
dragCleanupRef.current?.();
|
|
2207
|
-
const activeDrag = {
|
|
2208
|
-
kind,
|
|
2209
|
-
startClientX: clientX,
|
|
2210
|
-
startLeftIndent: props.paragraphLayout.leftIndent,
|
|
2211
|
-
startFirstLineOffset: props.paragraphLayout.firstLineOffset
|
|
2212
|
-
};
|
|
2213
|
-
setDragState(activeDrag);
|
|
2214
|
-
const handleMouseMove = (event) => {
|
|
2215
|
-
const track = trackRef.current;
|
|
2216
|
-
if (!track) {
|
|
2217
|
-
return;
|
|
2218
|
-
}
|
|
2219
|
-
const rect = track.getBoundingClientRect();
|
|
2220
|
-
const deltaPx = event.clientX - activeDrag.startClientX;
|
|
2221
|
-
const deltaTwips = pxToTwips(deltaPx, rect.width, usablePageWidth);
|
|
2222
|
-
if (activeDrag.kind === "left-indent") {
|
|
2223
|
-
setPreviewLayout({
|
|
2224
|
-
...props.paragraphLayout,
|
|
2225
|
-
leftIndent: clampTwips(activeDrag.startLeftIndent + deltaTwips),
|
|
2226
|
-
firstLineOffset: activeDrag.startFirstLineOffset
|
|
2227
|
-
});
|
|
2228
|
-
return;
|
|
2229
|
-
}
|
|
2230
|
-
setPreviewLayout({
|
|
2231
|
-
...props.paragraphLayout,
|
|
2232
|
-
leftIndent: activeDrag.startLeftIndent,
|
|
2233
|
-
firstLineOffset: activeDrag.startFirstLineOffset + deltaTwips
|
|
2234
|
-
});
|
|
2235
|
-
};
|
|
2236
|
-
const handleMouseUp = (event) => {
|
|
2237
|
-
const track = trackRef.current;
|
|
2238
|
-
if (!track || !props.onSetIndentation) {
|
|
2239
|
-
cleanupDrag();
|
|
2240
|
-
setDragState(null);
|
|
2241
|
-
setPreviewLayout(null);
|
|
2242
|
-
return;
|
|
2243
|
-
}
|
|
2244
|
-
const rect = track.getBoundingClientRect();
|
|
2245
|
-
const deltaPx = event.clientX - activeDrag.startClientX;
|
|
2246
|
-
const deltaTwips = pxToTwips(deltaPx, rect.width, usablePageWidth);
|
|
2247
|
-
const leftIndent = activeDrag.kind === "left-indent" ? clampTwips(activeDrag.startLeftIndent + deltaTwips) : activeDrag.startLeftIndent;
|
|
2248
|
-
const firstLineOffset = activeDrag.kind === "first-line" ? activeDrag.startFirstLineOffset + deltaTwips : activeDrag.startFirstLineOffset;
|
|
2249
|
-
cleanupDrag();
|
|
2250
|
-
props.onSetIndentation(
|
|
2251
|
-
composeIndentation(leftIndent, effectiveLayout?.rightIndent ?? props.paragraphLayout?.rightIndent ?? 0, firstLineOffset)
|
|
2252
|
-
);
|
|
2253
|
-
setDragState(null);
|
|
2254
|
-
setPreviewLayout(null);
|
|
2255
|
-
};
|
|
2256
|
-
const cleanupDrag = () => {
|
|
2257
|
-
window.removeEventListener("mousemove", handleMouseMove);
|
|
2258
|
-
window.removeEventListener("mouseup", handleMouseUp);
|
|
2259
|
-
if (dragCleanupRef.current === cleanupDrag) {
|
|
2260
|
-
dragCleanupRef.current = null;
|
|
2261
|
-
}
|
|
2262
|
-
};
|
|
2263
|
-
dragCleanupRef.current = cleanupDrag;
|
|
2264
|
-
window.addEventListener("mousemove", handleMouseMove);
|
|
2265
|
-
window.addEventListener("mouseup", handleMouseUp);
|
|
2266
|
-
}
|
|
2267
|
-
const markerLayout = useMemo(() => {
|
|
2268
|
-
if (!effectiveLayout || !isBodyParagraphContext) {
|
|
2269
|
-
return null;
|
|
2270
|
-
}
|
|
2271
|
-
return {
|
|
2272
|
-
leftIndent: twipsToPercent(effectiveLayout.leftIndent, usablePageWidth),
|
|
2273
|
-
firstLine: twipsToPercent(
|
|
2274
|
-
Math.max(MIN_HANDLE_TWIPS, effectiveLayout.leftIndent + effectiveLayout.firstLineOffset),
|
|
2275
|
-
usablePageWidth
|
|
2276
|
-
),
|
|
2277
|
-
tabStops: effectiveLayout.tabStops.map((tabStop, index) => ({
|
|
2278
|
-
id: `${tabStop.pos}-${index}`,
|
|
2279
|
-
left: twipsToPercent(tabStop.pos, usablePageWidth)
|
|
2280
|
-
}))
|
|
2281
|
-
};
|
|
2282
|
-
}, [effectiveLayout, isBodyParagraphContext, usablePageWidth]);
|
|
2283
|
-
const handlesOverlap = markerLayout ? Math.abs(markerLayout.leftIndent - markerLayout.firstLine) < HANDLE_OVERLAP_THRESHOLD_PERCENT : false;
|
|
2284
|
-
const leftIndentHandleLeft = markerLayout ? offsetHandlePercent(markerLayout.leftIndent, handlesOverlap ? -HANDLE_OFFSET_PERCENT : 0) : 0;
|
|
2285
|
-
const firstLineHandleLeft = markerLayout ? offsetHandlePercent(markerLayout.firstLine, handlesOverlap ? HANDLE_OFFSET_PERCENT : 0) : 0;
|
|
2286
|
-
return /* @__PURE__ */ jsxs13(
|
|
2287
|
-
"div",
|
|
2288
|
-
{
|
|
2289
|
-
"aria-label": "Page ruler",
|
|
2290
|
-
className: "mb-4 rounded-2xl border border-border bg-surface/80 px-4 py-3 shadow-sm",
|
|
2291
|
-
children: [
|
|
2292
|
-
/* @__PURE__ */ jsxs13("div", { className: "mb-3 flex flex-wrap items-center gap-2", children: [
|
|
2293
|
-
/* @__PURE__ */ jsx13(
|
|
2294
|
-
"button",
|
|
2295
|
-
{
|
|
2296
|
-
type: "button",
|
|
2297
|
-
"aria-label": "Return to document body",
|
|
2298
|
-
title: "Return to document body",
|
|
2299
|
-
onClick: props.onReturnToBody,
|
|
2300
|
-
className: regionButtonClass(activeRegion === "body"),
|
|
2301
|
-
children: "Body"
|
|
2302
|
-
}
|
|
2303
|
-
),
|
|
2304
|
-
availableHeader ? /* @__PURE__ */ jsx13(
|
|
2305
|
-
"button",
|
|
2306
|
-
{
|
|
2307
|
-
type: "button",
|
|
2308
|
-
"aria-label": "Open header story",
|
|
2309
|
-
title: "Open header story",
|
|
2310
|
-
onClick: props.onOpenHeader,
|
|
2311
|
-
className: regionButtonClass(activeRegion === "header"),
|
|
2312
|
-
children: "Header"
|
|
2313
|
-
}
|
|
2314
|
-
) : null,
|
|
2315
|
-
availableFooter ? /* @__PURE__ */ jsx13(
|
|
2316
|
-
"button",
|
|
2317
|
-
{
|
|
2318
|
-
type: "button",
|
|
2319
|
-
"aria-label": "Open footer story",
|
|
2320
|
-
title: "Open footer story",
|
|
2321
|
-
onClick: props.onOpenFooter,
|
|
2322
|
-
className: regionButtonClass(activeRegion === "footer"),
|
|
2323
|
-
children: "Footer"
|
|
2324
|
-
}
|
|
2325
|
-
) : null,
|
|
2326
|
-
props.viewState.activeListContext ? /* @__PURE__ */ jsxs13(Fragment7, { children: [
|
|
2327
|
-
/* @__PURE__ */ jsx13("div", { className: "h-4 w-px bg-border" }),
|
|
2328
|
-
/* @__PURE__ */ jsx13(
|
|
2329
|
-
"button",
|
|
2330
|
-
{
|
|
2331
|
-
type: "button",
|
|
2332
|
-
"aria-label": "Continue numbering",
|
|
2333
|
-
title: "Continue numbering from previous list",
|
|
2334
|
-
disabled: props.readOnly,
|
|
2335
|
-
onClick: props.onContinueNumbering,
|
|
2336
|
-
className: controlButtonClass,
|
|
2337
|
-
children: "Continue"
|
|
2338
|
-
}
|
|
2339
|
-
),
|
|
2340
|
-
/* @__PURE__ */ jsx13(
|
|
2341
|
-
"button",
|
|
2342
|
-
{
|
|
2343
|
-
type: "button",
|
|
2344
|
-
"aria-label": "Restart numbering",
|
|
2345
|
-
title: "Restart numbering at 1",
|
|
2346
|
-
disabled: props.readOnly,
|
|
2347
|
-
onClick: props.onRestartNumbering,
|
|
2348
|
-
className: controlButtonClass,
|
|
2349
|
-
children: "Restart"
|
|
2350
|
-
}
|
|
2351
|
-
)
|
|
2352
|
-
] }) : null
|
|
2353
|
-
] }),
|
|
2354
|
-
/* @__PURE__ */ jsx13(
|
|
2355
|
-
"div",
|
|
2356
|
-
{
|
|
2357
|
-
className: "mb-2 flex items-center justify-between",
|
|
2358
|
-
"aria-label": `Section ${props.pageLayout.sectionIndex + 1}, ${props.pageLayout.orientation}`,
|
|
2359
|
-
title: `Section ${props.pageLayout.sectionIndex + 1} \xB7 ${props.pageLayout.orientation}`,
|
|
2360
|
-
children: /* @__PURE__ */ jsx13("span", { className: "sr-only", children: "Page ruler" })
|
|
2361
|
-
}
|
|
2362
|
-
),
|
|
2363
|
-
/* @__PURE__ */ jsxs13(
|
|
2364
|
-
"div",
|
|
2365
|
-
{
|
|
2366
|
-
ref: trackRef,
|
|
2367
|
-
"aria-label": "Page ruler track",
|
|
2368
|
-
className: "relative h-14 overflow-hidden rounded-xl border border-border bg-canvas",
|
|
2369
|
-
onClick: (event) => {
|
|
2370
|
-
if (props.readOnly || !isBodyParagraphContext || !props.paragraphLayout || !props.onSetTabStops) {
|
|
2371
|
-
return;
|
|
2372
|
-
}
|
|
2373
|
-
if (event.target.dataset.handle === "true") {
|
|
2374
|
-
return;
|
|
2375
|
-
}
|
|
2376
|
-
const rect = event.currentTarget.getBoundingClientRect();
|
|
2377
|
-
const nextPos = clampTwips(pxToTwips(event.clientX - rect.left, rect.width, usablePageWidth));
|
|
2378
|
-
props.onSetTabStops(
|
|
2379
|
-
[...props.paragraphLayout.tabStops, { pos: nextPos, val: "left" }].sort((left, right) => left.pos - right.pos)
|
|
2380
|
-
);
|
|
2381
|
-
},
|
|
2382
|
-
children: [
|
|
2383
|
-
/* @__PURE__ */ jsx13("div", { className: "absolute inset-x-4 top-2 h-px bg-border" }),
|
|
2384
|
-
/* @__PURE__ */ jsx13("div", { className: "absolute inset-x-4 top-7 h-px bg-border/70" }),
|
|
2385
|
-
Array.from({ length: 8 }, (_, index) => /* @__PURE__ */ jsx13(
|
|
2386
|
-
"div",
|
|
2387
|
-
{
|
|
2388
|
-
className: "absolute top-1 h-3 w-px bg-border/80",
|
|
2389
|
-
style: { left: `${12 + index * 12}%` }
|
|
2390
|
-
},
|
|
2391
|
-
`tick-${index}`
|
|
2392
|
-
)),
|
|
2393
|
-
markerLayout ? /* @__PURE__ */ jsxs13(Fragment7, { children: [
|
|
2394
|
-
/* @__PURE__ */ jsx13(
|
|
2395
|
-
"button",
|
|
2396
|
-
{
|
|
2397
|
-
type: "button",
|
|
2398
|
-
"data-handle": "true",
|
|
2399
|
-
"aria-label": "Left indent handle",
|
|
2400
|
-
title: `Left indent: ${effectiveLayout?.leftIndent ?? 0} twips`,
|
|
2401
|
-
disabled: props.readOnly,
|
|
2402
|
-
className: `absolute top-8 h-4 w-4 -translate-x-1/2 rounded-[5px] border border-accent/40 bg-accent-soft shadow-sm transition-opacity ${handlesOverlap ? "opacity-80 z-10" : ""}`,
|
|
2403
|
-
style: { left: markerLeftStyle(leftIndentHandleLeft) },
|
|
2404
|
-
onMouseDown: (event) => {
|
|
2405
|
-
event.preventDefault();
|
|
2406
|
-
beginDrag("left-indent", event.clientX);
|
|
2407
|
-
}
|
|
2408
|
-
}
|
|
2409
|
-
),
|
|
2410
|
-
/* @__PURE__ */ jsx13(
|
|
2411
|
-
"button",
|
|
2412
|
-
{
|
|
2413
|
-
type: "button",
|
|
2414
|
-
"data-handle": "true",
|
|
2415
|
-
"aria-label": "First line indent handle",
|
|
2416
|
-
title: `First line offset: ${effectiveLayout?.firstLineOffset ?? 0} twips`,
|
|
2417
|
-
disabled: props.readOnly,
|
|
2418
|
-
className: `absolute top-1 h-4 w-4 -translate-x-1/2 rotate-45 rounded-[4px] border border-primary/30 bg-surface-raised shadow-sm transition-opacity ${handlesOverlap ? "opacity-80 z-20" : ""}`,
|
|
2419
|
-
style: { left: markerLeftStyle(firstLineHandleLeft) },
|
|
2420
|
-
onMouseDown: (event) => {
|
|
2421
|
-
event.preventDefault();
|
|
2422
|
-
beginDrag("first-line", event.clientX);
|
|
2423
|
-
}
|
|
2424
|
-
}
|
|
2425
|
-
),
|
|
2426
|
-
markerLayout.tabStops.map((tabStop) => /* @__PURE__ */ jsx13(
|
|
2427
|
-
"div",
|
|
2428
|
-
{
|
|
2429
|
-
"data-handle": "true",
|
|
2430
|
-
"aria-label": `Tab stop at ${tabStop.left.toFixed(0)}%`,
|
|
2431
|
-
title: `Tab stop`,
|
|
2432
|
-
className: "absolute top-5 h-4 w-4 -translate-x-1/2 rounded-sm border border-border bg-surface-raised shadow-sm",
|
|
2433
|
-
style: { left: markerLeftStyle(tabStop.left) }
|
|
2434
|
-
},
|
|
2435
|
-
tabStop.id
|
|
2436
|
-
))
|
|
2437
|
-
] }) : null
|
|
2438
|
-
]
|
|
2439
|
-
}
|
|
2440
|
-
)
|
|
2441
|
-
]
|
|
2442
|
-
}
|
|
2443
|
-
);
|
|
2444
|
-
}
|
|
2445
|
-
function composeIndentation(leftIndent, rightIndent, firstLineOffset) {
|
|
2446
|
-
const indentation = {};
|
|
2447
|
-
if (leftIndent > 0) {
|
|
2448
|
-
indentation.left = leftIndent;
|
|
2449
|
-
}
|
|
2450
|
-
if (rightIndent > 0) {
|
|
2451
|
-
indentation.right = rightIndent;
|
|
2452
|
-
}
|
|
2453
|
-
if (firstLineOffset > 0) {
|
|
2454
|
-
indentation.firstLine = Math.round(firstLineOffset);
|
|
2455
|
-
} else if (firstLineOffset < 0) {
|
|
2456
|
-
indentation.hanging = Math.round(Math.abs(firstLineOffset));
|
|
2457
|
-
}
|
|
2458
|
-
return indentation;
|
|
2459
|
-
}
|
|
2460
|
-
function regionButtonClass(active) {
|
|
2461
|
-
return `inline-flex items-center rounded-full border px-3 py-1 text-xs transition-colors ${active ? "border-accent/30 bg-accent-soft text-accent" : "border-border bg-canvas text-secondary hover:bg-surface"}`;
|
|
2462
|
-
}
|
|
2463
|
-
var controlButtonClass = "inline-flex items-center rounded-full border border-border bg-canvas px-3 py-1 text-xs text-secondary transition-colors hover:bg-surface disabled:cursor-not-allowed disabled:opacity-50";
|
|
2464
|
-
function twipsToPercent(value, usablePageWidth) {
|
|
2465
|
-
return Math.max(0, Math.min(100, value / usablePageWidth * 100));
|
|
2466
|
-
}
|
|
2467
|
-
function pxToTwips(px, width, usablePageWidth) {
|
|
2468
|
-
if (width <= 0) {
|
|
2469
|
-
return 0;
|
|
2470
|
-
}
|
|
2471
|
-
return Math.round(px / width * usablePageWidth);
|
|
2472
|
-
}
|
|
2473
|
-
function clampTwips(value) {
|
|
2474
|
-
return Math.max(MIN_HANDLE_TWIPS, Math.round(value));
|
|
2475
|
-
}
|
|
2476
|
-
function offsetHandlePercent(value, offset) {
|
|
2477
|
-
return Math.max(0, Math.min(100, value + offset));
|
|
2478
|
-
}
|
|
2479
|
-
function markerLeftStyle(value) {
|
|
2480
|
-
const clamped = Math.max(0, Math.min(100, value));
|
|
2481
|
-
return `clamp(${MARKER_HALF_PX}px, ${clamped}%, calc(100% - ${MARKER_HALF_PX}px))`;
|
|
2482
|
-
}
|
|
2483
|
-
|
|
2484
|
-
// src/ui-tailwind/chrome/tw-suggestion-card.tsx
|
|
2485
|
-
import * as Tooltip4 from "@radix-ui/react-tooltip";
|
|
2486
|
-
import { Check as Check3, MessageSquare as MessageSquare3, Pencil, X as X2 } from "lucide-react";
|
|
2487
|
-
import { jsx as jsx14, jsxs as jsxs14 } from "react/jsx-runtime";
|
|
2488
|
-
var focusRingClass7 = "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-accent focus-visible:ring-offset-2 focus-visible:ring-offset-canvas";
|
|
2489
|
-
function TwSuggestionCard(props) {
|
|
2490
|
-
const contextLabel = summarizeSuggestionContext(props.model);
|
|
2491
|
-
const commentDisabled = !props.model.canAddComment;
|
|
2492
|
-
const tooltipLabel = commentDisabled ? props.model.disabledReason ?? "Commenting is unavailable for this selection" : "Comment on suggestion";
|
|
2493
|
-
return /* @__PURE__ */ jsxs14(
|
|
2494
|
-
"div",
|
|
2495
|
-
{
|
|
2496
|
-
"data-testid": "suggestion-card",
|
|
2497
|
-
className: "inline-flex max-w-[min(28rem,calc(100vw-2rem))] flex-col gap-2 rounded-2xl border border-border/80 bg-canvas px-3 py-2 shadow-xl ring-1 ring-border/80",
|
|
2498
|
-
onFocusCapture: props.onFocusCapture,
|
|
2499
|
-
onBlurCapture: props.onBlurCapture,
|
|
2500
|
-
role: "group",
|
|
2501
|
-
"aria-label": "Suggestion actions",
|
|
2502
|
-
children: [
|
|
2503
|
-
/* @__PURE__ */ jsxs14("div", { className: "flex items-start justify-between gap-3", children: [
|
|
2504
|
-
/* @__PURE__ */ jsxs14("div", { className: "min-w-0", children: [
|
|
2505
|
-
/* @__PURE__ */ jsx14("div", { className: "text-[11px] font-semibold uppercase tracking-[0.12em] text-warning", children: props.model.kindLabel }),
|
|
2506
|
-
/* @__PURE__ */ jsx14("div", { className: "mt-1 max-w-[16rem] truncate text-sm text-primary", children: props.model.previewText })
|
|
2507
|
-
] }),
|
|
2508
|
-
contextLabel ? /* @__PURE__ */ jsx14("div", { className: "shrink-0 rounded-full bg-accent-soft px-2 py-0.5 text-[10px] font-medium uppercase tracking-[0.08em] text-accent", children: contextLabel }) : null
|
|
2509
|
-
] }),
|
|
2510
|
-
/* @__PURE__ */ jsxs14("div", { className: "flex flex-wrap items-center gap-1.5", children: [
|
|
2511
|
-
/* @__PURE__ */ jsx14(
|
|
2512
|
-
SuggestionActionButton,
|
|
2513
|
-
{
|
|
2514
|
-
icon: /* @__PURE__ */ jsx14(Check3, { className: "h-3.5 w-3.5" }),
|
|
2515
|
-
label: "Accept suggestion",
|
|
2516
|
-
disabled: !props.model.canAccept,
|
|
2517
|
-
tone: "accept",
|
|
2518
|
-
onClick: props.onAccept
|
|
2519
|
-
}
|
|
2520
|
-
),
|
|
2521
|
-
/* @__PURE__ */ jsx14(
|
|
2522
|
-
SuggestionActionButton,
|
|
2523
|
-
{
|
|
2524
|
-
icon: /* @__PURE__ */ jsx14(X2, { className: "h-3.5 w-3.5" }),
|
|
2525
|
-
label: "Reject suggestion",
|
|
2526
|
-
disabled: !props.model.canReject,
|
|
2527
|
-
tone: "reject",
|
|
2528
|
-
onClick: props.onReject
|
|
2529
|
-
}
|
|
2530
|
-
),
|
|
2531
|
-
/* @__PURE__ */ jsx14(
|
|
2532
|
-
SuggestionActionButton,
|
|
2533
|
-
{
|
|
2534
|
-
icon: /* @__PURE__ */ jsx14(Pencil, { className: "h-3.5 w-3.5" }),
|
|
2535
|
-
label: "Edit suggestion",
|
|
2536
|
-
disabled: !props.model.canEditSuggestion,
|
|
2537
|
-
tone: "neutral",
|
|
2538
|
-
onClick: props.onEditSuggestion
|
|
2539
|
-
}
|
|
2540
|
-
),
|
|
2541
|
-
/* @__PURE__ */ jsxs14(Tooltip4.Root, { children: [
|
|
2542
|
-
/* @__PURE__ */ jsx14(Tooltip4.Trigger, { asChild: true, children: /* @__PURE__ */ jsxs14(
|
|
2543
|
-
"button",
|
|
2544
|
-
{
|
|
2545
|
-
type: "button",
|
|
2546
|
-
"aria-label": "Comment on suggestion",
|
|
2547
|
-
disabled: commentDisabled,
|
|
2548
|
-
onMouseDown: preserveEditorSelectionMouseDown,
|
|
2549
|
-
onClick: props.onAddComment,
|
|
2550
|
-
className: `inline-flex h-8 items-center gap-1 rounded-lg border border-border px-2.5 text-xs font-medium text-secondary transition-colors hover:bg-surface disabled:cursor-not-allowed disabled:opacity-40 ${focusRingClass7}`,
|
|
2551
|
-
children: [
|
|
2552
|
-
/* @__PURE__ */ jsx14(MessageSquare3, { className: "h-3.5 w-3.5" }),
|
|
2553
|
-
"Comment"
|
|
2554
|
-
]
|
|
2555
|
-
}
|
|
2556
|
-
) }),
|
|
2557
|
-
/* @__PURE__ */ jsx14(Tooltip4.Portal, { children: /* @__PURE__ */ jsx14(
|
|
2558
|
-
Tooltip4.Content,
|
|
2559
|
-
{
|
|
2560
|
-
className: "rounded-md bg-primary px-2 py-1 text-xs text-white shadow-md z-50",
|
|
2561
|
-
sideOffset: 6,
|
|
2562
|
-
children: tooltipLabel
|
|
2563
|
-
}
|
|
2564
|
-
) })
|
|
2565
|
-
] })
|
|
2566
|
-
] })
|
|
2567
|
-
]
|
|
2568
|
-
}
|
|
2569
|
-
);
|
|
2570
|
-
}
|
|
2571
|
-
function summarizeSuggestionContext(model) {
|
|
2572
|
-
const labels = model.badges.map((badge) => badge.label.trim()).filter(Boolean);
|
|
2573
|
-
if (labels.length === 0) {
|
|
2574
|
-
return null;
|
|
2575
|
-
}
|
|
2576
|
-
const summary = labels.slice(0, 2).join(" \xB7 ");
|
|
2577
|
-
return summary.length > 36 ? `${summary.slice(0, 33)}...` : summary;
|
|
2578
|
-
}
|
|
2579
|
-
function SuggestionActionButton(props) {
|
|
2580
|
-
const toneClass = props.tone === "accept" ? "border-emerald-500/30 bg-emerald-500/10 text-emerald-700 hover:bg-emerald-500/15 dark:text-emerald-300" : props.tone === "reject" ? "border-rose-500/30 bg-rose-500/10 text-rose-700 hover:bg-rose-500/15 dark:text-rose-300" : "border-border text-secondary hover:bg-surface";
|
|
2581
|
-
return /* @__PURE__ */ jsxs14(
|
|
2582
|
-
"button",
|
|
2583
|
-
{
|
|
2584
|
-
type: "button",
|
|
2585
|
-
"aria-label": props.label,
|
|
2586
|
-
disabled: props.disabled,
|
|
2587
|
-
onMouseDown: preserveEditorSelectionMouseDown,
|
|
2588
|
-
onClick: props.onClick,
|
|
2589
|
-
className: `inline-flex h-8 items-center gap-1 rounded-lg border px-2.5 text-xs font-medium transition-colors disabled:cursor-not-allowed disabled:opacity-40 ${toneClass} ${focusRingClass7}`,
|
|
2590
|
-
children: [
|
|
2591
|
-
props.icon,
|
|
2592
|
-
props.label.replace(" suggestion", "").replace(" on suggestion", "")
|
|
2593
|
-
]
|
|
2594
|
-
}
|
|
2595
|
-
);
|
|
2596
|
-
}
|
|
2597
|
-
|
|
2598
|
-
// src/ui-tailwind/chrome/tw-table-context-toolbar.tsx
|
|
2599
|
-
import { jsx as jsx15, jsxs as jsxs15 } from "react/jsx-runtime";
|
|
2600
|
-
var CELL_COLORS = [
|
|
2601
|
-
"#ffffff",
|
|
2602
|
-
"#f0f0ee",
|
|
2603
|
-
"#dbeafe",
|
|
2604
|
-
"#fef3c7",
|
|
2605
|
-
"#dcfce7",
|
|
2606
|
-
"#fce7f3"
|
|
2607
|
-
];
|
|
2608
|
-
function TwTableContextToolbar(props) {
|
|
2609
|
-
return /* @__PURE__ */ jsxs15(
|
|
2610
|
-
"div",
|
|
2611
|
-
{
|
|
2612
|
-
"data-testid": "table-context-toolbar",
|
|
2613
|
-
className: "flex flex-wrap items-center gap-2 rounded-xl border border-border bg-canvas px-3 py-2 shadow-sm",
|
|
2614
|
-
children: [
|
|
2615
|
-
/* @__PURE__ */ jsx15("span", { className: "text-[10px] font-semibold uppercase tracking-[0.12em] text-tertiary", children: "Table" }),
|
|
2616
|
-
/* @__PURE__ */ jsxs15(
|
|
2617
|
-
"select",
|
|
2618
|
-
{
|
|
2619
|
-
"aria-label": "Table style",
|
|
2620
|
-
className: "h-8 rounded-md border border-border bg-canvas px-2 text-xs text-primary disabled:opacity-40",
|
|
2621
|
-
disabled: props.disabled || props.tableStyles.length === 0 || !props.onSetTableStyle,
|
|
2622
|
-
onMouseDown: preserveEditorSelectionMouseDown,
|
|
2623
|
-
onChange: (event) => props.onSetTableStyle?.(event.target.value),
|
|
2624
|
-
defaultValue: "",
|
|
2625
|
-
children: [
|
|
2626
|
-
/* @__PURE__ */ jsx15("option", { value: "", disabled: true, children: "Table style" }),
|
|
2627
|
-
props.tableStyles.map((style) => /* @__PURE__ */ jsx15("option", { value: style.styleId, children: style.displayName }, style.styleId))
|
|
2628
|
-
]
|
|
2629
|
-
}
|
|
2630
|
-
),
|
|
2631
|
-
/* @__PURE__ */ jsx15(ToolbarButton3, { ariaLabel: "Add row above", disabled: props.disabled, onClick: props.onAddRowBefore, children: "Row above" }),
|
|
2632
|
-
/* @__PURE__ */ jsx15(ToolbarButton3, { ariaLabel: "Add row below", disabled: props.disabled, onClick: props.onAddRowAfter, children: "Row below" }),
|
|
2633
|
-
/* @__PURE__ */ jsx15(ToolbarButton3, { ariaLabel: "Delete row", disabled: props.disabled, onClick: props.onDeleteRow, children: "Delete row" }),
|
|
2634
|
-
/* @__PURE__ */ jsx15(ToolbarButton3, { ariaLabel: "Add column left", disabled: props.disabled, onClick: props.onAddColumnBefore, children: "Column left" }),
|
|
2635
|
-
/* @__PURE__ */ jsx15(ToolbarButton3, { ariaLabel: "Add column right", disabled: props.disabled, onClick: props.onAddColumnAfter, children: "Column right" }),
|
|
2636
|
-
/* @__PURE__ */ jsx15(ToolbarButton3, { ariaLabel: "Delete column", disabled: props.disabled, onClick: props.onDeleteColumn, children: "Delete column" }),
|
|
2637
|
-
/* @__PURE__ */ jsx15(ToolbarButton3, { ariaLabel: "Merge cells", disabled: props.disabled, onClick: props.onMergeCells, children: "Merge" }),
|
|
2638
|
-
/* @__PURE__ */ jsx15(ToolbarButton3, { ariaLabel: "Split cell", disabled: props.disabled, onClick: props.onSplitCell, children: "Split" }),
|
|
2639
|
-
/* @__PURE__ */ jsxs15("div", { className: "flex items-center gap-1", children: [
|
|
2640
|
-
/* @__PURE__ */ jsx15("span", { className: "text-[11px] text-secondary", children: "Fill" }),
|
|
2641
|
-
CELL_COLORS.map((color) => /* @__PURE__ */ jsx15(
|
|
2642
|
-
"button",
|
|
2643
|
-
{
|
|
2644
|
-
type: "button",
|
|
2645
|
-
"aria-label": `Set cell fill ${color}`,
|
|
2646
|
-
disabled: props.disabled || !props.onSetCellBackground,
|
|
2647
|
-
onMouseDown: preserveEditorSelectionMouseDown,
|
|
2648
|
-
onClick: () => props.onSetCellBackground?.(color),
|
|
2649
|
-
className: "h-6 w-6 rounded border border-border disabled:opacity-40",
|
|
2650
|
-
style: { backgroundColor: color }
|
|
2651
|
-
},
|
|
2652
|
-
color
|
|
2653
|
-
))
|
|
2654
|
-
] }),
|
|
2655
|
-
/* @__PURE__ */ jsx15(ToolbarButton3, { ariaLabel: "Delete table", danger: true, disabled: props.disabled, onClick: props.onDeleteTable, children: "Delete table" })
|
|
2656
|
-
]
|
|
2657
|
-
}
|
|
2658
|
-
);
|
|
2659
|
-
}
|
|
2660
|
-
function ToolbarButton3(props) {
|
|
2661
|
-
return /* @__PURE__ */ jsx15(
|
|
2662
|
-
"button",
|
|
2663
|
-
{
|
|
2664
|
-
type: "button",
|
|
2665
|
-
"aria-label": props.ariaLabel,
|
|
2666
|
-
disabled: props.disabled || !props.onClick,
|
|
2667
|
-
onMouseDown: preserveEditorSelectionMouseDown,
|
|
2668
|
-
onClick: props.onClick,
|
|
2669
|
-
className: `inline-flex h-8 items-center rounded-md px-2 text-xs font-medium transition-colors disabled:cursor-not-allowed disabled:opacity-40 ${props.danger ? "text-danger hover:bg-danger/10" : "text-primary hover:bg-surface"}`,
|
|
2670
|
-
children: props.children
|
|
2671
|
-
}
|
|
2672
|
-
);
|
|
2673
|
-
}
|
|
2674
|
-
|
|
2675
|
-
// src/ui-tailwind/tw-review-workspace.tsx
|
|
2676
|
-
import { Fragment as Fragment8, jsx as jsx16, jsxs as jsxs16 } from "react/jsx-runtime";
|
|
2677
|
-
function TwReviewWorkspace(inputProps) {
|
|
2678
|
-
const props = {
|
|
2679
|
-
...inputProps,
|
|
2680
|
-
...inputProps.commands
|
|
2681
|
-
};
|
|
2682
|
-
const { snapshot, viewState } = props;
|
|
2683
|
-
const selectionToolbarRootRef = useRef3(null);
|
|
2684
|
-
const caps = props.capabilities;
|
|
2685
|
-
const isPageWorkspace = props.workspaceMode === "page";
|
|
2686
|
-
const markupDisplay = props.markupDisplay;
|
|
2687
|
-
const [navOpen, setNavOpen] = useState3(false);
|
|
2688
|
-
const [layoutToolsOpen, setLayoutToolsOpen] = useState3(false);
|
|
2689
|
-
const zoomLevel = props.zoomLevel ?? 100;
|
|
2690
|
-
const zoomScale = typeof zoomLevel === "number" ? zoomLevel / 100 : 1;
|
|
2691
|
-
const preserveOnlyCount = caps?.preserveOnlyCount ?? snapshot.compatibility.featureEntries.filter(
|
|
2692
|
-
(entry) => entry.featureClass === "preserve-only"
|
|
2693
|
-
).length;
|
|
2694
|
-
const blockedReasons = props.interactionGuardSnapshot?.blockedReasons ?? props.workflowScopeSnapshot?.blockedReasons ?? [];
|
|
2695
|
-
const chromeVisibility = {
|
|
2696
|
-
toolbar: true,
|
|
2697
|
-
alerts: true,
|
|
2698
|
-
selectionOverlay: true,
|
|
2699
|
-
contextToolbars: true,
|
|
2700
|
-
pageChrome: true,
|
|
2701
|
-
statusBar: true,
|
|
2702
|
-
reviewRail: true,
|
|
2703
|
-
...props.chromeVisibility
|
|
2704
|
-
};
|
|
2705
|
-
const showReviewRail = chromeVisibility.reviewRail && (caps?.reviewRailVisible ?? true);
|
|
2706
|
-
const headings = props.documentNavigation?.headings ?? [];
|
|
2707
|
-
const headerVariant = snapshot.pageLayout?.headerVariants[0]?.variant ?? "default";
|
|
2708
|
-
const footerVariant = snapshot.pageLayout?.footerVariants[0]?.variant ?? "default";
|
|
2709
|
-
const selectionPosition = viewState.selection.activeRange.kind === "node" ? viewState.selection.activeRange.at : viewState.selection.head;
|
|
2710
|
-
const activeParagraphLayout = useMemo2(
|
|
2711
|
-
() => resolveActiveParagraphLayout(snapshot.surface, selectionPosition),
|
|
2712
|
-
[selectionPosition, snapshot.surface]
|
|
2713
|
-
);
|
|
2714
|
-
const isTableContext = Boolean(
|
|
2715
|
-
props.formattingState?.breadcrumb.some((item) => item.kind === "table" || item.kind === "table_cell" || item.kind === "table_row")
|
|
2716
|
-
);
|
|
2717
|
-
const contextualSurface = props.activeImageContext ? "image" : props.activeObjectContext ? "object" : isTableContext ? "table" : null;
|
|
2718
|
-
const pageChromeModel = useMemo2(
|
|
2719
|
-
() => buildPageChromeModel(
|
|
2720
|
-
snapshot.surface,
|
|
2721
|
-
snapshot.pageLayout,
|
|
2722
|
-
props.documentNavigation,
|
|
2723
|
-
snapshot.activeStory
|
|
2724
|
-
),
|
|
2725
|
-
[props.documentNavigation, snapshot.activeStory, snapshot.pageLayout, snapshot.surface]
|
|
2726
|
-
);
|
|
2727
|
-
const selectionToolbarPlacement = resolveSelectionToolbarPlacement(
|
|
2728
|
-
props.selectionToolbarAnchor,
|
|
2729
|
-
selectionToolbarRootRef.current,
|
|
2730
|
-
zoomScale
|
|
2731
|
-
);
|
|
2732
|
-
const activePage = props.documentNavigation?.pages[props.documentNavigation.activePageIndex] ?? null;
|
|
2733
|
-
const pageShellMetrics = useMemo2(
|
|
2734
|
-
() => buildPageShellMetrics(snapshot.pageLayout),
|
|
2735
|
-
[snapshot.pageLayout]
|
|
2736
|
-
);
|
|
2737
|
-
const hidePageBorderForActiveEditing = isPageWorkspace && snapshot.activeStory.kind === "main" && shouldHidePageBorderForSelection(viewState.selection);
|
|
2738
|
-
const effectiveSelectionMode = props.interactionGuardSnapshot?.effectiveMode ?? "edit";
|
|
2739
|
-
const allowLocalChromeMutations = Boolean(caps?.canEdit) && effectiveSelectionMode === "edit";
|
|
2740
|
-
const pageChromeReadOnly = snapshot.readOnly || snapshot.activeStory.kind !== "main" || effectiveSelectionMode !== "edit";
|
|
2741
|
-
const toolbarInteractionPolicy = caps ? {
|
|
2742
|
-
mode: effectiveSelectionMode,
|
|
2743
|
-
canFormatText: caps.canEdit && effectiveSelectionMode === "edit",
|
|
2744
|
-
canInsertStructural: caps.canEdit && effectiveSelectionMode === "edit",
|
|
2745
|
-
canAddComment: caps.canAddComment && effectiveSelectionMode !== "view" && effectiveSelectionMode !== "blocked"
|
|
2746
|
-
} : void 0;
|
|
2747
|
-
useEffect3(() => {
|
|
2748
|
-
recordPerfSample("workspace.chrome");
|
|
2749
|
-
incrementInvalidationCounter("workspace.chrome.recomputes");
|
|
2750
|
-
}, [activeParagraphLayout, pageChromeModel, pageShellMetrics]);
|
|
2751
|
-
useEffect3(() => {
|
|
2752
|
-
if (isPageWorkspace && snapshot.activeStory.kind !== "main") {
|
|
2753
|
-
setLayoutToolsOpen(true);
|
|
2754
|
-
}
|
|
2755
|
-
}, [isPageWorkspace, snapshot.activeStory.kind]);
|
|
2756
|
-
const dismissSelectionToolbar = useCallback2(() => {
|
|
2757
|
-
props.onDismissSelectionToolbar?.();
|
|
2758
|
-
}, [props.onDismissSelectionToolbar]);
|
|
2759
|
-
const runWithSelectionToolbarDismiss = useCallback2(
|
|
2760
|
-
(action) => () => {
|
|
2761
|
-
dismissSelectionToolbar();
|
|
2762
|
-
action?.();
|
|
2763
|
-
},
|
|
2764
|
-
[dismissSelectionToolbar]
|
|
2765
|
-
);
|
|
2766
|
-
return /* @__PURE__ */ jsx16(Tooltip5.Provider, { delayDuration: 400, children: /* @__PURE__ */ jsxs16("div", { className: "flex h-full flex-col bg-canvas text-primary", children: [
|
|
2767
|
-
chromeVisibility.toolbar ? /* @__PURE__ */ jsx16(
|
|
2768
|
-
TwToolbar,
|
|
2769
|
-
{
|
|
2770
|
-
sourceLabel: snapshot.sourceLabel,
|
|
2771
|
-
capabilities: caps,
|
|
2772
|
-
compatibility: snapshot.compatibility,
|
|
2773
|
-
warnings: snapshot.warnings,
|
|
2774
|
-
interactionPolicy: toolbarInteractionPolicy,
|
|
2775
|
-
workspaceMode: props.workspaceMode,
|
|
2776
|
-
zoomLevel: props.zoomLevel,
|
|
2777
|
-
formattingState: props.formattingState,
|
|
2778
|
-
styleCatalog: props.styleCatalog,
|
|
2779
|
-
showTrackedChanges: props.showTrackedChanges,
|
|
2780
|
-
onUndo: runWithSelectionToolbarDismiss(props.onUndo),
|
|
2781
|
-
onRedo: runWithSelectionToolbarDismiss(props.onRedo),
|
|
2782
|
-
onSetParagraphStyle: props.onSetParagraphStyle ? (styleId) => {
|
|
2783
|
-
dismissSelectionToolbar();
|
|
2784
|
-
props.onSetParagraphStyle?.(styleId);
|
|
2785
|
-
} : void 0,
|
|
2786
|
-
onToggleBold: runWithSelectionToolbarDismiss(props.onToggleBold),
|
|
2787
|
-
onToggleItalic: runWithSelectionToolbarDismiss(props.onToggleItalic),
|
|
2788
|
-
onToggleUnderline: runWithSelectionToolbarDismiss(props.onToggleUnderline),
|
|
2789
|
-
onToggleStrikethrough: runWithSelectionToolbarDismiss(props.onToggleStrikethrough),
|
|
2790
|
-
onToggleSuperscript: runWithSelectionToolbarDismiss(props.onToggleSuperscript),
|
|
2791
|
-
onToggleSubscript: runWithSelectionToolbarDismiss(props.onToggleSubscript),
|
|
2792
|
-
onSetFontFamily: props.onSetFontFamily ? (fontFamily) => {
|
|
2793
|
-
dismissSelectionToolbar();
|
|
2794
|
-
props.onSetFontFamily?.(fontFamily);
|
|
2795
|
-
} : void 0,
|
|
2796
|
-
onSetFontSize: props.onSetFontSize ? (fontSize) => {
|
|
2797
|
-
dismissSelectionToolbar();
|
|
2798
|
-
props.onSetFontSize?.(fontSize);
|
|
2799
|
-
} : void 0,
|
|
2800
|
-
onSetTextColor: props.onSetTextColor ? (color) => {
|
|
2801
|
-
dismissSelectionToolbar();
|
|
2802
|
-
props.onSetTextColor?.(color);
|
|
2803
|
-
} : void 0,
|
|
2804
|
-
onSetHighlightColor: props.onSetHighlightColor ? (color) => {
|
|
2805
|
-
dismissSelectionToolbar();
|
|
2806
|
-
props.onSetHighlightColor?.(color);
|
|
2807
|
-
} : void 0,
|
|
2808
|
-
onSetAlignment: props.onSetAlignment ? (alignment) => {
|
|
2809
|
-
dismissSelectionToolbar();
|
|
2810
|
-
props.onSetAlignment?.(alignment);
|
|
2811
|
-
} : void 0,
|
|
2812
|
-
onOutdent: runWithSelectionToolbarDismiss(props.onOutdent),
|
|
2813
|
-
onIndent: runWithSelectionToolbarDismiss(props.onIndent),
|
|
2814
|
-
onAddComment: runWithSelectionToolbarDismiss(props.onAddComment),
|
|
2815
|
-
onInsertPageBreak: runWithSelectionToolbarDismiss(props.onInsertPageBreak),
|
|
2816
|
-
onInsertTable: runWithSelectionToolbarDismiss(props.onInsertTable),
|
|
2817
|
-
onInsertSectionBreak: props.onInsertSectionBreak ? (type) => {
|
|
2818
|
-
dismissSelectionToolbar();
|
|
2819
|
-
props.onInsertSectionBreak?.(type);
|
|
2820
|
-
} : void 0,
|
|
2821
|
-
onInsertImage: props.onInsertImage ? (options) => {
|
|
2822
|
-
dismissSelectionToolbar();
|
|
2823
|
-
props.onInsertImage?.(options);
|
|
2824
|
-
} : void 0,
|
|
2825
|
-
onExport: runWithSelectionToolbarDismiss(props.onExport),
|
|
2826
|
-
activeStory: snapshot.activeStory,
|
|
2827
|
-
onCloseStory: props.onCloseStory ? runWithSelectionToolbarDismiss(props.onCloseStory) : void 0,
|
|
2828
|
-
onWorkspaceModeChange: (value) => {
|
|
2829
|
-
dismissSelectionToolbar();
|
|
2830
|
-
props.onWorkspaceModeChange(value);
|
|
2831
|
-
},
|
|
2832
|
-
onZoomChange: props.onZoomChange ? (level) => {
|
|
2833
|
-
dismissSelectionToolbar();
|
|
2834
|
-
props.onZoomChange?.(level);
|
|
2835
|
-
} : void 0,
|
|
2836
|
-
onShowTrackedChangesChange: (show) => {
|
|
2837
|
-
dismissSelectionToolbar();
|
|
2838
|
-
props.onShowTrackedChangesChange(show);
|
|
2839
|
-
},
|
|
2840
|
-
blockedReasons
|
|
2841
|
-
}
|
|
2842
|
-
) : null,
|
|
2843
|
-
chromeVisibility.alerts ? /* @__PURE__ */ jsx16(
|
|
2844
|
-
TwAlertBanner,
|
|
2845
|
-
{
|
|
2846
|
-
snapshot,
|
|
2847
|
-
preserveOnlyCount,
|
|
2848
|
-
workflowBlockedReasons: blockedReasons
|
|
2849
|
-
}
|
|
2850
|
-
) : null,
|
|
2851
|
-
/* @__PURE__ */ jsxs16("div", { className: "flex flex-1 min-h-0", children: [
|
|
2852
|
-
isPageWorkspace && chromeVisibility.pageChrome ? /* @__PURE__ */ jsx16(
|
|
2853
|
-
"aside",
|
|
2854
|
-
{
|
|
2855
|
-
"aria-label": "Document navigator",
|
|
2856
|
-
className: `shrink-0 border-r border-border bg-surface transition-[width] duration-200 ${navOpen ? "w-48" : "w-0"} overflow-hidden`,
|
|
2857
|
-
children: navOpen ? /* @__PURE__ */ jsxs16("div", { className: "flex h-full flex-col", children: [
|
|
2858
|
-
/* @__PURE__ */ jsxs16("div", { className: "flex items-center justify-between px-3 py-2 border-b border-border", children: [
|
|
2859
|
-
/* @__PURE__ */ jsx16("span", { className: "text-xs font-medium text-secondary uppercase tracking-wider", children: "Navigator" }),
|
|
2860
|
-
/* @__PURE__ */ jsxs16(Tooltip5.Root, { children: [
|
|
2861
|
-
/* @__PURE__ */ jsx16(Tooltip5.Trigger, { asChild: true, children: /* @__PURE__ */ jsx16(
|
|
2862
|
-
"button",
|
|
2863
|
-
{
|
|
2864
|
-
type: "button",
|
|
2865
|
-
"aria-label": "Collapse navigator",
|
|
2866
|
-
onMouseDown: preserveEditorSelectionMouseDown,
|
|
2867
|
-
onClick: () => {
|
|
2868
|
-
dismissSelectionToolbar();
|
|
2869
|
-
setNavOpen(false);
|
|
2870
|
-
},
|
|
2871
|
-
className: "inline-flex h-6 w-6 items-center justify-center rounded-md text-secondary hover:bg-surface-hover transition-colors",
|
|
2872
|
-
children: /* @__PURE__ */ jsx16(ChevronLeft, { className: "h-3.5 w-3.5" })
|
|
2873
|
-
}
|
|
2874
|
-
) }),
|
|
2875
|
-
/* @__PURE__ */ jsx16(Tooltip5.Portal, { children: /* @__PURE__ */ jsx16(Tooltip5.Content, { className: "rounded-md bg-primary px-2 py-1 text-xs text-white shadow-md z-50", sideOffset: 6, children: "Collapse navigator" }) })
|
|
2876
|
-
] })
|
|
2877
|
-
] }),
|
|
2878
|
-
/* @__PURE__ */ jsx16("nav", { className: "flex-1 overflow-y-auto px-2 py-2", "aria-label": "Document headings", children: headings.length > 0 ? /* @__PURE__ */ jsx16("ul", { className: "space-y-0.5", children: headings.map((entry) => /* @__PURE__ */ jsx16("li", { children: /* @__PURE__ */ jsx16(
|
|
2879
|
-
"button",
|
|
2880
|
-
{
|
|
2881
|
-
type: "button",
|
|
2882
|
-
className: "block w-full truncate rounded-md px-2 py-1 text-left text-xs text-primary hover:bg-surface-hover",
|
|
2883
|
-
style: { paddingLeft: `${8 + (entry.level - 1) * 12}px` },
|
|
2884
|
-
onMouseDown: preserveEditorSelectionMouseDown,
|
|
2885
|
-
onClick: () => {
|
|
2886
|
-
dismissSelectionToolbar();
|
|
2887
|
-
props.onNavigateHeading?.(entry.headingId);
|
|
2888
|
-
setNavOpen(false);
|
|
2889
|
-
},
|
|
2890
|
-
children: entry.text
|
|
2891
|
-
}
|
|
2892
|
-
) }, entry.headingId)) }) : /* @__PURE__ */ jsx16("p", { className: "px-2 py-4 text-xs text-tertiary", children: "No headings found." }) })
|
|
2893
|
-
] }) : null
|
|
2894
|
-
}
|
|
2895
|
-
) : null,
|
|
2896
|
-
isPageWorkspace && chromeVisibility.pageChrome && !navOpen ? /* @__PURE__ */ jsx16("div", { className: "shrink-0 flex items-start pt-2 pl-1", children: /* @__PURE__ */ jsxs16(Tooltip5.Root, { children: [
|
|
2897
|
-
/* @__PURE__ */ jsx16(Tooltip5.Trigger, { asChild: true, children: /* @__PURE__ */ jsx16(
|
|
2898
|
-
"button",
|
|
2899
|
-
{
|
|
2900
|
-
type: "button",
|
|
2901
|
-
"aria-label": "Open document navigator",
|
|
2902
|
-
onMouseDown: preserveEditorSelectionMouseDown,
|
|
2903
|
-
onClick: () => {
|
|
2904
|
-
dismissSelectionToolbar();
|
|
2905
|
-
setNavOpen(true);
|
|
2906
|
-
},
|
|
2907
|
-
className: "inline-flex h-7 w-7 items-center justify-center rounded-md text-secondary hover:bg-surface-hover transition-colors",
|
|
2908
|
-
children: /* @__PURE__ */ jsx16(List2, { className: "h-3.5 w-3.5" })
|
|
2909
|
-
}
|
|
2910
|
-
) }),
|
|
2911
|
-
/* @__PURE__ */ jsx16(Tooltip5.Portal, { children: /* @__PURE__ */ jsx16(Tooltip5.Content, { className: "rounded-md bg-primary px-2 py-1 text-xs text-white shadow-md z-50", sideOffset: 6, children: "Open document navigator" }) })
|
|
2912
|
-
] }) }) : null,
|
|
2913
|
-
/* @__PURE__ */ jsxs16("div", { className: "flex flex-1 flex-col min-w-0", children: [
|
|
2914
|
-
/* @__PURE__ */ jsx16(
|
|
2915
|
-
"div",
|
|
2916
|
-
{
|
|
2917
|
-
className: `flex-1 overflow-y-auto ${isPageWorkspace ? "bg-surface" : "bg-canvas"}`,
|
|
2918
|
-
"data-wre-scroll-root": "true",
|
|
2919
|
-
children: /* @__PURE__ */ jsxs16(
|
|
2920
|
-
"div",
|
|
2921
|
-
{
|
|
2922
|
-
ref: selectionToolbarRootRef,
|
|
2923
|
-
className: `mx-auto min-h-full ${isPageWorkspace ? "wre-page-chrome wre-page-surface relative max-w-[840px] my-8 overflow-hidden" : "wre-canvas-surface relative bg-canvas"}`,
|
|
2924
|
-
style: isPageWorkspace && zoomScale !== 1 ? { transform: `scale(${zoomScale})`, transformOrigin: "top center" } : void 0,
|
|
2925
|
-
children: [
|
|
2926
|
-
isPageWorkspace && chromeVisibility.pageChrome && snapshot.pageLayout ? /* @__PURE__ */ jsx16("div", { className: "border-b border-border/70 bg-surface/65 px-5 py-3", "data-testid": "page-context-summary", children: /* @__PURE__ */ jsxs16("div", { className: "flex flex-wrap items-center justify-between gap-2", children: [
|
|
2927
|
-
/* @__PURE__ */ jsxs16("div", { className: "flex flex-wrap items-center gap-2 text-xs text-secondary", children: [
|
|
2928
|
-
/* @__PURE__ */ jsx16("span", { className: "rounded-full bg-canvas px-2 py-1 font-medium text-primary", children: activePage ? `Page ${activePage.pageIndex + 1} of ${props.documentNavigation?.pageCount ?? 1}` : "Page workspace" }),
|
|
2929
|
-
/* @__PURE__ */ jsx16("span", { children: `Section ${snapshot.pageLayout.sectionIndex + 1}` }),
|
|
2930
|
-
/* @__PURE__ */ jsx16("span", { className: "uppercase tracking-[0.12em] text-tertiary", children: snapshot.pageLayout.orientation })
|
|
2931
|
-
] }),
|
|
2932
|
-
/* @__PURE__ */ jsxs16("div", { className: "flex items-center gap-2", children: [
|
|
2933
|
-
snapshot.activeStory.kind !== "main" ? /* @__PURE__ */ jsx16(
|
|
2934
|
-
"button",
|
|
2935
|
-
{
|
|
2936
|
-
type: "button",
|
|
2937
|
-
"aria-label": "Return to document body",
|
|
2938
|
-
onMouseDown: preserveEditorSelectionMouseDown,
|
|
2939
|
-
onClick: runWithSelectionToolbarDismiss(props.onCloseStory),
|
|
2940
|
-
className: "inline-flex items-center gap-1 rounded-md border border-border bg-canvas px-2 py-1 text-xs font-medium text-primary transition-colors hover:bg-surface",
|
|
2941
|
-
children: "Body"
|
|
2942
|
-
}
|
|
2943
|
-
) : null,
|
|
2944
|
-
snapshot.activeStory.kind === "main" && snapshot.pageLayout.sectionIndex > 0 ? /* @__PURE__ */ jsxs16(Fragment8, { children: [
|
|
2945
|
-
/* @__PURE__ */ jsx16(
|
|
2946
|
-
"button",
|
|
2947
|
-
{
|
|
2948
|
-
type: "button",
|
|
2949
|
-
"aria-label": "Link header to previous",
|
|
2950
|
-
disabled: !props.onSetHeaderFooterLink || !allowLocalChromeMutations,
|
|
2951
|
-
onMouseDown: preserveEditorSelectionMouseDown,
|
|
2952
|
-
onClick: () => {
|
|
2953
|
-
dismissSelectionToolbar();
|
|
2954
|
-
props.onSetHeaderFooterLink?.(snapshot.pageLayout.sectionIndex, {
|
|
2955
|
-
kind: "header",
|
|
2956
|
-
variant: headerVariant,
|
|
2957
|
-
linkToPrevious: true
|
|
2958
|
-
});
|
|
2959
|
-
},
|
|
2960
|
-
className: "inline-flex items-center gap-1 rounded-md border border-border bg-canvas px-2 py-1 text-xs font-medium text-primary transition-colors hover:bg-surface disabled:cursor-not-allowed disabled:opacity-40",
|
|
2961
|
-
children: "Link header"
|
|
2962
|
-
}
|
|
2963
|
-
),
|
|
2964
|
-
/* @__PURE__ */ jsx16(
|
|
2965
|
-
"button",
|
|
2966
|
-
{
|
|
2967
|
-
type: "button",
|
|
2968
|
-
"aria-label": "Link footer to previous",
|
|
2969
|
-
disabled: !props.onSetHeaderFooterLink || !allowLocalChromeMutations,
|
|
2970
|
-
onMouseDown: preserveEditorSelectionMouseDown,
|
|
2971
|
-
onClick: () => {
|
|
2972
|
-
dismissSelectionToolbar();
|
|
2973
|
-
props.onSetHeaderFooterLink?.(snapshot.pageLayout.sectionIndex, {
|
|
2974
|
-
kind: "footer",
|
|
2975
|
-
variant: footerVariant,
|
|
2976
|
-
linkToPrevious: true
|
|
2977
|
-
});
|
|
2978
|
-
},
|
|
2979
|
-
className: "inline-flex items-center gap-1 rounded-md border border-border bg-canvas px-2 py-1 text-xs font-medium text-primary transition-colors hover:bg-surface disabled:cursor-not-allowed disabled:opacity-40",
|
|
2980
|
-
children: "Link footer"
|
|
2981
|
-
}
|
|
2982
|
-
)
|
|
2983
|
-
] }) : null,
|
|
2984
|
-
/* @__PURE__ */ jsxs16(
|
|
2985
|
-
"button",
|
|
2986
|
-
{
|
|
2987
|
-
type: "button",
|
|
2988
|
-
"aria-label": "Toggle layout tools",
|
|
2989
|
-
"aria-expanded": layoutToolsOpen,
|
|
2990
|
-
onMouseDown: preserveEditorSelectionMouseDown,
|
|
2991
|
-
onClick: () => {
|
|
2992
|
-
dismissSelectionToolbar();
|
|
2993
|
-
setLayoutToolsOpen((open) => !open);
|
|
2994
|
-
},
|
|
2995
|
-
className: "inline-flex items-center gap-1 rounded-md border border-border bg-canvas px-2 py-1 text-xs font-medium text-primary transition-colors hover:bg-surface",
|
|
2996
|
-
children: [
|
|
2997
|
-
/* @__PURE__ */ jsx16(ChevronRight, { className: `h-3.5 w-3.5 transition-transform ${layoutToolsOpen ? "rotate-90" : ""}` }),
|
|
2998
|
-
"Layout tools"
|
|
2999
|
-
]
|
|
3000
|
-
}
|
|
3001
|
-
)
|
|
3002
|
-
] })
|
|
3003
|
-
] }) }) : null,
|
|
3004
|
-
isPageWorkspace && chromeVisibility.pageChrome && snapshot.pageLayout && layoutToolsOpen ? /* @__PURE__ */ jsxs16("div", { className: "px-5 pt-3", children: [
|
|
3005
|
-
/* @__PURE__ */ jsx16(
|
|
3006
|
-
TwPageRuler,
|
|
3007
|
-
{
|
|
3008
|
-
pageLayout: snapshot.pageLayout,
|
|
3009
|
-
viewState,
|
|
3010
|
-
paragraphLayout: activeParagraphLayout,
|
|
3011
|
-
readOnly: pageChromeReadOnly,
|
|
3012
|
-
onReturnToBody: props.onCloseStory ? runWithSelectionToolbarDismiss(props.onCloseStory) : () => void 0,
|
|
3013
|
-
onOpenHeader: props.onOpenHeaderStory ? runWithSelectionToolbarDismiss(props.onOpenHeaderStory) : void 0,
|
|
3014
|
-
onOpenFooter: props.onOpenFooterStory ? runWithSelectionToolbarDismiss(props.onOpenFooterStory) : void 0,
|
|
3015
|
-
onSetIndentation: props.onSetParagraphIndentation ? (indentation) => {
|
|
3016
|
-
dismissSelectionToolbar();
|
|
3017
|
-
props.onSetParagraphIndentation?.(indentation);
|
|
3018
|
-
} : void 0,
|
|
3019
|
-
onSetTabStops: props.onSetParagraphTabStops ? (tabStops) => {
|
|
3020
|
-
dismissSelectionToolbar();
|
|
3021
|
-
props.onSetParagraphTabStops?.(tabStops);
|
|
3022
|
-
} : void 0,
|
|
3023
|
-
onRestartNumbering: props.onRestartNumbering ? runWithSelectionToolbarDismiss(props.onRestartNumbering) : void 0,
|
|
3024
|
-
onContinueNumbering: props.onContinueNumbering ? runWithSelectionToolbarDismiss(props.onContinueNumbering) : void 0
|
|
3025
|
-
}
|
|
3026
|
-
),
|
|
3027
|
-
/* @__PURE__ */ jsx16(
|
|
3028
|
-
TwLayoutPanel,
|
|
3029
|
-
{
|
|
3030
|
-
pageLayout: snapshot.pageLayout,
|
|
3031
|
-
readOnly: pageChromeReadOnly,
|
|
3032
|
-
onInsertSectionBreak: props.onInsertSectionBreak ? (type) => {
|
|
3033
|
-
dismissSelectionToolbar();
|
|
3034
|
-
props.onInsertSectionBreak?.(type);
|
|
3035
|
-
} : void 0,
|
|
3036
|
-
onDeleteSectionBreak: props.onDeleteSectionBreak ? (sectionIndex) => {
|
|
3037
|
-
dismissSelectionToolbar();
|
|
3038
|
-
props.onDeleteSectionBreak?.(sectionIndex);
|
|
3039
|
-
} : void 0,
|
|
3040
|
-
onUpdateSectionLayout: props.onUpdateSectionLayout ? (sectionIndex, patch) => {
|
|
3041
|
-
dismissSelectionToolbar();
|
|
3042
|
-
props.onUpdateSectionLayout?.(sectionIndex, patch);
|
|
3043
|
-
} : void 0,
|
|
3044
|
-
onSetSectionPageNumbering: props.onSetSectionPageNumbering ? (sectionIndex, patch) => {
|
|
3045
|
-
dismissSelectionToolbar();
|
|
3046
|
-
props.onSetSectionPageNumbering?.(sectionIndex, patch);
|
|
3047
|
-
} : void 0
|
|
3048
|
-
}
|
|
3049
|
-
)
|
|
3050
|
-
] }) : null,
|
|
3051
|
-
chromeVisibility.contextToolbars && contextualSurface ? /* @__PURE__ */ jsxs16("div", { className: "px-5 pt-3 space-y-3", children: [
|
|
3052
|
-
contextualSurface === "table" ? /* @__PURE__ */ jsx16(
|
|
3053
|
-
TwTableContextToolbar,
|
|
3054
|
-
{
|
|
3055
|
-
disabled: !allowLocalChromeMutations,
|
|
3056
|
-
tableStyles: props.styleCatalog?.tables ?? [],
|
|
3057
|
-
onSetTableStyle: props.onSetTableStyle ? (styleId) => {
|
|
3058
|
-
dismissSelectionToolbar();
|
|
3059
|
-
props.onSetTableStyle?.(styleId);
|
|
3060
|
-
} : void 0,
|
|
3061
|
-
onAddRowBefore: runWithSelectionToolbarDismiss(props.onAddRowBefore),
|
|
3062
|
-
onAddRowAfter: runWithSelectionToolbarDismiss(props.onAddRowAfter),
|
|
3063
|
-
onAddColumnBefore: runWithSelectionToolbarDismiss(props.onAddColumnBefore),
|
|
3064
|
-
onAddColumnAfter: runWithSelectionToolbarDismiss(props.onAddColumnAfter),
|
|
3065
|
-
onDeleteRow: runWithSelectionToolbarDismiss(props.onDeleteRow),
|
|
3066
|
-
onDeleteColumn: runWithSelectionToolbarDismiss(props.onDeleteColumn),
|
|
3067
|
-
onDeleteTable: runWithSelectionToolbarDismiss(props.onDeleteTable),
|
|
3068
|
-
onMergeCells: runWithSelectionToolbarDismiss(props.onMergeCells),
|
|
3069
|
-
onSplitCell: runWithSelectionToolbarDismiss(props.onSplitCell),
|
|
3070
|
-
onSetCellBackground: props.onSetCellBackground ? (color) => {
|
|
3071
|
-
dismissSelectionToolbar();
|
|
3072
|
-
props.onSetCellBackground?.(color);
|
|
3073
|
-
} : void 0
|
|
3074
|
-
}
|
|
3075
|
-
) : null,
|
|
3076
|
-
contextualSurface === "image" && props.activeImageContext ? /* @__PURE__ */ jsx16(
|
|
3077
|
-
TwImageContextToolbar,
|
|
3078
|
-
{
|
|
3079
|
-
activeImage: props.activeImageContext,
|
|
3080
|
-
disabled: !allowLocalChromeMutations,
|
|
3081
|
-
onSetImageLayout: props.onSetImageLayout ? (mediaId, dimensions) => {
|
|
3082
|
-
dismissSelectionToolbar();
|
|
3083
|
-
props.onSetImageLayout?.(mediaId, dimensions);
|
|
3084
|
-
} : void 0,
|
|
3085
|
-
onSetImageFrame: props.onSetImageFrame ? (mediaId, offsets) => {
|
|
3086
|
-
dismissSelectionToolbar();
|
|
3087
|
-
props.onSetImageFrame?.(mediaId, offsets);
|
|
3088
|
-
} : void 0
|
|
3089
|
-
}
|
|
3090
|
-
) : null,
|
|
3091
|
-
contextualSurface === "object" && props.activeObjectContext ? /* @__PURE__ */ jsx16(TwObjectContextToolbar, { activeObject: props.activeObjectContext }) : null
|
|
3092
|
-
] }) : null,
|
|
3093
|
-
chromeVisibility.selectionOverlay && props.suggestionCard && selectionToolbarPlacement ? /* @__PURE__ */ jsx16("div", { className: "pointer-events-none absolute inset-0 z-20", "data-testid": "suggestion-card-overlay", children: /* @__PURE__ */ jsx16(
|
|
3094
|
-
"div",
|
|
3095
|
-
{
|
|
3096
|
-
className: "pointer-events-auto absolute",
|
|
3097
|
-
"data-placement": selectionToolbarPlacement.placement,
|
|
3098
|
-
style: selectionToolbarPlacement.style,
|
|
3099
|
-
children: /* @__PURE__ */ jsx16(
|
|
3100
|
-
TwSuggestionCard,
|
|
3101
|
-
{
|
|
3102
|
-
model: props.suggestionCard,
|
|
3103
|
-
onFocusCapture: props.onSelectionToolbarFocusCapture,
|
|
3104
|
-
onBlurCapture: props.onSelectionToolbarBlurCapture,
|
|
3105
|
-
onAccept: props.onAcceptSuggestion,
|
|
3106
|
-
onReject: props.onRejectSuggestion,
|
|
3107
|
-
onEditSuggestion: props.onEditSuggestion,
|
|
3108
|
-
onAddComment: props.onAddCommentFromSuggestion ?? props.onAddComment
|
|
3109
|
-
}
|
|
3110
|
-
)
|
|
3111
|
-
}
|
|
3112
|
-
) }) : null,
|
|
3113
|
-
chromeVisibility.selectionOverlay && props.suggestionCard && !selectionToolbarPlacement ? /* @__PURE__ */ jsx16(
|
|
3114
|
-
"div",
|
|
3115
|
-
{
|
|
3116
|
-
className: "pointer-events-none absolute inset-x-0 top-0 z-20 flex justify-center px-4 pt-3",
|
|
3117
|
-
"data-testid": "suggestion-card-fallback",
|
|
3118
|
-
children: /* @__PURE__ */ jsx16("div", { className: "pointer-events-auto", "data-placement": "fallback", children: /* @__PURE__ */ jsx16(
|
|
3119
|
-
TwSuggestionCard,
|
|
3120
|
-
{
|
|
3121
|
-
model: props.suggestionCard,
|
|
3122
|
-
onFocusCapture: props.onSelectionToolbarFocusCapture,
|
|
3123
|
-
onBlurCapture: props.onSelectionToolbarBlurCapture,
|
|
3124
|
-
onAccept: props.onAcceptSuggestion,
|
|
3125
|
-
onReject: props.onRejectSuggestion,
|
|
3126
|
-
onEditSuggestion: props.onEditSuggestion,
|
|
3127
|
-
onAddComment: props.onAddCommentFromSuggestion ?? props.onAddComment
|
|
3128
|
-
}
|
|
3129
|
-
) })
|
|
3130
|
-
}
|
|
3131
|
-
) : null,
|
|
3132
|
-
chromeVisibility.selectionOverlay && props.selectionToolbar && !props.suggestionCard && selectionToolbarPlacement ? /* @__PURE__ */ jsx16("div", { className: "pointer-events-none absolute inset-0 z-20", "data-testid": "selection-toolbar-overlay", children: /* @__PURE__ */ jsx16(
|
|
3133
|
-
"div",
|
|
3134
|
-
{
|
|
3135
|
-
className: "pointer-events-auto absolute",
|
|
3136
|
-
"data-placement": selectionToolbarPlacement.placement,
|
|
3137
|
-
style: selectionToolbarPlacement.style,
|
|
3138
|
-
children: /* @__PURE__ */ jsx16(
|
|
3139
|
-
TwSelectionToolbar,
|
|
3140
|
-
{
|
|
3141
|
-
ref: props.selectionToolbarRef,
|
|
3142
|
-
model: props.selectionToolbar,
|
|
3143
|
-
disabledReason: props.selectionToolbar.disabledReason,
|
|
3144
|
-
onFocusCapture: props.onSelectionToolbarFocusCapture,
|
|
3145
|
-
onBlurCapture: props.onSelectionToolbarBlurCapture,
|
|
3146
|
-
onToggleBold: props.onToggleBold,
|
|
3147
|
-
onToggleItalic: props.onToggleItalic,
|
|
3148
|
-
onToggleUnderline: props.onToggleUnderline,
|
|
3149
|
-
onSetTextColor: props.onSetSelectionTextColor,
|
|
3150
|
-
onSetHighlightColor: props.onSetSelectionHighlightColor,
|
|
3151
|
-
onAddComment: props.onAddCommentFromSelection ?? props.onAddComment
|
|
3152
|
-
}
|
|
3153
|
-
)
|
|
3154
|
-
}
|
|
3155
|
-
) }) : null,
|
|
3156
|
-
chromeVisibility.selectionOverlay && props.selectionToolbar && !props.suggestionCard && !selectionToolbarPlacement ? /* @__PURE__ */ jsx16(
|
|
3157
|
-
"div",
|
|
3158
|
-
{
|
|
3159
|
-
className: "pointer-events-none absolute inset-x-0 top-0 z-20 flex justify-center px-4 pt-3",
|
|
3160
|
-
"data-testid": "selection-toolbar-fallback",
|
|
3161
|
-
children: /* @__PURE__ */ jsx16("div", { className: "pointer-events-auto", "data-placement": "fallback", children: /* @__PURE__ */ jsx16(
|
|
3162
|
-
TwSelectionToolbar,
|
|
3163
|
-
{
|
|
3164
|
-
ref: props.selectionToolbarRef,
|
|
3165
|
-
model: props.selectionToolbar,
|
|
3166
|
-
disabledReason: props.selectionToolbar.disabledReason,
|
|
3167
|
-
onFocusCapture: props.onSelectionToolbarFocusCapture,
|
|
3168
|
-
onBlurCapture: props.onSelectionToolbarBlurCapture,
|
|
3169
|
-
onToggleBold: props.onToggleBold,
|
|
3170
|
-
onToggleItalic: props.onToggleItalic,
|
|
3171
|
-
onToggleUnderline: props.onToggleUnderline,
|
|
3172
|
-
onSetTextColor: props.onSetSelectionTextColor,
|
|
3173
|
-
onSetHighlightColor: props.onSetSelectionHighlightColor,
|
|
3174
|
-
onAddComment: props.onAddCommentFromSelection ?? props.onAddComment
|
|
3175
|
-
}
|
|
3176
|
-
) })
|
|
3177
|
-
}
|
|
3178
|
-
) : null,
|
|
3179
|
-
/* @__PURE__ */ jsxs16(
|
|
3180
|
-
"div",
|
|
3181
|
-
{
|
|
3182
|
-
className: isPageWorkspace ? "relative" : void 0,
|
|
3183
|
-
"data-line-numbering": pageChromeModel.lineNumberingEnabled ? "enabled" : "disabled",
|
|
3184
|
-
children: [
|
|
3185
|
-
isPageWorkspace && chromeVisibility.pageChrome && pageChromeModel.lineNumberingEnabled ? /* @__PURE__ */ jsx16(
|
|
3186
|
-
"div",
|
|
3187
|
-
{
|
|
3188
|
-
"aria-hidden": "true",
|
|
3189
|
-
className: "pointer-events-none absolute inset-y-0 left-0 z-10",
|
|
3190
|
-
"data-testid": "page-line-number-gutter",
|
|
3191
|
-
style: { width: `${pageChromeModel.gutterWidthPx}px` },
|
|
3192
|
-
children: pageChromeModel.lineMarkers.map((marker) => /* @__PURE__ */ jsx16(
|
|
3193
|
-
"span",
|
|
3194
|
-
{
|
|
3195
|
-
className: "absolute right-2 font-[family-name:var(--font-legal-sans)] text-[10px] font-medium tabular-nums tracking-[0.12em] text-tertiary/80",
|
|
3196
|
-
style: { top: `${marker.topPx}px` },
|
|
3197
|
-
children: marker.label
|
|
3198
|
-
},
|
|
3199
|
-
marker.id
|
|
3200
|
-
))
|
|
3201
|
-
}
|
|
3202
|
-
) : null,
|
|
3203
|
-
/* @__PURE__ */ jsx16(
|
|
3204
|
-
"div",
|
|
3205
|
-
{
|
|
3206
|
-
className: isPageWorkspace && chromeVisibility.pageChrome && pageChromeModel.lineNumberingEnabled ? "pl-12" : void 0,
|
|
3207
|
-
style: isPageWorkspace ? pageShellMetrics.contentInsetStyle : void 0,
|
|
3208
|
-
children: /* @__PURE__ */ jsxs16(
|
|
3209
|
-
"div",
|
|
3210
|
-
{
|
|
3211
|
-
className: isPageWorkspace ? "relative" : void 0,
|
|
3212
|
-
"data-document-grid": pageChromeModel.documentGridType,
|
|
3213
|
-
"data-page-border-display": pageChromeModel.pageBorderDisplay,
|
|
3214
|
-
style: isPageWorkspace ? {
|
|
3215
|
-
...pageChromeModel.documentGridStyle,
|
|
3216
|
-
...pageShellMetrics.pageFrameStyle
|
|
3217
|
-
} : pageChromeModel.documentGridStyle,
|
|
3218
|
-
children: [
|
|
3219
|
-
isPageWorkspace && chromeVisibility.pageChrome ? /* @__PURE__ */ jsxs16(
|
|
3220
|
-
"div",
|
|
3221
|
-
{
|
|
3222
|
-
"data-testid": "page-header-band",
|
|
3223
|
-
className: "relative z-10 flex items-center justify-between border-b border-dashed border-border/60 px-4 text-[11px] text-secondary",
|
|
3224
|
-
style: pageShellMetrics.headerBandStyle,
|
|
3225
|
-
children: [
|
|
3226
|
-
/* @__PURE__ */ jsx16("span", { className: "uppercase tracking-[0.12em] text-tertiary", children: "Header" }),
|
|
3227
|
-
snapshot.pageLayout?.headerVariants[0] ? /* @__PURE__ */ jsx16(
|
|
3228
|
-
"button",
|
|
3229
|
-
{
|
|
3230
|
-
type: "button",
|
|
3231
|
-
"aria-label": "Open header story",
|
|
3232
|
-
onClick: props.onOpenHeaderStory,
|
|
3233
|
-
className: "rounded-md px-2 py-1 text-xs font-medium text-primary transition-colors hover:bg-surface",
|
|
3234
|
-
children: "Edit header"
|
|
3235
|
-
}
|
|
3236
|
-
) : null
|
|
3237
|
-
]
|
|
3238
|
-
}
|
|
3239
|
-
) : null,
|
|
3240
|
-
isPageWorkspace && chromeVisibility.pageChrome && pageChromeModel.showPageBorder && !hidePageBorderForActiveEditing ? /* @__PURE__ */ jsx16(
|
|
3241
|
-
"div",
|
|
3242
|
-
{
|
|
3243
|
-
"aria-hidden": "true",
|
|
3244
|
-
className: "pointer-events-none absolute inset-0 z-0 rounded-[2px]",
|
|
3245
|
-
"data-testid": "page-border-overlay",
|
|
3246
|
-
style: pageChromeModel.pageBorderStyle
|
|
3247
|
-
}
|
|
3248
|
-
) : null,
|
|
3249
|
-
/* @__PURE__ */ jsx16("div", { className: isPageWorkspace ? "relative z-10" : void 0, children: props.document }),
|
|
3250
|
-
isPageWorkspace && chromeVisibility.pageChrome ? /* @__PURE__ */ jsxs16(
|
|
3251
|
-
"div",
|
|
3252
|
-
{
|
|
3253
|
-
"data-testid": "page-footer-band",
|
|
3254
|
-
className: "relative z-10 flex items-center justify-between border-t border-dashed border-border/60 px-4 text-[11px] text-secondary",
|
|
3255
|
-
style: pageShellMetrics.footerBandStyle,
|
|
3256
|
-
children: [
|
|
3257
|
-
/* @__PURE__ */ jsx16("span", { className: "uppercase tracking-[0.12em] text-tertiary", children: "Footer" }),
|
|
3258
|
-
snapshot.pageLayout?.footerVariants[0] ? /* @__PURE__ */ jsx16(
|
|
3259
|
-
"button",
|
|
3260
|
-
{
|
|
3261
|
-
type: "button",
|
|
3262
|
-
"aria-label": "Open footer story",
|
|
3263
|
-
onClick: props.onOpenFooterStory,
|
|
3264
|
-
className: "rounded-md px-2 py-1 text-xs font-medium text-primary transition-colors hover:bg-surface",
|
|
3265
|
-
children: "Edit footer"
|
|
3266
|
-
}
|
|
3267
|
-
) : null
|
|
3268
|
-
]
|
|
3269
|
-
}
|
|
3270
|
-
) : null
|
|
3271
|
-
]
|
|
3272
|
-
}
|
|
3273
|
-
)
|
|
3274
|
-
}
|
|
3275
|
-
)
|
|
3276
|
-
]
|
|
3277
|
-
}
|
|
3278
|
-
)
|
|
3279
|
-
]
|
|
3280
|
-
}
|
|
3281
|
-
)
|
|
3282
|
-
}
|
|
3283
|
-
),
|
|
3284
|
-
chromeVisibility.statusBar ? /* @__PURE__ */ jsx16(
|
|
3285
|
-
TwStatusBar,
|
|
3286
|
-
{
|
|
3287
|
-
isDirty: snapshot.isDirty,
|
|
3288
|
-
isExportBlocked: snapshot.compatibility.blockExport,
|
|
3289
|
-
preserveOnlyCount,
|
|
3290
|
-
commentCount: snapshot.comments.totalCount,
|
|
3291
|
-
changeCount: snapshot.trackedChanges.totalCount,
|
|
3292
|
-
sessionId: snapshot.sessionId
|
|
3293
|
-
}
|
|
3294
|
-
) : null
|
|
3295
|
-
] }),
|
|
3296
|
-
showReviewRail ? /* @__PURE__ */ jsx16(
|
|
3297
|
-
TwReviewRail,
|
|
3298
|
-
{
|
|
3299
|
-
activeTab: props.activeRailTab,
|
|
3300
|
-
currentUserId: props.currentUserId,
|
|
3301
|
-
comments: snapshot.comments,
|
|
3302
|
-
trackedChanges: snapshot.trackedChanges,
|
|
3303
|
-
compatibility: snapshot.compatibility,
|
|
3304
|
-
warnings: snapshot.warnings,
|
|
3305
|
-
markupDisplay,
|
|
3306
|
-
activeCommentId: props.activeCommentId,
|
|
3307
|
-
activeRevisionId: props.activeRevisionId,
|
|
3308
|
-
onActiveTabChange: props.onActiveRailTabChange,
|
|
3309
|
-
onOpenComment: props.onOpenComment,
|
|
3310
|
-
onResolveComment: props.onResolveComment,
|
|
3311
|
-
onReopenComment: props.onReopenComment,
|
|
3312
|
-
onAddReply: props.onAddReply,
|
|
3313
|
-
onEditBody: props.onEditBody,
|
|
3314
|
-
onOpenRevision: props.onOpenRevision,
|
|
3315
|
-
onAcceptRevision: props.onAcceptRevision,
|
|
3316
|
-
onRejectRevision: props.onRejectRevision,
|
|
3317
|
-
onAcceptAllChanges: props.onAcceptAllChanges,
|
|
3318
|
-
onRejectAllChanges: props.onRejectAllChanges
|
|
3319
|
-
}
|
|
3320
|
-
) : null
|
|
3321
|
-
] })
|
|
3322
|
-
] }) });
|
|
3323
|
-
}
|
|
3324
|
-
function shouldHidePageBorderForSelection(selection) {
|
|
3325
|
-
if (selection.isCollapsed) {
|
|
3326
|
-
return false;
|
|
3327
|
-
}
|
|
3328
|
-
return selection.activeRange.kind === "range";
|
|
3329
|
-
}
|
|
3330
|
-
function resolveActiveParagraphLayout(surface, position) {
|
|
3331
|
-
const paragraph = surface ? findActiveParagraph(surface.blocks, position) : null;
|
|
3332
|
-
if (!paragraph) {
|
|
3333
|
-
return null;
|
|
3334
|
-
}
|
|
3335
|
-
return {
|
|
3336
|
-
leftIndent: paragraph.indentation?.left ?? 0,
|
|
3337
|
-
rightIndent: paragraph.indentation?.right ?? 0,
|
|
3338
|
-
firstLineOffset: paragraph.indentation?.firstLine ?? (paragraph.indentation?.hanging ? -paragraph.indentation.hanging : 0),
|
|
3339
|
-
tabStops: paragraph.tabStops ? [...paragraph.tabStops] : []
|
|
3340
|
-
};
|
|
3341
|
-
}
|
|
3342
|
-
function findActiveParagraph(blocks, position) {
|
|
3343
|
-
for (const block of blocks) {
|
|
3344
|
-
if (block.kind === "paragraph" && position >= block.from && position <= block.to) {
|
|
3345
|
-
return block;
|
|
3346
|
-
}
|
|
3347
|
-
if (block.kind === "table") {
|
|
3348
|
-
for (const row of block.rows) {
|
|
3349
|
-
for (const cell of row.cells) {
|
|
3350
|
-
const paragraph = findActiveParagraph(cell.content, position);
|
|
3351
|
-
if (paragraph) {
|
|
3352
|
-
return paragraph;
|
|
3353
|
-
}
|
|
3354
|
-
}
|
|
3355
|
-
}
|
|
3356
|
-
}
|
|
3357
|
-
if (block.kind === "sdt_block") {
|
|
3358
|
-
const paragraph = findActiveParagraph(block.children, position);
|
|
3359
|
-
if (paragraph) {
|
|
3360
|
-
return paragraph;
|
|
3361
|
-
}
|
|
3362
|
-
}
|
|
3363
|
-
}
|
|
3364
|
-
return null;
|
|
3365
|
-
}
|
|
3366
|
-
var EMPTY_PAGE_CHROME_MODEL = {
|
|
3367
|
-
lineNumberingEnabled: false,
|
|
3368
|
-
gutterWidthPx: 0,
|
|
3369
|
-
lineMarkers: [],
|
|
3370
|
-
showPageBorder: false,
|
|
3371
|
-
pageBorderDisplay: "none",
|
|
3372
|
-
pageBorderStyle: void 0,
|
|
3373
|
-
documentGridType: "none",
|
|
3374
|
-
documentGridStyle: void 0
|
|
3375
|
-
};
|
|
3376
|
-
var DOCUMENT_CONTENT_TOP_PADDING_PX = 40;
|
|
3377
|
-
function buildPageChromeModel(surface, pageLayout, navigation, activeStory) {
|
|
3378
|
-
if (!surface || !pageLayout || !navigation || activeStory.kind !== "main") {
|
|
3379
|
-
return EMPTY_PAGE_CHROME_MODEL;
|
|
3380
|
-
}
|
|
3381
|
-
const lineMarkers = computeLineMarkersIfEnabled({
|
|
3382
|
-
pageLayout,
|
|
3383
|
-
surfaceBlocks: surface.blocks,
|
|
3384
|
-
pages: navigation.pages,
|
|
3385
|
-
buildLineNumberMarkers
|
|
3386
|
-
});
|
|
3387
|
-
const lineNumberingEnabled = Boolean(pageLayout.lineNumbering) && lineMarkers.length > 0;
|
|
3388
|
-
const distance = pageLayout.lineNumbering?.distance ?? 0;
|
|
3389
|
-
const gutterWidthPx = lineNumberingEnabled ? Math.max(40, Math.min(88, 24 + Math.round(distance * DEFAULT_PAGE_ESTIMATE_PX_PER_TWIP))) : 0;
|
|
3390
|
-
const showPageBorder = shouldRenderPageBorder(pageLayout, navigation.pages, navigation.activePageIndex);
|
|
3391
|
-
return {
|
|
3392
|
-
lineNumberingEnabled,
|
|
3393
|
-
gutterWidthPx,
|
|
3394
|
-
lineMarkers,
|
|
3395
|
-
showPageBorder,
|
|
3396
|
-
pageBorderDisplay: pageLayout.pageBorders?.display ?? "none",
|
|
3397
|
-
pageBorderStyle: showPageBorder ? buildPageBorderStyle(pageLayout) : void 0,
|
|
3398
|
-
documentGridType: pageLayout.documentGrid?.type ?? "none",
|
|
3399
|
-
documentGridStyle: buildDocumentGridStyle(pageLayout.documentGrid)
|
|
3400
|
-
};
|
|
3401
|
-
}
|
|
3402
|
-
function buildPageShellMetrics(pageLayout) {
|
|
3403
|
-
if (!pageLayout) {
|
|
3404
|
-
return {
|
|
3405
|
-
contentInsetStyle: {},
|
|
3406
|
-
pageFrameStyle: {},
|
|
3407
|
-
headerBandStyle: {},
|
|
3408
|
-
footerBandStyle: {}
|
|
3409
|
-
};
|
|
3410
|
-
}
|
|
3411
|
-
const horizontalInsetPx = Math.max(
|
|
3412
|
-
24,
|
|
3413
|
-
Math.min(120, Math.round(pageLayout.marginLeft * DEFAULT_PAGE_ESTIMATE_PX_PER_TWIP))
|
|
3414
|
-
);
|
|
3415
|
-
const verticalInsetPx = Math.max(
|
|
3416
|
-
24,
|
|
3417
|
-
Math.min(140, Math.round(pageLayout.marginTop * DEFAULT_PAGE_ESTIMATE_PX_PER_TWIP))
|
|
3418
|
-
);
|
|
3419
|
-
const headerBandHeightPx = Math.max(
|
|
3420
|
-
40,
|
|
3421
|
-
Math.min(96, Math.round(pageLayout.headerMargin * DEFAULT_PAGE_ESTIMATE_PX_PER_TWIP + 16))
|
|
3422
|
-
);
|
|
3423
|
-
const footerBandHeightPx = Math.max(
|
|
3424
|
-
40,
|
|
3425
|
-
Math.min(96, Math.round(pageLayout.footerMargin * DEFAULT_PAGE_ESTIMATE_PX_PER_TWIP + 16))
|
|
3426
|
-
);
|
|
3427
|
-
return {
|
|
3428
|
-
contentInsetStyle: {
|
|
3429
|
-
paddingLeft: `${horizontalInsetPx}px`,
|
|
3430
|
-
paddingRight: `${horizontalInsetPx}px`,
|
|
3431
|
-
paddingTop: `${Math.max(20, verticalInsetPx - 12)}px`,
|
|
3432
|
-
paddingBottom: `${Math.max(20, Math.round(pageLayout.marginBottom * DEFAULT_PAGE_ESTIMATE_PX_PER_TWIP) - 12)}px`
|
|
3433
|
-
},
|
|
3434
|
-
pageFrameStyle: {
|
|
3435
|
-
backgroundColor: "var(--color-page-bg)"
|
|
3436
|
-
},
|
|
3437
|
-
headerBandStyle: {
|
|
3438
|
-
minHeight: `${headerBandHeightPx}px`
|
|
3439
|
-
},
|
|
3440
|
-
footerBandStyle: {
|
|
3441
|
-
minHeight: `${footerBandHeightPx}px`
|
|
3442
|
-
}
|
|
3443
|
-
};
|
|
3444
|
-
}
|
|
3445
|
-
function buildLineNumberMarkers(blocks, pages) {
|
|
3446
|
-
const markers = [];
|
|
3447
|
-
if (pages.length === 0) {
|
|
3448
|
-
return markers;
|
|
3449
|
-
}
|
|
3450
|
-
let currentTopTwips = 0;
|
|
3451
|
-
let lineNumber = 1;
|
|
3452
|
-
let lastPageIndex = -1;
|
|
3453
|
-
let lastSectionIndex = -1;
|
|
3454
|
-
for (const block of blocks) {
|
|
3455
|
-
const pageIndex = findPageForOffset(pages, block.from);
|
|
3456
|
-
const page = pages[pageIndex];
|
|
3457
|
-
if (!page) {
|
|
3458
|
-
continue;
|
|
3459
|
-
}
|
|
3460
|
-
const lineNumbering = page.layout.lineNumbering;
|
|
3461
|
-
const restartMode = lineNumbering?.restart ?? "newPage";
|
|
3462
|
-
const restartStart = lineNumbering?.start ?? 1;
|
|
3463
|
-
const countBy = Math.max(1, lineNumbering?.countBy ?? 1);
|
|
3464
|
-
const columnWidth = getUsableColumnWidth(page.layout);
|
|
3465
|
-
if (pageIndex !== lastPageIndex) {
|
|
3466
|
-
if (restartMode === "newPage" || lastPageIndex === -1) {
|
|
3467
|
-
lineNumber = restartStart;
|
|
3468
|
-
}
|
|
3469
|
-
lastPageIndex = pageIndex;
|
|
3470
|
-
}
|
|
3471
|
-
if (page.sectionIndex !== lastSectionIndex) {
|
|
3472
|
-
if (restartMode === "newSection" || lastSectionIndex === -1) {
|
|
3473
|
-
lineNumber = restartStart;
|
|
3474
|
-
}
|
|
3475
|
-
lastSectionIndex = page.sectionIndex;
|
|
3476
|
-
}
|
|
3477
|
-
if (block.kind === "paragraph" && lineNumbering) {
|
|
3478
|
-
const lineCount = estimateParagraphLineCount(block, columnWidth);
|
|
3479
|
-
const lineHeight = estimateParagraphLineHeight(block);
|
|
3480
|
-
const suppress = block.suppressLineNumbers === true;
|
|
3481
|
-
for (let lineIndex = 0; lineIndex < lineCount; lineIndex += 1) {
|
|
3482
|
-
if (!suppress && (lineNumber - restartStart) % countBy === 0) {
|
|
3483
|
-
markers.push({
|
|
3484
|
-
id: `${block.blockId}-${lineIndex}`,
|
|
3485
|
-
label: String(lineNumber),
|
|
3486
|
-
topPx: DOCUMENT_CONTENT_TOP_PADDING_PX + (currentTopTwips + lineIndex * lineHeight) * DEFAULT_PAGE_ESTIMATE_PX_PER_TWIP
|
|
3487
|
-
});
|
|
3488
|
-
}
|
|
3489
|
-
if (!suppress) {
|
|
3490
|
-
lineNumber += 1;
|
|
3491
|
-
}
|
|
3492
|
-
}
|
|
3493
|
-
}
|
|
3494
|
-
currentTopTwips += estimateBlockHeight(block, columnWidth);
|
|
3495
|
-
}
|
|
3496
|
-
return markers;
|
|
3497
|
-
}
|
|
3498
|
-
function shouldRenderPageBorder(pageLayout, pages, activePageIndex) {
|
|
3499
|
-
const display = pageLayout?.pageBorders?.display ?? "allPages";
|
|
3500
|
-
const activePage = pages[activePageIndex];
|
|
3501
|
-
if (!pageLayout?.pageBorders || !activePage) {
|
|
3502
|
-
return false;
|
|
3503
|
-
}
|
|
3504
|
-
switch (display) {
|
|
3505
|
-
case "firstPage":
|
|
3506
|
-
return activePage.pageInSection === 0;
|
|
3507
|
-
case "notFirstPage":
|
|
3508
|
-
return activePage.pageInSection > 0;
|
|
3509
|
-
default:
|
|
3510
|
-
return true;
|
|
3511
|
-
}
|
|
3512
|
-
}
|
|
3513
|
-
function buildPageBorderStyle(pageLayout) {
|
|
3514
|
-
const pageBorders = pageLayout.pageBorders;
|
|
3515
|
-
if (!pageBorders) {
|
|
3516
|
-
return void 0;
|
|
3517
|
-
}
|
|
3518
|
-
const leftInset = createInsetValue(
|
|
3519
|
-
pageBorders.left?.space,
|
|
3520
|
-
pageBorders.offsetFrom === "text" ? pageLayout.marginLeft / Math.max(1, pageLayout.pageWidth) * 100 : 1.25
|
|
3521
|
-
);
|
|
3522
|
-
const rightInset = createInsetValue(
|
|
3523
|
-
pageBorders.right?.space,
|
|
3524
|
-
pageBorders.offsetFrom === "text" ? pageLayout.marginRight / Math.max(1, pageLayout.pageWidth) * 100 : 1.25
|
|
3525
|
-
);
|
|
3526
|
-
const topInset = createInsetValue(
|
|
3527
|
-
pageBorders.top?.space,
|
|
3528
|
-
pageBorders.offsetFrom === "text" ? pageLayout.marginTop / Math.max(1, pageLayout.pageHeight) * 100 : 1.5
|
|
3529
|
-
);
|
|
3530
|
-
const bottomInset = createInsetValue(
|
|
3531
|
-
pageBorders.bottom?.space,
|
|
3532
|
-
pageBorders.offsetFrom === "text" ? pageLayout.marginBottom / Math.max(1, pageLayout.pageHeight) * 100 : 1.5
|
|
3533
|
-
);
|
|
3534
|
-
return {
|
|
3535
|
-
top: topInset,
|
|
3536
|
-
right: rightInset,
|
|
3537
|
-
bottom: bottomInset,
|
|
3538
|
-
left: leftInset,
|
|
3539
|
-
borderTop: toBorderCss(pageBorders.top),
|
|
3540
|
-
borderRight: toBorderCss(pageBorders.right),
|
|
3541
|
-
borderBottom: toBorderCss(pageBorders.bottom),
|
|
3542
|
-
borderLeft: toBorderCss(pageBorders.left),
|
|
3543
|
-
boxSizing: "border-box",
|
|
3544
|
-
mixBlendMode: pageBorders.zOrder === "back" ? "multiply" : void 0
|
|
3545
|
-
};
|
|
3546
|
-
}
|
|
3547
|
-
function buildDocumentGridStyle(documentGrid) {
|
|
3548
|
-
if (!documentGrid || !documentGrid.type || documentGrid.type === "default") {
|
|
3549
|
-
return void 0;
|
|
3550
|
-
}
|
|
3551
|
-
const linePitchPx = Math.max(
|
|
3552
|
-
18,
|
|
3553
|
-
Math.round((documentGrid.linePitch ?? 360) * DEFAULT_PAGE_ESTIMATE_PX_PER_TWIP)
|
|
3554
|
-
);
|
|
3555
|
-
const charSpacePx = Math.max(
|
|
3556
|
-
12,
|
|
3557
|
-
Math.round((documentGrid.charSpace ?? 204) * DEFAULT_PAGE_ESTIMATE_PX_PER_TWIP)
|
|
3558
|
-
);
|
|
3559
|
-
const gridColor = "rgba(15, 23, 42, 0.06)";
|
|
3560
|
-
const backgrounds = [];
|
|
3561
|
-
if (documentGrid.type === "lines" || documentGrid.type === "linesAndChars" || documentGrid.type === "snapToChars") {
|
|
3562
|
-
backgrounds.push(
|
|
3563
|
-
`repeating-linear-gradient(to bottom, ${gridColor} 0, ${gridColor} 1px, transparent 1px, transparent ${linePitchPx}px)`
|
|
3564
|
-
);
|
|
3565
|
-
}
|
|
3566
|
-
if (documentGrid.type === "linesAndChars" || documentGrid.type === "snapToChars") {
|
|
3567
|
-
backgrounds.push(
|
|
3568
|
-
`repeating-linear-gradient(to right, rgba(15, 23, 42, 0.04) 0, rgba(15, 23, 42, 0.04) 1px, transparent 1px, transparent ${charSpacePx}px)`
|
|
3569
|
-
);
|
|
3570
|
-
}
|
|
3571
|
-
if (backgrounds.length === 0) {
|
|
3572
|
-
return void 0;
|
|
3573
|
-
}
|
|
3574
|
-
return {
|
|
3575
|
-
backgroundImage: backgrounds.join(", "),
|
|
3576
|
-
backgroundOrigin: "content-box"
|
|
3577
|
-
};
|
|
3578
|
-
}
|
|
3579
|
-
function createInsetValue(spaceTwips, percent) {
|
|
3580
|
-
const spacingPx = Math.max(0, Math.round((spaceTwips ?? 0) * DEFAULT_PAGE_ESTIMATE_PX_PER_TWIP));
|
|
3581
|
-
return `calc(${percent.toFixed(2)}% + ${spacingPx}px)`;
|
|
3582
|
-
}
|
|
3583
|
-
function resolveSelectionToolbarPlacement(anchor, root, zoomScale) {
|
|
3584
|
-
if (!anchor || !root) {
|
|
3585
|
-
return null;
|
|
3586
|
-
}
|
|
3587
|
-
const rootRect = root.getBoundingClientRect();
|
|
3588
|
-
if (rootRect.width <= 0 || rootRect.height <= 0 || zoomScale <= 0) {
|
|
3589
|
-
return null;
|
|
3590
|
-
}
|
|
3591
|
-
const centerX = (anchor.left + anchor.right) / 2;
|
|
3592
|
-
const centerY = (anchor.top + anchor.bottom) / 2;
|
|
3593
|
-
const localLeftEdge = (anchor.left - rootRect.left) / zoomScale;
|
|
3594
|
-
const localRightEdge = (anchor.right - rootRect.left) / zoomScale;
|
|
3595
|
-
const localLeft = (centerX - rootRect.left) / zoomScale;
|
|
3596
|
-
const localCenterY = (centerY - rootRect.top) / zoomScale;
|
|
3597
|
-
const localTop = (anchor.top - rootRect.top) / zoomScale;
|
|
3598
|
-
const localBottom = (anchor.bottom - rootRect.top) / zoomScale;
|
|
3599
|
-
const edgePadding = 16 / zoomScale;
|
|
3600
|
-
const containerWidth = rootRect.width / zoomScale;
|
|
3601
|
-
const containerHeight = rootRect.height / zoomScale;
|
|
3602
|
-
const gapPx = 12 / zoomScale;
|
|
3603
|
-
const estimatedToolbarWidth = Math.min(260 / zoomScale, Math.max(168 / zoomScale, containerWidth * 0.32));
|
|
3604
|
-
const estimatedToolbarHeight = 44 / zoomScale;
|
|
3605
|
-
const clampedCenterLeft = Math.max(
|
|
3606
|
-
edgePadding,
|
|
3607
|
-
Math.min(localLeft, Math.max(edgePadding, containerWidth - edgePadding))
|
|
3608
|
-
);
|
|
3609
|
-
const clampedCenterY = Math.max(
|
|
3610
|
-
edgePadding + estimatedToolbarHeight / 2,
|
|
3611
|
-
Math.min(localCenterY, Math.max(edgePadding + estimatedToolbarHeight / 2, containerHeight - edgePadding - estimatedToolbarHeight / 2))
|
|
3612
|
-
);
|
|
3613
|
-
const rightClearance = containerWidth - localRightEdge - gapPx - edgePadding;
|
|
3614
|
-
const leftClearance = localLeftEdge - gapPx - edgePadding;
|
|
3615
|
-
if (rightClearance >= estimatedToolbarWidth) {
|
|
3616
|
-
return {
|
|
3617
|
-
placement: "right",
|
|
3618
|
-
style: {
|
|
3619
|
-
left: `${localRightEdge}px`,
|
|
3620
|
-
top: `${clampedCenterY}px`,
|
|
3621
|
-
maxWidth: `${Math.max(220, containerWidth - edgePadding * 2)}px`,
|
|
3622
|
-
transform: `translate(${gapPx}px, -50%)`
|
|
3623
|
-
}
|
|
3624
|
-
};
|
|
3625
|
-
}
|
|
3626
|
-
if (leftClearance >= estimatedToolbarWidth) {
|
|
3627
|
-
return {
|
|
3628
|
-
placement: "left",
|
|
3629
|
-
style: {
|
|
3630
|
-
left: `${localLeftEdge}px`,
|
|
3631
|
-
top: `${clampedCenterY}px`,
|
|
3632
|
-
maxWidth: `${Math.max(220, containerWidth - edgePadding * 2)}px`,
|
|
3633
|
-
transform: `translate(calc(-100% - ${gapPx}px), -50%)`
|
|
3634
|
-
}
|
|
3635
|
-
};
|
|
3636
|
-
}
|
|
3637
|
-
const placement = localTop < estimatedToolbarHeight + gapPx + edgePadding ? "below" : "above";
|
|
3638
|
-
return {
|
|
3639
|
-
placement,
|
|
3640
|
-
style: {
|
|
3641
|
-
left: `${clampedCenterLeft}px`,
|
|
3642
|
-
top: `${placement === "above" ? localTop : localBottom}px`,
|
|
3643
|
-
maxWidth: `${Math.max(220, containerWidth - edgePadding * 2)}px`,
|
|
3644
|
-
transform: placement === "above" ? `translate(-50%, calc(-100% - ${gapPx}px))` : `translate(-50%, ${gapPx}px)`
|
|
3645
|
-
}
|
|
3646
|
-
};
|
|
3647
|
-
}
|
|
3648
|
-
function toBorderCss(border) {
|
|
3649
|
-
if (!border || border.value === "none" || border.value === "nil") {
|
|
3650
|
-
return void 0;
|
|
3651
|
-
}
|
|
3652
|
-
const width = border.size ? `${Math.max(1, Math.round(border.size / 8))}px` : "1px";
|
|
3653
|
-
const style = border.value === "double" ? "double" : border.value === "dotted" ? "dotted" : border.value === "dashed" || border.value === "dashSmallGap" ? "dashed" : "solid";
|
|
3654
|
-
const color = border.color && border.color !== "auto" ? `#${border.color}` : "rgba(31, 31, 31, 0.28)";
|
|
3655
|
-
return `${width} ${style} ${color}`;
|
|
3656
|
-
}
|
|
3657
|
-
|
|
3658
|
-
// src/ui/headless/comment-decoration-model.ts
|
|
3659
|
-
function createCommentDecorationModel(snapshot) {
|
|
3660
|
-
if (!snapshot) {
|
|
3661
|
-
return void 0;
|
|
3662
|
-
}
|
|
3663
|
-
return {
|
|
3664
|
-
activeCommentId: snapshot.activeCommentId,
|
|
3665
|
-
threads: snapshot.threads.filter((thread) => thread.anchor.kind !== "detached").map((thread) => {
|
|
3666
|
-
const anchor = thread.anchor;
|
|
3667
|
-
const from = anchor.kind === "range" ? anchor.from : anchor.kind === "node" ? anchor.at : 0;
|
|
3668
|
-
const to = anchor.kind === "range" ? anchor.to : anchor.kind === "node" ? anchor.at : 0;
|
|
3669
|
-
return {
|
|
3670
|
-
commentId: thread.commentId,
|
|
3671
|
-
from,
|
|
3672
|
-
to,
|
|
3673
|
-
status: thread.status,
|
|
3674
|
-
isActive: thread.isActive
|
|
3675
|
-
};
|
|
3676
|
-
})
|
|
3677
|
-
};
|
|
3678
|
-
}
|
|
3679
|
-
function getCommentRangeState(model, from, to) {
|
|
3680
|
-
if (!model) {
|
|
3681
|
-
return {
|
|
3682
|
-
hasComments: false,
|
|
3683
|
-
hasOpen: false,
|
|
3684
|
-
hasResolved: false,
|
|
3685
|
-
hasActive: false,
|
|
3686
|
-
count: 0,
|
|
3687
|
-
overlapping: []
|
|
3688
|
-
};
|
|
3689
|
-
}
|
|
3690
|
-
const overlapping = model.threads.filter(
|
|
3691
|
-
(thread) => rangesOverlap(thread.from, thread.to, from, to)
|
|
3692
|
-
);
|
|
3693
|
-
return {
|
|
3694
|
-
hasComments: overlapping.length > 0,
|
|
3695
|
-
hasOpen: overlapping.some((thread) => thread.status === "open"),
|
|
3696
|
-
hasResolved: overlapping.some((thread) => thread.status === "resolved"),
|
|
3697
|
-
hasActive: overlapping.some((thread) => thread.isActive),
|
|
3698
|
-
count: overlapping.length,
|
|
3699
|
-
overlapping
|
|
3700
|
-
};
|
|
3701
|
-
}
|
|
3702
|
-
function getCommentHighlightClass(model, from, to, markupDisplay = "all") {
|
|
3703
|
-
const state = getCommentRangeState(model, from, to);
|
|
3704
|
-
if (!state.hasComments) {
|
|
3705
|
-
return "";
|
|
3706
|
-
}
|
|
3707
|
-
switch (markupDisplay) {
|
|
3708
|
-
case "clean":
|
|
3709
|
-
return state.hasActive ? "bg-comment-soft" : "";
|
|
3710
|
-
case "simple":
|
|
3711
|
-
if (state.hasActive) {
|
|
3712
|
-
return "underline decoration-comment decoration-2 underline-offset-4";
|
|
3713
|
-
}
|
|
3714
|
-
if (state.hasOpen) {
|
|
3715
|
-
return "underline decoration-comment/60 decoration-1 underline-offset-4";
|
|
3716
|
-
}
|
|
3717
|
-
return "underline decoration-comment/40 decoration-1 underline-offset-4";
|
|
3718
|
-
case "all":
|
|
3719
|
-
if (state.hasActive) {
|
|
3720
|
-
return "bg-comment-strong";
|
|
3721
|
-
}
|
|
3722
|
-
if (state.hasOpen) {
|
|
3723
|
-
return "bg-comment-soft";
|
|
3724
|
-
}
|
|
3725
|
-
return "bg-comment-soft opacity-60";
|
|
3726
|
-
}
|
|
3727
|
-
}
|
|
3728
|
-
function rangesOverlap(leftFrom, leftTo, rightFrom, rightTo) {
|
|
3729
|
-
const leftEnd = Math.max(leftFrom, leftTo);
|
|
3730
|
-
const rightEnd = Math.max(rightFrom, rightTo);
|
|
3731
|
-
return leftFrom < rightEnd && rightFrom < leftEnd;
|
|
3732
|
-
}
|
|
3733
|
-
|
|
3734
|
-
// src/ui/headless/revision-decoration-model.ts
|
|
3735
|
-
function createRevisionDecorationModel(snapshot, activeRevisionId) {
|
|
3736
|
-
if (!snapshot) {
|
|
3737
|
-
return void 0;
|
|
3738
|
-
}
|
|
3739
|
-
return {
|
|
3740
|
-
revisions: snapshot.revisions.filter((rev) => rev.anchor.kind !== "detached" && rev.status === "active").map((rev) => {
|
|
3741
|
-
const anchor = rev.anchor;
|
|
3742
|
-
const from = anchor.kind === "range" ? anchor.from : anchor.kind === "node" ? anchor.at : 0;
|
|
3743
|
-
const to = anchor.kind === "range" ? anchor.to : anchor.kind === "node" ? anchor.at : 0;
|
|
3744
|
-
return {
|
|
3745
|
-
revisionId: rev.revisionId,
|
|
3746
|
-
from,
|
|
3747
|
-
to,
|
|
3748
|
-
kind: rev.kind,
|
|
3749
|
-
status: rev.status,
|
|
3750
|
-
actionability: rev.actionability,
|
|
3751
|
-
isActive: rev.revisionId === activeRevisionId
|
|
3752
|
-
};
|
|
3753
|
-
})
|
|
3754
|
-
};
|
|
3755
|
-
}
|
|
3756
|
-
function getRevisionRangeState(model, from, to) {
|
|
3757
|
-
if (!model) {
|
|
3758
|
-
return {
|
|
3759
|
-
hasChanges: false,
|
|
3760
|
-
hasInsertions: false,
|
|
3761
|
-
hasDeletions: false,
|
|
3762
|
-
hasActive: false,
|
|
3763
|
-
count: 0,
|
|
3764
|
-
overlapping: []
|
|
3765
|
-
};
|
|
3766
|
-
}
|
|
3767
|
-
const overlapping = model.revisions.filter(
|
|
3768
|
-
(rev) => rangesOverlap(rev.from, rev.to, from, to)
|
|
3769
|
-
);
|
|
3770
|
-
return {
|
|
3771
|
-
hasChanges: overlapping.length > 0,
|
|
3772
|
-
hasInsertions: overlapping.some((rev) => rev.kind === "insertion"),
|
|
3773
|
-
hasDeletions: overlapping.some((rev) => rev.kind === "deletion"),
|
|
3774
|
-
hasActive: overlapping.some((rev) => rev.isActive),
|
|
3775
|
-
count: overlapping.length,
|
|
3776
|
-
overlapping
|
|
3777
|
-
};
|
|
3778
|
-
}
|
|
3779
|
-
function getRevisionHighlightClass(model, from, to, markupDisplay = "all") {
|
|
3780
|
-
const state = getRevisionRangeState(model, from, to);
|
|
3781
|
-
if (!state.hasChanges) {
|
|
3782
|
-
return "";
|
|
3783
|
-
}
|
|
3784
|
-
const activeRing = state.hasActive ? " ring-1 ring-accent/30" : "";
|
|
3785
|
-
switch (markupDisplay) {
|
|
3786
|
-
case "clean":
|
|
3787
|
-
return "";
|
|
3788
|
-
case "simple":
|
|
3789
|
-
if (state.hasInsertions) {
|
|
3790
|
-
return `underline decoration-insert/60 decoration-1 underline-offset-2 text-primary${activeRing}`;
|
|
3791
|
-
}
|
|
3792
|
-
if (state.hasDeletions) {
|
|
3793
|
-
return `text-secondary line-through decoration-danger/70 decoration-1${activeRing}`;
|
|
3794
|
-
}
|
|
3795
|
-
return activeRing;
|
|
3796
|
-
case "all":
|
|
3797
|
-
if (state.hasInsertions) {
|
|
3798
|
-
return `text-primary bg-insert-soft/80 ring-1 ring-insert/20${activeRing}`;
|
|
3799
|
-
}
|
|
3800
|
-
if (state.hasDeletions) {
|
|
3801
|
-
return `text-danger line-through decoration-danger/80 decoration-1 bg-delete-soft/70${activeRing}`;
|
|
3802
|
-
}
|
|
3803
|
-
return activeRing;
|
|
3804
|
-
}
|
|
3805
|
-
}
|
|
3806
|
-
function shouldHideInCleanMode(model, from, to) {
|
|
3807
|
-
const state = getRevisionRangeState(model, from, to);
|
|
3808
|
-
return state.hasDeletions;
|
|
3809
|
-
}
|
|
3810
|
-
|
|
3811
|
-
// src/ui/headless/selection-helpers.ts
|
|
3812
|
-
function createSelectionSnapshot(anchor, head = anchor) {
|
|
3813
|
-
const from = Math.min(anchor, head);
|
|
3814
|
-
const to = Math.max(anchor, head);
|
|
3815
|
-
return {
|
|
3816
|
-
anchor,
|
|
3817
|
-
head,
|
|
3818
|
-
isCollapsed: anchor === head,
|
|
3819
|
-
activeRange: {
|
|
3820
|
-
kind: "range",
|
|
3821
|
-
from,
|
|
3822
|
-
to,
|
|
3823
|
-
assoc: {
|
|
3824
|
-
start: -1,
|
|
3825
|
-
end: 1
|
|
3826
|
-
}
|
|
3827
|
-
}
|
|
3828
|
-
};
|
|
3829
|
-
}
|
|
3830
|
-
function createNodeSelectionSnapshot(at, assoc = 1) {
|
|
3831
|
-
return {
|
|
3832
|
-
anchor: at,
|
|
3833
|
-
head: at,
|
|
3834
|
-
isCollapsed: true,
|
|
3835
|
-
activeRange: {
|
|
3836
|
-
kind: "node",
|
|
3837
|
-
at,
|
|
3838
|
-
assoc
|
|
3839
|
-
}
|
|
3840
|
-
};
|
|
3841
|
-
}
|
|
3842
|
-
function selectionTouchesRange(selection, from, to) {
|
|
3843
|
-
if (selection.isCollapsed) {
|
|
3844
|
-
return false;
|
|
3845
|
-
}
|
|
3846
|
-
const selectionFrom = Math.min(selection.anchor, selection.head);
|
|
3847
|
-
const selectionTo = Math.max(selection.anchor, selection.head);
|
|
3848
|
-
return selectionFrom < to && from < selectionTo;
|
|
3849
|
-
}
|
|
3850
|
-
|
|
3851
|
-
export {
|
|
3852
|
-
deriveCapabilities,
|
|
3853
|
-
TwAlertBanner,
|
|
3854
|
-
TwSelectionToolbar,
|
|
3855
|
-
TwCommentSidebar,
|
|
3856
|
-
TwRevisionSidebar,
|
|
3857
|
-
TwReviewRail,
|
|
3858
|
-
TwStatusBar,
|
|
3859
|
-
TwHealthPanel,
|
|
3860
|
-
TwToolbarIconButton,
|
|
3861
|
-
TwToolbar,
|
|
3862
|
-
TwReviewWorkspace,
|
|
3863
|
-
createCommentDecorationModel,
|
|
3864
|
-
getCommentRangeState,
|
|
3865
|
-
getCommentHighlightClass,
|
|
3866
|
-
createRevisionDecorationModel,
|
|
3867
|
-
getRevisionRangeState,
|
|
3868
|
-
getRevisionHighlightClass,
|
|
3869
|
-
shouldHideInCleanMode,
|
|
3870
|
-
createSelectionSnapshot,
|
|
3871
|
-
createNodeSelectionSnapshot,
|
|
3872
|
-
selectionTouchesRange
|
|
3873
|
-
};
|
|
3874
|
-
//# sourceMappingURL=chunk-2TG72QSW.js.map
|