@rtif-sdk/web 1.0.0 → 1.1.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 (62) hide show
  1. package/dist/block-drag-handler.d.ts +5 -0
  2. package/dist/block-drag-handler.d.ts.map +1 -1
  3. package/dist/block-drag-handler.js +28 -2
  4. package/dist/block-drag-handler.js.map +1 -1
  5. package/dist/block-renderer.d.ts +12 -6
  6. package/dist/block-renderer.d.ts.map +1 -1
  7. package/dist/block-renderer.js +98 -9
  8. package/dist/block-renderer.js.map +1 -1
  9. package/dist/block-type-dropdown.d.ts +78 -0
  10. package/dist/block-type-dropdown.d.ts.map +1 -0
  11. package/dist/block-type-dropdown.js +276 -0
  12. package/dist/block-type-dropdown.js.map +1 -0
  13. package/dist/color-picker.d.ts +91 -0
  14. package/dist/color-picker.d.ts.map +1 -0
  15. package/dist/color-picker.js +346 -0
  16. package/dist/color-picker.js.map +1 -0
  17. package/dist/content-handlers.d.ts +7 -8
  18. package/dist/content-handlers.d.ts.map +1 -1
  19. package/dist/content-handlers.js +122 -93
  20. package/dist/content-handlers.js.map +1 -1
  21. package/dist/editor.d.ts.map +1 -1
  22. package/dist/editor.js +117 -14
  23. package/dist/editor.js.map +1 -1
  24. package/dist/embed-utils.d.ts +148 -0
  25. package/dist/embed-utils.d.ts.map +1 -0
  26. package/dist/embed-utils.js +197 -0
  27. package/dist/embed-utils.js.map +1 -0
  28. package/dist/font-family-picker.d.ts +105 -0
  29. package/dist/font-family-picker.d.ts.map +1 -0
  30. package/dist/font-family-picker.js +314 -0
  31. package/dist/font-family-picker.js.map +1 -0
  32. package/dist/font-size-picker.d.ts +82 -0
  33. package/dist/font-size-picker.d.ts.map +1 -0
  34. package/dist/font-size-picker.js +290 -0
  35. package/dist/font-size-picker.js.map +1 -0
  36. package/dist/index.d.ts +12 -2
  37. package/dist/index.d.ts.map +1 -1
  38. package/dist/index.js +21 -1
  39. package/dist/index.js.map +1 -1
  40. package/dist/plugins/index.d.ts +2 -1
  41. package/dist/plugins/index.d.ts.map +1 -1
  42. package/dist/plugins/index.js +1 -1
  43. package/dist/plugins/index.js.map +1 -1
  44. package/dist/plugins/link-plugin.d.ts +4 -0
  45. package/dist/plugins/link-plugin.d.ts.map +1 -1
  46. package/dist/plugins/link-plugin.js +17 -0
  47. package/dist/plugins/link-plugin.js.map +1 -1
  48. package/dist/plugins/mark-utils.d.ts +31 -0
  49. package/dist/plugins/mark-utils.d.ts.map +1 -1
  50. package/dist/plugins/mark-utils.js +46 -0
  51. package/dist/plugins/mark-utils.js.map +1 -1
  52. package/dist/renderer.d.ts +2 -2
  53. package/dist/renderer.d.ts.map +1 -1
  54. package/dist/renderer.js +62 -16
  55. package/dist/renderer.js.map +1 -1
  56. package/dist/selection-sync.d.ts +2 -26
  57. package/dist/selection-sync.d.ts.map +1 -1
  58. package/dist/selection-sync.js +49 -13
  59. package/dist/selection-sync.js.map +1 -1
  60. package/dist/types.d.ts +24 -0
  61. package/dist/types.d.ts.map +1 -1
  62. package/package.json +17 -5
