smartrte-react 0.3.5 → 1.0.0-beta.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (141) hide show
  1. package/CHANGELOG.md +10 -0
  2. package/README.md +106 -14
  3. package/dist/adapters/domChecklistCommandBridge.js +1 -1
  4. package/dist/adapters/domCommandBridge.d.ts +2 -2
  5. package/dist/adapters/domCommandBridge.js +2 -2
  6. package/dist/adapters/domInlineAtomCommandBridge.d.ts +10 -9
  7. package/dist/adapters/domInlineAtomCommandBridge.js +154 -50
  8. package/dist/adapters/domInlineImageCommandBridge.d.ts +7 -7
  9. package/dist/adapters/domInlineImageCommandBridge.js +6 -72
  10. package/dist/adapters/domMoveCommandBridge.js +1 -1
  11. package/dist/adapters/domSelectionBridge.d.ts +3 -3
  12. package/dist/adapters/domSmartDocument.d.ts +4 -4
  13. package/dist/adapters/domSmartDocument.js +2 -2
  14. package/dist/adapters/domTableCommandBridge.d.ts +42 -16
  15. package/dist/adapters/domTableCommandBridge.js +203 -173
  16. package/dist/adapters/internalFlags.d.ts +0 -8
  17. package/dist/adapters/internalFlags.js +0 -24
  18. package/dist/adapters/legacyListShadowComparator.d.ts +1 -1
  19. package/dist/adapters/legacyListShadowComparator.js +1 -1
  20. package/dist/adapters/pdfPrint.d.ts +8 -0
  21. package/dist/adapters/pdfPrint.js +22 -0
  22. package/dist/adapters/shadowMode.d.ts +3 -3
  23. package/dist/adapters/shadowMode.js +1 -1
  24. package/dist/canonicalEditorRuntime.d.ts +53 -1
  25. package/dist/canonicalEditorRuntime.js +61 -4
  26. package/dist/capabilityPresets.d.ts +27 -0
  27. package/dist/capabilityPresets.js +21 -0
  28. package/dist/collabTransport.d.ts +66 -0
  29. package/dist/collabTransport.js +1 -0
  30. package/dist/commentProvider.d.ts +24 -0
  31. package/dist/commentProvider.js +1 -0
  32. package/dist/components/CanonicalAuthorityEditor.d.ts +35 -1
  33. package/dist/components/CanonicalAuthorityEditor.js +1086 -112
  34. package/dist/components/ClassicEditorAuthority.d.ts +93 -22
  35. package/dist/components/ClassicEditorAuthority.js +11 -43
  36. package/dist/components/ColorPickerPopover.d.ts +39 -0
  37. package/dist/components/ColorPickerPopover.js +285 -0
  38. package/dist/components/CommentMarkers.d.ts +25 -0
  39. package/dist/components/CommentMarkers.js +105 -0
  40. package/dist/components/CommentThreadPanel.d.ts +26 -0
  41. package/dist/components/CommentThreadPanel.js +47 -0
  42. package/dist/components/ContextMenu.d.ts +23 -0
  43. package/dist/components/ContextMenu.js +141 -0
  44. package/dist/components/FormulaLibraryPopover.d.ts +16 -0
  45. package/dist/components/FormulaLibraryPopover.js +107 -0
  46. package/dist/components/LinkEditorPopover.d.ts +3 -1
  47. package/dist/components/LinkEditorPopover.js +22 -6
  48. package/dist/components/MediaManager.d.ts +4 -20
  49. package/dist/components/MediaManager.js +35 -6
  50. package/dist/components/MediaOverlay.d.ts +36 -0
  51. package/dist/components/MediaOverlay.js +163 -0
  52. package/dist/components/SpecialCharacterPopover.d.ts +18 -0
  53. package/dist/components/SpecialCharacterPopover.js +99 -0
  54. package/dist/components/StructuralSuggestionMarkers.d.ts +20 -0
  55. package/dist/components/StructuralSuggestionMarkers.js +56 -0
  56. package/dist/components/SuggestionPanel.d.ts +26 -0
  57. package/dist/components/SuggestionPanel.js +33 -0
  58. package/dist/components/TableBorderPopover.d.ts +59 -0
  59. package/dist/components/TableBorderPopover.js +147 -0
  60. package/dist/components/TableResizeHandles.d.ts +25 -0
  61. package/dist/components/TableResizeHandles.js +301 -0
  62. package/dist/components/TableSizePickerPopover.d.ts +16 -0
  63. package/dist/components/TableSizePickerPopover.js +126 -0
  64. package/dist/components/ToolbarPrimitives.d.ts +129 -0
  65. package/dist/components/ToolbarPrimitives.js +146 -0
  66. package/dist/components/VersionHistoryPanel.d.ts +9 -0
  67. package/dist/components/VersionHistoryPanel.js +157 -0
  68. package/dist/formulaLibrary.d.ts +31 -0
  69. package/dist/formulaLibrary.js +90 -0
  70. package/dist/index.d.ts +22 -24
  71. package/dist/index.js +14 -11
  72. package/dist/mediaManagerAdapter.d.ts +12 -0
  73. package/dist/mediaManagerAdapter.js +34 -0
  74. package/dist/mediaProvider.d.ts +21 -1
  75. package/dist/specialCharacters.d.ts +22 -0
  76. package/dist/specialCharacters.js +86 -0
  77. package/dist/standalone/classic-editor-embed.js +19 -12
  78. package/dist/suggestionProvider.d.ts +17 -0
  79. package/dist/suggestionProvider.js +1 -0
  80. package/dist/theme.d.ts +1 -1
  81. package/dist/theme.js +133 -1
  82. package/dist/versionProvider.d.ts +29 -0
  83. package/dist/versionProvider.js +1 -0
  84. package/package.json +28 -14
  85. package/dist/adapters/canonicalInlineCommandBridge.d.ts +0 -15
  86. package/dist/adapters/canonicalInlineCommandBridge.js +0 -269
  87. package/dist/adapters/canonicalListCommandBridge.d.ts +0 -26
  88. package/dist/adapters/canonicalListCommandBridge.js +0 -430
  89. package/dist/adapters/coreBold.d.ts +0 -5
  90. package/dist/adapters/coreBold.js +0 -3
  91. package/dist/adapters/documentFormats.d.ts +0 -26
  92. package/dist/adapters/documentFormats.js +0 -49
  93. package/dist/adapters/docxFormat.d.ts +0 -5
  94. package/dist/adapters/docxFormat.js +0 -272
  95. package/dist/adapters/domBlockCommandBridge.d.ts +0 -19
  96. package/dist/adapters/domBlockCommandBridge.js +0 -79
  97. package/dist/adapters/inlineMarkCoreExecution.d.ts +0 -9
  98. package/dist/adapters/inlineMarkCoreExecution.js +0 -25
  99. package/dist/adapters/pdfFormat.d.ts +0 -23
  100. package/dist/adapters/pdfFormat.js +0 -204
  101. package/dist/adapters/portableDocxAtoms.d.ts +0 -4
  102. package/dist/adapters/portableDocxAtoms.js +0 -58
  103. package/dist/adapters/styledDocxFormat.d.ts +0 -8
  104. package/dist/adapters/styledDocxFormat.js +0 -190
  105. package/dist/builtInFormatDefinitions.d.ts +0 -5
  106. package/dist/builtInFormatDefinitions.js +0 -82
  107. package/dist/canonicalAuthorityFlag.d.ts +0 -32
  108. package/dist/canonicalAuthorityFlag.js +0 -49
  109. package/dist/canonicalClipboardRuntime.d.ts +0 -15
  110. package/dist/canonicalClipboardRuntime.js +0 -76
  111. package/dist/components/ClassicEditor.d.ts +0 -76
  112. package/dist/components/ClassicEditor.js +0 -6729
  113. package/dist/editorController.d.ts +0 -78
  114. package/dist/editorController.js +0 -298
  115. package/dist/formatFidelity.d.ts +0 -14
  116. package/dist/formatFidelity.js +0 -107
  117. package/dist/formatRuntime.d.ts +0 -50
  118. package/dist/formatRuntime.js +0 -20
  119. package/dist/pluginRuntime.d.ts +0 -68
  120. package/dist/pluginRuntime.js +0 -78
  121. package/dist/standalone/editor.js +0 -1068
  122. package/dist/test-harness/atomShadowComparator.d.ts +0 -14
  123. package/dist/test-harness/atomShadowComparator.js +0 -63
  124. package/dist/test-harness/blockShadowComparator.d.ts +0 -30
  125. package/dist/test-harness/blockShadowComparator.js +0 -140
  126. package/dist/test-harness/clipboardShadowComparator.d.ts +0 -12
  127. package/dist/test-harness/clipboardShadowComparator.js +0 -46
  128. package/dist/test-harness/inlineShadowComparator.d.ts +0 -32
  129. package/dist/test-harness/inlineShadowComparator.js +0 -152
  130. package/dist/test-harness/legacyAtomEngine.d.ts +0 -10
  131. package/dist/test-harness/legacyAtomEngine.js +0 -15
  132. package/dist/test-harness/legacyBlockEngine.d.ts +0 -31
  133. package/dist/test-harness/legacyBlockEngine.js +0 -31
  134. package/dist/test-harness/legacyClipboardEngine.d.ts +0 -14
  135. package/dist/test-harness/legacyClipboardEngine.js +0 -67
  136. package/dist/test-harness/legacyInlineEngine.d.ts +0 -19
  137. package/dist/test-harness/legacyInlineEngine.js +0 -49
  138. package/dist/test-harness/legacyTableEngine.d.ts +0 -12
  139. package/dist/test-harness/legacyTableEngine.js +0 -25
  140. package/dist/test-harness/tableShadowComparator.d.ts +0 -29
  141. package/dist/test-harness/tableShadowComparator.js +0 -101
