@bendyline/squisq-editor-react 2.11.4 → 2.11.6
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/dist/chunk-DUO5XZQK.js +1653 -0
- package/dist/{chunk-CDISORBP.js → chunk-WMNH5ROU.js} +2799 -3761
- package/dist/index.d.ts +6 -54
- package/dist/index.js +13 -11
- package/dist/proofing/index.d.ts +2 -2
- package/dist/review/index.d.ts +285 -0
- package/dist/review/index.js +103 -0
- package/dist/shell/index.d.ts +4 -2
- package/dist/shell/index.js +5 -3
- package/dist/{shell-CJkHDwpz.d.ts → shell-Dwf_W4K4.d.ts} +116 -3
- package/dist/styles/index.css +166 -0
- package/dist/types-C0puuw-M.d.ts +81 -0
- package/dist/{types-B_aHRuSc.d.ts → types-De4z-gGb.d.ts} +1 -1
- package/package.json +10 -6
|
@@ -9,10 +9,11 @@ import { FenceRendererMap } from '@bendyline/squisq/fence';
|
|
|
9
9
|
import { CodeBlockCopyHandler } from '@bendyline/squisq-react';
|
|
10
10
|
import { MarkdownDocument } from '@bendyline/squisq/markdown';
|
|
11
11
|
import { ContentContainer } from '@bendyline/squisq/storage';
|
|
12
|
-
import {
|
|
12
|
+
import { a as ProofingCapability, c as ProofingIgnoreStore } from './types-De4z-gGb.js';
|
|
13
13
|
import { DocumentVersionManager, SaveVersionOptions, SaveVersionResult, PrunePolicy } from '@bendyline/squisq/versions';
|
|
14
14
|
import { Editor } from '@tiptap/core';
|
|
15
15
|
import { editor } from 'monaco-editor';
|
|
16
|
+
import { a as ReviewCapability } from './types-C0puuw-M.js';
|
|
16
17
|
|
|
17
18
|
/**
|
|
18
19
|
* Sidecar bytes → the grid's neutral `IngestTable`, via lazy formats
|
|
@@ -149,6 +150,56 @@ interface XlsxFormulaSession {
|
|
|
149
150
|
*/
|
|
150
151
|
declare function createXlsxFormulaSession(meta: XlsxSourceMeta, options?: FormulaSessionOptions): Promise<XlsxFormulaSession | null>;
|
|
151
152
|
|
|
153
|
+
/**
|
|
154
|
+
* blockRange
|
|
155
|
+
*
|
|
156
|
+
* Source-text-range slicing for the block-at-a-time editing view. Splits a
|
|
157
|
+
* full markdown document into ordered, contiguous slices — one per
|
|
158
|
+
* heading-defined block plus an optional leading preamble — so a single
|
|
159
|
+
* block can be shown in isolation and edits spliced back into the parent.
|
|
160
|
+
*
|
|
161
|
+
* A block runs from its heading line through the character just before the
|
|
162
|
+
* next heading at ANY depth (or EOF). Sub-headings therefore start their own
|
|
163
|
+
* slices — they are NOT folded into their parent — which matches the
|
|
164
|
+
* "don't see child blocks" requirement and the `slicePastHeading` boundary
|
|
165
|
+
* in `blockSlice.ts`. Ranges are half-open `[startOffset, endOffset)` and
|
|
166
|
+
* line-aligned, so trailing blank lines stay with the current block and
|
|
167
|
+
* `spliceBlock(src, range, getBlockSlices(src)[i].text) === src` for every i.
|
|
168
|
+
*
|
|
169
|
+
* These are pure functions over a markdown string — no React, no editor
|
|
170
|
+
* coupling — so any host can reuse them.
|
|
171
|
+
*/
|
|
172
|
+
/** Half-open character range into the full source: `[startOffset, endOffset)`. */
|
|
173
|
+
interface BlockRange {
|
|
174
|
+
startOffset: number;
|
|
175
|
+
endOffset: number;
|
|
176
|
+
}
|
|
177
|
+
/** One block's source text plus the range it occupies in the full document. */
|
|
178
|
+
interface BlockSlice {
|
|
179
|
+
text: string;
|
|
180
|
+
range: BlockRange;
|
|
181
|
+
}
|
|
182
|
+
/**
|
|
183
|
+
* Split `fullSource` into ordered block slices.
|
|
184
|
+
*
|
|
185
|
+
* - With no headings, the entire post-frontmatter body is a single slice
|
|
186
|
+
* (so an empty or heading-less document still shows one editable card).
|
|
187
|
+
* - With headings, a leading preamble slice is included only when the text
|
|
188
|
+
* before the first heading has non-whitespace content. Each heading then
|
|
189
|
+
* yields one slice spanning up to the next heading (any depth) or EOF.
|
|
190
|
+
*
|
|
191
|
+
* Frontmatter is never part of any slice — slices start at the body offset.
|
|
192
|
+
*/
|
|
193
|
+
declare function getBlockSlices(fullSource: string): BlockSlice[];
|
|
194
|
+
/** Replace the text in `range` with `newText`, returning the new full source. */
|
|
195
|
+
declare function spliceBlock(fullSource: string, range: BlockRange, newText: string): string;
|
|
196
|
+
/** Character offset of the start of 1-based `line` (clamps past EOF). */
|
|
197
|
+
declare function lineToOffset(source: string, line: number): number;
|
|
198
|
+
/** 1-based line number containing `offset`. */
|
|
199
|
+
declare function offsetToLine(source: string, offset: number): number;
|
|
200
|
+
/** Index of the slice whose range contains `offset`, or -1. */
|
|
201
|
+
declare function sliceIndexAtOffset(slices: BlockSlice[], offset: number): number;
|
|
202
|
+
|
|
152
203
|
/**
|
|
153
204
|
* Configuration a Scene host (diagram / drawing / layout widget) supplies
|
|
154
205
|
* so the shared inline text editor knows how to read and write the text of
|
|
@@ -230,6 +281,15 @@ interface DocumentLinkCandidate {
|
|
|
230
281
|
*/
|
|
231
282
|
type DocumentLinkProvider = (query: string) => Promise<DocumentLinkCandidate[]>;
|
|
232
283
|
type EditorView = 'raw' | 'wysiwyg' | 'preview';
|
|
284
|
+
/** What is selected in the active editing surface. */
|
|
285
|
+
interface EditorSelectionInfo {
|
|
286
|
+
/** Which surface reported it. */
|
|
287
|
+
view: EditorView;
|
|
288
|
+
/** The selected text, empty when the selection is a bare cursor. */
|
|
289
|
+
text: string;
|
|
290
|
+
/** True when the selection is a bare cursor rather than a range. */
|
|
291
|
+
empty: boolean;
|
|
292
|
+
}
|
|
233
293
|
/**
|
|
234
294
|
* Light/dark chrome mode for the editor shell (toolbar, tabs, status bar,
|
|
235
295
|
* side panes). This is the editor's *UI color scheme* — distinct from a
|
|
@@ -375,6 +435,14 @@ interface EditorState {
|
|
|
375
435
|
activeBlockKey: number;
|
|
376
436
|
/** 1-based source line where the active block begins, or null. */
|
|
377
437
|
activeBlockStartLine: number | null;
|
|
438
|
+
/**
|
|
439
|
+
* Bumped on every selection change in either surface.
|
|
440
|
+
*
|
|
441
|
+
* Exists so a host can gate on "is there a selection" without subscribing to
|
|
442
|
+
* Tiptap or Monaco internals. The counter, rather than the selection itself,
|
|
443
|
+
* is what keeps a toolbar from re-rendering on every keystroke inside one.
|
|
444
|
+
*/
|
|
445
|
+
selectionVersion: number;
|
|
378
446
|
}
|
|
379
447
|
interface EditorActions {
|
|
380
448
|
/** Set markdown source and trigger re-parse */
|
|
@@ -421,6 +489,28 @@ interface EditorActions {
|
|
|
421
489
|
setBlockTagVisibility: (visibility: BlockTagVisibility) => void;
|
|
422
490
|
/** Change how much of the active Squisq theme the WYSIWYG surface mirrors. */
|
|
423
491
|
setThemeInheritance: (mode: ThemeInheritance) => void;
|
|
492
|
+
/**
|
|
493
|
+
* The current selection in the active surface, or null when the surface has
|
|
494
|
+
* no selection to report (Preview, or an editor that has not mounted).
|
|
495
|
+
*/
|
|
496
|
+
getSelection: () => EditorSelectionInfo | null;
|
|
497
|
+
/**
|
|
498
|
+
* Replace the current selection with markdown, as ONE undoable edit.
|
|
499
|
+
*
|
|
500
|
+
* Returns false when the active surface cannot be edited, so a caller can
|
|
501
|
+
* offer to switch views rather than silently dropping the text. With an
|
|
502
|
+
* empty selection this inserts at the cursor.
|
|
503
|
+
*/
|
|
504
|
+
replaceSelection: (markdown: string) => boolean;
|
|
505
|
+
/**
|
|
506
|
+
* The block containing the cursor.
|
|
507
|
+
*
|
|
508
|
+
* Exact in Source view. Null in Write view, where there is no public mapping
|
|
509
|
+
* from a ProseMirror position back to a markdown source offset — returning a
|
|
510
|
+
* plausible-but-wrong block would be worse than returning nothing, since a
|
|
511
|
+
* caller would edit the wrong paragraph.
|
|
512
|
+
*/
|
|
513
|
+
getBlockAtCursor: () => BlockSlice | null;
|
|
424
514
|
/** Insert text at the current cursor position in the active editor */
|
|
425
515
|
insertAtCursor: (text: string) => void;
|
|
426
516
|
/** Replace all editor content with the given text */
|
|
@@ -1029,6 +1119,29 @@ interface EditorShellProps {
|
|
|
1029
1119
|
toolbarSlotRight?: ReactNode;
|
|
1030
1120
|
/** Host-supplied content rendered at the right edge of the bottom status bar. */
|
|
1031
1121
|
statusBarSlotRight?: ReactNode;
|
|
1122
|
+
/**
|
|
1123
|
+
* Host-supplied panel docked beside the editor, as a flex sibling of the
|
|
1124
|
+
* preview — so opening it reflows the editor narrower rather than covering
|
|
1125
|
+
* it. Renders nothing when absent.
|
|
1126
|
+
*
|
|
1127
|
+
* The built-in panels (Files, proofing, the theme designer) are fixed
|
|
1128
|
+
* siblings here. This is the seam for a host's own: a review drawer, an
|
|
1129
|
+
* assistant, an inspector. Without it a host has to portal into a DOM node
|
|
1130
|
+
* it owns and give up the editor context in the process.
|
|
1131
|
+
*
|
|
1132
|
+
* Markdown modes only: the image and JSON surfaces have no panel row.
|
|
1133
|
+
*/
|
|
1134
|
+
sidePanelSlot?: ReactNode;
|
|
1135
|
+
/**
|
|
1136
|
+
* Review providers, each scheduled independently.
|
|
1137
|
+
*
|
|
1138
|
+
* A list rather than one capability because the providers are independent: a
|
|
1139
|
+
* spellchecker and a document reviewer disagree about latency, about what a
|
|
1140
|
+
* suggestion is, and about which hue they draw in, and a host should be able
|
|
1141
|
+
* to run either without the other. Absent or empty means no review at all —
|
|
1142
|
+
* nothing is scheduled and no provider is constructed.
|
|
1143
|
+
*/
|
|
1144
|
+
reviewProviders?: readonly ReviewCapability[];
|
|
1032
1145
|
/**
|
|
1033
1146
|
* Whether to show the "Play" (preview) tab in the toolbar. When false, the
|
|
1034
1147
|
* tab and its preview panel are hidden, and ⌘3 becomes a no-op. Use this
|
|
@@ -1377,7 +1490,7 @@ interface EditorShellProps {
|
|
|
1377
1490
|
* Complete markdown editor shell with toolbar, view switcher, and three
|
|
1378
1491
|
* editing modes: Raw (Monaco), WYSIWYG (Tiptap), and Preview.
|
|
1379
1492
|
*/
|
|
1380
|
-
declare function EditorShell({ initialMarkdown, initialView, hostMode, defaultViewportPreset, articleId, basePath, onChange, onLinkClick, showCodeCopyButton, onCopyCode, colorScheme, className, height, minHeight, maxHeight, mediaProvider, workspaceContainer, allowVersioning, versionBasename, versioningPrunePolicy, versioningAutoSaveIdleMs, onSaveVersion, showFilesToggle, showFilesWhenNotEmpty, showFormattingControls, showInsertControls, allowBinaryDownloads, toolbarSlotLeft, toolbarSlotAfterActions, toolbarSlotRight, statusBarSlotRight, showPlayTab, allowPresentationWindow, allowPresentationFullscreen, allowPrint, submitOnEnter, calcEngineFactory, codeContext, fullWidth, uxFont, thinMargins, writeCanvasSettings, showStatusBar, imageDisplayMode, fileName, saveCoverImageOutput, saveDashboardImageOutput, language, findMode, onFindModeChange, mentionProvider, proofing, proofingDefaultEnabled, proofingSpellingEnabled, proofingGrammarEnabled, proofingIgnoreStore, documentLinkProvider, fenceRenderers, linkSchemes, allowRecording, allowNarrate, preserveSourceWrapping, placeholder, readOnly, imageSrc, imageAlt, imageMode, imageEditorContainer, onImageExport, inlinePreview, inlinePreviewWidth, outline, outlineWidth, blockTags, blockTagVisibility, themeInheritance, viewPreferences, onViewPreferencesChange, themeOverride, }: EditorShellProps): react_jsx_runtime.JSX.Element;
|
|
1493
|
+
declare function EditorShell({ initialMarkdown, initialView, hostMode, defaultViewportPreset, articleId, basePath, onChange, onLinkClick, showCodeCopyButton, onCopyCode, colorScheme, className, height, minHeight, maxHeight, mediaProvider, workspaceContainer, allowVersioning, versionBasename, versioningPrunePolicy, versioningAutoSaveIdleMs, onSaveVersion, showFilesToggle, showFilesWhenNotEmpty, showFormattingControls, showInsertControls, allowBinaryDownloads, toolbarSlotLeft, toolbarSlotAfterActions, toolbarSlotRight, statusBarSlotRight, sidePanelSlot, reviewProviders, showPlayTab, allowPresentationWindow, allowPresentationFullscreen, allowPrint, submitOnEnter, calcEngineFactory, codeContext, fullWidth, uxFont, thinMargins, writeCanvasSettings, showStatusBar, imageDisplayMode, fileName, saveCoverImageOutput, saveDashboardImageOutput, language, findMode, onFindModeChange, mentionProvider, proofing, proofingDefaultEnabled, proofingSpellingEnabled, proofingGrammarEnabled, proofingIgnoreStore, documentLinkProvider, fenceRenderers, linkSchemes, allowRecording, allowNarrate, preserveSourceWrapping, placeholder, readOnly, imageSrc, imageAlt, imageMode, imageEditorContainer, onImageExport, inlinePreview, inlinePreviewWidth, outline, outlineWidth, blockTags, blockTagVisibility, themeInheritance, viewPreferences, onViewPreferencesChange, themeOverride, }: EditorShellProps): react_jsx_runtime.JSX.Element;
|
|
1381
1494
|
|
|
1382
1495
|
/**
|
|
1383
1496
|
* Shared editor context menu.
|
|
@@ -1527,4 +1640,4 @@ interface PreviewPanelProps {
|
|
|
1527
1640
|
*/
|
|
1528
1641
|
declare function PreviewPanel({ basePath, className, workspaceContainer, onLinkClick, showCodeCopyButton, onCopyCode, }: PreviewPanelProps): react_jsx_runtime.JSX.Element;
|
|
1529
1642
|
|
|
1530
|
-
export {
|
|
1643
|
+
export { sliceIndexAtOffset as $, type MentionProvider as A, type BlockRange as B, type CodeContext as C, type DashboardImageSaveOutput as D, type EditorHostMode as E, type FormulaEditRecord as F, type PreviewPanelProps as G, type RawEditorProps as H, type ImageDisplayMode as I, WysiwygEditor as J, type WysiwygEditorProps as K, type LayoutMode as L, type MentionCandidate as M, XLSX_LOCKED_REASON as N, type XlsxFormulaSession as O, PreviewPanel as P, createXlsxFormulaSession as Q, RawEditor as R, type SceneTextChannel as S, type ThemeInheritance as T, getBlockSlices as U, type ViewPreferences as V, type WriteCanvasSettings as W, type XlsxSourceMeta as X, ingestSidecarBytes as Y, lineToOffset as Z, offsetToLine as _, type CalcEngineFactory as a, spliceBlock as a0, useEditorContext as a1, useEditorContextMenuItems as a2, type CsvSourceMeta as b, type BlockSlice as c, type BlockTagVisibility as d, type CodeContextSection as e, type CoverImageSaveOutput as f, type DocumentLinkCandidate as g, type DocumentLinkProvider as h, type EditorActions as i, type EditorColorScheme as j, type EditorContextMenuContext as k, type EditorContextMenuItem as l, type EditorContextMenuItemVisibility as m, EditorContextMenuProvider as n, type EditorContextMenuProviderProps as o, type EditorContextValue as p, type EditorMode as q, EditorProvider as r, type EditorProviderProps as s, type EditorSelectionInfo as t, EditorShell as u, type EditorShellProps as v, type EditorState as w, type EditorView as x, type FormulaSessionOptions as y, type IngestedSidecar as z };
|
package/dist/styles/index.css
CHANGED
|
@@ -7110,6 +7110,7 @@
|
|
|
7110
7110
|
--squisq-proof-spelling: #d93025;
|
|
7111
7111
|
--squisq-proof-grammar: #188038;
|
|
7112
7112
|
--squisq-proof-style: #1a73e8;
|
|
7113
|
+
--squisq-review-assist: #6c4bd6;
|
|
7113
7114
|
--squisq-find-match: #fde68a;
|
|
7114
7115
|
--squisq-find-match-current: #f59e0b;
|
|
7115
7116
|
--squisq-find-match-ring: #b45309;
|
|
@@ -7185,6 +7186,7 @@
|
|
|
7185
7186
|
--squisq-proof-spelling: #f28b82;
|
|
7186
7187
|
--squisq-proof-grammar: #81c995;
|
|
7187
7188
|
--squisq-proof-style: #8ab4f8;
|
|
7189
|
+
--squisq-review-assist: #b39ddb;
|
|
7188
7190
|
--squisq-tag-text: #ffe3ad;
|
|
7189
7191
|
--squisq-tag-bg: #3a2818;
|
|
7190
7192
|
--squisq-tag-border: #d79a45;
|
|
@@ -7376,6 +7378,7 @@
|
|
|
7376
7378
|
align-self: stretch;
|
|
7377
7379
|
}
|
|
7378
7380
|
.squisq-toolbar-use-tab {
|
|
7381
|
+
position: relative;
|
|
7379
7382
|
border-bottom: 2px solid transparent;
|
|
7380
7383
|
}
|
|
7381
7384
|
.squisq-toolbar-use-tab > .squisq-toolbar-view-tab {
|
|
@@ -7386,6 +7389,19 @@
|
|
|
7386
7389
|
.squisq-toolbar-use-tab--active {
|
|
7387
7390
|
border-bottom-color: var(--squisq-accent);
|
|
7388
7391
|
}
|
|
7392
|
+
.squisq-toolbar-use-tab > .squisq-toolbar-view-tab:focus-visible,
|
|
7393
|
+
.squisq-toolbar-use-tab > .squisq-use-mode-trigger:focus-visible {
|
|
7394
|
+
outline: none;
|
|
7395
|
+
}
|
|
7396
|
+
.squisq-toolbar-use-tab:has(> .squisq-toolbar-view-tab:focus-visible, > .squisq-use-mode-trigger:focus-visible)::after {
|
|
7397
|
+
content: "";
|
|
7398
|
+
position: absolute;
|
|
7399
|
+
inset: 2px 0 4px;
|
|
7400
|
+
border: 2px solid var(--squisq-focus-ring);
|
|
7401
|
+
border-radius: 6px;
|
|
7402
|
+
box-sizing: border-box;
|
|
7403
|
+
pointer-events: none;
|
|
7404
|
+
}
|
|
7389
7405
|
.squisq-use-mode-trigger {
|
|
7390
7406
|
align-self: stretch;
|
|
7391
7407
|
display: inline-flex;
|
|
@@ -17583,6 +17599,25 @@ button.squisq-ascii-timeline-track-name:focus-visible {
|
|
|
17583
17599
|
text-decoration: underline dotted var(--squisq-proof-style) 1.5px;
|
|
17584
17600
|
text-decoration-skip-ink: none;
|
|
17585
17601
|
}
|
|
17602
|
+
.squisq-review-underline {
|
|
17603
|
+
text-decoration-skip-ink: none;
|
|
17604
|
+
}
|
|
17605
|
+
.squisq-review-underline--spelling {
|
|
17606
|
+
text-decoration: underline wavy var(--squisq-proof-spelling) 1px;
|
|
17607
|
+
text-decoration-skip-ink: none;
|
|
17608
|
+
}
|
|
17609
|
+
.squisq-review-underline--grammar {
|
|
17610
|
+
text-decoration: underline wavy var(--squisq-proof-grammar) 1px;
|
|
17611
|
+
text-decoration-skip-ink: none;
|
|
17612
|
+
}
|
|
17613
|
+
.squisq-review-underline--style {
|
|
17614
|
+
text-decoration: underline dotted var(--squisq-proof-style) 1.5px;
|
|
17615
|
+
text-decoration-skip-ink: none;
|
|
17616
|
+
}
|
|
17617
|
+
.squisq-review-underline--assist {
|
|
17618
|
+
text-decoration: underline dashed var(--squisq-review-assist) 1.5px;
|
|
17619
|
+
text-decoration-skip-ink: none;
|
|
17620
|
+
}
|
|
17586
17621
|
.squisq-proof-dot {
|
|
17587
17622
|
display: inline-block;
|
|
17588
17623
|
width: 8px;
|
|
@@ -17955,6 +17990,137 @@ button.squisq-ascii-timeline-track-name:focus-visible {
|
|
|
17955
17990
|
.squisq-proof-tooltip[data-theme=dark] .squisq-proof-tooltip-actions {
|
|
17956
17991
|
border-top-color: var(--squisq-border-subtle);
|
|
17957
17992
|
}
|
|
17993
|
+
.squisq-review-panel {
|
|
17994
|
+
width: 260px;
|
|
17995
|
+
flex: 0 0 260px;
|
|
17996
|
+
display: flex;
|
|
17997
|
+
flex-direction: column;
|
|
17998
|
+
overflow-y: auto;
|
|
17999
|
+
border-left: 1px solid var(--squisq-border-subtle);
|
|
18000
|
+
background: var(--squisq-surface-subtle);
|
|
18001
|
+
min-height: 0;
|
|
18002
|
+
font-size: 12px;
|
|
18003
|
+
}
|
|
18004
|
+
.squisq-editor-shell[data-theme=dark] .squisq-review-panel {
|
|
18005
|
+
background: var(--squisq-surface-sunken);
|
|
18006
|
+
border-left-color: var(--squisq-border-subtle);
|
|
18007
|
+
}
|
|
18008
|
+
.squisq-review-panel-header {
|
|
18009
|
+
display: flex;
|
|
18010
|
+
align-items: center;
|
|
18011
|
+
justify-content: space-between;
|
|
18012
|
+
gap: 8px;
|
|
18013
|
+
padding: 6px 10px;
|
|
18014
|
+
border-bottom: 1px solid var(--squisq-border-subtle);
|
|
18015
|
+
}
|
|
18016
|
+
.squisq-review-panel-title {
|
|
18017
|
+
display: flex;
|
|
18018
|
+
align-items: center;
|
|
18019
|
+
gap: 6px;
|
|
18020
|
+
font-weight: 600;
|
|
18021
|
+
color: var(--squisq-text);
|
|
18022
|
+
}
|
|
18023
|
+
.squisq-review-panel-count {
|
|
18024
|
+
color: var(--squisq-text-muted);
|
|
18025
|
+
font-weight: 400;
|
|
18026
|
+
}
|
|
18027
|
+
.squisq-review-panel-button {
|
|
18028
|
+
border: none;
|
|
18029
|
+
background: transparent;
|
|
18030
|
+
color: var(--squisq-text-soft);
|
|
18031
|
+
cursor: pointer;
|
|
18032
|
+
font: inherit;
|
|
18033
|
+
padding: 2px 6px;
|
|
18034
|
+
border-radius: 3px;
|
|
18035
|
+
}
|
|
18036
|
+
.squisq-review-panel-button:hover:not(:disabled) {
|
|
18037
|
+
background: var(--squisq-surface-hover);
|
|
18038
|
+
color: var(--squisq-text);
|
|
18039
|
+
}
|
|
18040
|
+
.squisq-review-panel-button:disabled {
|
|
18041
|
+
cursor: default;
|
|
18042
|
+
opacity: 0.6;
|
|
18043
|
+
}
|
|
18044
|
+
.squisq-review-panel-group-title {
|
|
18045
|
+
margin: 0;
|
|
18046
|
+
padding: 8px 10px 2px;
|
|
18047
|
+
font-size: 11px;
|
|
18048
|
+
font-weight: 600;
|
|
18049
|
+
text-transform: uppercase;
|
|
18050
|
+
letter-spacing: 0.04em;
|
|
18051
|
+
color: var(--squisq-text-muted);
|
|
18052
|
+
}
|
|
18053
|
+
.squisq-review-panel-empty {
|
|
18054
|
+
padding: 4px 10px 8px;
|
|
18055
|
+
color: var(--squisq-text-muted);
|
|
18056
|
+
}
|
|
18057
|
+
.squisq-review-panel-list {
|
|
18058
|
+
list-style: none;
|
|
18059
|
+
margin: 0;
|
|
18060
|
+
padding: 0;
|
|
18061
|
+
}
|
|
18062
|
+
.squisq-review-panel-row {
|
|
18063
|
+
display: flex;
|
|
18064
|
+
align-items: flex-start;
|
|
18065
|
+
gap: 4px;
|
|
18066
|
+
}
|
|
18067
|
+
.squisq-review-panel-row:hover {
|
|
18068
|
+
background: var(--squisq-row-hover);
|
|
18069
|
+
}
|
|
18070
|
+
.squisq-review-panel-row-main {
|
|
18071
|
+
display: flex;
|
|
18072
|
+
align-items: flex-start;
|
|
18073
|
+
gap: 8px;
|
|
18074
|
+
flex: 1 1 auto;
|
|
18075
|
+
min-width: 0;
|
|
18076
|
+
border: none;
|
|
18077
|
+
background: transparent;
|
|
18078
|
+
text-align: left;
|
|
18079
|
+
padding: 6px 4px 6px 10px;
|
|
18080
|
+
cursor: pointer;
|
|
18081
|
+
font: inherit;
|
|
18082
|
+
color: inherit;
|
|
18083
|
+
}
|
|
18084
|
+
.squisq-review-panel-row-body {
|
|
18085
|
+
display: flex;
|
|
18086
|
+
flex-direction: column;
|
|
18087
|
+
gap: 2px;
|
|
18088
|
+
min-width: 0;
|
|
18089
|
+
}
|
|
18090
|
+
.squisq-review-panel-excerpt {
|
|
18091
|
+
color: var(--squisq-text);
|
|
18092
|
+
font-weight: 600;
|
|
18093
|
+
overflow: hidden;
|
|
18094
|
+
text-overflow: ellipsis;
|
|
18095
|
+
white-space: nowrap;
|
|
18096
|
+
}
|
|
18097
|
+
.squisq-review-panel-message {
|
|
18098
|
+
color: var(--squisq-text-soft);
|
|
18099
|
+
}
|
|
18100
|
+
.squisq-review-panel-rationale {
|
|
18101
|
+
color: var(--squisq-text-muted);
|
|
18102
|
+
}
|
|
18103
|
+
.squisq-review-dot {
|
|
18104
|
+
display: inline-block;
|
|
18105
|
+
width: 8px;
|
|
18106
|
+
height: 8px;
|
|
18107
|
+
border-radius: 50%;
|
|
18108
|
+
margin-top: 4px;
|
|
18109
|
+
flex: 0 0 auto;
|
|
18110
|
+
background: var(--squisq-text-muted);
|
|
18111
|
+
}
|
|
18112
|
+
.squisq-review-dot--error {
|
|
18113
|
+
background: var(--squisq-proof-spelling);
|
|
18114
|
+
}
|
|
18115
|
+
.squisq-review-dot--warning {
|
|
18116
|
+
background: var(--squisq-warning);
|
|
18117
|
+
}
|
|
18118
|
+
.squisq-review-dot--suggestion {
|
|
18119
|
+
background: var(--squisq-review-assist);
|
|
18120
|
+
}
|
|
18121
|
+
.squisq-review-dot--info {
|
|
18122
|
+
background: var(--squisq-text-faint);
|
|
18123
|
+
}
|
|
17958
18124
|
|
|
17959
18125
|
/* src/scene/scene.css */
|
|
17960
18126
|
.squisq-scene-root {
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import { ReviewRequest, ReviewEvent } from '@bendyline/squisq/review';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* The review capability contract between an editor host and the shell.
|
|
5
|
+
*
|
|
6
|
+
* A host passes providers to `EditorShell`'s `reviewProviders` prop, the same
|
|
7
|
+
* capability-injection semantics as `proofing`: absent means the feature is
|
|
8
|
+
* off and nothing is loaded. Unlike `proofing` this is a list, because the
|
|
9
|
+
* providers are independent — a spellchecker and a document reviewer disagree
|
|
10
|
+
* about latency, about what a suggestion is, and about which hue they draw in,
|
|
11
|
+
* and a host should be able to run either without the other.
|
|
12
|
+
*
|
|
13
|
+
* The surface is plain data end to end, so a provider can be an engine in the
|
|
14
|
+
* page, a call to a local service, or a test fake.
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Which hue a provider's findings draw in.
|
|
19
|
+
*
|
|
20
|
+
* Named rather than free-form so the palette stays a theme decision. The first
|
|
21
|
+
* three are proofing's existing colours; `assist` is the fourth, for a provider
|
|
22
|
+
* whose findings are suggestions rather than mistakes.
|
|
23
|
+
*/
|
|
24
|
+
type ReviewHue = 'spelling' | 'grammar' | 'style' | 'assist';
|
|
25
|
+
interface ReviewProvider {
|
|
26
|
+
/**
|
|
27
|
+
* Stable namespace, e.g. `harper`. Prefixes decoration keys and groups the
|
|
28
|
+
* panel, so two providers reporting the same span never collide.
|
|
29
|
+
*/
|
|
30
|
+
readonly id: string;
|
|
31
|
+
/** Shown as the panel group header and in the status segment. */
|
|
32
|
+
readonly label: string;
|
|
33
|
+
/** Defaults to `style`. */
|
|
34
|
+
readonly hue?: ReviewHue;
|
|
35
|
+
/**
|
|
36
|
+
* Idle delay before this provider runs, in milliseconds.
|
|
37
|
+
*
|
|
38
|
+
* Per provider because the right answer differs by an order of magnitude:
|
|
39
|
+
* a local spellchecker can re-run 450 ms after a keystroke, while a model
|
|
40
|
+
* that takes seconds and owns the device's accelerator should not. Defaults
|
|
41
|
+
* to a conservative value rather than to proofing's.
|
|
42
|
+
*/
|
|
43
|
+
readonly debounceMs?: number;
|
|
44
|
+
/**
|
|
45
|
+
* Prepare the provider. Idempotent, retryable, and where all expensive work
|
|
46
|
+
* belongs. A rejection is not fatal: the editor reports the provider as
|
|
47
|
+
* unavailable and keeps the others running.
|
|
48
|
+
*/
|
|
49
|
+
setup?(): Promise<void>;
|
|
50
|
+
/**
|
|
51
|
+
* Review a document.
|
|
52
|
+
*
|
|
53
|
+
* Streaming and cancellable, which is the whole reason this is not `lint`.
|
|
54
|
+
* The editor aborts the signal as soon as the document changes, and a
|
|
55
|
+
* provider must stop promptly rather than finish and return stale findings.
|
|
56
|
+
*/
|
|
57
|
+
review(request: ReviewRequest, signal: AbortSignal): AsyncIterable<ReviewEvent>;
|
|
58
|
+
/**
|
|
59
|
+
* Persistently dismiss a finding. Optional: a provider with no notion of
|
|
60
|
+
* "don't tell me again" simply omits it and the editor hides the action.
|
|
61
|
+
*/
|
|
62
|
+
dismissFinding?(findingId: string): Promise<void>;
|
|
63
|
+
/** Release resources. Further calls may reject. */
|
|
64
|
+
dispose?(): void;
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Deferred construction. A factory's provider is created on first activation
|
|
68
|
+
* and disposed on unmount; a host that passes an instance owns its lifetime,
|
|
69
|
+
* which is what lets one warm engine survive shell remounts.
|
|
70
|
+
*/
|
|
71
|
+
type ReviewProviderFactory = () => ReviewProvider;
|
|
72
|
+
/** What each entry of the `reviewProviders` shell prop accepts. */
|
|
73
|
+
type ReviewCapability = ReviewProvider | ReviewProviderFactory;
|
|
74
|
+
/** Resolve a capability to a provider instance. */
|
|
75
|
+
declare function resolveReviewProvider(capability: ReviewCapability): ReviewProvider;
|
|
76
|
+
/** The delay a provider gets when it does not ask for one. */
|
|
77
|
+
declare const DEFAULT_REVIEW_DEBOUNCE_MS = 2000;
|
|
78
|
+
/** The hue a provider draws in when it does not ask for one. */
|
|
79
|
+
declare const DEFAULT_REVIEW_HUE: ReviewHue;
|
|
80
|
+
|
|
81
|
+
export { DEFAULT_REVIEW_DEBOUNCE_MS as D, type ReviewProvider as R, type ReviewCapability as a, type ReviewHue as b, DEFAULT_REVIEW_HUE as c, type ReviewProviderFactory as d, resolveReviewProvider as r };
|
|
@@ -153,4 +153,4 @@ interface HarperProofingConfig {
|
|
|
153
153
|
binary?: unknown;
|
|
154
154
|
}
|
|
155
155
|
|
|
156
|
-
export type { HarperProofingConfig as H,
|
|
156
|
+
export type { HarperProofingConfig as H, ProofingProvider as P, ProofingCapability as a, ProofingDocumentRef as b, ProofingIgnoreStore as c, ProofingLanguage as d, ProofingLintOptions as e, ProofingProviderFactory as f };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bendyline/squisq-editor-react",
|
|
3
|
-
"version": "2.11.
|
|
3
|
+
"version": "2.11.6",
|
|
4
4
|
"description": "React editor shell with raw/WYSIWYG/preview modes for Squisq documents",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "Bendyline",
|
|
@@ -72,6 +72,10 @@
|
|
|
72
72
|
"types": "./dist/proofing/index.d.ts",
|
|
73
73
|
"import": "./dist/proofing/index.js"
|
|
74
74
|
},
|
|
75
|
+
"./review": {
|
|
76
|
+
"types": "./dist/review/index.d.ts",
|
|
77
|
+
"import": "./dist/review/index.js"
|
|
78
|
+
},
|
|
75
79
|
"./styles": {
|
|
76
80
|
"types": "./dist/styles/index.d.ts",
|
|
77
81
|
"default": "./dist/styles/index.css"
|
|
@@ -94,12 +98,12 @@
|
|
|
94
98
|
}
|
|
95
99
|
},
|
|
96
100
|
"dependencies": {
|
|
97
|
-
"@bendyline/squisq": "2.11.
|
|
101
|
+
"@bendyline/squisq": "2.11.6",
|
|
98
102
|
"@bendyline/squisq-calc": "2.11.0",
|
|
99
|
-
"@bendyline/squisq-formats": "2.6.
|
|
100
|
-
"@bendyline/squisq-grid-react": "2.11.
|
|
101
|
-
"@bendyline/squisq-react": "2.11.
|
|
102
|
-
"@bendyline/squisq-video-react": "2.4.
|
|
103
|
+
"@bendyline/squisq-formats": "2.6.6",
|
|
104
|
+
"@bendyline/squisq-grid-react": "2.11.7",
|
|
105
|
+
"@bendyline/squisq-react": "2.11.6",
|
|
106
|
+
"@bendyline/squisq-video-react": "2.4.10",
|
|
103
107
|
"@fortawesome/fontawesome-free": "7.2.0",
|
|
104
108
|
"@tiptap/core": "2.27.2",
|
|
105
109
|
"@tiptap/extension-heading": "2.27.2",
|