@rtif-sdk/web 1.0.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.
Files changed (215) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +67 -0
  3. package/dist/block-drag-handler.d.ts +189 -0
  4. package/dist/block-drag-handler.d.ts.map +1 -0
  5. package/dist/block-drag-handler.js +745 -0
  6. package/dist/block-drag-handler.js.map +1 -0
  7. package/dist/block-renderer.d.ts +402 -0
  8. package/dist/block-renderer.d.ts.map +1 -0
  9. package/dist/block-renderer.js +424 -0
  10. package/dist/block-renderer.js.map +1 -0
  11. package/dist/clipboard.d.ts +178 -0
  12. package/dist/clipboard.d.ts.map +1 -0
  13. package/dist/clipboard.js +432 -0
  14. package/dist/clipboard.js.map +1 -0
  15. package/dist/command-bus.d.ts +113 -0
  16. package/dist/command-bus.d.ts.map +1 -0
  17. package/dist/command-bus.js +70 -0
  18. package/dist/command-bus.js.map +1 -0
  19. package/dist/composition.d.ts +220 -0
  20. package/dist/composition.d.ts.map +1 -0
  21. package/dist/composition.js +271 -0
  22. package/dist/composition.js.map +1 -0
  23. package/dist/content-extraction.d.ts +69 -0
  24. package/dist/content-extraction.d.ts.map +1 -0
  25. package/dist/content-extraction.js +228 -0
  26. package/dist/content-extraction.js.map +1 -0
  27. package/dist/content-handler-file.d.ts +40 -0
  28. package/dist/content-handler-file.d.ts.map +1 -0
  29. package/dist/content-handler-file.js +91 -0
  30. package/dist/content-handler-file.js.map +1 -0
  31. package/dist/content-handler-image.d.ts +82 -0
  32. package/dist/content-handler-image.d.ts.map +1 -0
  33. package/dist/content-handler-image.js +120 -0
  34. package/dist/content-handler-image.js.map +1 -0
  35. package/dist/content-handler-url.d.ts +129 -0
  36. package/dist/content-handler-url.d.ts.map +1 -0
  37. package/dist/content-handler-url.js +244 -0
  38. package/dist/content-handler-url.js.map +1 -0
  39. package/dist/content-handlers.d.ts +67 -0
  40. package/dist/content-handlers.d.ts.map +1 -0
  41. package/dist/content-handlers.js +263 -0
  42. package/dist/content-handlers.js.map +1 -0
  43. package/dist/content-pipeline.d.ts +383 -0
  44. package/dist/content-pipeline.d.ts.map +1 -0
  45. package/dist/content-pipeline.js +232 -0
  46. package/dist/content-pipeline.js.map +1 -0
  47. package/dist/cursor-nav.d.ts +149 -0
  48. package/dist/cursor-nav.d.ts.map +1 -0
  49. package/dist/cursor-nav.js +230 -0
  50. package/dist/cursor-nav.js.map +1 -0
  51. package/dist/cursor-rect.d.ts +65 -0
  52. package/dist/cursor-rect.d.ts.map +1 -0
  53. package/dist/cursor-rect.js +98 -0
  54. package/dist/cursor-rect.js.map +1 -0
  55. package/dist/drop-indicator.d.ts +108 -0
  56. package/dist/drop-indicator.d.ts.map +1 -0
  57. package/dist/drop-indicator.js +236 -0
  58. package/dist/drop-indicator.js.map +1 -0
  59. package/dist/editor.d.ts +41 -0
  60. package/dist/editor.d.ts.map +1 -0
  61. package/dist/editor.js +710 -0
  62. package/dist/editor.js.map +1 -0
  63. package/dist/floating-toolbar.d.ts +93 -0
  64. package/dist/floating-toolbar.d.ts.map +1 -0
  65. package/dist/floating-toolbar.js +159 -0
  66. package/dist/floating-toolbar.js.map +1 -0
  67. package/dist/index.d.ts +62 -0
  68. package/dist/index.d.ts.map +1 -0
  69. package/dist/index.js +119 -0
  70. package/dist/index.js.map +1 -0
  71. package/dist/input-bridge.d.ts +273 -0
  72. package/dist/input-bridge.d.ts.map +1 -0
  73. package/dist/input-bridge.js +884 -0
  74. package/dist/input-bridge.js.map +1 -0
  75. package/dist/link-popover.d.ts +38 -0
  76. package/dist/link-popover.d.ts.map +1 -0
  77. package/dist/link-popover.js +278 -0
  78. package/dist/link-popover.js.map +1 -0
  79. package/dist/mark-renderer.d.ts +275 -0
  80. package/dist/mark-renderer.d.ts.map +1 -0
  81. package/dist/mark-renderer.js +210 -0
  82. package/dist/mark-renderer.js.map +1 -0
  83. package/dist/perf.d.ts +145 -0
  84. package/dist/perf.d.ts.map +1 -0
  85. package/dist/perf.js +260 -0
  86. package/dist/perf.js.map +1 -0
  87. package/dist/plugin-kit.d.ts +265 -0
  88. package/dist/plugin-kit.d.ts.map +1 -0
  89. package/dist/plugin-kit.js +234 -0
  90. package/dist/plugin-kit.js.map +1 -0
  91. package/dist/plugins/alignment-plugin.d.ts +68 -0
  92. package/dist/plugins/alignment-plugin.d.ts.map +1 -0
  93. package/dist/plugins/alignment-plugin.js +98 -0
  94. package/dist/plugins/alignment-plugin.js.map +1 -0
  95. package/dist/plugins/block-utils.d.ts +113 -0
  96. package/dist/plugins/block-utils.d.ts.map +1 -0
  97. package/dist/plugins/block-utils.js +191 -0
  98. package/dist/plugins/block-utils.js.map +1 -0
  99. package/dist/plugins/blockquote-plugin.d.ts +39 -0
  100. package/dist/plugins/blockquote-plugin.d.ts.map +1 -0
  101. package/dist/plugins/blockquote-plugin.js +88 -0
  102. package/dist/plugins/blockquote-plugin.js.map +1 -0
  103. package/dist/plugins/bold-plugin.d.ts +37 -0
  104. package/dist/plugins/bold-plugin.d.ts.map +1 -0
  105. package/dist/plugins/bold-plugin.js +48 -0
  106. package/dist/plugins/bold-plugin.js.map +1 -0
  107. package/dist/plugins/callout-plugin.d.ts +100 -0
  108. package/dist/plugins/callout-plugin.d.ts.map +1 -0
  109. package/dist/plugins/callout-plugin.js +200 -0
  110. package/dist/plugins/callout-plugin.js.map +1 -0
  111. package/dist/plugins/code-block-plugin.d.ts +62 -0
  112. package/dist/plugins/code-block-plugin.d.ts.map +1 -0
  113. package/dist/plugins/code-block-plugin.js +176 -0
  114. package/dist/plugins/code-block-plugin.js.map +1 -0
  115. package/dist/plugins/code-plugin.d.ts +37 -0
  116. package/dist/plugins/code-plugin.d.ts.map +1 -0
  117. package/dist/plugins/code-plugin.js +48 -0
  118. package/dist/plugins/code-plugin.js.map +1 -0
  119. package/dist/plugins/embed-plugin.d.ts +90 -0
  120. package/dist/plugins/embed-plugin.d.ts.map +1 -0
  121. package/dist/plugins/embed-plugin.js +147 -0
  122. package/dist/plugins/embed-plugin.js.map +1 -0
  123. package/dist/plugins/font-family-plugin.d.ts +58 -0
  124. package/dist/plugins/font-family-plugin.d.ts.map +1 -0
  125. package/dist/plugins/font-family-plugin.js +57 -0
  126. package/dist/plugins/font-family-plugin.js.map +1 -0
  127. package/dist/plugins/font-size-plugin.d.ts +57 -0
  128. package/dist/plugins/font-size-plugin.d.ts.map +1 -0
  129. package/dist/plugins/font-size-plugin.js +56 -0
  130. package/dist/plugins/font-size-plugin.js.map +1 -0
  131. package/dist/plugins/heading-plugin.d.ts +52 -0
  132. package/dist/plugins/heading-plugin.d.ts.map +1 -0
  133. package/dist/plugins/heading-plugin.js +114 -0
  134. package/dist/plugins/heading-plugin.js.map +1 -0
  135. package/dist/plugins/hr-plugin.d.ts +33 -0
  136. package/dist/plugins/hr-plugin.d.ts.map +1 -0
  137. package/dist/plugins/hr-plugin.js +75 -0
  138. package/dist/plugins/hr-plugin.js.map +1 -0
  139. package/dist/plugins/image-plugin.d.ts +115 -0
  140. package/dist/plugins/image-plugin.d.ts.map +1 -0
  141. package/dist/plugins/image-plugin.js +199 -0
  142. package/dist/plugins/image-plugin.js.map +1 -0
  143. package/dist/plugins/indent-plugin.d.ts +62 -0
  144. package/dist/plugins/indent-plugin.d.ts.map +1 -0
  145. package/dist/plugins/indent-plugin.js +128 -0
  146. package/dist/plugins/indent-plugin.js.map +1 -0
  147. package/dist/plugins/index.d.ts +45 -0
  148. package/dist/plugins/index.d.ts.map +1 -0
  149. package/dist/plugins/index.js +42 -0
  150. package/dist/plugins/index.js.map +1 -0
  151. package/dist/plugins/italic-plugin.d.ts +37 -0
  152. package/dist/plugins/italic-plugin.d.ts.map +1 -0
  153. package/dist/plugins/italic-plugin.js +48 -0
  154. package/dist/plugins/italic-plugin.js.map +1 -0
  155. package/dist/plugins/link-plugin.d.ts +129 -0
  156. package/dist/plugins/link-plugin.d.ts.map +1 -0
  157. package/dist/plugins/link-plugin.js +212 -0
  158. package/dist/plugins/link-plugin.js.map +1 -0
  159. package/dist/plugins/list-plugin.d.ts +53 -0
  160. package/dist/plugins/list-plugin.d.ts.map +1 -0
  161. package/dist/plugins/list-plugin.js +309 -0
  162. package/dist/plugins/list-plugin.js.map +1 -0
  163. package/dist/plugins/mark-utils.d.ts +173 -0
  164. package/dist/plugins/mark-utils.d.ts.map +1 -0
  165. package/dist/plugins/mark-utils.js +425 -0
  166. package/dist/plugins/mark-utils.js.map +1 -0
  167. package/dist/plugins/mention-plugin.d.ts +191 -0
  168. package/dist/plugins/mention-plugin.d.ts.map +1 -0
  169. package/dist/plugins/mention-plugin.js +295 -0
  170. package/dist/plugins/mention-plugin.js.map +1 -0
  171. package/dist/plugins/strikethrough-plugin.d.ts +37 -0
  172. package/dist/plugins/strikethrough-plugin.d.ts.map +1 -0
  173. package/dist/plugins/strikethrough-plugin.js +48 -0
  174. package/dist/plugins/strikethrough-plugin.js.map +1 -0
  175. package/dist/plugins/text-color-plugin.d.ts +57 -0
  176. package/dist/plugins/text-color-plugin.d.ts.map +1 -0
  177. package/dist/plugins/text-color-plugin.js +56 -0
  178. package/dist/plugins/text-color-plugin.js.map +1 -0
  179. package/dist/plugins/underline-plugin.d.ts +37 -0
  180. package/dist/plugins/underline-plugin.d.ts.map +1 -0
  181. package/dist/plugins/underline-plugin.js +48 -0
  182. package/dist/plugins/underline-plugin.js.map +1 -0
  183. package/dist/presets.d.ts +95 -0
  184. package/dist/presets.d.ts.map +1 -0
  185. package/dist/presets.js +159 -0
  186. package/dist/presets.js.map +1 -0
  187. package/dist/renderer.d.ts +125 -0
  188. package/dist/renderer.d.ts.map +1 -0
  189. package/dist/renderer.js +415 -0
  190. package/dist/renderer.js.map +1 -0
  191. package/dist/scroll-to-cursor.d.ts +25 -0
  192. package/dist/scroll-to-cursor.d.ts.map +1 -0
  193. package/dist/scroll-to-cursor.js +59 -0
  194. package/dist/scroll-to-cursor.js.map +1 -0
  195. package/dist/selection-sync.d.ts +159 -0
  196. package/dist/selection-sync.d.ts.map +1 -0
  197. package/dist/selection-sync.js +527 -0
  198. package/dist/selection-sync.js.map +1 -0
  199. package/dist/shortcut-handler.d.ts +98 -0
  200. package/dist/shortcut-handler.d.ts.map +1 -0
  201. package/dist/shortcut-handler.js +155 -0
  202. package/dist/shortcut-handler.js.map +1 -0
  203. package/dist/toolbar.d.ts +103 -0
  204. package/dist/toolbar.d.ts.map +1 -0
  205. package/dist/toolbar.js +134 -0
  206. package/dist/toolbar.js.map +1 -0
  207. package/dist/trigger-manager.d.ts +205 -0
  208. package/dist/trigger-manager.d.ts.map +1 -0
  209. package/dist/trigger-manager.js +466 -0
  210. package/dist/trigger-manager.js.map +1 -0
  211. package/dist/types.d.ts +216 -0
  212. package/dist/types.d.ts.map +1 -0
  213. package/dist/types.js +2 -0
  214. package/dist/types.js.map +1 -0
  215. package/package.json +30 -0