@@ -0,0 +1,29 @@
1
+ import type { DocumentVersion } from "smartrte-core/foundation";
2
+ /**
3
+ * The listing-cheap projection of a `DocumentVersion` - a host's backend
4
+ * shouldn't have to ship every saved version's full document body just to
5
+ * render a history list. Mirrors `MediaProvider.search` returning
6
+ * `MediaItem` (metadata) rather than raw asset bytes.
7
+ */
8
+ export interface VersionListEntry {
9
+ readonly id: string;
10
+ readonly label?: string;
11
+ readonly createdAt: number;
12
+ readonly authorId?: string;
13
+ }
14
+ /**
15
+ * Host-owned version-storage boundary, mirroring `MediaProvider`'s shape
16
+ * and its "the editor never persists anything itself" contract: the host
17
+ * backend is the source of truth, and `save`/`list`/`load`/`remove` are
18
+ * the entire boundary. There is deliberately no shipped default
19
+ * implementation, exactly like `MediaProvider` - when a host doesn't
20
+ * supply one, the version-history feature is simply unavailable, the same
21
+ * way the media toolbar buttons are disabled when `mediaProvider` is
22
+ * absent.
23
+ */
24
+ export interface VersionProvider {
25
+ save(version: DocumentVersion): Promise<VersionListEntry>;
26
+ list(): Promise<readonly VersionListEntry[]>;
27
+ load(id: string): Promise<DocumentVersion>;
28
+ remove(id: string): Promise<void>;
29
+ }
@@ -0,0 +1 @@
1
+ export {};
package/package.json CHANGED
@@ -1,15 +1,26 @@
1
1
  {
2
2
  "name": "smartrte-react",
3
- "version": "0.3.5",
3
+ "version": "1.0.0-beta.1",
4
4
  "description": "A powerful, feature-rich Rich Text Editor for React with support for tables, mathematical formulas (LaTeX/KaTeX), and media management",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
7
7
  "module": "dist/index.js",
8
8
  "types": "dist/index.d.ts",
9
+ "exports": {
10
+ ".": {
11
+ "types": "./dist/index.d.ts",
12
+ "import": "./dist/index.js"
13
+ },
14
+ "./standalone/classic-editor-embed": {
15
+ "types": "./dist/standalone/classic-editor-embed.d.ts",
16
+ "import": "./dist/standalone/classic-editor-embed.js"
17
+ }
18
+ },
9
19
  "files": [
10
20
  "dist",
11
21
  "!dist/**/*.test.js",
12
22
  "!dist/**/*.test.d.ts",
23
+ "!dist/test-harness/**",
13
24
  "README.md",
14
25
  "CHANGELOG.md"
15
26
  ],
@@ -41,16 +52,6 @@
41
52
  },
