@rcarls/rc-textarea 0.6.0 → 0.7.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/CHANGELOG.md +189 -0
- package/README.md +67 -31
- package/dist/custom-elements.json +612 -21
- package/dist/folding-action-controller-sxM3IomW.js +91 -0
- package/dist/folding-action-controller-sxM3IomW.js.map +1 -0
- package/dist/{line-actions-controller-BcsnmSPS.js → line-actions-controller-DUdXQxMA.js} +912 -790
- package/dist/line-actions-controller-DUdXQxMA.js.map +1 -0
- package/dist/rc-textarea-define.js +2 -2
- package/dist/rc-textarea-folding.js +5 -0
- package/dist/rc-textarea-folding.js.map +1 -0
- package/dist/rc-textarea.js +1 -1
- package/dist/types/packages/rc-textarea/src/decoration.d.ts +1 -0
- package/dist/types/packages/rc-textarea/src/document.d.ts +1 -0
- package/dist/types/packages/rc-textarea/src/folding-action-controller.d.ts +46 -0
- package/dist/types/packages/rc-textarea/src/folding.d.ts +2 -0
- package/dist/types/packages/rc-textarea/src/index.d.ts +1 -1
- package/dist/types/packages/rc-textarea/src/line-actions-controller.d.ts +4 -3
- package/dist/types/packages/rc-textarea/src/rc-textarea.d.ts +119 -18
- package/dist/types/packages/rc-textarea/src/selection.d.ts +2 -0
- package/dist/types/packages/rc-textarea/src/types.d.ts +52 -9
- package/package.json +9 -3
- package/dist/line-actions-controller-BcsnmSPS.js.map +0 -1
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { R as e } from "./line-actions-controller-
|
|
2
|
-
import { L as o, c as s, m as c } from "./line-actions-controller-
|
|
1
|
+
import { R as e } from "./line-actions-controller-DUdXQxMA.js";
|
|
2
|
+
import { L as o, c as s, m as c } from "./line-actions-controller-DUdXQxMA.js";
|
|
3
3
|
customElements.get("rc-textarea") || customElements.define("rc-textarea", e);
|
|
4
4
|
export {
|
|
5
5
|
o as LineActionsController,
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rc-textarea-folding.js","sources":[],"sourcesContent":[],"names":[],"mappings":";"}
|
package/dist/rc-textarea.js
CHANGED
|
@@ -32,6 +32,7 @@ export declare function findEdit(oldValue: string, newValue: string): Edit;
|
|
|
32
32
|
* - `LineDecoration`: dropped if its line falls within the deleted region;
|
|
33
33
|
* otherwise shifted by the line delta.
|
|
34
34
|
* - `WidgetDecoration`: treated like a zero-width mark at its offset.
|
|
35
|
+
* - `FoldDecoration`: dropped; the owning plugin recalculates source ranges.
|
|
35
36
|
*
|
|
36
37
|
* Returns a new array. The input array and its elements are not mutated.
|
|
37
38
|
*/
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { DecorationInput, RCTextareaPluginAPI } from './types.js';
|
|
2
|
+
export interface SourceFoldRange {
|
|
3
|
+
/** First source line hidden by the fold (one-based, inclusive). */
|
|
4
|
+
fromLine: number;
|
|
5
|
+
/** Last source line hidden by the fold (one-based, inclusive). */
|
|
6
|
+
toLine: number;
|
|
7
|
+
}
|
|
8
|
+
export interface FoldingAction {
|
|
9
|
+
/** Stable identity for the expansion state across plugin updates. */
|
|
10
|
+
key: string;
|
|
11
|
+
/** Name the region and its context; aria-expanded supplies its current state. */
|
|
12
|
+
label: string;
|
|
13
|
+
/** Source lines or a caller-owned panel. The caller renders panel widgets separately. */
|
|
14
|
+
target: SourceFoldRange | HTMLElement;
|
|
15
|
+
/** One-based gutter line. Omit to place the button in the trailing lane. */
|
|
16
|
+
gutterLine?: number;
|
|
17
|
+
/** Source offset for a trailing-lane button; required without gutterLine. */
|
|
18
|
+
offset?: number;
|
|
19
|
+
/** Initial state for a newly seen key. Defaults to true. */
|
|
20
|
+
initiallyExpanded?: boolean;
|
|
21
|
+
/** Add decorative content beside the gutter button. */
|
|
22
|
+
createGutterContent?: ($button: HTMLButtonElement) => HTMLElement;
|
|
23
|
+
/** Refresh the cached gutter content without replacing its focused button. */
|
|
24
|
+
updateGutterContent?: ($content: HTMLElement) => void;
|
|
25
|
+
}
|
|
26
|
+
export interface FoldingActionControllerOptions {
|
|
27
|
+
/** Render a decorative icon for the current expansion state. */
|
|
28
|
+
createTriggerIcon?: (expanded: boolean) => Element | null;
|
|
29
|
+
}
|
|
30
|
+
/** Reconcile independent, accessible folding actions without owning their content. */
|
|
31
|
+
export declare class FoldingActionController {
|
|
32
|
+
private readonly entries;
|
|
33
|
+
private readonly gutterGroupElements;
|
|
34
|
+
private readonly api;
|
|
35
|
+
private readonly options;
|
|
36
|
+
constructor(api: RCTextareaPluginAPI, options?: FoldingActionControllerOptions);
|
|
37
|
+
private updateIcon;
|
|
38
|
+
private applyState;
|
|
39
|
+
/** Return trigger and collapsed-range decorations; callers provide any panel widget. */
|
|
40
|
+
getDecorations(actions: readonly FoldingAction[]): DecorationInput[];
|
|
41
|
+
/** Get expansion state for an existing key. */
|
|
42
|
+
isExpanded(key: string): boolean | undefined;
|
|
43
|
+
/** Discard expansion state and return focus before removing a focused control. */
|
|
44
|
+
clear(): void;
|
|
45
|
+
private release;
|
|
46
|
+
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
export { RCTextarea } from './rc-textarea.js';
|
|
2
|
-
export type { Decoration, DecorationInput, MarkDecoration, MarkDecorationStyle, LineDecoration, WidgetDecoration, RCTextareaPlugin, RCTextareaPluginAPI, TextPattern, LineDecoratorPlugin, Token, } from './types.js';
|
|
2
|
+
export type { Decoration, DecorationInput, MarkDecoration, MarkDecorationStyle, LineDecoration, WidgetDecoration, FoldDecoration, RCTextareaPlugin, RCTextareaPluginAPI, TextPattern, LineDecoratorPlugin, Token, } from './types.js';
|
|
3
3
|
export { matchPatternResults } from './pattern-matcher.js';
|
|
4
4
|
export { createLineDecoratorPlugin } from './line-decorator.js';
|
|
5
5
|
export type { LineDecoratorPluginOptions } from './line-decorator.js';
|
|
@@ -13,8 +13,9 @@ export interface LineActionsOptions {
|
|
|
13
13
|
/** Where to place the inline widget. Default: `'append'`. */
|
|
14
14
|
position?: 'append';
|
|
15
15
|
/**
|
|
16
|
-
* Create and return a DOM element for the given icon name (e.g. `'mdi-lock-outline'`)
|
|
17
|
-
* Called when `action.iconName` is set.
|
|
16
|
+
* Create and return a DOM element for the given icon name (e.g. `'mdi-lock-outline'`),
|
|
17
|
+
* such as an `<svg>` or an icon custom element. Called when `action.iconName` is set.
|
|
18
|
+
* Return `null` to fall back to text label.
|
|
18
19
|
*
|
|
19
20
|
* @example
|
|
20
21
|
* ```ts
|
|
@@ -25,7 +26,7 @@ export interface LineActionsOptions {
|
|
|
25
26
|
* }
|
|
26
27
|
* ```
|
|
27
28
|
*/
|
|
28
|
-
createIcon?: (iconName: string) =>
|
|
29
|
+
createIcon?: (iconName: string) => Element | null;
|
|
29
30
|
/**
|
|
30
31
|
* Full control over button content. Called instead of the default icon/label
|
|
31
32
|
* logic. Use `createIcon` when you only need to swap the icon renderer —
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { LitElement, CSSResultGroup } from 'lit';
|
|
2
|
-
import { NativeChildController } from '@rcarls/rc-common';
|
|
2
|
+
import { FlowController, LocaleController, NativeChildController } from '@rcarls/rc-common';
|
|
3
3
|
import { RCDocument } from './document.js';
|
|
4
4
|
import { SavedSelection } from './selection.js';
|
|
5
|
-
import { Decoration, DecorationInput, RCTextareaPlugin, RCTextareaPluginAPI, TextPattern } from './types.js';
|
|
5
|
+
import { Decoration, DecorationInput, RCTextareaPlugin, RCTextareaPluginAPI, TextPattern, FoldDecoration } from './types.js';
|
|
6
6
|
declare global {
|
|
7
7
|
interface HTMLElementTagNameMap {
|
|
8
8
|
'rc-textarea': RCTextarea;
|
|
@@ -13,8 +13,14 @@ interface UndoEntry {
|
|
|
13
13
|
anchorOffset: number;
|
|
14
14
|
focusOffset: number;
|
|
15
15
|
}
|
|
16
|
+
interface FoldBounds {
|
|
17
|
+
from: number;
|
|
18
|
+
to: number;
|
|
19
|
+
anchorEnd: number;
|
|
20
|
+
reveal: () => void;
|
|
21
|
+
}
|
|
16
22
|
/**
|
|
17
|
-
* Textarea wrapper with line decorations, gutter rendering,
|
|
23
|
+
* Textarea wrapper with line decorations, gutter rendering, folding actions, and plugin hooks.
|
|
18
24
|
*
|
|
19
25
|
* Provide a native `<textarea>` as the direct child when the component is
|
|
20
26
|
* editable. Read-only displays may be driven from `value` or `defaultValue`.
|
|
@@ -38,6 +44,11 @@ interface UndoEntry {
|
|
|
38
44
|
* });
|
|
39
45
|
* ```
|
|
40
46
|
*
|
|
47
|
+
* The slotted `<textarea>` describes the content: its `lang` and `spellcheck` are
|
|
48
|
+
* mirrored onto the editor, and its `dir` sets the editor's base direction (`auto`
|
|
49
|
+
* resolves from the first strong character of the value, else the host's direction).
|
|
50
|
+
* The host's own `lang` stays the interface language, which formats line numbers.
|
|
51
|
+
*
|
|
41
52
|
* @slot - Accepts a native `<textarea>` element for form wiring.
|
|
42
53
|
*
|
|
43
54
|
* @fires rc-textarea-change - Fired when the field value changes
|
|
@@ -48,6 +59,8 @@ interface UndoEntry {
|
|
|
48
59
|
* @csspart root - The outer flex container wrapping the gutter and editor area.
|
|
49
60
|
* @csspart gutter - The gutter column container.
|
|
50
61
|
* @csspart gutter-cells - The gutter's line-label list.
|
|
62
|
+
* @csspart fold-trigger - Native button created by a folding action; style its visual appearance without changing its target or keyboard behavior.
|
|
63
|
+
* @csspart fold-icon - Consumer-supplied icon inside a folding action button, when provided.
|
|
51
64
|
* @csspart editor-area - The container positioning the editor over the slotted textarea.
|
|
52
65
|
* @csspart editor - The contenteditable field surface.
|
|
53
66
|
*
|
|
@@ -55,26 +68,46 @@ interface UndoEntry {
|
|
|
55
68
|
* @attr gutter - Enable the gutter column without any built-in content.
|
|
56
69
|
* @attr word-wrap - Wrap long lines within the field to prevent horizontal overflow.
|
|
57
70
|
* @attr auto-grow - Allow the field to grow vertically with content to prevent vertical overflow.
|
|
58
|
-
* @attr
|
|
71
|
+
* @attr line-direction - `base` (default) gives every line the editor's base direction; `auto` gives
|
|
72
|
+
* each line the direction of its first strong character, holding lines without one to the base.
|
|
73
|
+
* @attr [data-readonly] - Reflected while the slotted `<textarea>` is `readonly`. The editor stays
|
|
74
|
+
* focusable and selectable, announces `aria-readonly`, and blocks edits.
|
|
59
75
|
* @attr value - Current field value.
|
|
60
76
|
* @attr default-value - Initial uncontrolled value.
|
|
61
77
|
*
|
|
62
78
|
* @cssprop [--rc-textarea-border=1px solid ButtonBorder] - Border around the field
|
|
63
79
|
* @cssprop [--rc-textarea-border-radius=2px] - Border radius of the field
|
|
64
80
|
* @cssprop [--rc-textarea-background=Field] - Background color of the field
|
|
65
|
-
* @cssprop [--rc-textarea-color=FieldText] - Text color
|
|
81
|
+
* @cssprop [--rc-textarea-color=var(--rc-field-text, FieldText)] - Text color
|
|
66
82
|
* @cssprop [--rc-textarea-font-family=monospace] - Font family
|
|
67
83
|
* @cssprop [--rc-textarea-font-size=1em] - Font size
|
|
68
84
|
* @cssprop [--rc-textarea-line-height=1.5] - Line height
|
|
69
|
-
* @cssprop [--rc-textarea-padding=0.5em] -
|
|
85
|
+
* @cssprop [--rc-textarea-padding-block=0.5em] - Block padding of the editor and gutter; any `padding-block` value
|
|
86
|
+
* @cssprop [--rc-textarea-padding-inline=0.5em] - Inline padding on both sides of the editor and before the gutter; one length, which the active line highlight bleeds through
|
|
87
|
+
* @cssprop [--rc-textarea-gutter-min-inline-size=24px] - Minimum width of the gutter, including its padding
|
|
88
|
+
* @cssprop [--rc-textarea-trailing-size=2.5em] - Reserved inline space and minimum block size for trailing controls
|
|
70
89
|
* @cssprop [--rc-textarea-focus-outline=2px solid Highlight] - Focus ring outline
|
|
71
90
|
* @cssprop [--rc-textarea-caret-color=FieldText] - Caret color
|
|
72
|
-
* @cssprop [--rc-textarea-active-line-bg=transparent] - Active line highlight color
|
|
91
|
+
* @cssprop [--rc-textarea-active-line-bg=transparent] - Active line highlight color, including editor and gutter padding
|
|
73
92
|
* @cssprop [--rc-textarea-gutter-bg=Canvas] - Gutter background color
|
|
74
93
|
* @cssprop [--rc-textarea-gutter-color=GrayText] - Gutter text color
|
|
75
94
|
* @cssprop [--rc-textarea-gutter-border=1px solid ButtonBorder] - Gutter right border
|
|
76
95
|
* @cssprop [--rc-textarea-gutter-font-family=var(--rc-textarea-font-family, monospace)] - Gutter font family
|
|
96
|
+
* @cssprop [--rc-textarea-gutter-content-gap=0.25em] - Gap between a retained line number and custom gutter content
|
|
77
97
|
* @cssprop [--rc-textarea-gutter-padding-inline-end=0.75em] - Space between gutter labels and text
|
|
98
|
+
* @cssprop [--rc-line-actions-gap=2px] - Gap between inline line actions; popover actions default to 4px
|
|
99
|
+
* @cssprop [--rc-line-actions-margin-start=6px] - Inline-start margin before line actions
|
|
100
|
+
* @cssprop [--rc-line-action-padding=1px] - Inline line-action padding; popover actions default to 4px 6px
|
|
101
|
+
* @cssprop [--rc-line-action-border=none] - Line-action border; the popover surface defaults to 1px solid ButtonBorder
|
|
102
|
+
* @cssprop [--rc-line-action-border-radius=3px] - Line-action border radius; the popover surface defaults to 4px
|
|
103
|
+
* @cssprop [--rc-line-action-bg=transparent] - Line-action background; the popover surface defaults to Canvas
|
|
104
|
+
* @cssprop [--rc-line-action-color=inherit] - Line-action color; popover actions default to ButtonText
|
|
105
|
+
* @cssprop [--rc-line-action-font-size=1em] - Inline line-action font size; popover actions default to 0.85em
|
|
106
|
+
* @cssprop [--rc-line-action-opacity=0.4] - Resting opacity of inline line actions
|
|
107
|
+
* @cssprop [--rc-line-action-hover-opacity=1] - Hover and focus opacity of inline line actions
|
|
108
|
+
* @cssprop [--rc-line-action-hover-bg=transparent] - Hover and focus background; popover actions default to ButtonFace
|
|
109
|
+
* @cssprop [--rc-line-action-hover-color=inherit] - Hover and focus text color
|
|
110
|
+
* @cssprop [--rc-line-action-shadow=0 2px 8px color-mix(in srgb, CanvasText 15%, transparent)] - Line-action popover shadow
|
|
78
111
|
*/
|
|
79
112
|
export declare class RCTextarea extends LitElement {
|
|
80
113
|
static styles: CSSResultGroup;
|
|
@@ -99,8 +132,20 @@ export declare class RCTextarea extends LitElement {
|
|
|
99
132
|
wordWrap: boolean;
|
|
100
133
|
/** Allow the field to grow vertically with content to prevent vertical overflow. */
|
|
101
134
|
autoGrow: boolean;
|
|
102
|
-
/**
|
|
103
|
-
|
|
135
|
+
/**
|
|
136
|
+
* How each line's direction is chosen. `base` gives every line the editor's
|
|
137
|
+
* base direction, which suits code. `auto` gives a line with a letter the
|
|
138
|
+
* direction of its first strong character, for prose that mixes scripts, and
|
|
139
|
+
* holds lines without one (empty, digits, punctuation) to the base direction.
|
|
140
|
+
*/
|
|
141
|
+
lineDirection: 'auto' | 'base';
|
|
142
|
+
/**
|
|
143
|
+
* Whether the slotted `<textarea>` is `readonly`. The native control is the
|
|
144
|
+
* source of truth; set `readonly` on it to change this state.
|
|
145
|
+
*/
|
|
146
|
+
get readOnly(): boolean;
|
|
147
|
+
private _readOnly;
|
|
148
|
+
private _textareaAttributeObserver;
|
|
104
149
|
/** Declarative plugin hook for framework integrations. */
|
|
105
150
|
get plugin(): RCTextareaPlugin | null;
|
|
106
151
|
/** Declarative plugin hook for framework integrations. */
|
|
@@ -132,6 +177,9 @@ export declare class RCTextarea extends LitElement {
|
|
|
132
177
|
protected _document: RCDocument | null;
|
|
133
178
|
protected _$textareaRef: WeakRef<HTMLTextAreaElement> | null;
|
|
134
179
|
protected readonly _textareaController: NativeChildController<HTMLTextAreaElement>;
|
|
180
|
+
protected readonly _flowController: FlowController;
|
|
181
|
+
/** The interface locale, which formats line numbers. */
|
|
182
|
+
protected readonly _localeController: LocaleController;
|
|
135
183
|
/** Plugin-owned decorations */
|
|
136
184
|
protected _pluginDecorations: Map<string, Decoration>;
|
|
137
185
|
/** Pattern-generated decorations (rebuilt on each value change). */
|
|
@@ -150,6 +198,9 @@ export declare class RCTextarea extends LitElement {
|
|
|
150
198
|
protected _savedSelection: SavedSelection | null;
|
|
151
199
|
protected _rafHandle: number | null;
|
|
152
200
|
protected _composing: boolean;
|
|
201
|
+
private _contentAttributesPendingRender;
|
|
202
|
+
/** Set by Escape: the next Tab moves focus instead of inserting `\t`. */
|
|
203
|
+
private _tabMovesFocus;
|
|
153
204
|
protected _isRendering: boolean;
|
|
154
205
|
/** The currently highlighted `.line` element (active line). */
|
|
155
206
|
protected _$activeLine: HTMLElement | null;
|
|
@@ -160,8 +211,18 @@ export declare class RCTextarea extends LitElement {
|
|
|
160
211
|
protected _undoStack: UndoEntry[];
|
|
161
212
|
protected _undoIndex: number;
|
|
162
213
|
protected _resizeObserver: ResizeObserver | null;
|
|
214
|
+
protected _gutterBlockAxis: 'x' | 'y' | null;
|
|
163
215
|
/** Cached per-line gutter labels from the last render — reused by ResizeObserver. */
|
|
164
|
-
protected _gutterLabels: (string | null
|
|
216
|
+
protected _gutterLabels: (string | HTMLElement | null | {
|
|
217
|
+
number: string;
|
|
218
|
+
content: string | HTMLElement;
|
|
219
|
+
})[];
|
|
220
|
+
/** Gutter cells with explicitly accessible plugin controls. */
|
|
221
|
+
protected _accessibleGutterLines: Set<number>;
|
|
222
|
+
/** Collapsed source ranges from the most recent render. */
|
|
223
|
+
protected _foldedRanges: FoldDecoration[];
|
|
224
|
+
protected _foldBounds: FoldBounds[];
|
|
225
|
+
protected _hiddenGutterLines: Set<number>;
|
|
165
226
|
/**
|
|
166
227
|
* The current field value.
|
|
167
228
|
*
|
|
@@ -178,18 +239,52 @@ export declare class RCTextarea extends LitElement {
|
|
|
178
239
|
disconnectedCallback(): void;
|
|
179
240
|
firstUpdated(): void;
|
|
180
241
|
updated(changed: Map<string, unknown>): void;
|
|
181
|
-
|
|
242
|
+
private _observeTextarea;
|
|
243
|
+
/**
|
|
244
|
+
* Mirror the native textarea's content attributes onto the editor. `lang`
|
|
245
|
+
* picks glyphs, the spelling dictionary and word boundaries; `spellcheck`
|
|
246
|
+
* stays off unless the textarea sets it. The host's own `lang` is the
|
|
247
|
+
* interface language and is never copied.
|
|
248
|
+
*/
|
|
249
|
+
protected _syncContentAttributes(): void;
|
|
250
|
+
/**
|
|
251
|
+
* Set the editor's base direction from the textarea's `dir`. `auto` reads
|
|
252
|
+
* the native control's directionality, including its LTR neutral fallback;
|
|
253
|
+
* without `dir` the editor inherits. Composition keeps the current direction
|
|
254
|
+
* so the IME session isn't disturbed.
|
|
255
|
+
*/
|
|
256
|
+
protected _syncContentDirection(): void;
|
|
257
|
+
/** The textarea's `lang`, or `''` when it sets none. */
|
|
258
|
+
protected _contentLang(): string;
|
|
259
|
+
/** The editor's resolved base direction. */
|
|
260
|
+
protected _contentDirection(): 'ltr' | 'rtl';
|
|
261
|
+
/**
|
|
262
|
+
* Mark lines with no strong character so `line-direction="auto"` holds them
|
|
263
|
+
* to the base direction. Reads the model value, which composition text
|
|
264
|
+
* doesn't reach until `compositionend`, so a composing line keeps its mark.
|
|
265
|
+
*/
|
|
266
|
+
protected _syncLineDirections(value: string): void;
|
|
267
|
+
/**
|
|
268
|
+
* Mirror the native textarea's `readonly` attribute: the editor stays a
|
|
269
|
+
* focusable, selectable textbox that announces `aria-readonly`, and edits
|
|
270
|
+
* are blocked by the existing input guards.
|
|
271
|
+
*/
|
|
272
|
+
protected _syncReadOnly(): void;
|
|
273
|
+
render(): import('lit-html').TemplateResult<1>;
|
|
182
274
|
protected _onSlotChange(): void;
|
|
183
275
|
protected _setupTextarea($textarea: HTMLTextAreaElement | null, $previousTextarea?: HTMLTextAreaElement | null): void;
|
|
184
276
|
protected _onTextareaInvalid: () => void;
|
|
185
277
|
protected _bindEditorEvents($editor: HTMLElement): void;
|
|
186
278
|
protected _onInputEvent: () => void;
|
|
187
279
|
protected _onBeforeInput: (event: InputEvent) => void;
|
|
280
|
+
protected _revealFoldAtOffset(offset: number): boolean;
|
|
281
|
+
protected _revealFoldForEdit(inputType: string): boolean;
|
|
188
282
|
protected _onInput(): void;
|
|
189
283
|
protected _onSelectionChange: () => void;
|
|
190
284
|
protected _updateActiveLine(): void;
|
|
191
285
|
protected _updateActiveGutterCell(): void;
|
|
192
286
|
protected _onKeyDown: (e: KeyboardEvent) => void;
|
|
287
|
+
protected _isWidgetEvent(event: Event): boolean;
|
|
193
288
|
protected _insertText(text: string): void;
|
|
194
289
|
/**
|
|
195
290
|
* Wrap the current selection with `prefix` and `suffix`.
|
|
@@ -206,6 +301,7 @@ export declare class RCTextarea extends LitElement {
|
|
|
206
301
|
* When the selection is collapsed this is equivalent to `insertText`.
|
|
207
302
|
*/
|
|
208
303
|
replaceSelection(text: string): void;
|
|
304
|
+
protected _onCopy: (event: ClipboardEvent) => void;
|
|
209
305
|
protected _onPaste: (e: ClipboardEvent) => void;
|
|
210
306
|
/** Reset the undo/redo history. Call when the field receives entirely new content. */
|
|
211
307
|
clearHistory(): void;
|
|
@@ -253,15 +349,17 @@ export declare class RCTextarea extends LitElement {
|
|
|
253
349
|
* - `string` — the label to display
|
|
254
350
|
* - `null` — render an empty cell
|
|
255
351
|
*/
|
|
256
|
-
protected _computeGutterLabels(allDecorations: Decoration[], value?: string): (string | null
|
|
352
|
+
protected _computeGutterLabels(allDecorations: Decoration[], value?: string): (string | HTMLElement | null | {
|
|
353
|
+
number: string;
|
|
354
|
+
content: string | HTMLElement;
|
|
355
|
+
})[];
|
|
257
356
|
/**
|
|
258
|
-
* Synchronize the
|
|
357
|
+
* Synchronize the block size of each gutter cell to match the
|
|
259
358
|
* corresponding `.line` element in the editor.
|
|
260
359
|
*
|
|
261
|
-
* In non-word-wrap mode the gutter uses a uniform
|
|
262
|
-
*
|
|
263
|
-
*
|
|
264
|
-
* Also copies the editor's computed `paddingTop`/`paddingBottom` to the
|
|
360
|
+
* In non-word-wrap mode without block widgets the gutter uses a uniform
|
|
361
|
+
* line height. Wrapped lines and block widgets use per-line heights instead.
|
|
362
|
+
* Also copies the editor's computed block padding to the
|
|
265
363
|
* gutter to compensate for browser UA overrides on contenteditable.
|
|
266
364
|
*/
|
|
267
365
|
protected _syncGutterHeights(): void;
|
|
@@ -271,7 +369,10 @@ export declare class RCTextarea extends LitElement {
|
|
|
271
369
|
* `_gutterLabels` is updated first; otherwise the cached labels are reused
|
|
272
370
|
* (called by the `ResizeObserver` without a new render pass).
|
|
273
371
|
*/
|
|
274
|
-
protected _syncGutter(labels?: (string | null
|
|
372
|
+
protected _syncGutter(labels?: (string | HTMLElement | null | {
|
|
373
|
+
number: string;
|
|
374
|
+
content: string | HTMLElement;
|
|
375
|
+
})[]): void;
|
|
275
376
|
protected _syncLabel(): void;
|
|
276
377
|
protected _syncTypography($textarea: HTMLTextAreaElement): void;
|
|
277
378
|
protected _syncTextareaValue(fromUser?: boolean): void;
|
|
@@ -28,6 +28,8 @@ interface DomPosition {
|
|
|
28
28
|
* Returns null if offset is out of range.
|
|
29
29
|
*/
|
|
30
30
|
export declare function textOffsetToDom($root: Element, targetOffset: number): DomPosition | null;
|
|
31
|
+
/** Returns the current selection focus node when it belongs to `$root`. */
|
|
32
|
+
export declare function getSelectionFocusNode($root: Element): Node | null;
|
|
31
33
|
/**
|
|
32
34
|
* Captures the current browser selection as plain-text offsets relative to `$root`.
|
|
33
35
|
*
|
|
@@ -61,13 +61,19 @@ export interface LineDecoration {
|
|
|
61
61
|
/** Additional HTML attributes set directly on the line element. */
|
|
62
62
|
attributes?: Record<string, string>;
|
|
63
63
|
/**
|
|
64
|
-
* Override the built-in gutter cell
|
|
64
|
+
* Override the built-in gutter cell content for this line.
|
|
65
65
|
*
|
|
66
66
|
* - `string` — custom label (e.g. `"!"`, `"▶"`)
|
|
67
|
+
* - `HTMLElement` — plugin-owned marker or control; reuse its node between updates.
|
|
68
|
+
* Set `gutterAccessible` when it contains an interactive control.
|
|
67
69
|
* - `null` — force empty cell (suppress built-in content)
|
|
68
70
|
* - `undefined` — use the built-in mode default (`line-numbers`, `gutter`, etc.)
|
|
69
71
|
*/
|
|
70
|
-
gutterContent?: string | null;
|
|
72
|
+
gutterContent?: string | HTMLElement | null;
|
|
73
|
+
/** Keep the built-in line number before custom gutter content when `line-numbers` is enabled. */
|
|
74
|
+
gutterLineNumber?: boolean;
|
|
75
|
+
/** Expose this gutter cell to assistive technology when it contains a control. */
|
|
76
|
+
gutterAccessible?: boolean;
|
|
71
77
|
}
|
|
72
78
|
/**
|
|
73
79
|
* A non-editable DOM element inserted at a character offset.
|
|
@@ -81,17 +87,36 @@ export interface WidgetDecoration {
|
|
|
81
87
|
type: 'widget';
|
|
82
88
|
/** Character offset. Widget is placed before (or after) the character at this position. */
|
|
83
89
|
offset: number;
|
|
84
|
-
/**
|
|
90
|
+
/** Create widget content when its line rebuilds. With a stable key, content may be reused. */
|
|
85
91
|
create(): HTMLElement;
|
|
86
92
|
/** Whether to place the widget before or after the character at `offset`. Default: 'before'. */
|
|
87
93
|
side?: 'before' | 'after';
|
|
94
|
+
/** Preserve this widget's line DOM while its key and decorations remain unchanged.
|
|
95
|
+
* Change the key when its content changes. Scope keys to the owning plugin.
|
|
96
|
+
*/
|
|
97
|
+
key?: string;
|
|
98
|
+
/** Place the widget inline, below its logical line, or in a reserved trailing lane. */
|
|
99
|
+
layout?: 'inline' | 'block' | 'trailing';
|
|
100
|
+
/** Expose interactive or meaningful widget content to assistive technology. Default: false. */
|
|
101
|
+
accessible?: boolean;
|
|
102
|
+
}
|
|
103
|
+
/** Hide complete source lines while retaining their text and model offsets. */
|
|
104
|
+
export interface FoldDecoration {
|
|
105
|
+
id: string;
|
|
106
|
+
type: 'fold';
|
|
107
|
+
/** First hidden line, one-based and inclusive. */
|
|
108
|
+
fromLine: number;
|
|
109
|
+
/** Last hidden line, one-based and inclusive. */
|
|
110
|
+
toLine: number;
|
|
111
|
+
/** Reveal this range before a user edit or caret move enters its hidden lines. */
|
|
112
|
+
reveal(): void;
|
|
88
113
|
}
|
|
89
114
|
/** Decorations are visual formatting applied to the field content without affecting
|
|
90
115
|
* the underlying plain text value.
|
|
91
116
|
*/
|
|
92
|
-
export type Decoration = MarkDecoration | LineDecoration | WidgetDecoration;
|
|
117
|
+
export type Decoration = MarkDecoration | LineDecoration | WidgetDecoration | FoldDecoration;
|
|
93
118
|
/** Input shape for creating a decoration — id-less variant of each decoration type. */
|
|
94
|
-
export type DecorationInput = Omit<MarkDecoration, 'id'> | Omit<LineDecoration, 'id'> | Omit<WidgetDecoration, 'id'>;
|
|
119
|
+
export type DecorationInput = Omit<MarkDecoration, 'id'> | Omit<LineDecoration, 'id'> | Omit<WidgetDecoration, 'id'> | Omit<FoldDecoration, 'id'>;
|
|
95
120
|
/**
|
|
96
121
|
* A semantic token produced by an external tokenizer (lezer, tree-sitter, shiki, etc.).
|
|
97
122
|
*
|
|
@@ -138,6 +163,19 @@ export interface RCTextareaPluginAPI {
|
|
|
138
163
|
readonly selectionStart: number;
|
|
139
164
|
/** Normalized selection end offset (always ≥ `selectionStart`). Equals `selectionStart` when the cursor is collapsed. */
|
|
140
165
|
readonly selectionEnd: number;
|
|
166
|
+
/**
|
|
167
|
+
* The editor's resolved base direction, from the textarea's `dir` or the
|
|
168
|
+
* host's. Anchor caret-relative popups with this, not the host's flow.
|
|
169
|
+
*/
|
|
170
|
+
readonly contentDirection: 'ltr' | 'rtl';
|
|
171
|
+
/** The content language: the textarea's `lang`, or `''` when it sets none. */
|
|
172
|
+
readonly contentLang: string;
|
|
173
|
+
/**
|
|
174
|
+
* The resolved direction of a 1-based line. Under `line-direction="auto"`
|
|
175
|
+
* that is the direction of the line's first strong character; otherwise,
|
|
176
|
+
* and for lines without one, it is `contentDirection`.
|
|
177
|
+
*/
|
|
178
|
+
lineDirection(line: number): 'ltr' | 'rtl';
|
|
141
179
|
/**
|
|
142
180
|
* Returns the bounding rect of the cursor (caret) in viewport coordinates.
|
|
143
181
|
*
|
|
@@ -150,8 +188,13 @@ export interface RCTextareaPluginAPI {
|
|
|
150
188
|
/**
|
|
151
189
|
* Returns the word boundaries at the current cursor position.
|
|
152
190
|
*
|
|
153
|
-
*
|
|
154
|
-
*
|
|
191
|
+
* Words come from `Intl.Segmenter` for `contentLang` (UAX #29, with
|
|
192
|
+
* dictionary segmentation for Japanese and Thai), so `crème`, `don't` and
|
|
193
|
+
* `snake_case` are each one word. The word starting at the cursor wins over
|
|
194
|
+
* the one ending there.
|
|
195
|
+
*
|
|
196
|
+
* @returns the word and its `[from, to)` offsets, or `null` if the cursor
|
|
197
|
+
* touches no letter or digit
|
|
155
198
|
*/
|
|
156
199
|
getWordAtCursor(): {
|
|
157
200
|
word: string;
|
|
@@ -341,8 +384,8 @@ export interface RCTextareaPlugin {
|
|
|
341
384
|
/** Called when the plugin is replaced or the element disconnects. */
|
|
342
385
|
destroy?(): void;
|
|
343
386
|
/**
|
|
344
|
-
* Display-layer value transform — called before `update`/`highlight`
|
|
345
|
-
*
|
|
387
|
+
* Display-layer value transform — called before `update`/`highlight`
|
|
388
|
+
* while the slotted textarea is `readonly`.
|
|
346
389
|
*
|
|
347
390
|
* Return a non-null string to substitute it as the rendered
|
|
348
391
|
* text passed to all subsequent hooks and to the document builder.
|
package/package.json
CHANGED
|
@@ -3,8 +3,8 @@
|
|
|
3
3
|
"publishConfig": {
|
|
4
4
|
"access": "public"
|
|
5
5
|
},
|
|
6
|
-
"version": "0.
|
|
7
|
-
"description": "Textarea wrapper with line decorations, gutter rendering,
|
|
6
|
+
"version": "0.7.0",
|
|
7
|
+
"description": "Textarea wrapper with line decorations, gutter rendering, folding actions, and plugin hooks.",
|
|
8
8
|
"repository": {
|
|
9
9
|
"type": "git",
|
|
10
10
|
"url": "git+https://github.com/richardcarls/rc-webcomponents.git",
|
|
@@ -29,6 +29,12 @@
|
|
|
29
29
|
"types": "./dist/types/packages/rc-textarea/src/define.d.ts",
|
|
30
30
|
"default": "./dist/rc-textarea-define.js"
|
|
31
31
|
}
|
|
32
|
+
},
|
|
33
|
+
"./folding": {
|
|
34
|
+
"import": {
|
|
35
|
+
"types": "./dist/types/packages/rc-textarea/src/folding.d.ts",
|
|
36
|
+
"default": "./dist/rc-textarea-folding.js"
|
|
37
|
+
}
|
|
32
38
|
}
|
|
33
39
|
},
|
|
34
40
|
"types": "./dist/types/packages/rc-textarea/src/index.d.ts",
|
|
@@ -45,7 +51,7 @@
|
|
|
45
51
|
"test:browser:firefox": "vitest --run --project=firefox"
|
|
46
52
|
},
|
|
47
53
|
"dependencies": {
|
|
48
|
-
"@rcarls/rc-common": "0.
|
|
54
|
+
"@rcarls/rc-common": "0.7.0",
|
|
49
55
|
"parchment": "^3.0.0"
|
|
50
56
|
},
|
|
51
57
|
"devDependencies": {
|