@k2b/ui 0.34.0 → 0.35.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/browser/actions/Dropdown.js +1 -0
- package/dist/browser/actions/Dropdown.js.map +1 -1
- package/dist/browser/content/MatchText.js +61 -0
- package/dist/browser/content/MatchText.js.map +1 -0
- package/dist/browser/content/index.js +1 -0
- package/dist/browser/content/index.js.map +1 -1
- package/dist/browser/text-editor/TextEditor.js +1358 -0
- package/dist/browser/text-editor/TextEditor.js.map +1 -0
- package/dist/browser/text-editor/clipboard-html.js +152 -0
- package/dist/browser/text-editor/clipboard-html.js.map +1 -0
- package/dist/browser/text-editor/clipboard-loading.js +68 -0
- package/dist/browser/text-editor/clipboard-loading.js.map +1 -0
- package/dist/browser/text-editor/clipboard.js +51 -0
- package/dist/browser/text-editor/clipboard.js.map +1 -0
- package/dist/browser/text-editor/engine.js +125 -0
- package/dist/browser/text-editor/engine.js.map +1 -0
- package/dist/browser/text-editor/format.js +218 -0
- package/dist/browser/text-editor/format.js.map +1 -0
- package/dist/browser/text-editor/formatted.js +164 -0
- package/dist/browser/text-editor/formatted.js.map +1 -0
- package/dist/browser/text-editor/language.js +19 -0
- package/dist/browser/text-editor/language.js.map +1 -0
- package/dist/browser/text-editor/markdown-table.js +563 -0
- package/dist/browser/text-editor/markdown-table.js.map +1 -0
- package/dist/browser/text-editor/messages.js +233 -0
- package/dist/browser/text-editor/messages.js.map +1 -0
- package/dist/browser/text-editor/paste.js +115 -0
- package/dist/browser/text-editor/paste.js.map +1 -0
- package/dist/browser/text-editor/table.js +1760 -0
- package/dist/browser/text-editor/table.js.map +1 -0
- package/dist/browser/text-editor.js +5 -0
- package/dist/browser/text-editor.js.map +1 -0
- package/dist/ssr/actions/Dropdown.js +1 -0
- package/dist/ssr/actions/Dropdown.js.map +1 -1
- package/dist/ssr/content/MatchText.js +56 -0
- package/dist/ssr/content/MatchText.js.map +1 -0
- package/dist/ssr/content/index.js +1 -0
- package/dist/ssr/content/index.js.map +1 -1
- package/dist/ssr/text-editor/TextEditor.js +1155 -0
- package/dist/ssr/text-editor/TextEditor.js.map +1 -0
- package/dist/ssr/text-editor/clipboard-html.js +152 -0
- package/dist/ssr/text-editor/clipboard-html.js.map +1 -0
- package/dist/ssr/text-editor/clipboard-loading.js +68 -0
- package/dist/ssr/text-editor/clipboard-loading.js.map +1 -0
- package/dist/ssr/text-editor/clipboard.js +51 -0
- package/dist/ssr/text-editor/clipboard.js.map +1 -0
- package/dist/ssr/text-editor/engine.js +125 -0
- package/dist/ssr/text-editor/engine.js.map +1 -0
- package/dist/ssr/text-editor/format.js +218 -0
- package/dist/ssr/text-editor/format.js.map +1 -0
- package/dist/ssr/text-editor/formatted.js +164 -0
- package/dist/ssr/text-editor/formatted.js.map +1 -0
- package/dist/ssr/text-editor/language.js +19 -0
- package/dist/ssr/text-editor/language.js.map +1 -0
- package/dist/ssr/text-editor/markdown-table.js +563 -0
- package/dist/ssr/text-editor/markdown-table.js.map +1 -0
- package/dist/ssr/text-editor/messages.js +233 -0
- package/dist/ssr/text-editor/messages.js.map +1 -0
- package/dist/ssr/text-editor/paste.js +115 -0
- package/dist/ssr/text-editor/paste.js.map +1 -0
- package/dist/ssr/text-editor/table.js +1760 -0
- package/dist/ssr/text-editor/table.js.map +1 -0
- package/dist/ssr/text-editor.js +5 -0
- package/dist/ssr/text-editor.js.map +1 -0
- package/dist/styles.css +1 -1
- package/dist/types/actions/Dropdown.d.ts +2 -0
- package/dist/types/content/MatchText.d.ts +21 -0
- package/dist/types/content/index.d.ts +1 -0
- package/dist/types/text-editor/TextEditor.d.ts +69 -0
- package/dist/types/text-editor/clipboard-html.d.ts +9 -0
- package/dist/types/text-editor/clipboard-loading.d.ts +8 -0
- package/dist/types/text-editor/clipboard.d.ts +20 -0
- package/dist/types/text-editor/engine.d.ts +34 -0
- package/dist/types/text-editor/format.d.ts +34 -0
- package/dist/types/text-editor/formatted.d.ts +1 -0
- package/dist/types/text-editor/language.d.ts +8 -0
- package/dist/types/text-editor/markdown-table.d.ts +105 -0
- package/dist/types/text-editor/messages.d.ts +113 -0
- package/dist/types/text-editor/paste.d.ts +6 -0
- package/dist/types/text-editor/table.d.ts +81 -0
- package/dist/types/text-editor.d.ts +4 -0
- package/package.json +23 -3
|
@@ -102,6 +102,8 @@ export type DropdownProps = {
|
|
|
102
102
|
* Defaults to `menu`. A controlled menu (`open`) always stays a menu.
|
|
103
103
|
*/
|
|
104
104
|
phone?: "menu" | "sheet";
|
|
105
|
+
/** Content above the phone sheet's menu. `close` dismisses it with normal history and focus restoration. */
|
|
106
|
+
sheetTop?: (close: () => void) => JSX.Element;
|
|
105
107
|
/**
|
|
106
108
|
* Renders the entries only once the menu first opens, for a menu repeated on every row of a long list: the page
|
|
107
109
|
* then carries each row's trigger, not each row's entries. Fixed for the menu's lifetime.
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { type JSX } from "solid-js";
|
|
2
|
+
/** A half-open `[start, end)` range of Unicode code points. */
|
|
3
|
+
export type MatchRange = readonly [number, number];
|
|
4
|
+
export type MatchTextProps = {
|
|
5
|
+
text: string;
|
|
6
|
+
/** Code point ranges to mark, as search engines such as Filegate return them; not UTF-16 offsets. */
|
|
7
|
+
ranges?: readonly MatchRange[];
|
|
8
|
+
};
|
|
9
|
+
/** Splits text into marked and plain parts. Ranges are clipped to the text, sorted, and merged when they touch. */
|
|
10
|
+
export declare function matchParts(text: string, ranges?: readonly MatchRange[]): {
|
|
11
|
+
text: string;
|
|
12
|
+
hit: boolean;
|
|
13
|
+
}[];
|
|
14
|
+
/**
|
|
15
|
+
* Text with its search matches marked, for result names and paths. It renders inline text and `mark` elements
|
|
16
|
+
* only, so the host's element keeps truncating and styling the whole text. The marks change only the fill, never
|
|
17
|
+
* the text's width, and screen readers read the text unchanged.
|
|
18
|
+
* @example <span class="name"><MatchText text="Rechnung Oktober.pdf" ranges={[[0, 8]]} /></span>
|
|
19
|
+
*/
|
|
20
|
+
export declare function MatchText(props: MatchTextProps): JSX.Element;
|
|
21
|
+
export default MatchText;
|
|
@@ -40,6 +40,7 @@ export { MapAttribution } from "./MapAttribution";
|
|
|
40
40
|
export { MapView } from "./MapView";
|
|
41
41
|
export { MapViewFrame } from "./MapViewFrame";
|
|
42
42
|
export { default as MarkdownView, type MarkdownRenderOptions, type MarkdownViewProps, renderSafeMarkdown } from "./MarkdownView";
|
|
43
|
+
export { type MatchRange, MatchText, type MatchTextProps, matchParts } from "./MatchText";
|
|
43
44
|
export type { MessageEventGroupProps, MessageEventRowProps, MessageGroupEntry, MessageRowAction, MessageRowAttachment, MessageRowAuthor, MessageRowFile, MessageRowMedia, MessageRowOrigin, MessageRowProgress, MessageRowProps, MessageRowQuote, MessageRowReaction, MessageRowStatus, MessageRowThread, MessageSystemRowProps, } from "./MessageRow";
|
|
44
45
|
export { MessageEventGroup, MessageEventRow, MessageRow, MessageSystemRow, startsMessageGroup } from "./MessageRow";
|
|
45
46
|
export { type MapPaletteColors, type MapTheme, mapPalette } from "./map-palette";
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import type { Extension } from "@codemirror/state";
|
|
2
|
+
import { type JSX } from "solid-js";
|
|
3
|
+
import { type DropdownPosition } from "../actions/Dropdown";
|
|
4
|
+
import { type TextEditorController, type TextEditorMode, type TextEditorOptions } from "./engine";
|
|
5
|
+
import { type InlineFormat } from "./format";
|
|
6
|
+
import { type TableHost } from "./table";
|
|
7
|
+
export type TextEditorProps = {
|
|
8
|
+
label: string;
|
|
9
|
+
initialValue?: string;
|
|
10
|
+
mode?: TextEditorMode;
|
|
11
|
+
onModeChange?: (mode: TextEditorMode) => void;
|
|
12
|
+
readOnly?: boolean;
|
|
13
|
+
loading?: boolean;
|
|
14
|
+
placeholder?: string;
|
|
15
|
+
extensions?: Extension;
|
|
16
|
+
/** Host-owned Markdown presentation; see `createTextEditor`. The host then also styles the editor surface. */
|
|
17
|
+
presentation?: TextEditorOptions["presentation"];
|
|
18
|
+
/** `false` when the host renders its own formatting toolbar and mode control; place `controls.TableMenu` in it. */
|
|
19
|
+
toolbar?: boolean;
|
|
20
|
+
/** Collaboration supplies history and server-owned structure here. */
|
|
21
|
+
host?: Pick<TableHost, "structure" | "renderCell" | "onCellSelection" | "tabMovesFocus"> & Partial<Pick<TableHost, "undo" | "redo" | "boundary">>;
|
|
22
|
+
maxLength: number;
|
|
23
|
+
maxPasteCells?: number;
|
|
24
|
+
onChange?: (text: string) => void;
|
|
25
|
+
onReady?: (editor: TextEditorController, controls: TextEditorControls) => void;
|
|
26
|
+
/** Return `true` when the host attached the images itself; otherwise the editor shows its attachment hint. */
|
|
27
|
+
onDroppedImages?: (count: number, files: File[]) => boolean | void;
|
|
28
|
+
/** Opens the host's attachment picker when clipboard images cannot be inserted. */
|
|
29
|
+
onAttachImages?: () => void;
|
|
30
|
+
onTableCheck?: (needsCheck: boolean) => void;
|
|
31
|
+
/** Host-owned sync status; its place is reserved across transitions. */
|
|
32
|
+
status?: JSX.Element;
|
|
33
|
+
class?: string;
|
|
34
|
+
};
|
|
35
|
+
export type TableSizePickerProps = {
|
|
36
|
+
maxRows: number;
|
|
37
|
+
maxColumns: number;
|
|
38
|
+
onPick: (size: {
|
|
39
|
+
rows: number;
|
|
40
|
+
columns: number;
|
|
41
|
+
}) => void;
|
|
42
|
+
/** Share this picker with slash commands or secondary menus. */
|
|
43
|
+
onReady?: (open: () => void) => void;
|
|
44
|
+
disabled?: boolean;
|
|
45
|
+
class?: string;
|
|
46
|
+
size?: "xs" | "sm";
|
|
47
|
+
};
|
|
48
|
+
/** Shared table-size control: pointer grid on desktop, large fields in a phone sheet. */
|
|
49
|
+
export declare function TableSizePicker(props: TableSizePickerProps): JSX.Element;
|
|
50
|
+
type TableMenuTrigger = {
|
|
51
|
+
text?: string;
|
|
52
|
+
class?: string;
|
|
53
|
+
size?: "xs" | "sm";
|
|
54
|
+
position?: DropdownPosition;
|
|
55
|
+
};
|
|
56
|
+
/** Shared table controls for a host-owned toolbar (`toolbar={false}`). */
|
|
57
|
+
export type TextEditorControls = {
|
|
58
|
+
/** A table cell has focus in the formatted view. */
|
|
59
|
+
tableActive: () => boolean;
|
|
60
|
+
/** The shared cell menu behind a host-styled trigger; on phones it opens as a sheet. */
|
|
61
|
+
TableMenu: (props: TableMenuTrigger) => JSX.Element;
|
|
62
|
+
/** Formats the focused cell's selection; `false` when no cell has focus. */
|
|
63
|
+
formatCell: (format: InlineFormat) => boolean;
|
|
64
|
+
/** Shows a host message, such as a server's reason for a rejected table action, in the editor's notice. */
|
|
65
|
+
notify: (message: string) => void;
|
|
66
|
+
};
|
|
67
|
+
/** A Markdown text field with app-injected collaboration and a directly editable table view. */
|
|
68
|
+
export declare function TextEditor(props: TextEditorProps): JSX.Element;
|
|
69
|
+
export {};
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/** Parse only the HTML vocabulary that the Markdown converter consumes.
|
|
2
|
+
* Resource attributes and active elements never reach a clipboard consumer.
|
|
3
|
+
* The returned detached body is read as data and never mounted in the editor.
|
|
4
|
+
*/
|
|
5
|
+
export declare const parseClipboardHtml: (html: string) => HTMLElement;
|
|
6
|
+
export declare const convertHtml: (html: string, code: boolean) => {
|
|
7
|
+
markdown: string;
|
|
8
|
+
droppedImages: number;
|
|
9
|
+
} | null;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { type EditorView, ViewPlugin } from "@codemirror/view";
|
|
2
|
+
import type { TableHost } from "./table";
|
|
3
|
+
/** Load the HTML sanitizer only when needed, before either paste consumer runs.
|
|
4
|
+
* A delayed paste never overwrites edits made while its parser was loading.
|
|
5
|
+
*/
|
|
6
|
+
export declare const clipboardLoading: (getHost: (view: EditorView) => TableHost | null, syncSelection?: (view: EditorView) => void) => ViewPlugin<{
|
|
7
|
+
destroy(): void;
|
|
8
|
+
}, undefined>;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
export declare const htmlClipboardReady: () => boolean;
|
|
2
|
+
export declare const loadHtmlClipboard: () => Promise<void>;
|
|
3
|
+
export declare const parseClipboardHtml: (html: string) => HTMLElement;
|
|
4
|
+
export declare const convertClipboardHtml: (html: string, code: boolean) => {
|
|
5
|
+
markdown: string;
|
|
6
|
+
droppedImages: number;
|
|
7
|
+
} | null;
|
|
8
|
+
/** All clipboard entry paths share one preflight, before insertion or conversion. */
|
|
9
|
+
export declare function inspectClipboard(data: DataTransfer, limits: {
|
|
10
|
+
maxLength: number;
|
|
11
|
+
maxPasteCells: number;
|
|
12
|
+
}): {
|
|
13
|
+
error: "textTooLarge" | "pasteTooLarge";
|
|
14
|
+
} | {
|
|
15
|
+
text: string;
|
|
16
|
+
html: string;
|
|
17
|
+
images: number;
|
|
18
|
+
files: File[];
|
|
19
|
+
tsv: string[][] | null;
|
|
20
|
+
};
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { type Extension } from "@codemirror/state";
|
|
2
|
+
import { EditorView } from "@codemirror/view";
|
|
3
|
+
import { type TableHost } from "./table";
|
|
4
|
+
export type TextEditorMode = "formatted" | "source" | "plain";
|
|
5
|
+
export type TextEditorOptions = {
|
|
6
|
+
parent: HTMLElement;
|
|
7
|
+
/** Initial Markdown. Subsequent collaborative changes arrive through extensions. */
|
|
8
|
+
doc?: string;
|
|
9
|
+
mode?: TextEditorMode;
|
|
10
|
+
readOnly?: boolean;
|
|
11
|
+
placeholder?: string;
|
|
12
|
+
label: string;
|
|
13
|
+
extensions?: Extension;
|
|
14
|
+
/**
|
|
15
|
+
* Replaces the built-in Markdown language, highlighting, formatted markers and
|
|
16
|
+
* formatting keys of the formatted and source modes. The engine keeps the
|
|
17
|
+
* table grid, clean paste, limits and history routing in every mode.
|
|
18
|
+
*/
|
|
19
|
+
presentation?: (mode: Exclude<TextEditorMode, "plain">) => Extension;
|
|
20
|
+
/** The host owns history; collaboration bindings supply theirs. */
|
|
21
|
+
host: TableHost;
|
|
22
|
+
onChange?: (text: string) => void;
|
|
23
|
+
onDroppedImages?: (count: number, files: File[]) => void;
|
|
24
|
+
};
|
|
25
|
+
/** Shared engine; application extensions own transport, awareness and domain features. */
|
|
26
|
+
export declare function createTextEditor(options: TextEditorOptions): {
|
|
27
|
+
view: EditorView;
|
|
28
|
+
/** Also re-reads `presentation`, so a host can refresh it, e.g. after a theme change. */
|
|
29
|
+
setMode: (mode: TextEditorMode) => void;
|
|
30
|
+
setLabel: (label: string) => void;
|
|
31
|
+
setReadOnly: (readOnly: boolean) => void;
|
|
32
|
+
destroy: () => void;
|
|
33
|
+
};
|
|
34
|
+
export type TextEditorController = ReturnType<typeof createTextEditor>;
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/** Toolbar and keyboard commands. Each one is a plain Markdown edit of the selection. */
|
|
2
|
+
import { type EditorState, Facet, type TransactionSpec } from "@codemirror/state";
|
|
3
|
+
import type { EditorView } from "@codemirror/view";
|
|
4
|
+
/** Insertion text follows the editor's inherited locale, including keyboard commands. */
|
|
5
|
+
export declare const formatLabels: Facet<{
|
|
6
|
+
link: string;
|
|
7
|
+
column: (column: number) => string;
|
|
8
|
+
}, {
|
|
9
|
+
link: string;
|
|
10
|
+
column: (column: number) => string;
|
|
11
|
+
}>;
|
|
12
|
+
/** Named Markdown marks or an app's single-line paired delimiter (for example Notebook's `==`). */
|
|
13
|
+
export type InlineFormat = "bold" | "italic" | "code" | "strike" | "link" | {
|
|
14
|
+
marker: string;
|
|
15
|
+
};
|
|
16
|
+
/** Pure transaction spec, also used when a missing table cell must be materialized atomically. */
|
|
17
|
+
export declare const inlineFormat: (state: EditorState, name: InlineFormat) => TransactionSpec;
|
|
18
|
+
export declare const commands: {
|
|
19
|
+
bold: (view: EditorView) => boolean;
|
|
20
|
+
italic: (view: EditorView) => boolean;
|
|
21
|
+
code: (view: EditorView) => boolean;
|
|
22
|
+
strike: (view: EditorView) => boolean;
|
|
23
|
+
heading: (view: EditorView) => boolean;
|
|
24
|
+
heading1: (view: EditorView) => boolean;
|
|
25
|
+
heading2: (view: EditorView) => boolean;
|
|
26
|
+
heading3: (view: EditorView) => boolean;
|
|
27
|
+
codeBlock: (view: EditorView) => boolean;
|
|
28
|
+
bulletList: (view: EditorView) => boolean;
|
|
29
|
+
orderedList: (view: EditorView) => boolean;
|
|
30
|
+
quote: (view: EditorView) => boolean;
|
|
31
|
+
link: (view: EditorView) => boolean;
|
|
32
|
+
table: (view: EditorView) => boolean;
|
|
33
|
+
rule: (view: EditorView) => boolean;
|
|
34
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const formattedView: import("@codemirror/state").Extension[];
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Markdown language without `@codemirror/lang-markdown`: that package pulls in
|
|
3
|
+
* `@codemirror/lang-html` (and with it CSS and JavaScript) for HTML blocks.
|
|
4
|
+
* The shared editor needs only the GFM tree, so it wraps `@lezer/markdown`.
|
|
5
|
+
*/
|
|
6
|
+
import { Language, LanguageSupport } from "@codemirror/language";
|
|
7
|
+
export declare const markdownLanguage: Language;
|
|
8
|
+
export declare const markdown: () => LanguageSupport;
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pure GFM table edits in original Markdown coordinates. Markdown is the only
|
|
3
|
+
* model; callers reparse after applying a transaction. No repair of damaged
|
|
4
|
+
* tables or prose is attempted. Extra and missing body cells remain inspectable.
|
|
5
|
+
*/
|
|
6
|
+
import type { ChangeDesc } from "@codemirror/state";
|
|
7
|
+
export type Align = "left" | "center" | "right" | null;
|
|
8
|
+
export type Change = {
|
|
9
|
+
from: number;
|
|
10
|
+
to: number;
|
|
11
|
+
insert: string;
|
|
12
|
+
};
|
|
13
|
+
/** Trimmed raw content, with absolute UTF-16 source offsets. */
|
|
14
|
+
export type Cell = {
|
|
15
|
+
from: number;
|
|
16
|
+
to: number;
|
|
17
|
+
text: string;
|
|
18
|
+
};
|
|
19
|
+
export type Line = {
|
|
20
|
+
from: number;
|
|
21
|
+
to: number;
|
|
22
|
+
pipes: number[];
|
|
23
|
+
leadingPipe: boolean;
|
|
24
|
+
trailingPipe: boolean;
|
|
25
|
+
cells: Cell[];
|
|
26
|
+
/** Original terminator, used when inserting rows. */
|
|
27
|
+
lineBreak?: string;
|
|
28
|
+
};
|
|
29
|
+
export type Table = {
|
|
30
|
+
from: number;
|
|
31
|
+
to: number;
|
|
32
|
+
/** Header, delimiter, then body rows. */
|
|
33
|
+
lines: Line[];
|
|
34
|
+
align: Align[];
|
|
35
|
+
columns: number;
|
|
36
|
+
};
|
|
37
|
+
/** Only top-level Lezer GFM tables: never code, block quotes, or list items. */
|
|
38
|
+
export declare const findTables: (doc: string) => Table[];
|
|
39
|
+
export declare const tableAt: (doc: string, pos: number) => Table | null;
|
|
40
|
+
/**
|
|
41
|
+
* Problems that must stay visible before formatted output is sent. A damaged
|
|
42
|
+
* separator makes GFM fall back to a paragraph: two adjacent pipe-framed rows
|
|
43
|
+
* there still need review. This only inspects top-level paragraph nodes, never
|
|
44
|
+
* code, quotations or lists, and does not repair or rewrite any text.
|
|
45
|
+
*/
|
|
46
|
+
export declare const inspectTableStructure: (doc: string) => {
|
|
47
|
+
extraCells: boolean;
|
|
48
|
+
missingSeparator: boolean;
|
|
49
|
+
};
|
|
50
|
+
export declare const gridLine: (table: Table, row: number) => Line | undefined;
|
|
51
|
+
export declare const rowCount: (table: Table) => number;
|
|
52
|
+
/** Literal displayed text → safe raw content. Call once, never on existing raw Markdown. */
|
|
53
|
+
export declare const escapeCell: (value: string) => string;
|
|
54
|
+
/** Display text and a raw offset for every displayed UTF-16 boundary. */
|
|
55
|
+
export declare const cellDisplayMap: (raw: string) => {
|
|
56
|
+
text: string;
|
|
57
|
+
offsets: number[];
|
|
58
|
+
};
|
|
59
|
+
/** Decode only table pipes and backslashes; leave inline Markdown source editable. */
|
|
60
|
+
export declare const displayCell: (raw: string) => string;
|
|
61
|
+
/**
|
|
62
|
+
* One minimal contiguous source edit from literal displayed input. Unchanged
|
|
63
|
+
* escapes keep their exact bytes, including noncanonical lone backslashes.
|
|
64
|
+
* `from` is the old cell's absolute start; input must NOT be pre-escaped.
|
|
65
|
+
*/
|
|
66
|
+
export declare const cellChanges: (raw: string, nextDisplayed: string, from: number) => Change[];
|
|
67
|
+
/**
|
|
68
|
+
* Map an edit based on an old cell through intervening document changes.
|
|
69
|
+
* Deletes only surviving old-source spans (iterGaps), preserving remote inserts
|
|
70
|
+
* and excluding replaced/deleted identities. Returns current-document offsets.
|
|
71
|
+
* The caller must first verify that the mapped range is still the same cell;
|
|
72
|
+
* concurrent structural/escape edits require resyncing its displayed snapshot.
|
|
73
|
+
*/
|
|
74
|
+
export declare const mappedCellChanges: (raw: string, nextDisplayed: string, from: number, changes: ChangeDesc) => Change[];
|
|
75
|
+
/** Spike-compatible escaped RAW input; fills ragged cells within the existing grid width. */
|
|
76
|
+
export declare const setCellText: (table: Table, row: number, col: number, next: string) => Change[];
|
|
77
|
+
export declare const insertRow: (table: Table, after: number) => Change[];
|
|
78
|
+
export declare const deleteRow: (table: Table, row: number) => Change[];
|
|
79
|
+
/** Move a body row, retaining every untouched row's original source and identities. */
|
|
80
|
+
export declare const moveRow: (source: string, table: Table, row: number, to: number) => Change[];
|
|
81
|
+
/** Swap adjacent columns, including their alignment, without rewriting other cells. */
|
|
82
|
+
export declare const moveColumn: (table: Table, column: number, to: number) => Change[];
|
|
83
|
+
/** A hidden header is an empty GFM header; its former values become the first body row. */
|
|
84
|
+
export declare const toggleHeader: (source: string, table: Table) => Change[];
|
|
85
|
+
/** Delete only the selected table; surrounding prose remains byte-for-byte intact. */
|
|
86
|
+
export declare const deleteTable: (table: Table) => Change[];
|
|
87
|
+
/** Insert before `at`, including at the widest row's end; pad ragged rows without dropping cells. */
|
|
88
|
+
export declare const insertColumn: (table: Table, at: number) => Change[];
|
|
89
|
+
/** Complete a ragged grid without changing or removing any existing cell. */
|
|
90
|
+
export declare const completeColumns: (table: Table) => Change[];
|
|
91
|
+
export declare const deleteColumn: (table: Table, col: number) => Change[];
|
|
92
|
+
export declare const setAlign: (table: Table, col: number, align: Align) => Change[];
|
|
93
|
+
/** First grid row is the header; pad short rows, preserve every extra cell. */
|
|
94
|
+
export declare const tableFromGrid: (grid: string[][]) => string;
|
|
95
|
+
/** Quoted TSV (including doubled quotes and embedded newlines). Invalid quotes stay raw. */
|
|
96
|
+
export declare const parseTsv: (text: string) => string[][] | null;
|
|
97
|
+
/** Apply sorted or unsorted, non-overlapping edits in old-document coordinates. */
|
|
98
|
+
export declare const applyChanges: (doc: string, changes: Change[]) => string;
|
|
99
|
+
/**
|
|
100
|
+
* Settle recognized ragged GFM tables without deleting or rewriting source.
|
|
101
|
+
* Extra cells become named-grid positions with empty headers, never discarded.
|
|
102
|
+
* Unrecognizable tables remain raw text for the application's check state;
|
|
103
|
+
* code, quotes and lists are not repair candidates.
|
|
104
|
+
*/
|
|
105
|
+
export declare const repairTables: (doc: string, maxLength: number) => Change[];
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
export declare const textEditorMessages: import("@k2b/stdlib").Catalog<{
|
|
2
|
+
formatting: string;
|
|
3
|
+
formatted: string;
|
|
4
|
+
source: string;
|
|
5
|
+
view: string;
|
|
6
|
+
loading: string;
|
|
7
|
+
bold: string;
|
|
8
|
+
italic: string;
|
|
9
|
+
heading: string;
|
|
10
|
+
heading1: string;
|
|
11
|
+
heading2: string;
|
|
12
|
+
heading3: string;
|
|
13
|
+
strike: string;
|
|
14
|
+
codeBlock: string;
|
|
15
|
+
inlineCode: string;
|
|
16
|
+
column: (column: number) => string;
|
|
17
|
+
menuRow: (row: number) => string;
|
|
18
|
+
menuColumn: (name: string) => string;
|
|
19
|
+
menuAbove: string;
|
|
20
|
+
menuBelow: string;
|
|
21
|
+
menuUp: string;
|
|
22
|
+
menuDown: string;
|
|
23
|
+
menuInsertLeft: string;
|
|
24
|
+
menuInsertRight: string;
|
|
25
|
+
menuMoveLeft: string;
|
|
26
|
+
menuMoveRight: string;
|
|
27
|
+
menuDelete: string;
|
|
28
|
+
menuCopy: string;
|
|
29
|
+
menuMarkdown: string;
|
|
30
|
+
columnAlignment: (column: number) => string;
|
|
31
|
+
discardRecovery: string;
|
|
32
|
+
bulletList: string;
|
|
33
|
+
orderedList: string;
|
|
34
|
+
quote: string;
|
|
35
|
+
link: string;
|
|
36
|
+
code: string;
|
|
37
|
+
table: string;
|
|
38
|
+
insertTable: string;
|
|
39
|
+
rows: string;
|
|
40
|
+
columns: string;
|
|
41
|
+
insertSize: ({ rows, columns }: {
|
|
42
|
+
rows: number;
|
|
43
|
+
columns: number;
|
|
44
|
+
}) => string;
|
|
45
|
+
rule: string;
|
|
46
|
+
rowAbove: string;
|
|
47
|
+
rowBelow: string;
|
|
48
|
+
colLeft: string;
|
|
49
|
+
colRight: string;
|
|
50
|
+
deleteRow: string;
|
|
51
|
+
deleteCol: string;
|
|
52
|
+
moveRowUp: string;
|
|
53
|
+
moveRowDown: string;
|
|
54
|
+
moveColLeft: string;
|
|
55
|
+
moveColRight: string;
|
|
56
|
+
toggleHeader: string;
|
|
57
|
+
deleteTable: string;
|
|
58
|
+
alignment: string;
|
|
59
|
+
copyTable: string;
|
|
60
|
+
copyMarkdown: string;
|
|
61
|
+
copyingTable: string;
|
|
62
|
+
copiedTable: string;
|
|
63
|
+
copiedMarkdown: string;
|
|
64
|
+
copyFailed: string;
|
|
65
|
+
alignLeft: string;
|
|
66
|
+
alignCenter: string;
|
|
67
|
+
alignRight: string;
|
|
68
|
+
cellLabel: ({ row, column, name }: {
|
|
69
|
+
row: number;
|
|
70
|
+
column: number;
|
|
71
|
+
name?: string;
|
|
72
|
+
}) => string;
|
|
73
|
+
structureUnavailable: string;
|
|
74
|
+
recoveredInput: string;
|
|
75
|
+
cellRemoved: string;
|
|
76
|
+
structureFailed: string;
|
|
77
|
+
pasteTooLarge: string;
|
|
78
|
+
textTooLarge: string;
|
|
79
|
+
checkTable: string;
|
|
80
|
+
checkTableDetail: string;
|
|
81
|
+
checkSeparatorDetail: string;
|
|
82
|
+
reviewMarkdown: string;
|
|
83
|
+
imageHint: string;
|
|
84
|
+
dismiss: string;
|
|
85
|
+
tableMenu: string;
|
|
86
|
+
tableChanged: ({ rows, columns }: {
|
|
87
|
+
rows: number;
|
|
88
|
+
columns: number;
|
|
89
|
+
}) => string;
|
|
90
|
+
rowMenu: string;
|
|
91
|
+
columnMenu: string;
|
|
92
|
+
addRow: string;
|
|
93
|
+
emptyCell: string;
|
|
94
|
+
editMarkdown: string;
|
|
95
|
+
showTable: string;
|
|
96
|
+
done: string;
|
|
97
|
+
markdownValid: string;
|
|
98
|
+
markdownInvalid: string;
|
|
99
|
+
markdownLine: (line: number) => string;
|
|
100
|
+
markdownSeparator: ({ header, separator }: {
|
|
101
|
+
header: number;
|
|
102
|
+
separator: number;
|
|
103
|
+
}) => string;
|
|
104
|
+
markdownExtra: (line: number) => string;
|
|
105
|
+
applyingTable: string;
|
|
106
|
+
markdownApplyFailed: string;
|
|
107
|
+
markdownStructural: string;
|
|
108
|
+
markdownChanged: string;
|
|
109
|
+
discardMarkdown: string;
|
|
110
|
+
continueMarkdown: string;
|
|
111
|
+
addColumn: string;
|
|
112
|
+
completeColumns: string;
|
|
113
|
+
}>;
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
/** HTML clipboard content as Markdown; `null` when it is better pasted as plain text. */
|
|
2
|
+
export declare const htmlToMarkdown: (html: string) => {
|
|
3
|
+
markdown: string;
|
|
4
|
+
droppedImages: number;
|
|
5
|
+
} | null;
|
|
6
|
+
export declare const cleanPaste: (onDroppedImages?: (count: number, files: File[]) => void, plain?: boolean) => import("@codemirror/state").Extension;
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import { EditorState, type Extension, Facet } from "@codemirror/state";
|
|
2
|
+
import { EditorView } from "@codemirror/view";
|
|
3
|
+
import { type InlineFormat } from "./format";
|
|
4
|
+
import * as T from "./markdown-table";
|
|
5
|
+
export type TableTarget = {
|
|
6
|
+
tableFrom: number;
|
|
7
|
+
rowFrom: number;
|
|
8
|
+
columnFrom: number;
|
|
9
|
+
row: number;
|
|
10
|
+
column: number;
|
|
11
|
+
};
|
|
12
|
+
/** Resolve a server-returned identity against the current document immediately before focus. */
|
|
13
|
+
export type TableFocusTarget = () => TableTarget | null;
|
|
14
|
+
export type TableHost = {
|
|
15
|
+
undo: () => void;
|
|
16
|
+
redo: () => void;
|
|
17
|
+
boundary: () => void;
|
|
18
|
+
cellLabel: (row: number, column: number, name?: string) => string;
|
|
19
|
+
sourceLabels?: () => {
|
|
20
|
+
edit: string;
|
|
21
|
+
valid: string;
|
|
22
|
+
invalid: string;
|
|
23
|
+
changed: string;
|
|
24
|
+
structural: string;
|
|
25
|
+
applying?: string;
|
|
26
|
+
applyFailed?: string;
|
|
27
|
+
done: string;
|
|
28
|
+
discard: string;
|
|
29
|
+
continue: string;
|
|
30
|
+
line?: (line: number) => string;
|
|
31
|
+
separator?: (header: number, separator: number) => string;
|
|
32
|
+
extra?: (line: number) => string;
|
|
33
|
+
complete?: string;
|
|
34
|
+
};
|
|
35
|
+
actionLabel?: (action: "rowMenu" | "columnMenu" | "addRow" | "addColumn" | "emptyCell") => string;
|
|
36
|
+
/** Respect a host's personal Tab-for-focus preference inside cells too. */
|
|
37
|
+
tabMovesFocus?: () => boolean;
|
|
38
|
+
/** Capture durable anchors synchronously, then send the action to the owning server. */
|
|
39
|
+
structure?: {
|
|
40
|
+
available: () => boolean;
|
|
41
|
+
perform: (action: MenuAction, target: TableTarget) => Promise<TableFocusTarget | void>;
|
|
42
|
+
/** Resolves only after the confirmed update is applied; rejects without discarding the draft. */
|
|
43
|
+
replaceSource?: (target: TableTarget, expected: string, source: string, caret: {
|
|
44
|
+
row: number;
|
|
45
|
+
column: number;
|
|
46
|
+
}) => Promise<TableFocusTarget | void>;
|
|
47
|
+
};
|
|
48
|
+
onError: (code: "structureUnavailable" | "structureFailed" | "pasteTooLarge" | "textTooLarge" | "cellRemoved") => void;
|
|
49
|
+
onRecovery: (text: string) => void;
|
|
50
|
+
/** Cell focus is separate from CodeMirror contentDOM focus; collaboration maps these offsets to its own cursor. */
|
|
51
|
+
onCellSelection?: (selection: {
|
|
52
|
+
anchor: number;
|
|
53
|
+
head: number;
|
|
54
|
+
} | null) => void;
|
|
55
|
+
onDroppedImages?: (count: number, files: File[]) => void;
|
|
56
|
+
maxLength: number;
|
|
57
|
+
maxPasteCells: number;
|
|
58
|
+
/** App-owned presentation, e.g. formula results. Called only outside the active cell. */
|
|
59
|
+
renderCell?: (element: HTMLElement, raw: string, table: T.Table, row: number, column: number) => void;
|
|
60
|
+
};
|
|
61
|
+
export type MenuAction = "completeColumns" | "rowAbove" | "rowBelow" | "colLeft" | "colRight" | "deleteRow" | "deleteCol" | "moveRowUp" | "moveRowDown" | "moveColLeft" | "moveColRight" | "toggleHeader" | "deleteTable" | "alignLeft" | "alignCenter" | "alignRight";
|
|
62
|
+
export declare const tableHost: Facet<TableHost, TableHost | null>;
|
|
63
|
+
export declare const tablesIn: (state: EditorState) => T.Table[];
|
|
64
|
+
/** A local source draft for one table. Invalid drafts never replace shared text.
|
|
65
|
+
* Collaborative structure changes require the host's confirmed anchored action. */
|
|
66
|
+
export declare const editTableSource: (view: EditorView, wrap: HTMLElement) => void;
|
|
67
|
+
export declare const tableActionEnabled: (view: EditorView, wrap: HTMLElement, action: MenuAction) => boolean;
|
|
68
|
+
/** Copy the visible table through the browser clipboard, with spreadsheet and rich-text payloads. */
|
|
69
|
+
export declare const copyTable: (view: EditorView, wrap: HTMLElement, format: "table" | "markdown") => Promise<void>;
|
|
70
|
+
export declare const runMenuAction: (view: EditorView, wrap: HTMLElement, action: MenuAction) => void;
|
|
71
|
+
/** Structural actions also work in source mode, without a mounted table widget. */
|
|
72
|
+
export declare const runTableAction: (view: EditorView, tableFrom: number, r: number, c: number, action: MenuAction,
|
|
73
|
+
/** `false` when the gesture already moved the caret out of the table: the result must not pull it back. */
|
|
74
|
+
options?: {
|
|
75
|
+
follow?: boolean;
|
|
76
|
+
}) => void;
|
|
77
|
+
/** Route formatting to the active cell instead of the hidden outer-editor caret. */
|
|
78
|
+
export declare const formatActiveCell: (view: EditorView, name: InlineFormat) => boolean;
|
|
79
|
+
/** First `<table>` of pasted HTML as a grid (Excel, Sheets, Word, web pages). */
|
|
80
|
+
export declare const htmlTableGrid: (html: string) => string[][] | null;
|
|
81
|
+
export declare const tableGrid: () => Extension;
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
export { createTextEditor, type TextEditorController, type TextEditorMode, type TextEditorOptions } from "./text-editor/engine";
|
|
2
|
+
export { commands as textEditorCommands, formatLabels as textEditorFormatLabels, type InlineFormat } from "./text-editor/format";
|
|
3
|
+
export { TableSizePicker, type TableSizePickerProps, TextEditor, type TextEditorControls, type TextEditorProps, } from "./text-editor/TextEditor";
|
|
4
|
+
export { editTableSource, type MenuAction, runMenuAction, runTableAction, type TableFocusTarget, type TableHost, type TableTarget, tableGrid, tableHost, } from "./text-editor/table";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@k2b/ui",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.35.0",
|
|
4
4
|
"description": "Production-ready components for SolidJS applications.",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -37,7 +37,18 @@
|
|
|
37
37
|
"default": "./dist/ssr/charts.js"
|
|
38
38
|
},
|
|
39
39
|
"./package.json": "./package.json",
|
|
40
|
-
"./map-glyphs/*": "./map-glyphs/*"
|
|
40
|
+
"./map-glyphs/*": "./map-glyphs/*",
|
|
41
|
+
"./text-editor": {
|
|
42
|
+
"types": "./dist/types/text-editor.d.ts",
|
|
43
|
+
"browser": "./dist/browser/text-editor.js",
|
|
44
|
+
"import": "./dist/ssr/text-editor.js",
|
|
45
|
+
"default": "./dist/ssr/text-editor.js"
|
|
46
|
+
},
|
|
47
|
+
"./text-editor/model": {
|
|
48
|
+
"types": "./dist/types/text-editor/markdown-table.d.ts",
|
|
49
|
+
"import": "./dist/ssr/text-editor/markdown-table.js",
|
|
50
|
+
"default": "./dist/ssr/text-editor/markdown-table.js"
|
|
51
|
+
}
|
|
41
52
|
},
|
|
42
53
|
"files": [
|
|
43
54
|
"dist",
|
|
@@ -55,10 +66,16 @@
|
|
|
55
66
|
"prepack": "bun run build"
|
|
56
67
|
},
|
|
57
68
|
"dependencies": {
|
|
69
|
+
"@codemirror/commands": "6.10.4",
|
|
70
|
+
"@codemirror/language": "6.12.4",
|
|
71
|
+
"@codemirror/state": "6.7.1",
|
|
72
|
+
"@codemirror/view": "6.43.7",
|
|
58
73
|
"@fontsource/ibm-plex-mono": "5.3.0",
|
|
59
74
|
"@fontsource/ibm-plex-sans": "5.3.0",
|
|
60
75
|
"@k2b/stdlib": "0.30.0",
|
|
76
|
+
"@lezer/markdown": "1.7.2",
|
|
61
77
|
"@tabler/icons-webfont": "3.48.0",
|
|
78
|
+
"dompurify": "3.4.17",
|
|
62
79
|
"maplibre-gl": "6.14.0",
|
|
63
80
|
"marked": "18.0.14",
|
|
64
81
|
"qr-scanner": "1.4.2"
|
|
@@ -86,7 +103,10 @@
|
|
|
86
103
|
"typescript": "7.0.2",
|
|
87
104
|
"@typescript/typescript6": "6.0.2",
|
|
88
105
|
"@maplibre/maplibre-gl-style-spec": "26.4.4",
|
|
89
|
-
"fontnik": "0.7.7"
|
|
106
|
+
"fontnik": "0.7.7",
|
|
107
|
+
"yjs": "13.6.33",
|
|
108
|
+
"y-codemirror.next": "0.3.6",
|
|
109
|
+
"y-protocols": "1.0.7"
|
|
90
110
|
},
|
|
91
111
|
"publishConfig": {
|
|
92
112
|
"access": "public"
|