42
53
  "author": "Smart RTE Contributors",
43
54
  "license": "MIT",
44
- "scripts": {
45
- "build": "tsc -p tsconfig.json",
46
- "prepublishOnly": "npm run build",
47
- "dev": "pnpm build",
48
- "lint": "tsc -p tsconfig.json --noEmit",
49
- "test": "vitest run --passWithNoTests",
50
- "storybook": "storybook dev -p 6006",
51
- "build-storybook": "storybook build",
52
- "e2e": "playwright test --pass-with-no-tests"
53
- },
54
55
  "publishConfig": {
55
56
  "access": "public"
56
57
  },
@@ -60,16 +61,18 @@
60
61
  "react-dom": ">=18"
61
62
  },
62
63
  "devDependencies": {
64
+ "@axe-core/playwright": "^4.12.1",
63
65
  "@playwright/test": "^1.48.2",
64
66
  "@storybook/addon-essentials": "^8.6.14",
65
67
  "@storybook/react": "^8.6.14",
66
68
  "@storybook/react-vite": "^8.6.14",
69
+ "@types/node": "^22",
67
70
  "@types/pdfjs-dist": "^2.10.377",
68
71
  "@types/react": "^18.3.4",
69
72
  "@types/react-dom": "^18.3.0",
73
+ "jsdom": "^25.0.1",
70
74
  "react": "18.3.1",
71
75
  "react-dom": "18.3.1",
72
- "jsdom": "^25.0.1",
73
76
  "storybook": "^8.6.14",
74
77
  "typescript": "^5.6.2",
75
78
  "vite": "^5.4.8",
@@ -77,8 +80,19 @@
77
80
  },
