@rcarls/rc-textarea 0.1.0 → 0.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/README.md +173 -1176
- package/dist/custom-elements.json +168 -72
- package/dist/{line-actions-controller-BsM6DJ0b.js → line-actions-controller-ChmbiQ-G.js} +573 -532
- package/dist/line-actions-controller-ChmbiQ-G.js.map +1 -0
- package/dist/rc-textarea-define.js +2 -2
- package/dist/rc-textarea.js +1 -1
- package/dist/types/packages/rc-textarea/src/blots.d.ts +7 -7
- package/dist/types/packages/rc-textarea/src/decoration.d.ts +5 -2
- package/dist/types/packages/rc-textarea/src/document.d.ts +7 -9
- package/dist/types/packages/rc-textarea/src/line-actions-controller.d.ts +12 -9
- package/dist/types/packages/rc-textarea/src/line-decorator.d.ts +9 -8
- package/dist/types/packages/rc-textarea/src/pattern-matcher.d.ts +4 -2
- package/dist/types/packages/rc-textarea/src/rc-textarea.d.ts +101 -32
- package/dist/types/packages/rc-textarea/src/selection.d.ts +17 -13
- package/dist/types/packages/rc-textarea/src/test-helpers.d.ts +6 -4
- package/dist/types/packages/rc-textarea/src/types.d.ts +119 -40
- package/package.json +7 -8
- package/dist/demo.css +0 -85
- package/dist/demo.js +0 -40
- package/dist/line-actions-controller-BsM6DJ0b.js.map +0 -1
|
@@ -1,39 +1,52 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* A styled inline range over characters [from, to).
|
|
3
|
+
*
|
|
3
4
|
* Rich formatting properties (bold, italic, color, etc.) are rendered as
|
|
4
5
|
* inline styles on the blot span; `className` adds an extra CSS class.
|
|
5
6
|
*/
|
|
6
7
|
export interface MarkDecoration {
|
|
8
|
+
/** Unique identifier assigned at creation time. */
|
|
7
9
|
id: string;
|
|
10
|
+
/** Decoration type discriminant. */
|
|
8
11
|
type: 'mark';
|
|
9
12
|
/** Inclusive start offset (0-based character index into plain text). */
|
|
10
13
|
from: number;
|
|
11
14
|
/** Exclusive end offset. */
|
|
12
15
|
to: number;
|
|
16
|
+
/** Space-separated CSS class name(s) added to the blot span. */
|
|
13
17
|
className?: string;
|
|
18
|
+
/** Renders the range bold (`font-weight: bold`). */
|
|
14
19
|
bold?: boolean;
|
|
20
|
+
/** Renders the range italic (`font-style: italic`). */
|
|
15
21
|
italic?: boolean;
|
|
22
|
+
/** Text color (`color` CSS property). Accepts any CSS color value. */
|
|
16
23
|
color?: string;
|
|
24
|
+
/** Background color (`background` CSS property). Accepts any CSS color value. */
|
|
17
25
|
background?: string;
|
|
26
|
+
/** Underline style (`text-decoration-style`). */
|
|
18
27
|
underline?: 'solid' | 'wavy' | 'dotted' | 'dashed';
|
|
28
|
+
/** Underline color (`text-decoration-color`). Defaults to the text `color` when omitted. */
|
|
19
29
|
underlineColor?: string;
|
|
30
|
+
/** Additional HTML attributes set directly on the blot span element. */
|
|
20
31
|
attributes?: Record<string, string>;
|
|
21
32
|
}
|
|
22
33
|
/**
|
|
23
34
|
* A decoration applied to an entire logical line.
|
|
35
|
+
*
|
|
24
36
|
* Adds a CSS class and/or data attributes to the line div, and optionally
|
|
25
|
-
* appends
|
|
37
|
+
* appends a diagnostic message at the end of the line.
|
|
26
38
|
*/
|
|
27
39
|
export interface LineDecoration {
|
|
40
|
+
/** Unique identifier assigned at creation time. */
|
|
28
41
|
id: string;
|
|
42
|
+
/** Decoration type discriminant. */
|
|
29
43
|
type: 'line';
|
|
30
44
|
/** 1-based logical line number. */
|
|
31
45
|
line: number;
|
|
46
|
+
/** Space-separated CSS class name(s) added to the line div. */
|
|
32
47
|
className?: string;
|
|
33
48
|
/**
|
|
34
|
-
* Error-lens style
|
|
35
|
-
* Rendered via `::after` pseudo-element on the line div (not a real DOM node),
|
|
36
|
-
* so it is completely excluded from selection and clipboard operations.
|
|
49
|
+
* Error-lens style diagnostic text shown at the end of the line.
|
|
37
50
|
*/
|
|
38
51
|
message?: string;
|
|
39
52
|
/**
|
|
@@ -41,25 +54,30 @@ export interface LineDecoration {
|
|
|
41
54
|
* on the line div. Use attribute selectors in CSS to style the message:
|
|
42
55
|
*
|
|
43
56
|
* ```css
|
|
44
|
-
* .
|
|
57
|
+
* .line[data-message-class~="error"][data-message]::after { color: red; }
|
|
45
58
|
* ```
|
|
46
59
|
*/
|
|
47
60
|
messageClassName?: string;
|
|
61
|
+
/** Additional HTML attributes set directly on the line element. */
|
|
48
62
|
attributes?: Record<string, string>;
|
|
49
63
|
/**
|
|
50
64
|
* Override the built-in gutter cell text for this line.
|
|
65
|
+
*
|
|
51
66
|
* - `string` — custom label (e.g. `"!"`, `"▶"`)
|
|
52
67
|
* - `null` — force empty cell (suppress built-in content)
|
|
53
|
-
* - `undefined` — use the built-in mode default (`line-numbers`, `
|
|
68
|
+
* - `undefined` — use the built-in mode default (`line-numbers`, `gutter`, etc.)
|
|
54
69
|
*/
|
|
55
70
|
gutterContent?: string | null;
|
|
56
71
|
}
|
|
57
72
|
/**
|
|
58
73
|
* A non-editable DOM element inserted at a character offset.
|
|
74
|
+
*
|
|
59
75
|
* Widgets are purely visual and do not appear in the plain text value.
|
|
60
76
|
*/
|
|
61
77
|
export interface WidgetDecoration {
|
|
78
|
+
/** Unique identifier assigned at creation time. */
|
|
62
79
|
id: string;
|
|
80
|
+
/** Decoration type discriminant. */
|
|
63
81
|
type: 'widget';
|
|
64
82
|
/** Character offset. Widget is placed before (or after) the character at this position. */
|
|
65
83
|
offset: number;
|
|
@@ -68,10 +86,15 @@ export interface WidgetDecoration {
|
|
|
68
86
|
/** Whether to place the widget before or after the character at `offset`. Default: 'before'. */
|
|
69
87
|
side?: 'before' | 'after';
|
|
70
88
|
}
|
|
89
|
+
/** Decorations are visual formatting applied to the field content without affecting
|
|
90
|
+
* the underlying plain text value.
|
|
91
|
+
*/
|
|
71
92
|
export type Decoration = MarkDecoration | LineDecoration | WidgetDecoration;
|
|
93
|
+
/** Input shape for creating a decoration — id-less variant of each decoration type. */
|
|
72
94
|
export type DecorationInput = Omit<MarkDecoration, 'id'> | Omit<LineDecoration, 'id'> | Omit<WidgetDecoration, 'id'>;
|
|
73
95
|
/**
|
|
74
96
|
* A semantic token produced by an external tokenizer (lezer, tree-sitter, shiki, etc.).
|
|
97
|
+
*
|
|
75
98
|
* Offsets are absolute character indices into the plain-text value — the same coordinate
|
|
76
99
|
* space as `MarkDecoration.from` / `MarkDecoration.to`.
|
|
77
100
|
*
|
|
@@ -83,9 +106,9 @@ export interface Token {
|
|
|
83
106
|
from: number;
|
|
84
107
|
/** Exclusive end offset. */
|
|
85
108
|
to: number;
|
|
86
|
-
/** Semantic token type
|
|
109
|
+
/** Semantic token type. */
|
|
87
110
|
type: string;
|
|
88
|
-
/** Optional
|
|
111
|
+
/** Optional scope list. */
|
|
89
112
|
scopes?: string[];
|
|
90
113
|
}
|
|
91
114
|
/**
|
|
@@ -100,28 +123,35 @@ export interface Token {
|
|
|
100
123
|
* mount(a) { api = a; },
|
|
101
124
|
* update() {},
|
|
102
125
|
* });
|
|
126
|
+
*
|
|
103
127
|
* // later:
|
|
104
128
|
* api.setDecorations([...]);
|
|
105
129
|
* api.scheduleUpdate();
|
|
106
130
|
* ```
|
|
107
131
|
*/
|
|
108
132
|
export interface RCTextareaPluginAPI {
|
|
109
|
-
/** The host rc-textarea element. */
|
|
133
|
+
/** The host `rc-textarea` element. */
|
|
110
134
|
readonly host: HTMLElement;
|
|
135
|
+
/** The current plain-text field value at the time of the callback. */
|
|
111
136
|
readonly value: string;
|
|
112
|
-
/** Normalized selection start offset (always ≤ selectionEnd). */
|
|
137
|
+
/** Normalized selection start offset (always ≤ `selectionEnd`). */
|
|
113
138
|
readonly selectionStart: number;
|
|
114
|
-
/** Normalized selection end offset (always ≥ selectionStart). Equals selectionStart when the cursor is collapsed. */
|
|
139
|
+
/** Normalized selection end offset (always ≥ `selectionStart`). Equals `selectionStart` when the cursor is collapsed. */
|
|
115
140
|
readonly selectionEnd: number;
|
|
116
141
|
/**
|
|
117
|
-
* Returns the bounding rect of the cursor (caret) in viewport coordinates
|
|
118
|
-
*
|
|
142
|
+
* Returns the bounding rect of the cursor (caret) in viewport coordinates.
|
|
143
|
+
*
|
|
119
144
|
* Useful for anchoring autocomplete popups or hover tooltips to the cursor.
|
|
145
|
+
*
|
|
146
|
+
* @returns the cursor bounding rect, or `null` if the editor is not focused
|
|
147
|
+
* or the cursor is outside the editor
|
|
120
148
|
*/
|
|
121
149
|
getCursorRect(): DOMRect | null;
|
|
122
150
|
/**
|
|
123
|
-
* Returns the word at the current cursor position
|
|
124
|
-
*
|
|
151
|
+
* Returns the word boundaries at the current cursor position.
|
|
152
|
+
*
|
|
153
|
+
* @returns the word and its `[from, to)` offsets, or `null` if the cursor is
|
|
154
|
+
* not on a word character (`\w` — alphanumeric + underscore)
|
|
125
155
|
*/
|
|
126
156
|
getWordAtCursor(): {
|
|
127
157
|
word: string;
|
|
@@ -131,7 +161,8 @@ export interface RCTextareaPluginAPI {
|
|
|
131
161
|
/**
|
|
132
162
|
* Subscribe to cursor/selection changes. The callback fires on every cursor
|
|
133
163
|
* move (arrow keys, mouse clicks, selection changes) while the editor is focused.
|
|
134
|
-
*
|
|
164
|
+
*
|
|
165
|
+
* @returns an unsubscribe function. Call this in `destroy()`
|
|
135
166
|
*
|
|
136
167
|
* @example
|
|
137
168
|
* ```ts
|
|
@@ -148,24 +179,35 @@ export interface RCTextareaPluginAPI {
|
|
|
148
179
|
* ```
|
|
149
180
|
*/
|
|
150
181
|
onCursorMove(callback: (selectionStart: number, selectionEnd: number) => void): () => void;
|
|
182
|
+
/**
|
|
183
|
+
* Add a single decoration to the plugin's decoration set.
|
|
184
|
+
*
|
|
185
|
+
* Use the returned id with `removeDecoration` to remove it individually.
|
|
186
|
+
*
|
|
187
|
+
* @returns the assigned `id`, used to remove or look up the decoration later
|
|
188
|
+
*/
|
|
151
189
|
addDecoration(d: DecorationInput): string;
|
|
190
|
+
/** Remove a previously added decoration by its id. */
|
|
152
191
|
removeDecoration(id: string): void;
|
|
192
|
+
/** Remove all decorations set by this plugin. */
|
|
153
193
|
clearDecorations(): void;
|
|
194
|
+
/**
|
|
195
|
+
* Replace the full decoration set with `decorations`.
|
|
196
|
+
*/
|
|
154
197
|
setDecorations(decorations: DecorationInput[]): void;
|
|
155
|
-
/**
|
|
198
|
+
/**
|
|
199
|
+
* @returns the decorations this plugin has currently set, in insertion order
|
|
200
|
+
*/
|
|
156
201
|
getDecorations(): readonly Decoration[];
|
|
157
202
|
/** Trigger a render pass outside of normal text input events. */
|
|
158
203
|
scheduleUpdate(): void;
|
|
159
204
|
/**
|
|
160
205
|
* Inject a stylesheet into the component's shadow root via `adoptedStyleSheets`.
|
|
161
206
|
*
|
|
162
|
-
*
|
|
163
|
-
* extra parsing cost), or a raw CSS text string to compile and adopt a new one.
|
|
164
|
-
* Returns the adopted `CSSStyleSheet` so it can be passed to `removeStyleSheet`
|
|
165
|
-
* if explicit removal is needed before the plugin is unmounted.
|
|
207
|
+
* Adopted sheets are automatically removed when the plugin is unmounted.
|
|
166
208
|
*
|
|
167
|
-
*
|
|
168
|
-
*
|
|
209
|
+
* @returns the adopted `CSSStyleSheet`, which can be passed to `removeStyleSheet`
|
|
210
|
+
* if explicit removal is needed before unmount
|
|
169
211
|
*
|
|
170
212
|
* @example CSS text string
|
|
171
213
|
* ```ts
|
|
@@ -192,8 +234,6 @@ export interface RCTextareaPluginAPI {
|
|
|
192
234
|
adoptStyleSheet(sheetOrCssText: CSSStyleSheet | string): CSSStyleSheet;
|
|
193
235
|
/**
|
|
194
236
|
* Remove a previously adopted stylesheet from the shadow root.
|
|
195
|
-
* The sheet does not need to have been adopted via `adoptStyleSheet` —
|
|
196
|
-
* any sheet already present in `adoptedStyleSheets` may be removed.
|
|
197
237
|
*/
|
|
198
238
|
removeStyleSheet(sheet: CSSStyleSheet): void;
|
|
199
239
|
/**
|
|
@@ -204,15 +244,20 @@ export interface RCTextareaPluginAPI {
|
|
|
204
244
|
* them into `MarkDecoration` objects covering the corresponding character
|
|
205
245
|
* ranges of the plain text value.
|
|
206
246
|
*
|
|
247
|
+
* @example
|
|
207
248
|
* ```ts
|
|
208
249
|
* editor.usePlugin({
|
|
209
250
|
* highlight(value, api) {
|
|
210
251
|
* const html = hljs.highlight(value, { language: 'js' }).value;
|
|
211
|
-
* api.setDecorations(api.
|
|
252
|
+
* api.setDecorations(api.parseDecorationsFromHtml(html));
|
|
212
253
|
* },
|
|
213
254
|
* });
|
|
214
255
|
* ```
|
|
215
256
|
*/
|
|
257
|
+
parseDecorationsFromHtml(html: string): Omit<MarkDecoration, 'id'>[];
|
|
258
|
+
/**
|
|
259
|
+
* @deprecated Use `parseDecorationsFromHtml` instead.
|
|
260
|
+
*/
|
|
216
261
|
decorationsFromHtml(html: string): Omit<MarkDecoration, 'id'>[];
|
|
217
262
|
/**
|
|
218
263
|
* Convert a flat token array from an external tokenizer (lezer, tree-sitter, shiki, moo, etc.)
|
|
@@ -222,6 +267,7 @@ export interface RCTextareaPluginAPI {
|
|
|
222
267
|
* (same coordinate space as `MarkDecoration.from` / `MarkDecoration.to`).
|
|
223
268
|
* Types not present in `themeMap` are silently ignored.
|
|
224
269
|
*
|
|
270
|
+
* @example
|
|
225
271
|
* ```ts
|
|
226
272
|
* editor.usePlugin({
|
|
227
273
|
* update(value, api) {
|
|
@@ -238,13 +284,16 @@ export interface RCTextareaPluginAPI {
|
|
|
238
284
|
decorationsFromTokens(tokens: Token[], themeMap: Record<string, Omit<MarkDecoration, 'id' | 'type' | 'from' | 'to'>>): Omit<MarkDecoration, 'id'>[];
|
|
239
285
|
/**
|
|
240
286
|
* Insert `text` at the current cursor position, replacing any active selection.
|
|
287
|
+
*
|
|
241
288
|
* Equivalent to typing the text with the keyboard.
|
|
242
289
|
*/
|
|
243
290
|
insertText(text: string): void;
|
|
244
291
|
/**
|
|
245
292
|
* Wrap the current selection with `prefix` and `suffix`.
|
|
293
|
+
*
|
|
246
294
|
* No-op when the selection is collapsed (no text selected).
|
|
247
295
|
*
|
|
296
|
+
* @example
|
|
248
297
|
* ```ts
|
|
249
298
|
* api.wrapSelection('**', '**'); // bold
|
|
250
299
|
* api.wrapSelection('`', '`'); // inline code
|
|
@@ -253,6 +302,7 @@ export interface RCTextareaPluginAPI {
|
|
|
253
302
|
wrapSelection(prefix: string, suffix: string): void;
|
|
254
303
|
/**
|
|
255
304
|
* Replace the current selection with `text`.
|
|
305
|
+
*
|
|
256
306
|
* When the selection is collapsed this is equivalent to `insertText`.
|
|
257
307
|
*/
|
|
258
308
|
replaceSelection(text: string): void;
|
|
@@ -266,12 +316,14 @@ export interface RCTextareaPluginAPI {
|
|
|
266
316
|
* ```ts
|
|
267
317
|
* import hljs from 'highlight.js/lib/core';
|
|
268
318
|
* import javascript from 'highlight.js/lib/languages/javascript';
|
|
319
|
+
*
|
|
269
320
|
* hljs.registerLanguage('javascript', javascript);
|
|
270
321
|
*
|
|
271
322
|
* editor.usePlugin({
|
|
272
323
|
* highlight(value, api) {
|
|
273
324
|
* const html = hljs.highlight(value, { language: 'javascript' }).value;
|
|
274
|
-
*
|
|
325
|
+
*
|
|
326
|
+
* api.setDecorations(api.parseDecorationsFromHtml(html));
|
|
275
327
|
* },
|
|
276
328
|
* });
|
|
277
329
|
* ```
|
|
@@ -281,6 +333,7 @@ export interface RCTextareaPluginAPI {
|
|
|
281
333
|
* editor.usePlugin({
|
|
282
334
|
* async update(value, api) {
|
|
283
335
|
* const decs = await myParser.decorate(value);
|
|
336
|
+
*
|
|
284
337
|
* api.setDecorations(decs);
|
|
285
338
|
* },
|
|
286
339
|
* });
|
|
@@ -293,50 +346,69 @@ export interface RCTextareaPlugin {
|
|
|
293
346
|
destroy?(): void;
|
|
294
347
|
/**
|
|
295
348
|
* Display-layer value transform — called before `update`/`highlight` in
|
|
296
|
-
* read-only mode.
|
|
349
|
+
* read-only mode.
|
|
350
|
+
*
|
|
351
|
+
* Return a non-null string to substitute it as the rendered
|
|
297
352
|
* text passed to all subsequent hooks and to the document builder.
|
|
298
|
-
* The underlying `element.value` is
|
|
353
|
+
* The underlying `element.value` is never modified; only the display
|
|
299
354
|
* layer sees the transformed text.
|
|
355
|
+
*
|
|
300
356
|
* Return `null` or `void` to leave the value unchanged.
|
|
301
357
|
*/
|
|
302
358
|
transform?(value: string, api: RCTextareaPluginAPI): string | null | void;
|
|
303
359
|
/**
|
|
304
|
-
* Imperative decoration API
|
|
305
|
-
* Use `api.setDecorations()` to apply decorations.
|
|
360
|
+
* Imperative decoration API
|
|
306
361
|
*/
|
|
307
362
|
update?(value: string, api: RCTextareaPluginAPI): void | Promise<void>;
|
|
308
363
|
/**
|
|
309
|
-
* HTML-based compat
|
|
364
|
+
* HTML-based compat
|
|
365
|
+
*
|
|
310
366
|
* Return an HTML string (e.g. from hljs/prism); it will be parsed via
|
|
311
|
-
* `api.
|
|
367
|
+
* `api.parseDecorationsFromHtml()` and applied as mark decorations.
|
|
368
|
+
*
|
|
312
369
|
* Return `null` or `void` to skip.
|
|
313
370
|
*/
|
|
314
371
|
highlight?(value: string, api: RCTextareaPluginAPI): string | null | void | Promise<string | null | void>;
|
|
315
372
|
}
|
|
316
373
|
/**
|
|
317
374
|
* The subset of `MarkDecoration` properties used for styling.
|
|
375
|
+
*
|
|
318
376
|
* Used in `TextPattern.captureGroups` to assign a style to each named capture group.
|
|
319
377
|
*/
|
|
320
378
|
export type MarkDecorationStyle = Pick<MarkDecoration, 'className' | 'bold' | 'italic' | 'color' | 'background' | 'underline' | 'underlineColor' | 'attributes'>;
|
|
321
379
|
export interface TextPattern {
|
|
380
|
+
/** Unique identifier used to register and unregister the pattern. */
|
|
322
381
|
id: string;
|
|
382
|
+
/** Regular expression matched against the full editor value. Use the `g` flag for multiple matches. */
|
|
323
383
|
pattern: RegExp;
|
|
384
|
+
/** Space-separated CSS class name(s) applied to matched ranges. */
|
|
324
385
|
className?: string;
|
|
386
|
+
/** Renders matched ranges bold (`font-weight: bold`). */
|
|
325
387
|
bold?: boolean;
|
|
388
|
+
/** Renders matched ranges italic (`font-style: italic`). */
|
|
326
389
|
italic?: boolean;
|
|
390
|
+
/** Text color for matched ranges. Accepts any CSS color value. */
|
|
327
391
|
color?: string;
|
|
392
|
+
/** Background color for matched ranges. Accepts any CSS color value. */
|
|
328
393
|
background?: string;
|
|
394
|
+
/** Underline style for matched ranges (`text-decoration-style`). */
|
|
329
395
|
underline?: 'solid' | 'wavy' | 'dotted' | 'dashed';
|
|
396
|
+
/** Underline color for matched ranges (`text-decoration-color`). Defaults to the text `color` when omitted. */
|
|
330
397
|
underlineColor?: string;
|
|
398
|
+
/** Additional HTML attributes set directly on matched-range spans. */
|
|
331
399
|
attributes?: Record<string, string>;
|
|
332
400
|
/**
|
|
333
|
-
* Factory called for each regex match.
|
|
334
|
-
*
|
|
335
|
-
*
|
|
401
|
+
* Factory called for each regex match.
|
|
402
|
+
*
|
|
403
|
+
* Return a partial LineDecoration
|
|
404
|
+
* (message, messageClassName, className, attributes) to add a diagnostic
|
|
405
|
+
* message on the matched line, or `null` to skip.
|
|
336
406
|
*/
|
|
337
407
|
createLineDecoration?: (match: RegExpMatchArray) => Omit<LineDecoration, 'id' | 'type' | 'line'> | null;
|
|
338
408
|
/**
|
|
339
|
-
*
|
|
409
|
+
* Decoration styles for each named capture group in the pattern.
|
|
410
|
+
*
|
|
411
|
+
* When provided, one
|
|
340
412
|
* `MarkDecoration` is emitted per captured group (unmatched optional groups
|
|
341
413
|
* are skipped) instead of one decoration for the whole match.
|
|
342
414
|
*
|
|
@@ -360,8 +432,10 @@ export interface TextPattern {
|
|
|
360
432
|
/**
|
|
361
433
|
* A simplified plugin variant for per-line decoration.
|
|
362
434
|
*
|
|
363
|
-
* Return mark/line decorations with offsets
|
|
364
|
-
* line
|
|
435
|
+
* Return mark/line decorations with offsets relative to the start of the
|
|
436
|
+
* line.
|
|
437
|
+
*
|
|
438
|
+
* `createLineDecoratorPlugin()` converts them to absolute document
|
|
365
439
|
* offsets automatically, so no `lineStart` bookkeeping is needed.
|
|
366
440
|
*
|
|
367
441
|
* @example
|
|
@@ -371,10 +445,15 @@ export interface TextPattern {
|
|
|
371
445
|
* decorateLine(line) {
|
|
372
446
|
* const results: Omit<MarkDecoration | LineDecoration, 'id'>[] = [];
|
|
373
447
|
* const m = /\bfunction\b/.exec(line);
|
|
374
|
-
*
|
|
448
|
+
*
|
|
449
|
+
* if (m) {
|
|
450
|
+
* results.push({ type: 'mark', from: m.index, to: m.index + m[0].length, className: 'kw' });
|
|
451
|
+
* }
|
|
452
|
+
*
|
|
375
453
|
* return results;
|
|
376
454
|
* },
|
|
377
455
|
* };
|
|
456
|
+
*
|
|
378
457
|
* editor.usePlugin(createLineDecoratorPlugin(myDecorator));
|
|
379
458
|
* ```
|
|
380
459
|
*/
|
package/package.json
CHANGED
|
@@ -3,14 +3,14 @@
|
|
|
3
3
|
"publishConfig": {
|
|
4
4
|
"access": "public"
|
|
5
5
|
},
|
|
6
|
-
"version": "0.
|
|
7
|
-
"description": "
|
|
6
|
+
"version": "0.3.0",
|
|
7
|
+
"description": "Textarea wrapper with line decorations, gutter rendering, inline widgets, and plugin hooks.",
|
|
8
8
|
"repository": {
|
|
9
9
|
"type": "git",
|
|
10
10
|
"url": "git+https://github.com/richardcarls/rc-webcomponents.git",
|
|
11
11
|
"directory": "packages/rc-textarea"
|
|
12
12
|
},
|
|
13
|
-
"homepage": "https://github.
|
|
13
|
+
"homepage": "https://richardcarls.github.io/rc-webcomponents/components/rc-textarea",
|
|
14
14
|
"license": "MIT",
|
|
15
15
|
"type": "module",
|
|
16
16
|
"files": [
|
|
@@ -37,20 +37,19 @@
|
|
|
37
37
|
],
|
|
38
38
|
"customElements": "dist/custom-elements.json",
|
|
39
39
|
"scripts": {
|
|
40
|
-
"dev": "vite",
|
|
41
40
|
"build": "tsc && vite build && cem analyze",
|
|
42
41
|
"cem:analyze": "cem analyze",
|
|
43
42
|
"preview": "vite preview",
|
|
44
|
-
"test:browser": "vitest",
|
|
45
|
-
"test:browser:chrome": "vitest --project=chromium",
|
|
46
|
-
"test:browser:firefox": "vitest --project=firefox"
|
|
43
|
+
"test:browser": "vitest --run",
|
|
44
|
+
"test:browser:chrome": "vitest --run --project=chromium",
|
|
45
|
+
"test:browser:firefox": "vitest --run --project=firefox"
|
|
47
46
|
},
|
|
48
47
|
"dependencies": {
|
|
48
|
+
"@rcarls/rc-common": "workspace:*",
|
|
49
49
|
"parchment": "^3.0.0"
|
|
50
50
|
},
|
|
51
51
|
"devDependencies": {
|
|
52
52
|
"@custom-elements-manifest/analyzer": "0.11.0",
|
|
53
|
-
"@guanghechen/rollup-plugin-copy": "^6.0.9",
|
|
54
53
|
"@types/node": "^25.6.0",
|
|
55
54
|
"@vitest/browser-playwright": "4.1.5",
|
|
56
55
|
"lit": "^3.0.0",
|
package/dist/demo.css
DELETED
|
@@ -1,85 +0,0 @@
|
|
|
1
|
-
*, *::before, *::after {
|
|
2
|
-
box-sizing: border-box;
|
|
3
|
-
}
|
|
4
|
-
|
|
5
|
-
:root {
|
|
6
|
-
color-scheme: light dark;
|
|
7
|
-
--rc-accent: Highlight; /* Chrome doesn't support AccentColor on the open web */
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
@supports (color: AccentColor) {
|
|
11
|
-
:root {
|
|
12
|
-
--rc-accent: AccentColor;
|
|
13
|
-
}
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
[data-theme="light"] { color-scheme: light; }
|
|
17
|
-
[data-theme="dark"] { color-scheme: dark; }
|
|
18
|
-
|
|
19
|
-
[data-theme="solarized-light"] {
|
|
20
|
-
color-scheme: light;
|
|
21
|
-
--rc-surface: #fdf6e3;
|
|
22
|
-
--rc-text: #657b83;
|
|
23
|
-
--rc-border: 1px solid #93a1a1;
|
|
24
|
-
--rc-shadow: 0 2px 8px rgba(0, 0, 0, .12);
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
[data-theme="solarized-dark"] {
|
|
28
|
-
color-scheme: dark;
|
|
29
|
-
--rc-surface: #002b36;
|
|
30
|
-
--rc-text: #839496;
|
|
31
|
-
--rc-border: 1px solid #586e75;
|
|
32
|
-
--rc-shadow: 0 2px 8px rgba(0, 0, 0, .3);
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
body {
|
|
36
|
-
font-family: system-ui, sans-serif;
|
|
37
|
-
margin: 0;
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
.demo-page {
|
|
41
|
-
max-width: 60rem;
|
|
42
|
-
margin: 0 auto;
|
|
43
|
-
padding: 2rem 1.5rem;
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
.demo-controls {
|
|
47
|
-
display: flex;
|
|
48
|
-
align-items: center;
|
|
49
|
-
gap: 1rem;
|
|
50
|
-
margin-bottom: 2rem;
|
|
51
|
-
padding-bottom: 1rem;
|
|
52
|
-
border-bottom: 1px solid ButtonBorder;
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
.demo-controls .demo-title {
|
|
56
|
-
flex: 1;
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
.demo-controls h1 {
|
|
60
|
-
margin: 0 0 0.15rem;
|
|
61
|
-
font-size: 1.5rem;
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
.demo-controls a {
|
|
65
|
-
font-size: 0.8rem;
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
.demo-section {
|
|
69
|
-
margin-bottom: 2rem;
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
.demo-section h2 {
|
|
73
|
-
margin: 0 0 0.5rem;
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
.theme-picker {
|
|
77
|
-
padding: 0.35em 0.75em;
|
|
78
|
-
font-family: inherit;
|
|
79
|
-
font-size: 0.8rem;
|
|
80
|
-
cursor: pointer;
|
|
81
|
-
border: 1px solid ButtonBorder;
|
|
82
|
-
border-radius: 4px;
|
|
83
|
-
background: Canvas;
|
|
84
|
-
color: CanvasText;
|
|
85
|
-
}
|
package/dist/demo.js
DELETED
|
@@ -1,40 +0,0 @@
|
|
|
1
|
-
const THEMES = ['', 'light', 'dark', 'solarized-light', 'solarized-dark'];
|
|
2
|
-
const LABELS = ['Auto', 'Light', 'Dark', 'Solarized ☀', 'Solarized ☾'];
|
|
3
|
-
|
|
4
|
-
const stored = localStorage.getItem('rc-demo-theme') ?? '';
|
|
5
|
-
applyTheme(stored);
|
|
6
|
-
|
|
7
|
-
function applyTheme(theme) {
|
|
8
|
-
if (theme) {
|
|
9
|
-
document.documentElement.dataset.theme = theme;
|
|
10
|
-
} else {
|
|
11
|
-
delete document.documentElement.dataset.theme;
|
|
12
|
-
}
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
function currentIndex() {
|
|
16
|
-
const current = document.documentElement.dataset.theme ?? '';
|
|
17
|
-
const idx = THEMES.indexOf(current);
|
|
18
|
-
return idx === -1 ? 0 : idx;
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
function updateButtons() {
|
|
22
|
-
const label = LABELS[currentIndex()];
|
|
23
|
-
document.querySelectorAll('.theme-picker').forEach((btn) => {
|
|
24
|
-
btn.textContent = label;
|
|
25
|
-
});
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
window.cycleTheme = function () {
|
|
29
|
-
const next = THEMES[(currentIndex() + 1) % THEMES.length];
|
|
30
|
-
applyTheme(next);
|
|
31
|
-
localStorage.setItem('rc-demo-theme', next);
|
|
32
|
-
updateButtons();
|
|
33
|
-
};
|
|
34
|
-
|
|
35
|
-
document.addEventListener('DOMContentLoaded', () => {
|
|
36
|
-
updateButtons();
|
|
37
|
-
document.querySelectorAll('.theme-picker').forEach((btn) => {
|
|
38
|
-
btn.addEventListener('click', window.cycleTheme);
|
|
39
|
-
});
|
|
40
|
-
});
|