@@ -0,0 +1,155 @@
1
+ /**
2
+ * Keyboard shortcut handler for the RTIF web editor.
3
+ *
4
+ * Reads shortcut bindings from the engine and intercepts `keydown` events
5
+ * to dispatch the corresponding commands through the {@link CommandBus}.
6
+ * Uses platform-aware modifier key detection (Cmd on Mac, Ctrl on Win/Linux).
7
+ *
8
+ * The shortcut handler fires BEFORE the cursor-nav handler's keydown listener,
9
+ * so plugin-registered shortcuts take priority over built-in navigation.
10
+ *
11
+ * @module
12
+ */
13
+ import { isMac } from './cursor-nav.js';
14
+ // ---------------------------------------------------------------------------
15
+ // ShortcutHandler
16
+ // ---------------------------------------------------------------------------
17
+ /**
18
+ * Intercepts `keydown` events and matches them against engine-registered
19
+ * keyboard shortcuts.
20
+ *
21
+ * When a match is found, the corresponding command is executed via the
22
+ * command bus and the event is prevented/stopped.
23
+ *
24
+ * @example
25
+ * ```ts
26
+ * const handler = new ShortcutHandler(root, {
27
+ * getShortcuts: () => engine.getShortcuts(),
28
+ * commandBus: bus,
29
+ * isComposing: () => compositionHandler.isComposing(),
30
+ * });
31
+ * handler.attach();
32
+ * ```
33
+ */
34
+ export class ShortcutHandler {
35
+ _root;
36
+ _deps;
37
+ _attached = false;
38
+ _boundHandler;
39
+ constructor(root, deps) {
40
+ this._root = root;
41
+ this._deps = deps;
42
+ this._boundHandler = (e) => this._handleKeyDown(e);
43
+ }
44
+ /**
45
+ * Attach the `keydown` event listener to the root element.
46
+ *
47
+ * Uses `capture: true` so shortcuts fire before other keydown handlers.
48
+ *
49
+ * @example
50
+ * ```ts
51
+ * handler.attach();
52
+ * ```
53
+ */
54
+ attach() {
55
+ if (this._attached)
56
+ return;
57
+ this._root.addEventListener('keydown', this._boundHandler, true);
58
+ this._attached = true;
59
+ }
60
+ /**
61
+ * Remove the `keydown` event listener.
62
+ *
63
+ * @example
64
+ * ```ts
65
+ * handler.detach();
66
+ * ```
67
+ */
68
+ detach() {
69
+ if (!this._attached)
70
+ return;
71
+ this._root.removeEventListener('keydown', this._boundHandler, true);
72
+ this._attached = false;
73
+ }
74
+ _handleKeyDown(e) {
75
+ // Suppress shortcuts during IME composition
76
+ if (this._deps.isComposing())
77
+ return;
78
+ const shortcuts = this._deps.getShortcuts();
79
+ if (shortcuts.length === 0)
80
+ return;
81
+ for (const binding of shortcuts) {
82
+ if (matchesShortcut(e, binding)) {
83
+ // Check canExecute before consuming the event — if the command
84
+ // cannot execute (e.g., Tab outside a list), let the event pass
85
+ // through to the browser.
86
+ let canExec = true;
87
+ try {
88
+ canExec = this._deps.commandBus.canExecute(binding.command, binding.payload);
89
+ }
90
+ catch {
91
+ /* default to allowing */
92
+ }
93
+ if (!canExec)
94
+ continue;
95
+ e.preventDefault();
96
+ e.stopPropagation();
97
+ this._deps.commandBus.execute(binding.command, binding.payload);
98
+ return;
99
+ }
100
+ }
101
+ }
102
+ }
103
+ // ---------------------------------------------------------------------------
104
+ // Matching
105
+ // ---------------------------------------------------------------------------
106
+ /**
107
+ * Check whether a keyboard event matches a shortcut binding.
108
+ *
109
+ * Platform-aware: `mod` matches `metaKey` on Mac, `ctrlKey` on other platforms.
110
+ *
111
+ * @param e - The keyboard event
112
+ * @param binding - The shortcut binding to match against
113
+ * @returns Whether the event matches the binding
114
+ *
115
+ * @example
116
+ * ```ts
117
+ * const matches = matchesShortcut(event, {
118
+ * descriptor: { key: 'b', mod: true },
119
+ * command: 'toggleBold',
120
+ * });
121
+ * ```
122
+ */
123
+ export function matchesShortcut(e, binding) {
124
+ const desc = binding.descriptor;
125
+ // Key comparison (case-insensitive for single characters)
126
+ if (e.key.toLowerCase() !== desc.key.toLowerCase())
127
+ return false;
128
+ // Platform modifier: Cmd on Mac, Ctrl on others
129
+ const mac = isMac();
130
+ const modRequired = desc.mod ?? false;
131
+ const modPressed = mac ? e.metaKey : e.ctrlKey;
132
+ if (modRequired !== modPressed)
133
+ return false;
134
+ // On Mac, if mod is required (metaKey), we don't also require ctrlKey to be false,
135
+ // but we do check the other modifiers
136
+ const shiftRequired = desc.shift ?? false;
137
+ if (shiftRequired !== e.shiftKey)
138
+ return false;
139
+ const altRequired = desc.alt ?? false;
140
+ if (altRequired !== e.altKey)
141
+ return false;
142
+ // Reject if extra modifier keys are held that aren't required
143
+ // On Mac: ctrl shouldn't be pressed (unless it's not a mod shortcut)
144
+ // On Win/Linux: meta shouldn't be pressed
145
+ if (mac && !modRequired && e.metaKey)
146
+ return false;
147
+ if (!mac && !modRequired && e.ctrlKey)
148
+ return false;
149
+ if (mac && e.ctrlKey && modRequired)
150
+ return false; // Ctrl+Cmd combo not expected
151
+ if (!mac && e.metaKey)
152
+ return false;
153
+ return true;
154
+ }
155
+ //# sourceMappingURL=shortcut-handler.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"shortcut-handler.js","sourceRoot":"","sources":["../src/shortcut-handler.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,103 @@
1
+ /**
2
+ * Fixed toolbar primitive for the RTIF web editor.
3
+ *
4
+ * Renders a horizontal toolbar with buttons that execute editor commands.
5
+ * Button state (active, disabled) updates live via the {@link CommandBus}.
6
+ * Uses `mousedown` + `preventDefault()` to avoid stealing focus from the editor.
7
+ *
8
+ * @module
9
+ */
10
+ import type { CommandBus } from './command-bus.js';
11
+ /**
12
+ * Type-safe constants for common toolbar group names.
13
+ *
14
+ * Use these when building `ToolbarButtonConfig` arrays to ensure consistent
15
+ * grouping across your toolbar.
16
+ *
17
+ * @example
18
+ * ```ts
19
+ * const buttons: ToolbarButtonConfig[] = [
20
+ * { command: 'undo', icon: '↩', label: 'Undo', group: ToolbarGroup.HISTORY },
21
+ * { command: 'toggleMark:bold', icon: 'B', label: 'Bold', group: ToolbarGroup.MARKS },
22
+ * ];
23
+ * ```
24
+ */
25
+ export declare const ToolbarGroup: {
26
+ readonly HISTORY: "history";
27
+ readonly MARKS: "marks";
28
+ readonly BLOCKS: "blocks";
29
+ readonly INSERT: "insert";
30
+ readonly ALIGN: "align";
31
+ readonly INDENT: "indent";
32
+ readonly STYLE: "style";
33
+ };
34
+ /**
35
+ * Configuration for a single toolbar button.
36
+ *
37
+ * @example
38
+ * ```ts
39
+ * const boldButton: ToolbarButtonConfig = {
40
+ * command: 'toggleMark:bold',
41
+ * icon: 'B',
42
+ * label: 'Bold',
43
+ * group: 'format',
44
+ * };
45
+ * ```
46
+ */
47
+ export interface ToolbarButtonConfig {
48
+ /** The command to execute when the button is clicked */
49
+ readonly command: string;
50
+ /** Optional payload to pass to the command handler */
51
+ readonly payload?: unknown;
52
+ /** Icon text or HTML to display in the button (e.g., "B", "<svg>...") */
53
+ readonly icon: string;
54
+ /** Accessible label for the button */
55
+ readonly label: string;
56
+ /** Optional group name for visual grouping (rendered as a separator between groups) */
57
+ readonly group?: string;
58
+ }
59
+ /**
60
+ * Handle returned by `createToolbar()` for lifecycle management.
61
+ *
62
+ * @example
63
+ * ```ts
64
+ * const toolbar = createToolbar(container, bus, buttons);
65
+ * // ... later:
66
+ * toolbar.destroy();
67
+ * ```
68
+ */
69
+ export interface ToolbarHandle {
70
+ /** The toolbar's root DOM element */
71
+ readonly element: HTMLElement;
72
+ /** Remove all event listeners and subscriptions. Idempotent. */
73
+ destroy(): void;
74
+ }
75
+ /**
76
+ * Create a fixed toolbar with command-driven buttons.
77
+ *
78
+ * Buttons reflect live command state:
79
+ * - `aria-pressed="true"` when the command's `isActive` returns true
80
+ * - `aria-disabled="true"` when the command's `canExecute` returns false
81
+ *
82
+ * The toolbar subscribes to the CommandBus for automatic state updates.
83
+ *
84
+ * @param container - The DOM element to render the toolbar into
85
+ * @param bus - The CommandBus to execute commands and query state
86
+ * @param buttons - Array of button configurations
87
+ * @returns A ToolbarHandle for lifecycle management
88
+ *
89
+ * @example
90
+ * ```ts
91
+ * const toolbar = createToolbar(
92
+ * document.getElementById('toolbar')!,
93
+ * bus,
94
+ * [
95
+ * { command: 'toggleMark:bold', icon: 'B', label: 'Bold', group: 'format' },
96
+ * { command: 'toggleMark:italic', icon: 'I', label: 'Italic', group: 'format' },
97
+ * { command: 'undo', icon: '↩', label: 'Undo', group: 'history' },
98
+ * ],
99
+ * );
100
+ * ```
101
+ */
102
+ export declare function createToolbar(container: HTMLElement, bus: CommandBus, buttons: ReadonlyArray<ToolbarButtonConfig>): ToolbarHandle;
103
+ //# sourceMappingURL=toolbar.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"toolbar.d.ts","sourceRoot":"","sources":["../src/toolbar.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAMnD;;;;;;;;;;;;;GAaG;AACH,eAAO,MAAM,YAAY;;;;;;;;CAQf,CAAC;AAMX;;;;;;;;;;;;GAYG;AACH,MAAM,WAAW,mBAAmB;IAClC,wDAAwD;IACxD,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,sDAAsD;IACtD,QAAQ,CAAC,OAAO,CAAC,EAAE,OAAO,CAAC;IAC3B,yEAAyE;IACzE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,sCAAsC;IACtC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,uFAAuF;IACvF,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;CACzB;AAED;;;;;;;;;GASG;AACH,MAAM,WAAW,aAAa;IAC5B,qCAAqC;IACrC,QAAQ,CAAC,OAAO,EAAE,WAAW,CAAC;IAC9B,gEAAgE;IAChE,OAAO,IAAI,IAAI,CAAC;CACjB;AAMD;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,wBAAgB,aAAa,CAC3B,SAAS,EAAE,WAAW,EACtB,GAAG,EAAE,UAAU,EACf,OAAO,EAAE,aAAa,CAAC,mBAAmB,CAAC,GAC1C,aAAa,CA+Ef"}
@@ -0,0 +1,134 @@
1
+ /**
2
+ * Fixed toolbar primitive for the RTIF web editor.
3
+ *
4
+ * Renders a horizontal toolbar with buttons that execute editor commands.
5
+ * Button state (active, disabled) updates live via the {@link CommandBus}.
6
+ * Uses `mousedown` + `preventDefault()` to avoid stealing focus from the editor.
7
+ *
8
+ * @module
9
+ */
10
+ // ---------------------------------------------------------------------------
11
+ // Toolbar group constants
12
+ // ---------------------------------------------------------------------------
13
+ /**
14
+ * Type-safe constants for common toolbar group names.
15
+ *
16
+ * Use these when building `ToolbarButtonConfig` arrays to ensure consistent
17
+ * grouping across your toolbar.
18
+ *
19
+ * @example
20
+ * ```ts
21
+ * const buttons: ToolbarButtonConfig[] = [
22
+ * { command: 'undo', icon: '↩', label: 'Undo', group: ToolbarGroup.HISTORY },
23
+ * { command: 'toggleMark:bold', icon: 'B', label: 'Bold', group: ToolbarGroup.MARKS },
24
+ * ];
25
+ * ```
26
+ */
27
+ export const ToolbarGroup = {
28
+ HISTORY: 'history',
29
+ MARKS: 'marks',
30
+ BLOCKS: 'blocks',
31
+ INSERT: 'insert',
32
+ ALIGN: 'align',
33
+ INDENT: 'indent',
34
+ STYLE: 'style',
35
+ };
36
+ // ---------------------------------------------------------------------------
37
+ // Factory
38
+ // ---------------------------------------------------------------------------
39
+ /**
40
+ * Create a fixed toolbar with command-driven buttons.
41
+ *
42
+ * Buttons reflect live command state:
43
+ * - `aria-pressed="true"` when the command's `isActive` returns true
44
+ * - `aria-disabled="true"` when the command's `canExecute` returns false
45
+ *
46
+ * The toolbar subscribes to the CommandBus for automatic state updates.
47
+ *
48
+ * @param container - The DOM element to render the toolbar into
49
+ * @param bus - The CommandBus to execute commands and query state
50
+ * @param buttons - Array of button configurations
51
+ * @returns A ToolbarHandle for lifecycle management
52
+ *
53
+ * @example
54
+ * ```ts
55
+ * const toolbar = createToolbar(
56
+ * document.getElementById('toolbar')!,
57
+ * bus,
58
+ * [
59
+ * { command: 'toggleMark:bold', icon: 'B', label: 'Bold', group: 'format' },
60
+ * { command: 'toggleMark:italic', icon: 'I', label: 'Italic', group: 'format' },
61
+ * { command: 'undo', icon: '↩', label: 'Undo', group: 'history' },
62
+ * ],
63
+ * );
64
+ * ```
65
+ */
66
+ export function createToolbar(container, bus, buttons) {
67
+ // Create the toolbar element
68
+ const toolbar = container.ownerDocument.createElement('div');
69
+ toolbar.setAttribute('role', 'toolbar');
70
+ toolbar.setAttribute('aria-label', 'Editor toolbar');
71
+ // Track button elements for state updates
72
+ const buttonElements = [];
73
+ let lastGroup;
74
+ for (const config of buttons) {
75
+ // Add separator between groups
76
+ if (config.group !== undefined && config.group !== lastGroup && lastGroup !== undefined) {
77
+ const separator = container.ownerDocument.createElement('span');
78
+ separator.setAttribute('role', 'separator');
79
+ separator.setAttribute('aria-orientation', 'vertical');
80
+ separator.className = 'rtif-toolbar-separator';
81
+ toolbar.appendChild(separator);
82
+ }
83
+ lastGroup = config.group;
84
+ const btn = container.ownerDocument.createElement('button');
85
+ btn.type = 'button';
86
+ btn.setAttribute('aria-label', config.label);
87
+ btn.setAttribute('data-command', config.command);
88
+ btn.className = 'rtif-toolbar-button';
89
+ btn.innerHTML = config.icon;
90
+ // Prevent focus steal on mousedown
91
+ btn.addEventListener('mousedown', (e) => {
92
+ e.preventDefault();
93
+ });
94
+ // Execute command on click
95
+ btn.addEventListener('click', () => {
96
+ bus.execute(config.command, config.payload);
97
+ });
98
+ toolbar.appendChild(btn);
99
+ buttonElements.push({ el: btn, config });
100
+ }
101
+ container.appendChild(toolbar);
102
+ // Update button states
103
+ function updateStates() {
104
+ for (const { el, config } of buttonElements) {
105
+ const active = bus.isActive(config.command, config.payload);
106
+ const canExec = bus.canExecute(config.command, config.payload);
107
+ el.setAttribute('aria-pressed', String(active));
108
+ el.setAttribute('aria-disabled', String(!canExec));
109
+ el.disabled = !canExec;
110
+ if (active) {
111
+ el.classList.add('rtif-toolbar-active');
112
+ }
113
+ else {
114
+ el.classList.remove('rtif-toolbar-active');
115
+ }
116
+ }
117
+ }
118
+ // Initial state update
119
+ updateStates();
120
+ // Subscribe to state changes for live updates
121
+ const unsubscribe = bus.subscribe(() => updateStates());
122
+ let destroyed = false;
123
+ return {
124
+ element: toolbar,
125
+ destroy() {
126
+ if (destroyed)
127
+ return;
128
+ destroyed = true;
129
+ unsubscribe();
130
+ toolbar.remove();
131
+ },
132
+ };
133
+ }
134
+ //# sourceMappingURL=toolbar.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"toolbar.js","sourceRoot":"","sources":["../src/toolbar.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,205 @@
1
+ /**
2
+ * Generic trigger infrastructure for character-triggered interactions.
3
+ *
4
+ * Detects trigger characters (e.g., `@`, `#`, `/`), manages TriggerSession
5
+ * lifecycle, handles keyboard routing and dismissal. Fully reusable for
6
+ * @mentions, #hashtags, /slash-commands, etc.
7
+ *
8
+ * @module
9
+ */
10
+ import type { IEditorEngine } from '@rtif-sdk/engine';
11
+ import type { CursorRectAPI } from './cursor-rect.js';
12
+ import type { Disposable } from './types.js';
13
+ /** Reason a trigger session was deactivated. */
14
+ export type TriggerDeactivateReason = 'accepted' | 'dismissed' | 'cursor-moved' | 'deleted';
15
+ /** Position constraint for trigger activation. */
16
+ export type TriggerPosition = 'start' | 'after-whitespace' | 'anywhere';
17
+ /**
18
+ * Configuration for registering a trigger character.
19
+ *
20
+ * @example
21
+ * ```ts
22
+ * const config: TriggerConfig = {
23
+ * id: 'mention',
24
+ * char: '@',
25
+ * onActivate(session) { showDropdown(session.query); },
26
+ * onChange(session) { filterDropdown(session.query); },
27
+ * onDeactivate(reason) { hideDropdown(); },
28
+ * };
29
+ * ```
30
+ */
31
+ export interface TriggerConfig {
32
+ /** Unique identifier for this trigger. */
33
+ readonly id: string;
34
+ /** The trigger character (e.g., "@", "#", "/"). */
35
+ readonly char: string;
36
+ /**
37
+ * Position constraint for when the trigger activates.
38
+ * - `'start'` — Only at the start of a block.
39
+ * - `'after-whitespace'` — After whitespace or at block start.
40
+ * - `'anywhere'` — At any position.
41
+ *
42
+ * Default: `'after-whitespace'`.
43
+ */
44
+ readonly position?: TriggerPosition;
45
+ /** Called when a trigger session activates. */
46
+ readonly onActivate: (session: TriggerSession) => void;
47
+ /** Called when a trigger session deactivates. */
48
+ readonly onDeactivate?: (reason: TriggerDeactivateReason) => void;
49
+ /** Called when the query text changes during an active session. */
50
+ readonly onChange?: (session: TriggerSession) => void;
51
+ /**
52
+ * Called on keydown during an active session.
53
+ * Return `true` to stop event propagation (e.g., ArrowDown in dropdown).
54
+ * Return `false` to let the event propagate to the editor.
55
+ */
56
+ readonly onKeyDown?: (session: TriggerSession, event: KeyboardEvent) => boolean;
57
+ /**
58
+ * If true, the session is deactivated when the query contains a space.
59
+ * Default: false.
60
+ */
61
+ readonly cancelOnSpace?: boolean;
62
+ /**
63
+ * Called when the trigger position may have changed due to scroll or resize.
64
+ * Consumers should re-query `getTriggerRect()` / `getCursorRect()` and
65
+ * reposition their UI.
66
+ *
67
+ * Only fires while a session for this trigger is active.
68
+ */
69
+ readonly onPositionChange?: (session: TriggerSession) => void;
70
+ }
71
+ /**
72
+ * Represents an active trigger session.
73
+ *
74
+ * @example
75
+ * ```ts
76
+ * function handleActivate(session: TriggerSession) {
77
+ * console.log('Trigger:', session.trigger.char, 'Query:', session.query);
78
+ * const rect = session.getTriggerRect();
79
+ * if (rect) positionDropdown(rect);
80
+ * }
81
+ * ```
82
+ */
83
+ export interface TriggerSession {
84
+ /** The trigger configuration that activated this session. */
85
+ readonly trigger: Readonly<TriggerConfig>;
86
+ /** Absolute offset of the trigger character in the document. */
87
+ readonly triggerOffset: number;
88
+ /** Text between the trigger character and the cursor. */
89
+ readonly query: string;
90
+ /** Get the screen rect of the trigger character. */
91
+ getTriggerRect(): DOMRect | null;
92
+ /** Get the screen rect of the current cursor position. */
93
+ getCursorRect(): DOMRect | null;
94
+ /**
95
+ * Accept a result — replaces trigger+query with the result text/marks.
96
+ *
97
+ * @param result - The text and optional marks to insert
98
+ */
99
+ accept(result: TriggerAcceptResult): void;
100
+ /** Dismiss the session — leaves text as-is, closes session. */
101
+ dismiss(): void;
102
+ /** Returns true if this session is still active. */
103
+ isActive(): boolean;
104
+ }
105
+ /**
106
+ * The result passed to `session.accept()`.
107
+ *
108
+ * @example
109
+ * ```ts
110
+ * session.accept({
111
+ * text: '@Alice Johnson',
112
+ * marks: { mention: { id: 'user-123', displayName: 'Alice Johnson' } },
113
+ * appendSpace: true,
114
+ * });
115
+ * ```
116
+ */
117
+ export interface TriggerAcceptResult {
118
+ /** The text to insert in place of trigger+query. */
119
+ readonly text: string;
120
+ /** Optional marks to apply to the inserted text. */
121
+ readonly marks?: Record<string, unknown>;
122
+ /**
123
+ * Whether to append a space after the inserted text.
124
+ * Default: true.
125
+ */
126
+ readonly appendSpace?: boolean;
127
+ }
128
+ /**
129
+ * The TriggerManager interface.
130
+ *
131
+ * @example
132
+ * ```ts
133
+ * const manager = createTriggerManager(deps);
134
+ * const disposable = manager.register(mentionTriggerConfig);
135
+ * // later:
136
+ * disposable.dispose();
137
+ * manager.destroy();
138
+ * ```
139
+ */
140
+ export interface TriggerManager {
141
+ /**
142
+ * Register a trigger character configuration.
143
+ *
144
+ * @param config - The trigger configuration
145
+ * @returns A disposable to unregister the trigger
146
+ */
147
+ register(config: TriggerConfig): Disposable;
148
+ /**
149
+ * Get the currently active trigger session, or null if none.
150
+ *
151
+ * @returns The active session, or null
152
+ */
153
+ getActiveSession(): TriggerSession | null;
154
+ /**
155
+ * Returns true if any trigger session is currently active.
156
+ *
157
+ * @returns Whether a session is active
158
+ */
159
+ isActive(): boolean;
160
+ /** Tear down the TriggerManager — removes all listeners. */
161
+ destroy(): void;
162
+ }
163
+ /**
164
+ * Dependencies injected into the TriggerManager.
165
+ *
166
+ * @example
167
+ * ```ts
168
+ * const deps: TriggerManagerDeps = {
169
+ * root,
170
+ * engine,
171
+ * cursorRect,
172
+ * isComposing: () => compositionHandler.isComposing(),
173
+ * };
174
+ * ```
175
+ */
176
+ export interface TriggerManagerDeps {
177
+ /** The editor root element. */
178
+ readonly root: HTMLElement;
179
+ /** The RTIF engine instance. */
180
+ readonly engine: IEditorEngine;
181
+ /** The cursor rect API for positioning. */
182
+ readonly cursorRect: CursorRectAPI;
183
+ /** Whether an IME composition is in progress. */
184
+ readonly isComposing: () => boolean;
185
+ }
186
+ /**
187
+ * Create a TriggerManager instance.
188
+ *
189
+ * The trigger manager detects trigger characters, manages sessions,
190
+ * and handles keyboard routing. Attach its keydown listener BEFORE
191
+ * the shortcut handler for correct priority.
192
+ *
193
+ * @param deps - Dependencies for the trigger manager
194
+ * @returns A TriggerManager instance
195
+ *
196
+ * @example
197
+ * ```ts
198
+ * const triggerManager = createTriggerManager({
199
+ * root, engine, cursorRect,
200
+ * isComposing: () => compositionHandler.isComposing(),
201
+ * });
202
+ * ```
203
+ */
204
+ export declare function createTriggerManager(deps: TriggerManagerDeps): TriggerManager;
205
+ //# sourceMappingURL=trigger-manager.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"trigger-manager.d.ts","sourceRoot":"","sources":["../src/trigger-manager.ts"],"names":[],"mappings":"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"}