78
81
  "dependencies": {
79
82
  "jszip": "^3.10.1",
83
+ "katex": "^0.18.4",
84
+ "lucide-react": "^1.35.0",
80
85
  "mammoth": "^1.11.0",
81
86
  "pdfjs-dist": "^5.4.530",
82
- "smartrte-core": "^0.2.1"
87
+ "smartrte-core": "^1.0.0-beta.1"
88
+ },
89
+ "scripts": {
90
+ "build": "rm -rf dist && tsc -p tsconfig.json",
91
+ "dev": "pnpm build",
92
+ "lint": "tsc -p tsconfig.json --noEmit",
93
+ "test": "vitest run --passWithNoTests",
94
+ "storybook": "storybook dev -p 6006",
95
+ "build-storybook": "storybook build",
96
+ "e2e": "pnpm --filter smartrte-core build && pnpm build && playwright test --pass-with-no-tests"
83
97
  }
84
- }
98
+ }
@@ -1,15 +0,0 @@
1
- import { inlineToolDeclarations, type Attrs, type SmartMark } from "smartrte-core";
2
- export type CanonicalInlineToolId = typeof inlineToolDeclarations[number]["id"];
3
- export type CanonicalInlineIntent = "apply" | "remove" | "toggle" | "setAttrs" | "clearAll" | "editLink";
4
- export interface CanonicalInlineExecution {
5
- readonly changed: boolean;
6
- readonly operations: number;
7
- readonly coverage: "all" | "partial" | "none";
8
- }
9
- export declare const executeCanonicalInlineTool: (root: HTMLElement, id: CanonicalInlineToolId, intent?: CanonicalInlineIntent, attrs?: Attrs) => CanonicalInlineExecution;
10
- /** Consumes adapter stored marks for ordinary text input. Composition remains
11
- * owned by the canonical surface; atom-aware composition is explicitly Phase 7. */
12
- export declare const installCanonicalInlineStoredMarkInput: (root: HTMLElement) => (() => void);
13
- export declare const canonicalInlineStoredMarks: (root: HTMLElement) => readonly SmartMark[];
14
- export declare const hasCanonicalInlineStoredMarkOverride: (root: HTMLElement) => boolean;
15
- export declare const describeCanonicalInlineCoverage: (root: HTMLElement) => Readonly<Record<string, "all" | "partial">>;
@@ -1,269 +0,0 @@
1
- import { applyMarkCommand, applyOperations, clearAllMarksCommand, createFoundationEditor, createNodeId, createScopeIndex, editLinkCommand, executeMarkTool, foundationSchema, inlineToolDeclarations, parseCanonicalListHtml, removeLinkCommand, removeMarkCommand, serializeCanonicalListHtml, toggleMarkCommand, } from "smartrte-core";
2
- const storedMarks = new WeakMap();
3
- const ownerSelector = "p,h1,h2,h3,h4,h5,h6";
4
- const ownerId = (owner) => {
5
- var _a;
6
- (_a = owner.dataset).smartId || (_a.smartId = createNodeId());
7
- return owner.dataset.smartId;
8
- };
9
- const contentWidth = (node) => {
10
- if (node.nodeType === node.TEXT_NODE)
11
- return node.nodeValue?.length || 0;
12
- if (!(node instanceof HTMLElement))
13
- return [...node.childNodes].reduce((sum, child) => sum + contentWidth(child), 0);
14
- if (node.closest("[data-smart-ui]"))
15
- return 0;
16
- if (node.matches("br,[data-smart-atomic='true']"))
17
- return 1;
18
- return [...node.childNodes].reduce((sum, child) => sum + contentWidth(child), 0);
19
- };
20
- const pointInOwner = (root, node, offset) => {
21
- const element = node instanceof HTMLElement ? node : node?.parentElement;
22
- const owner = element?.closest(ownerSelector);
23
- if (!owner || !root.contains(owner) || !node)
24
- return null;
25
- const range = root.ownerDocument.createRange();
26
- range.selectNodeContents(owner);
27
- try {
28
- range.setEnd(node, offset);
29
- }
30
- catch {
31
- return null;
32
- }
33
- return { ownerId: ownerId(owner), offset: contentWidth(range.cloneContents()) };
34
- };
35
- const captureSelection = (root) => {
36
- const native = root.ownerDocument.defaultView?.getSelection();
37
- if (!native?.anchorNode || !native.focusNode)
38
- return null;
39
- const anchor = pointInOwner(root, native.anchorNode, native.anchorOffset);
40
- const head = pointInOwner(root, native.focusNode, native.focusOffset);
41
- return anchor && head ? { anchor, head } : null;
42
- };
43
- const domPointAt = (owner, requested) => {
44
- let remaining = Math.max(0, requested);
45
- const visit = (parent) => {
46
- for (let index = 0; index < parent.childNodes.length; index += 1) {
47
- const child = parent.childNodes[index];
48
- if (child.nodeType === child.TEXT_NODE) {
49
- const length = child.nodeValue?.length || 0;
50
- if (remaining <= length)
51
- return { node: child, offset: remaining };
52
- remaining -= length;
53
- }
54
- else if (child instanceof HTMLElement && child.matches("br,[data-smart-atomic='true']")) {
55
- if (remaining === 0)
56
- return { node: parent, offset: index };
57
- if (remaining === 1)
58
- return { node: parent, offset: index + 1 };
59
- remaining -= 1;
60
- }
61
- else if (!(child instanceof HTMLElement && child.closest("[data-smart-ui]"))) {
62
- const found = visit(child);
63
- if (found)
64
- return found;
65
- }
66
- }
67
- return null;
68
- };
69
- return visit(owner) || { node: owner, offset: owner.childNodes.length };
70
- };
71
- const restoreSelection = (root, snapshot) => {
72
- const byId = (id) => Array.from(root.querySelectorAll("[data-smart-id]"))
73
- .find((node) => node.matches(ownerSelector) && node.dataset.smartId === id) || null;
74
- const anchorOwner = byId(snapshot.anchor.ownerId);
75
- const headOwner = byId(snapshot.head.ownerId);
76
- const native = root.ownerDocument.defaultView?.getSelection();
77
- if (!anchorOwner || !headOwner || !native)
78
- return;
79
- const anchor = domPointAt(anchorOwner, snapshot.anchor.offset);
80
- const head = domPointAt(headOwner, snapshot.head.offset);
81
- native.setBaseAndExtent(anchor.node, anchor.offset, head.node, head.offset);
82
- };
83
- const selectedOwners = (root, snapshot) => {
84
- const owners = Array.from(root.querySelectorAll(ownerSelector));
85
- const indexes = [snapshot.anchor.ownerId, snapshot.head.ownerId].map((id) => owners.findIndex((owner) => ownerId(owner) === id));
86
- if (indexes.some((index) => index < 0))
87
- return [];
88
- const [from, to] = [Math.min(...indexes), Math.max(...indexes)];
89
- return owners.slice(from, to + 1);
90
- };
91
- const modelSelection = (document, snapshot) => {
92
- const positions = createScopeIndex().positions(document, foundationSchema);
93
- const point = (value) => {
94
- const content = positions.contentRangeOf(value.ownerId);
95
- return content ? { path: [...content.from.path], offset: value.offset } : null;
96
- };
97
- const anchor = point(snapshot.anchor);
98
- const head = point(snapshot.head);
99
- return anchor && head ? { type: "text", anchor, head } : null;
100
- };
101
- const parseOwners = (owners) => parseCanonicalListHtml(owners.map((owner) => owner.outerHTML).join(""));
102
- const renderOwners = (root, owners, document, preserveEditedLink = false) => {
103
- const template = root.ownerDocument.createElement("template");
104
- template.innerHTML = serializeCanonicalListHtml(document, { fragment: true });
105
- owners.forEach((owner) => {
106
- const id = ownerId(owner);
107
- const replacement = Array.from(template.content.querySelectorAll("[data-smart-id]"))
108
- .find((candidate) => candidate.dataset.smartId === id);
109
- if (replacement) {
110
- const existingLinks = owner.querySelectorAll("a");
111
- const replacementLinks = replacement.querySelectorAll("a");
112
- if (preserveEditedLink && existingLinks.length === 1 && replacementLinks.length === 1
113
- && existingLinks[0].textContent === replacementLinks[0].textContent
114
- && owner.textContent === replacement.textContent) {
115
- const next = replacementLinks[0];
116
- existingLinks[0].setAttribute("href", next.getAttribute("href") || "");
117
- if (next.target) {
118
- existingLinks[0].target = next.target;
119
- existingLinks[0].rel = "noopener noreferrer";
120
- }
121
- else {
122
- existingLinks[0].removeAttribute("target");
123
- existingLinks[0].removeAttribute("rel");
124
- }
125
- return;
126
- }
127
- owner.innerHTML = replacement.innerHTML;
128
- owner.querySelectorAll("span[style]").forEach((span) => {
129
- const color = span.style.color;
130
- const background = span.style.backgroundColor;
131
- const size = span.style.fontSize;
132
- const family = span.style.fontFamily;
133
- span.removeAttribute("style");
134
- if (color)
135
- span.style.color = color;
136
- if (background)
137
- span.style.backgroundColor = background;
138
- if (size)
139
- span.style.fontSize = size;
140
- if (family)
141
- span.style.fontFamily = family;
142
- });
143
- }
144
- });
145
- };
146
- const declarationFor = (id) => {
147
- const declaration = inlineToolDeclarations.find((tool) => tool.id === id);
148
- if (!declaration)
149
- throw new Error(`Unknown inline tool "${id}".`);
150
- return declaration;
151
- };
152
- export const executeCanonicalInlineTool = (root, id, intent = "toggle", attrs) => {
153
- const ownerElements = Array.from(root.querySelectorAll(ownerSelector));
154
- const ownersWithPersistedIds = new Set(ownerElements.filter((owner) => owner.hasAttribute("data-smart-id")));
155
- const cleanupTemporaryIds = () => ownerElements.forEach((owner) => {
156
- if (!ownersWithPersistedIds.has(owner))
157
- owner.removeAttribute("data-smart-id");
158
- });
159
- const snapshot = captureSelection(root);
160
- if (!snapshot)
161
- return { changed: false, operations: 0, coverage: "none" };
162
- const owners = selectedOwners(root, snapshot);
163
- if (!owners.length)
164
- return { changed: false, operations: 0, coverage: "none" };
165
- const document = parseOwners(owners);
166
- const selection = modelSelection(document, snapshot);
167
- if (!selection)
168
- return { changed: false, operations: 0, coverage: "none" };
169
- const declaration = declarationFor(id);
170
- const index = createScopeIndex();
171
- const scope = index.resolve(document, selection, { want: "inline-range" }, foundationSchema);
172
- const description = index.resolve(document, selection, { want: "describe" }, foundationSchema);
173
- const coverage = description.marks.some((entry) => entry.mark.type === declaration.markType && entry.coverage === "all")
174
- ? "all" : description.marks.some((entry) => entry.mark.type === declaration.markType) ? "partial" : "none";
175
- if (scope.collapsed && !(declaration.markType === "link" && (intent === "remove" || intent === "editLink"))) {
176
- const editor = createFoundationEditor({ document, selection, storedMarks: storedMarks.get(root) });
177
- executeMarkTool(editor, declaration, intent, attrs);
178
- storedMarks.set(root, [...(editor.storedMarks || [])]);
179
- cleanupTemporaryIds();
180
- return { changed: false, operations: 0, coverage };
181
- }
182
- const ctx = { schema: foundationSchema, positions: index.positions(document, foundationSchema) };
183
- const operations = intent === "clearAll" ? clearAllMarksCommand(document, scope, {}, ctx)
184
- : intent === "remove" && declaration.markType === "link" ? removeLinkCommand(document, scope, { markType: "link" }, ctx)
185
- : intent === "editLink" && declaration.markType === "link" ? editLinkCommand(document, scope, attrs, ctx)
186
- : intent === "remove" ? removeMarkCommand(document, scope, { markType: declaration.markType }, ctx)
187
- : intent === "toggle" ? toggleMarkCommand(document, scope, { markType: declaration.markType, attrs, coverage }, ctx)
188
- : applyMarkCommand(document, scope, { markType: declaration.markType, attrs }, ctx);
189
- if (!operations.length)
190
- return { changed: false, operations: 0, coverage };
191
- const output = applyOperations(document, operations);
192
- renderOwners(root, owners, output, intent === "editLink");
193
- restoreSelection(root, snapshot);
194
- cleanupTemporaryIds();
195
- storedMarks.delete(root);
196
- return { changed: true, operations: operations.length, coverage };
197
- };
198
- /** Consumes adapter stored marks for ordinary text input. Composition remains
199
- * owned by the canonical surface; atom-aware composition is explicitly Phase 7. */
200
- export const installCanonicalInlineStoredMarkInput = (root) => {
201
- const beforeInput = (event) => {
202
- if (!storedMarks.has(root) || event.inputType !== "insertText" || !event.data)
203
- return;
204
- const marks = storedMarks.get(root) || [];
205
- const ownerElements = Array.from(root.querySelectorAll(ownerSelector));
206
- const ownersWithPersistedIds = new Set(ownerElements.filter((owner) => owner.hasAttribute("data-smart-id")));
207
- const snapshot = captureSelection(root);
208
- if (!snapshot || snapshot.anchor.ownerId !== snapshot.head.ownerId || snapshot.anchor.offset !== snapshot.head.offset)
209
- return;
210
- event.preventDefault();
211
- const owners = selectedOwners(root, snapshot);
212
- const document = parseOwners(owners);
213
- const selection = modelSelection(document, snapshot);
214
- if (!selection)
215
- return;
216
- const editor = createFoundationEditor({ document, selection, storedMarks: marks });
217
- if (marks.length)
218
- editor.typeText(event.data, { timestamp: Date.now() });
219
- else
220
- editor.transact((builder) => {
221
- builder.operations.push({ type: "insertText", pos: selection.head, text: event.data });
222
- const next = { path: [...selection.head.path], offset: selection.head.offset + event.data.length };
223
- builder.setSelection({ type: "text", anchor: next, head: next });
224
- builder.setStoredMarks([]);
225
- }, { source: "input", timestamp: Date.now(), addToHistory: true });
226
- renderOwners(root, owners, editor.document);
227
- const next = { anchor: { ...snapshot.anchor, offset: snapshot.anchor.offset + event.data.length }, head: { ...snapshot.head, offset: snapshot.head.offset + event.data.length } };
228
- restoreSelection(root, next);
229
- ownerElements.forEach((owner) => { if (!ownersWithPersistedIds.has(owner))
230
- owner.removeAttribute("data-smart-id"); });
231
- storedMarks.set(root, [...(editor.storedMarks || [])]);
232
- };
233
- const selectionChange = () => {
234
- const ownerElements = Array.from(root.querySelectorAll(ownerSelector));
235
- const ownersWithPersistedIds = new Set(ownerElements.filter((owner) => owner.hasAttribute("data-smart-id")));
236
- const snapshot = captureSelection(root);
237
- if (!snapshot || snapshot.anchor.ownerId !== snapshot.head.ownerId || snapshot.anchor.offset !== snapshot.head.offset)
238
- storedMarks.delete(root);
239
- ownerElements.forEach((owner) => { if (!ownersWithPersistedIds.has(owner))
240
- owner.removeAttribute("data-smart-id"); });
241
- };
242
- root.addEventListener("beforeinput", beforeInput);
243
- root.ownerDocument.addEventListener("selectionchange", selectionChange);
244
- return () => {
245
- root.removeEventListener("beforeinput", beforeInput);
246
- root.ownerDocument.removeEventListener("selectionchange", selectionChange);
247
- storedMarks.delete(root);
248
- };
249
- };
250
- export const canonicalInlineStoredMarks = (root) => storedMarks.get(root) || [];
251
- export const hasCanonicalInlineStoredMarkOverride = (root) => storedMarks.has(root);
252
- export const describeCanonicalInlineCoverage = (root) => {
253
- if (storedMarks.has(root))
254
- return Object.fromEntries((storedMarks.get(root) || []).map((mark) => [mark.type, "all"]));
255
- const ownerElements = Array.from(root.querySelectorAll(ownerSelector));
256
- const ownersWithPersistedIds = new Set(ownerElements.filter((owner) => owner.hasAttribute("data-smart-id")));
257
- const snapshot = captureSelection(root);
258
- if (!snapshot)
259
- return {};
260
- const owners = selectedOwners(root, snapshot);
261
- const document = parseOwners(owners);
262
- const selection = modelSelection(document, snapshot);
263
- const description = selection
264
- ? createScopeIndex().resolve(document, selection, { want: "describe" }, foundationSchema)
265
- : null;
266
- ownerElements.forEach((owner) => { if (!ownersWithPersistedIds.has(owner))
267
- owner.removeAttribute("data-smart-id"); });
268
- return Object.fromEntries((description?.marks || []).map((entry) => [entry.mark.type, entry.coverage]));
269
- };
@@ -1,26 +0,0 @@
1
- import { type SmartSelection } from "smartrte-core";
2
- export declare const executeCanonicalListDepth: (root: HTMLElement, items: readonly HTMLElement[], direction: "indent" | "outdent") => boolean;
3
- export declare const executeCanonicalListMove: (root: HTMLElement, items: readonly HTMLElement[], direction: "up" | "down") => boolean;
4
- export declare const executeCanonicalListStyle: (args: {
5
- root: HTMLElement;
6
- items: readonly HTMLElement[];
7
- style?: string;
8
- preset?: string;
9
- checkable?: boolean;
10
- }) => boolean;
11
- export declare const executeCanonicalListCheck: (root: HTMLElement, item: HTMLElement, checked: boolean) => boolean;
12
- export declare const executeCanonicalListToggle: (args: {
13
- root: HTMLElement;
14
- items: readonly HTMLElement[];
15
- blocks: readonly HTMLElement[];
16
- listTag: "ul" | "ol";
17
- range?: Range;
18
- style?: string;
19
- preset?: string;
20
- checkable?: boolean;
21
- }) => boolean;
22
- export interface CanonicalListBridgeResult {
23
- readonly changed: boolean;
24
- readonly selection: SmartSelection | null;
25
- }
26
- export declare const executeCanonicalListStructuralInput: (root: HTMLElement, input: "enter" | "backspace" | "delete") => boolean;