@rtif-sdk/web 1.0.0 → 1.3.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/block-drag-handler.d.ts +5 -0
- package/dist/block-drag-handler.d.ts.map +1 -1
- package/dist/block-drag-handler.js +32 -3
- package/dist/block-drag-handler.js.map +1 -1
- package/dist/block-renderer.d.ts +12 -6
- package/dist/block-renderer.d.ts.map +1 -1
- package/dist/block-renderer.js +98 -9
- package/dist/block-renderer.js.map +1 -1
- package/dist/block-type-dropdown.d.ts +78 -0
- package/dist/block-type-dropdown.d.ts.map +1 -0
- package/dist/block-type-dropdown.js +276 -0
- package/dist/block-type-dropdown.js.map +1 -0
- package/dist/color-picker.d.ts +91 -0
- package/dist/color-picker.d.ts.map +1 -0
- package/dist/color-picker.js +346 -0
- package/dist/color-picker.js.map +1 -0
- package/dist/content-handlers.d.ts +7 -8
- package/dist/content-handlers.d.ts.map +1 -1
- package/dist/content-handlers.js +122 -93
- package/dist/content-handlers.js.map +1 -1
- package/dist/editor.d.ts.map +1 -1
- package/dist/editor.js +224 -15
- package/dist/editor.js.map +1 -1
- package/dist/embed-utils.d.ts +148 -0
- package/dist/embed-utils.d.ts.map +1 -0
- package/dist/embed-utils.js +197 -0
- package/dist/embed-utils.js.map +1 -0
- package/dist/font-family-picker.d.ts +105 -0
- package/dist/font-family-picker.d.ts.map +1 -0
- package/dist/font-family-picker.js +314 -0
- package/dist/font-family-picker.js.map +1 -0
- package/dist/font-size-picker.d.ts +82 -0
- package/dist/font-size-picker.d.ts.map +1 -0
- package/dist/font-size-picker.js +290 -0
- package/dist/font-size-picker.js.map +1 -0
- package/dist/index.d.ts +18 -4
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +30 -2
- package/dist/index.js.map +1 -1
- package/dist/plugins/index.d.ts +2 -1
- package/dist/plugins/index.d.ts.map +1 -1
- package/dist/plugins/index.js +1 -1
- package/dist/plugins/index.js.map +1 -1
- package/dist/plugins/link-plugin.d.ts +4 -0
- package/dist/plugins/link-plugin.d.ts.map +1 -1
- package/dist/plugins/link-plugin.js +17 -0
- package/dist/plugins/link-plugin.js.map +1 -1
- package/dist/plugins/mark-utils.d.ts +31 -0
- package/dist/plugins/mark-utils.d.ts.map +1 -1
- package/dist/plugins/mark-utils.js +46 -0
- package/dist/plugins/mark-utils.js.map +1 -1
- package/dist/renderer.d.ts +31 -2
- package/dist/renderer.d.ts.map +1 -1
- package/dist/renderer.js +131 -55
- package/dist/renderer.js.map +1 -1
- package/dist/selection-sync.d.ts +2 -26
- package/dist/selection-sync.d.ts.map +1 -1
- package/dist/selection-sync.js +49 -13
- package/dist/selection-sync.js.map +1 -1
- package/dist/spatial-index.d.ts +203 -0
- package/dist/spatial-index.d.ts.map +1 -0
- package/dist/spatial-index.js +211 -0
- package/dist/spatial-index.js.map +1 -0
- package/dist/types.d.ts +93 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/virtual-viewport.d.ts +241 -0
- package/dist/virtual-viewport.d.ts.map +1 -0
- package/dist/virtual-viewport.js +584 -0
- package/dist/virtual-viewport.js.map +1 -0
- package/package.json +17 -5
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"embed-utils.d.ts","sourceRoot":"","sources":["../src/embed-utils.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAMH;;;;;;;;GAQG;AACH,MAAM,MAAM,aAAa,GAAG,SAAS,GAAG,OAAO,GAAG,SAAS,GAAG,SAAS,CAAC;AAExE;;;;;;;;;;;;;;;;;;GAkBG;AACH,MAAM,WAAW,iBAAiB;IAChC,mCAAmC;IACnC,QAAQ,CAAC,QAAQ,EAAE,aAAa,CAAC;IACjC,+DAA+D;IAC/D,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;IAC5B,yCAAyC;IACzC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,4CAA4C;IAC5C,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,mDAAmD;IACnD,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;CAC7B;AAMD;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,qBAAqB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAchE;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAM9D;AAMD;;;;;;;;;;GAUG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAEvD;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,aAAa,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAErD;AAMD;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAOrD;AAMD;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAgB,oBAAoB,CAAC,GAAG,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,MAAM,GAAG,iBAAiB,CAqDvF"}
|
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Embed utilities — pure URL transformation functions for provider-specific
|
|
3
|
+
* embed rendering.
|
|
4
|
+
*
|
|
5
|
+
* All functions are pure with zero DOM dependency. They convert a stored
|
|
6
|
+
* `(url, embedType)` pair into rendering configuration at render time,
|
|
7
|
+
* keeping the document model clean.
|
|
8
|
+
*
|
|
9
|
+
* @module
|
|
10
|
+
*/
|
|
11
|
+
// ---------------------------------------------------------------------------
|
|
12
|
+
// Video ID extraction
|
|
13
|
+
// ---------------------------------------------------------------------------
|
|
14
|
+
/**
|
|
15
|
+
* Extract a YouTube video ID from a URL.
|
|
16
|
+
*
|
|
17
|
+
* Supports `youtube.com/watch?v=ID` and `youtu.be/ID` formats.
|
|
18
|
+
* Returns `null` if the URL is not a recognized YouTube URL.
|
|
19
|
+
*
|
|
20
|
+
* @param url - The URL to extract from
|
|
21
|
+
* @returns The video ID string, or null
|
|
22
|
+
*
|
|
23
|
+
* @example
|
|
24
|
+
* ```ts
|
|
25
|
+
* extractYouTubeVideoId('https://www.youtube.com/watch?v=dQw4w9WgXcQ'); // 'dQw4w9WgXcQ'
|
|
26
|
+
* extractYouTubeVideoId('https://youtu.be/dQw4w9WgXcQ'); // 'dQw4w9WgXcQ'
|
|
27
|
+
* extractYouTubeVideoId('https://example.com'); // null
|
|
28
|
+
* ```
|
|
29
|
+
*/
|
|
30
|
+
export function extractYouTubeVideoId(url) {
|
|
31
|
+
// youtube.com/watch?v=ID
|
|
32
|
+
const longMatch = /^https?:\/\/(?:www\.)?youtube\.com\/watch\?.*v=([\w-]+)/.exec(url);
|
|
33
|
+
if (longMatch) {
|
|
34
|
+
return longMatch[1] ?? null;
|
|
35
|
+
}
|
|
36
|
+
// youtu.be/ID
|
|
37
|
+
const shortMatch = /^https?:\/\/youtu\.be\/([\w-]+)/.exec(url);
|
|
38
|
+
if (shortMatch) {
|
|
39
|
+
return shortMatch[1] ?? null;
|
|
40
|
+
}
|
|
41
|
+
return null;
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Extract a Vimeo video ID from a URL.
|
|
45
|
+
*
|
|
46
|
+
* Supports `vimeo.com/ID` format where ID is numeric.
|
|
47
|
+
* Returns `null` if the URL is not a recognized Vimeo URL.
|
|
48
|
+
*
|
|
49
|
+
* @param url - The URL to extract from
|
|
50
|
+
* @returns The video ID string, or null
|
|
51
|
+
*
|
|
52
|
+
* @example
|
|
53
|
+
* ```ts
|
|
54
|
+
* extractVimeoVideoId('https://vimeo.com/123456789'); // '123456789'
|
|
55
|
+
* extractVimeoVideoId('https://example.com'); // null
|
|
56
|
+
* ```
|
|
57
|
+
*/
|
|
58
|
+
export function extractVimeoVideoId(url) {
|
|
59
|
+
const match = /^https?:\/\/(?:www\.)?vimeo\.com\/(\d+)/.exec(url);
|
|
60
|
+
if (match) {
|
|
61
|
+
return match[1] ?? null;
|
|
62
|
+
}
|
|
63
|
+
return null;
|
|
64
|
+
}
|
|
65
|
+
// ---------------------------------------------------------------------------
|
|
66
|
+
// Embed URL builders
|
|
67
|
+
// ---------------------------------------------------------------------------
|
|
68
|
+
/**
|
|
69
|
+
* Build a YouTube embed iframe URL from a video ID.
|
|
70
|
+
*
|
|
71
|
+
* @param videoId - The YouTube video ID
|
|
72
|
+
* @returns The embeddable YouTube URL
|
|
73
|
+
*
|
|
74
|
+
* @example
|
|
75
|
+
* ```ts
|
|
76
|
+
* youtubeEmbedSrc('dQw4w9WgXcQ'); // 'https://www.youtube.com/embed/dQw4w9WgXcQ'
|
|
77
|
+
* ```
|
|
78
|
+
*/
|
|
79
|
+
export function youtubeEmbedSrc(videoId) {
|
|
80
|
+
return `https://www.youtube.com/embed/${videoId}`;
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Build a Vimeo embed iframe URL from a video ID.
|
|
84
|
+
*
|
|
85
|
+
* @param videoId - The Vimeo video ID
|
|
86
|
+
* @returns The embeddable Vimeo URL
|
|
87
|
+
*
|
|
88
|
+
* @example
|
|
89
|
+
* ```ts
|
|
90
|
+
* vimeoEmbedSrc('123456789'); // 'https://player.vimeo.com/video/123456789'
|
|
91
|
+
* ```
|
|
92
|
+
*/
|
|
93
|
+
export function vimeoEmbedSrc(videoId) {
|
|
94
|
+
return `https://player.vimeo.com/video/${videoId}`;
|
|
95
|
+
}
|
|
96
|
+
// ---------------------------------------------------------------------------
|
|
97
|
+
// Display URL extraction
|
|
98
|
+
// ---------------------------------------------------------------------------
|
|
99
|
+
/**
|
|
100
|
+
* Extract a display-friendly hostname from a URL, stripping the `www.` prefix.
|
|
101
|
+
*
|
|
102
|
+
* Falls back to the raw input string if URL parsing fails.
|
|
103
|
+
*
|
|
104
|
+
* @param url - The URL to extract a hostname from
|
|
105
|
+
* @returns A display-friendly hostname string
|
|
106
|
+
*
|
|
107
|
+
* @example
|
|
108
|
+
* ```ts
|
|
109
|
+
* extractDisplayUrl('https://www.youtube.com/watch?v=abc'); // 'youtube.com'
|
|
110
|
+
* extractDisplayUrl('https://example.com/page'); // 'example.com'
|
|
111
|
+
* extractDisplayUrl('not a url'); // 'not a url'
|
|
112
|
+
* ```
|
|
113
|
+
*/
|
|
114
|
+
export function extractDisplayUrl(url) {
|
|
115
|
+
try {
|
|
116
|
+
const parsed = new URL(url);
|
|
117
|
+
return parsed.hostname.replace(/^www\./, '');
|
|
118
|
+
}
|
|
119
|
+
catch {
|
|
120
|
+
return url;
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
// ---------------------------------------------------------------------------
|
|
124
|
+
// Main config function
|
|
125
|
+
// ---------------------------------------------------------------------------
|
|
126
|
+
/**
|
|
127
|
+
* Compute the embed render configuration for a given URL and embed type.
|
|
128
|
+
*
|
|
129
|
+
* This is the main function called by the embed renderer at render time.
|
|
130
|
+
* It maps the stored `(url, embedType)` attrs to a provider-specific
|
|
131
|
+
* configuration object that determines what DOM content to create.
|
|
132
|
+
*
|
|
133
|
+
* @param url - The embed URL from `block.attrs.url`
|
|
134
|
+
* @param embedType - The embed type from `block.attrs.embedType` (e.g., 'video', 'tweet')
|
|
135
|
+
* @returns The render configuration for the embed
|
|
136
|
+
*
|
|
137
|
+
* @example
|
|
138
|
+
* ```ts
|
|
139
|
+
* const config = getEmbedRenderConfig('https://youtube.com/watch?v=abc', 'video');
|
|
140
|
+
* // config.provider === 'youtube'
|
|
141
|
+
* // config.iframeSrc === 'https://www.youtube.com/embed/abc'
|
|
142
|
+
*
|
|
143
|
+
* const tweet = getEmbedRenderConfig('https://twitter.com/user/status/123', 'tweet');
|
|
144
|
+
* // tweet.provider === 'twitter'
|
|
145
|
+
* // tweet.iframeSrc === undefined
|
|
146
|
+
* ```
|
|
147
|
+
*/
|
|
148
|
+
export function getEmbedRenderConfig(url, embedType) {
|
|
149
|
+
const displayUrl = extractDisplayUrl(url);
|
|
150
|
+
if (embedType === 'video') {
|
|
151
|
+
// Try YouTube
|
|
152
|
+
const ytId = extractYouTubeVideoId(url);
|
|
153
|
+
if (ytId) {
|
|
154
|
+
return {
|
|
155
|
+
provider: 'youtube',
|
|
156
|
+
iframeSrc: youtubeEmbedSrc(ytId),
|
|
157
|
+
title: 'YouTube video',
|
|
158
|
+
url,
|
|
159
|
+
displayUrl,
|
|
160
|
+
};
|
|
161
|
+
}
|
|
162
|
+
// Try Vimeo
|
|
163
|
+
const vimeoId = extractVimeoVideoId(url);
|
|
164
|
+
if (vimeoId) {
|
|
165
|
+
return {
|
|
166
|
+
provider: 'vimeo',
|
|
167
|
+
iframeSrc: vimeoEmbedSrc(vimeoId),
|
|
168
|
+
title: 'Vimeo video',
|
|
169
|
+
url,
|
|
170
|
+
displayUrl,
|
|
171
|
+
};
|
|
172
|
+
}
|
|
173
|
+
// Unknown video provider — fall through to generic
|
|
174
|
+
return {
|
|
175
|
+
provider: 'generic',
|
|
176
|
+
title: 'Embedded content',
|
|
177
|
+
url,
|
|
178
|
+
displayUrl,
|
|
179
|
+
};
|
|
180
|
+
}
|
|
181
|
+
if (embedType === 'tweet') {
|
|
182
|
+
return {
|
|
183
|
+
provider: 'twitter',
|
|
184
|
+
title: 'Post on X',
|
|
185
|
+
url,
|
|
186
|
+
displayUrl,
|
|
187
|
+
};
|
|
188
|
+
}
|
|
189
|
+
// Unknown or missing embed type
|
|
190
|
+
return {
|
|
191
|
+
provider: 'generic',
|
|
192
|
+
title: 'Embedded content',
|
|
193
|
+
url,
|
|
194
|
+
displayUrl,
|
|
195
|
+
};
|
|
196
|
+
}
|
|
197
|
+
//# sourceMappingURL=embed-utils.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"embed-utils.js","sourceRoot":"","sources":["../src/embed-utils.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,105 @@
|
|
|
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 type { IEditorEngine } from '@rtif-sdk/engine';
|
|
12
|
+
import type { CommandBus } from './command-bus.js';
|
|
13
|
+
/**
|
|
14
|
+
* A font family option with a display label and CSS font-family stack.
|
|
15
|
+
*
|
|
16
|
+
* @example
|
|
17
|
+
* ```ts
|
|
18
|
+
* const custom: FontFamilyOption = {
|
|
19
|
+
* value: 'Comic Sans MS',
|
|
20
|
+
* label: 'Comic Sans',
|
|
21
|
+
* stack: '"Comic Sans MS", cursive',
|
|
22
|
+
* };
|
|
23
|
+
* ```
|
|
24
|
+
*/
|
|
25
|
+
export interface FontFamilyOption {
|
|
26
|
+
/** The font family value stored in the mark (e.g., "Georgia"). */
|
|
27
|
+
readonly value: string;
|
|
28
|
+
/** Display label shown in the dropdown (e.g., "Georgia"). */
|
|
29
|
+
readonly label: string;
|
|
30
|
+
/** Full CSS font-family stack for rendering the option (e.g., "Georgia, serif"). */
|
|
31
|
+
readonly stack: string;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Default font families displayed in the picker dropdown.
|
|
35
|
+
*
|
|
36
|
+
* Organized by category: sans-serif, serif, monospace.
|
|
37
|
+
*
|
|
38
|
+
* @example
|
|
39
|
+
* ```ts
|
|
40
|
+
* const picker = createFontFamilyPicker({
|
|
41
|
+
* container, bus, engine,
|
|
42
|
+
* families: DEFAULT_FONT_FAMILIES.filter(f => f.stack.includes('sans')),
|
|
43
|
+
* });
|
|
44
|
+
* ```
|
|
45
|
+
*/
|
|
46
|
+
export declare const DEFAULT_FONT_FAMILIES: readonly FontFamilyOption[];
|
|
47
|
+
/**
|
|
48
|
+
* Configuration for the font family picker.
|
|
49
|
+
*
|
|
50
|
+
* @example
|
|
51
|
+
* ```ts
|
|
52
|
+
* const picker = createFontFamilyPicker({
|
|
53
|
+
* container: document.getElementById('toolbar')!,
|
|
54
|
+
* bus: editor.commandBus,
|
|
55
|
+
* engine,
|
|
56
|
+
* });
|
|
57
|
+
* ```
|
|
58
|
+
*/
|
|
59
|
+
export interface FontFamilyPickerConfig {
|
|
60
|
+
/** The DOM element to render the picker into. */
|
|
61
|
+
readonly container: HTMLElement;
|
|
62
|
+
/** The command bus for executing font family commands. */
|
|
63
|
+
readonly bus: CommandBus;
|
|
64
|
+
/** The engine for querying the current mark value. */
|
|
65
|
+
readonly engine: IEditorEngine;
|
|
66
|
+
/** Font families to display (default: {@link DEFAULT_FONT_FAMILIES}). */
|
|
67
|
+
readonly families?: readonly FontFamilyOption[];
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Handle returned by {@link createFontFamilyPicker} for lifecycle management.
|
|
71
|
+
*
|
|
72
|
+
* @example
|
|
73
|
+
* ```ts
|
|
74
|
+
* const picker = createFontFamilyPicker({ container, bus, engine });
|
|
75
|
+
* // ... later:
|
|
76
|
+
* picker.destroy();
|
|
77
|
+
* ```
|
|
78
|
+
*/
|
|
79
|
+
export interface FontFamilyPickerHandle {
|
|
80
|
+
/** The picker's root wrapper element. */
|
|
81
|
+
readonly element: HTMLElement;
|
|
82
|
+
/** Remove all event listeners and DOM nodes. Idempotent. */
|
|
83
|
+
destroy(): void;
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* Create a font family picker dropdown backed by a {@link CommandBus}.
|
|
87
|
+
*
|
|
88
|
+
* The picker reflects the current font family by querying the engine's
|
|
89
|
+
* mark state. It subscribes to the bus for live updates. Each option
|
|
90
|
+
* is rendered in its own font face for preview.
|
|
91
|
+
*
|
|
92
|
+
* @param config - Picker configuration
|
|
93
|
+
* @returns A handle for lifecycle management
|
|
94
|
+
*
|
|
95
|
+
* @example
|
|
96
|
+
* ```ts
|
|
97
|
+
* const picker = createFontFamilyPicker({
|
|
98
|
+
* container: toolbar,
|
|
99
|
+
* bus: editor.commandBus,
|
|
100
|
+
* engine,
|
|
101
|
+
* });
|
|
102
|
+
* ```
|
|
103
|
+
*/
|
|
104
|
+
export declare function createFontFamilyPicker(config: FontFamilyPickerConfig): FontFamilyPickerHandle;
|
|
105
|
+
//# sourceMappingURL=font-family-picker.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"font-family-picker.d.ts","sourceRoot":"","sources":["../src/font-family-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;;;;;;;;;;;GAWG;AACH,MAAM,WAAW,gBAAgB;IAC/B,kEAAkE;IAClE,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,6DAA6D;IAC7D,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,oFAAoF;IACpF,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;CACxB;AAED;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,qBAAqB,EAAE,SAAS,gBAAgB,EAiB5D,CAAC;AAMF;;;;;;;;;;;GAWG;AACH,MAAM,WAAW,sBAAsB;IACrC,iDAAiD;IACjD,QAAQ,CAAC,SAAS,EAAE,WAAW,CAAC;IAChC,0DAA0D;IAC1D,QAAQ,CAAC,GAAG,EAAE,UAAU,CAAC;IACzB,sDAAsD;IACtD,QAAQ,CAAC,MAAM,EAAE,aAAa,CAAC;IAC/B,yEAAyE;IACzE,QAAQ,CAAC,QAAQ,CAAC,EAAE,SAAS,gBAAgB,EAAE,CAAC;CACjD;AAED;;;;;;;;;GASG;AACH,MAAM,WAAW,sBAAsB;IACrC,yCAAyC;IACzC,QAAQ,CAAC,OAAO,EAAE,WAAW,CAAC;IAC9B,4DAA4D;IAC5D,OAAO,IAAI,IAAI,CAAC;CACjB;AAMD;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,sBAAsB,GAAG,sBAAsB,CAwS7F"}
|
|
@@ -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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"}
|