@@ -0,0 +1,314 @@
1
+ /**
2
+ * Font family picker — a dropdown for selecting text font.
3
+ *
4
+ * Each option is rendered in its own font face so the user can preview
5
+ * how the font looks. Shows the current font name in the trigger button.
6
+ * Uses the same `mousedown + preventDefault()` pattern as the toolbar to
7
+ * avoid stealing editor focus.
8
+ *
9
+ * @module
10
+ */
11
+ import { getMarkValueAtSelection } from './plugins/mark-utils.js';
12
+ // ---------------------------------------------------------------------------
13
+ // Module-scoped counter for unique IDs
14
+ // ---------------------------------------------------------------------------
15
+ let instanceCounter = 0;
16
+ /**
17
+ * Default font families displayed in the picker dropdown.
18
+ *
19
+ * Organized by category: sans-serif, serif, monospace.
20
+ *
21
+ * @example
22
+ * ```ts
23
+ * const picker = createFontFamilyPicker({
24
+ * container, bus, engine,
25
+ * families: DEFAULT_FONT_FAMILIES.filter(f => f.stack.includes('sans')),
26
+ * });
27
+ * ```
28
+ */
29
+ export const DEFAULT_FONT_FAMILIES = [
30
+ // Sans-serif
31
+ { value: 'Arial', label: 'Arial', stack: 'Arial, sans-serif' },
32
+ { value: 'Helvetica Neue', label: 'Helvetica Neue', stack: '"Helvetica Neue", Helvetica, sans-serif' },
33
+ { value: 'Verdana', label: 'Verdana', stack: 'Verdana, sans-serif' },
34
+ { value: 'Trebuchet MS', label: 'Trebuchet MS', stack: '"Trebuchet MS", sans-serif' },
35
+ { value: 'Tahoma', label: 'Tahoma', stack: 'Tahoma, sans-serif' },
36
+ // Serif
37
+ { value: 'Times New Roman', label: 'Times New Roman', stack: '"Times New Roman", Times, serif' },
38
+ { value: 'Georgia', label: 'Georgia', stack: 'Georgia, serif' },
39
+ { value: 'Garamond', label: 'Garamond', stack: 'Garamond, serif' },
40
+ { value: 'Palatino', label: 'Palatino', stack: 'Palatino, "Palatino Linotype", serif' },
41
+ // Monospace
42
+ { value: 'Courier New', label: 'Courier New', stack: '"Courier New", Courier, monospace' },
43
+ { value: 'Lucida Console', label: 'Lucida Console', stack: '"Lucida Console", Monaco, monospace' },
44
+ { value: 'Consolas', label: 'Consolas', stack: 'Consolas, monospace' },
45
+ { value: 'Monaco', label: 'Monaco', stack: 'Monaco, monospace' },
46
+ ];
47
+ // ---------------------------------------------------------------------------
48
+ // Factory
49
+ // ---------------------------------------------------------------------------
50
+ /**
51
+ * Create a font family picker dropdown backed by a {@link CommandBus}.
52
+ *
53
+ * The picker reflects the current font family by querying the engine's
54
+ * mark state. It subscribes to the bus for live updates. Each option
55
+ * is rendered in its own font face for preview.
56
+ *
57
+ * @param config - Picker configuration
58
+ * @returns A handle for lifecycle management
59
+ *
60
+ * @example
61
+ * ```ts
62
+ * const picker = createFontFamilyPicker({
63
+ * container: toolbar,
64
+ * bus: editor.commandBus,
65
+ * engine,
66
+ * });
67
+ * ```
68
+ */
69
+ export function createFontFamilyPicker(config) {
70
+ const { container, bus, engine, families = DEFAULT_FONT_FAMILIES, } = config;
71
+ const doc = container.ownerDocument;
72
+ const id = ++instanceCounter;
73
+ const menuId = `rtif-font-family-menu-${id}`;
74
+ let isOpen = false;
75
+ let highlightIndex = -1;
76
+ let destroyed = false;
77
+ // Total selectable items: "Default" + family options
78
+ const totalItems = 1 + families.length;
79
+ // -----------------------------------------------------------------------
80
+ // DOM creation
81
+ // -----------------------------------------------------------------------
82
+ const wrapper = doc.createElement('div');
83
+ wrapper.className = 'rtif-font-family-picker';
84
+ // Trigger button
85
+ const trigger = doc.createElement('button');
86
+ trigger.type = 'button';
87
+ trigger.className = 'rtif-font-family-picker-trigger';
88
+ trigger.setAttribute('role', 'combobox');
89
+ trigger.setAttribute('aria-haspopup', 'listbox');
90
+ trigger.setAttribute('aria-expanded', 'false');
91
+ trigger.setAttribute('aria-controls', menuId);
92
+ trigger.setAttribute('aria-label', 'Font family');
93
+ const labelSpan = doc.createElement('span');
94
+ labelSpan.className = 'rtif-font-family-picker-label';
95
+ const chevron = doc.createElement('span');
96
+ chevron.className = 'rtif-font-family-picker-chevron';
97
+ chevron.textContent = '\u25BE'; // ▾
98
+ trigger.appendChild(labelSpan);
99
+ trigger.appendChild(chevron);
100
+ // Menu
101
+ const menu = doc.createElement('div');
102
+ menu.id = menuId;
103
+ menu.className = 'rtif-font-family-picker-menu';
104
+ menu.setAttribute('role', 'listbox');
105
+ menu.setAttribute('aria-label', 'Font families');
106
+ menu.hidden = true;
107
+ // "Default" option (removes font family)
108
+ const defaultOption = doc.createElement('div');
109
+ defaultOption.className = 'rtif-font-family-picker-option rtif-font-family-picker-default';
110
+ defaultOption.id = `rtif-font-family-opt-${id}-default`;
111
+ defaultOption.setAttribute('role', 'option');
112
+ defaultOption.setAttribute('aria-selected', 'false');
113
+ defaultOption.textContent = 'Default';
114
+ defaultOption.addEventListener('mousedown', (e) => {
115
+ e.preventDefault();
116
+ selectDefault();
117
+ });
118
+ menu.appendChild(defaultOption);
119
+ // Separator
120
+ const sep = doc.createElement('div');
121
+ sep.className = 'rtif-font-family-picker-separator';
122
+ sep.setAttribute('role', 'separator');
123
+ menu.appendChild(sep);
124
+ // Family options
125
+ const optionEls = [];
126
+ for (let i = 0; i < families.length; i++) {
127
+ const family = families[i];
128
+ const option = doc.createElement('div');
129
+ option.className = 'rtif-font-family-picker-option';
130
+ option.id = `rtif-font-family-opt-${id}-${i}`;
131
+ option.setAttribute('role', 'option');
132
+ option.setAttribute('aria-selected', 'false');
133
+ option.setAttribute('data-family', family.value);
134
+ option.textContent = family.label;
135
+ option.style.fontFamily = family.stack;
136
+ option.addEventListener('mousedown', (e) => {
137
+ e.preventDefault();
138
+ selectFamily(family.value);
139
+ });
140
+ menu.appendChild(option);
141
+ optionEls.push(option);
142
+ }
143
+ wrapper.appendChild(trigger);
144
+ wrapper.appendChild(menu);
145
+ container.appendChild(wrapper);
146
+ // -----------------------------------------------------------------------
147
+ // Active state detection
148
+ // -----------------------------------------------------------------------
149
+ function findFamilyOption(value) {
150
+ return families.find((f) => f.value === value);
151
+ }
152
+ function updateDisplay() {
153
+ const { value, isMixed } = getMarkValueAtSelection(engine, 'fontFamily');
154
+ if (isMixed) {
155
+ labelSpan.textContent = '\u2014'; // em dash
156
+ labelSpan.style.fontFamily = '';
157
+ }
158
+ else if (value != null) {
159
+ const familyStr = value;
160
+ const matched = findFamilyOption(familyStr);
161
+ labelSpan.textContent = matched?.label ?? familyStr;
162
+ labelSpan.style.fontFamily = matched?.stack ?? familyStr;
163
+ }
164
+ else {
165
+ labelSpan.textContent = 'Default';
166
+ labelSpan.style.fontFamily = '';
167
+ }
168
+ // Update option selection
169
+ defaultOption.setAttribute('aria-selected', value == null && !isMixed ? 'true' : 'false');
170
+ for (const opt of optionEls) {
171
+ const optFamily = opt.getAttribute('data-family');
172
+ opt.setAttribute('aria-selected', !isMixed && value === optFamily ? 'true' : 'false');
173
+ }
174
+ }
175
+ // -----------------------------------------------------------------------
176
+ // Open / close
177
+ // -----------------------------------------------------------------------
178
+ function openMenu() {
179
+ if (isOpen)
180
+ return;
181
+ isOpen = true;
182
+ highlightIndex = -1;
183
+ menu.hidden = false;
184
+ trigger.setAttribute('aria-expanded', 'true');
185
+ trigger.removeAttribute('aria-activedescendant');
186
+ doc.addEventListener('mousedown', onDocumentMouseDown);
187
+ }
188
+ function closeMenu() {
189
+ if (!isOpen)
190
+ return;
191
+ isOpen = false;
192
+ highlightIndex = -1;
193
+ menu.hidden = true;
194
+ trigger.setAttribute('aria-expanded', 'false');
195
+ trigger.removeAttribute('aria-activedescendant');
196
+ // Clear highlight
197
+ defaultOption.classList.remove('rtif-font-family-picker-option-highlighted');
198
+ for (const el of optionEls) {
199
+ el.classList.remove('rtif-font-family-picker-option-highlighted');
200
+ }
201
+ doc.removeEventListener('mousedown', onDocumentMouseDown);
202
+ }
203
+ // -----------------------------------------------------------------------
204
+ // Selection
205
+ // -----------------------------------------------------------------------
206
+ function selectDefault() {
207
+ bus.execute('removeFontFamily');
208
+ closeMenu();
209
+ }
210
+ function selectFamily(family) {
211
+ bus.execute('setFontFamily', { family });
212
+ closeMenu();
213
+ }
214
+ // -----------------------------------------------------------------------
215
+ // Keyboard navigation
216
+ // -----------------------------------------------------------------------
217
+ function getOptionId(index) {
218
+ if (index === 0)
219
+ return defaultOption.id;
220
+ return optionEls[index - 1]?.id ?? '';
221
+ }
222
+ function onKeyDown(e) {
223
+ if (!isOpen)
224
+ return;
225
+ switch (e.key) {
226
+ case 'ArrowDown': {
227
+ e.preventDefault();
228
+ highlightIndex = (highlightIndex + 1) % totalItems;
229
+ updateHighlight();
230
+ break;
231
+ }
232
+ case 'ArrowUp': {
233
+ e.preventDefault();
234
+ highlightIndex = highlightIndex <= 0
235
+ ? totalItems - 1
236
+ : highlightIndex - 1;
237
+ updateHighlight();
238
+ break;
239
+ }
240
+ case 'Enter': {
241
+ e.preventDefault();
242
+ if (highlightIndex === 0) {
243
+ selectDefault();
244
+ }
245
+ else if (highlightIndex > 0 && highlightIndex <= families.length) {
246
+ selectFamily(families[highlightIndex - 1].value);
247
+ }
248
+ break;
249
+ }
250
+ case 'Escape': {
251
+ e.preventDefault();
252
+ closeMenu();
253
+ break;
254
+ }
255
+ }
256
+ }
257
+ function updateHighlight() {
258
+ defaultOption.classList.toggle('rtif-font-family-picker-option-highlighted', highlightIndex === 0);
259
+ for (let i = 0; i < optionEls.length; i++) {
260
+ optionEls[i].classList.toggle('rtif-font-family-picker-option-highlighted', highlightIndex === i + 1);
261
+ }
262
+ if (highlightIndex >= 0 && highlightIndex < totalItems) {
263
+ trigger.setAttribute('aria-activedescendant', getOptionId(highlightIndex));
264
+ }
265
+ else {
266
+ trigger.removeAttribute('aria-activedescendant');
267
+ }
268
+ }
269
+ // -----------------------------------------------------------------------
270
+ // Event handlers
271
+ // -----------------------------------------------------------------------
272
+ function onTriggerMouseDown(e) {
273
+ e.preventDefault();
274
+ }
275
+ function onTriggerClick() {
276
+ if (isOpen) {
277
+ closeMenu();
278
+ }
279
+ else {
280
+ openMenu();
281
+ }
282
+ }
283
+ function onDocumentMouseDown(e) {
284
+ if (!wrapper.contains(e.target)) {
285
+ closeMenu();
286
+ }
287
+ }
288
+ trigger.addEventListener('mousedown', onTriggerMouseDown);
289
+ trigger.addEventListener('click', onTriggerClick);
290
+ trigger.addEventListener('keydown', onKeyDown);
291
+ // -----------------------------------------------------------------------
292
+ // Bus subscription
293
+ // -----------------------------------------------------------------------
294
+ updateDisplay();
295
+ const unsubscribe = bus.subscribe(() => updateDisplay());
296
+ // -----------------------------------------------------------------------
297
+ // Handle
298
+ // -----------------------------------------------------------------------
299
+ return {
300
+ element: wrapper,
301
+ destroy() {
302
+ if (destroyed)
303
+ return;
304
+ destroyed = true;
305
+ unsubscribe();
306
+ closeMenu();
307
+ trigger.removeEventListener('mousedown', onTriggerMouseDown);
308
+ trigger.removeEventListener('click', onTriggerClick);
309
+ trigger.removeEventListener('keydown', onKeyDown);
310
+ wrapper.remove();
311
+ },
312
+ };
313
+ }
314
+ //# sourceMappingURL=font-family-picker.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"font-family-picker.js","sourceRoot":"","sources":["../src/font-family-picker.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,82 @@
1
+ /**
2
+ * Font size picker — a dropdown for selecting text size.
3
+ *
4
+ * Shows the current font size in the trigger button and lets the user
5
+ * choose from a list of preset sizes. Uses the same
6
+ * `mousedown + preventDefault()` pattern as the toolbar to avoid stealing
7
+ * editor focus.
8
+ *
9
+ * @module
10
+ */
11
+ import type { IEditorEngine } from '@rtif-sdk/engine';
12
+ import type { CommandBus } from './command-bus.js';
13
+ /**
14
+ * Default font sizes displayed in the picker dropdown.
15
+ *
16
+ * @example
17
+ * ```ts
18
+ * const picker = createFontSizePicker({
19
+ * container, bus, engine,
20
+ * sizes: DEFAULT_FONT_SIZES.filter(s => s >= 12 && s <= 36),
21
+ * });
22
+ * ```
23
+ */
24
+ export declare const DEFAULT_FONT_SIZES: readonly number[];
25
+ /**
26
+ * Configuration for the font size picker.
27
+ *
28
+ * @example
29
+ * ```ts
30
+ * const picker = createFontSizePicker({
31
+ * container: document.getElementById('toolbar')!,
32
+ * bus: editor.commandBus,
33
+ * engine,
34
+ * });
35
+ * ```
36
+ */
37
+ export interface FontSizePickerConfig {
38
+ /** The DOM element to render the picker into. */
39
+ readonly container: HTMLElement;
40
+ /** The command bus for executing font size commands. */
41
+ readonly bus: CommandBus;
42
+ /** The engine for querying the current mark value. */
43
+ readonly engine: IEditorEngine;
44
+ /** Font sizes to display (default: {@link DEFAULT_FONT_SIZES}). */
45
+ readonly sizes?: readonly number[];
46
+ }
47
+ /**
48
+ * Handle returned by {@link createFontSizePicker} for lifecycle management.
49
+ *
50
+ * @example
51
+ * ```ts
52
+ * const picker = createFontSizePicker({ container, bus, engine });
53
+ * // ... later:
54
+ * picker.destroy();
55
+ * ```
56
+ */
57
+ export interface FontSizePickerHandle {
58
+ /** The picker's root wrapper element. */
59
+ readonly element: HTMLElement;
60
+ /** Remove all event listeners and DOM nodes. Idempotent. */
61
+ destroy(): void;
62
+ }
63
+ /**
64
+ * Create a font size picker dropdown backed by a {@link CommandBus}.
65
+ *
66
+ * The picker reflects the current font size by querying the engine's
67
+ * mark state. It subscribes to the bus for live updates.
68
+ *
69
+ * @param config - Picker configuration
70
+ * @returns A handle for lifecycle management
71
+ *
72
+ * @example
73
+ * ```ts
74
+ * const picker = createFontSizePicker({
75
+ * container: toolbar,
76
+ * bus: editor.commandBus,
77
+ * engine,
78
+ * });
79
+ * ```
80
+ */
81
+ export declare function createFontSizePicker(config: FontSizePickerConfig): FontSizePickerHandle;
82
+ //# sourceMappingURL=font-size-picker.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"font-size-picker.d.ts","sourceRoot":"","sources":["../src/font-size-picker.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AACtD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAanD;;;;;;;;;;GAUG;AACH,eAAO,MAAM,kBAAkB,EAAE,SAAS,MAAM,EAE/C,CAAC;AAMF;;;;;;;;;;;GAWG;AACH,MAAM,WAAW,oBAAoB;IACnC,iDAAiD;IACjD,QAAQ,CAAC,SAAS,EAAE,WAAW,CAAC;IAChC,wDAAwD;IACxD,QAAQ,CAAC,GAAG,EAAE,UAAU,CAAC;IACzB,sDAAsD;IACtD,QAAQ,CAAC,MAAM,EAAE,aAAa,CAAC;IAC/B,mEAAmE;IACnE,QAAQ,CAAC,KAAK,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;CACpC;AAED;;;;;;;;;GASG;AACH,MAAM,WAAW,oBAAoB;IACnC,yCAAyC;IACzC,QAAQ,CAAC,OAAO,EAAE,WAAW,CAAC;IAC9B,4DAA4D;IAC5D,OAAO,IAAI,IAAI,CAAC;CACjB;AAMD;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,oBAAoB,GAAG,oBAAoB,CA8RvF"}