react-x11 1.2.0 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +330 -81
- package/package.json +132 -14
- package/src/ClickToComponent.js +9 -2
- package/src/DevToolsIntegration.js +440 -32
- package/src/Reconciler.js +463 -165
- package/src/a11y.js +1299 -0
- package/src/acceleratorhooks.js +86 -0
- package/src/accelerators.js +128 -0
- package/src/activate.js +168 -0
- package/src/anchor.js +360 -0
- package/src/appcontext.js +161 -0
- package/src/appearance.js +748 -0
- package/src/appearancehooks.js +96 -0
- package/src/apphooks.js +73 -0
- package/src/application.js +748 -0
- package/src/atspi.js +1953 -0
- package/src/bus.js +545 -0
- package/src/bushooks.js +136 -0
- package/src/clientmessage.js +140 -0
- package/src/clipboard.js +121 -0
- package/src/components/Button.js +148 -33
- package/src/components/Checkbox.js +66 -32
- package/src/components/Dialog.js +96 -29
- package/src/components/FileDialog.js +491 -0
- package/src/components/Icon.js +329 -0
- package/src/components/Menu.js +797 -133
- package/src/components/PasswordInput.js +434 -0
- package/src/components/ProgressBar.js +91 -12
- package/src/components/Radio.js +78 -35
- package/src/components/Select.js +255 -65
- package/src/components/Slider.js +102 -41
- package/src/components/SplitPane.js +206 -0
- package/src/components/Switch.js +100 -22
- package/src/components/Table.js +529 -0
- package/src/components/Tabs.js +211 -0
- package/src/components/Tooltip.js +528 -54
- package/src/components/anchor.js +154 -107
- package/src/components/change.js +34 -0
- package/src/components/dnd.js +103 -0
- package/src/components/index.js +16 -3
- package/src/components/keys.js +17 -20
- package/src/components/scribble.js +247 -0
- package/src/components/theme.js +350 -42
- package/src/components/typeahead.js +12 -2
- package/src/compose.js +868 -0
- package/src/compositing.js +224 -0
- package/src/dbusmenu.js +384 -0
- package/src/debug.d.ts +63 -0
- package/src/debug.js +642 -0
- package/src/decorations.js +486 -0
- package/src/desktopsettings.js +209 -0
- package/src/desktopsettingshooks.js +62 -0
- package/src/dnd.js +1725 -0
- package/src/editmenu.js +272 -0
- package/src/errors.js +98 -0
- package/src/events.js +1406 -162
- package/src/extensions.js +45 -0
- package/src/filedialog.js +375 -0
- package/src/filedialoghooks.js +132 -0
- package/src/fonthooks.js +64 -0
- package/src/fonts.js +301 -0
- package/src/foreignnodes.js +519 -0
- package/src/frame/child.js +33 -0
- package/src/frame/childmain.js +274 -0
- package/src/frame/env.js +140 -0
- package/src/frame/index.js +444 -0
- package/src/frame/lifecycle.js +67 -0
- package/src/frame/protocol.js +179 -0
- package/src/frames.js +73 -0
- package/src/glbackend.js +114 -0
- package/src/glnodes.js +125 -67
- package/src/globalmenu.js +683 -0
- package/src/host.d.ts +88 -0
- package/src/host.js +42 -0
- package/src/idle.js +490 -0
- package/src/idlehooks.js +100 -0
- package/src/imagesource.js +349 -0
- package/src/index.d.ts +475 -0
- package/src/index.js +83 -9
- package/src/inputtime.js +206 -0
- package/src/jsx-dev-runtime.d.ts +21 -0
- package/src/jsx-dev-runtime.js +2 -0
- package/src/jsx-runtime.d.ts +39 -0
- package/src/jsx-runtime.js +6 -0
- package/src/keyboard.js +256 -0
- package/src/keyboardstate.js +278 -0
- package/src/keyboardstatehooks.js +58 -0
- package/src/keysyms.d.ts +149 -0
- package/src/keysyms.js +270 -0
- package/src/locale.js +170 -0
- package/src/localehooks.js +47 -0
- package/src/menuitem.js +223 -0
- package/src/node.d.ts +597 -0
- package/src/node.js +44 -0
- package/src/nodes.js +9546 -690
- package/src/ntk.d.ts +44 -0
- package/src/ntk.js +25 -0
- package/src/paintcache.js +366 -0
- package/src/palette.js +380 -0
- package/src/pastestate.js +66 -0
- package/src/portal.js +461 -0
- package/src/priority.js +26 -0
- package/src/refresh/index.d.ts +40 -0
- package/src/refresh/index.js +122 -0
- package/src/refresh/loader.d.ts +37 -0
- package/src/refresh/loader.js +401 -0
- package/src/refresh/register.d.ts +5 -0
- package/src/refresh/register.js +13 -0
- package/src/registry.js +232 -0
- package/src/scale.js +626 -0
- package/src/scalehooks.js +27 -0
- package/src/screencolor.js +640 -0
- package/src/screencolorhooks.js +101 -0
- package/src/screens.js +754 -0
- package/src/screenshooks.js +137 -0
- package/src/startup.js +302 -0
- package/src/style.d.ts +126 -0
- package/src/style.js +33 -0
- package/src/styles.js +1482 -6
- package/src/svgnodes.js +306 -0
- package/src/testing/a11y.js +484 -0
- package/src/testing/components.js +414 -0
- package/src/testing/events.js +407 -0
- package/src/testing/harness.js +455 -0
- package/src/testing/index.d.ts +558 -0
- package/src/testing/index.js +85 -0
- package/src/testing/mock-app.js +463 -0
- package/src/testing/pixels.js +152 -0
- package/src/testing/queries.js +224 -0
- package/src/textrange.js +83 -0
- package/src/textselection.js +439 -0
- package/src/trace-registry.js +63 -0
- package/src/transfer.js +93 -0
- package/src/types/appearance.d.ts +84 -0
- package/src/types/application.d.ts +173 -0
- package/src/types/components.d.ts +820 -0
- package/src/types/dbus.d.ts +177 -0
- package/src/types/elements.d.ts +897 -0
- package/src/types/events.d.ts +549 -0
- package/src/types/filedialog.d.ts +260 -0
- package/src/types/fonts.d.ts +124 -0
- package/src/types/frame.d.ts +146 -0
- package/src/types/globalmenu.d.ts +42 -0
- package/src/types/nodes.d.ts +199 -0
- package/src/types/screencolor.d.ts +84 -0
- package/src/types/style.d.ts +434 -0
- package/src/types/system.d.ts +287 -0
- package/src/windowid.js +151 -0
- package/src/windowstate.js +393 -0
- package/src/xsettings.js +336 -0
- package/src/yoga.d.ts +55 -0
- package/src/yoga.js +135 -0
- package/src/components/Canvas3D.js +0 -28
- package/src/geometry3d.js +0 -223
- package/src/pointer3d.js +0 -158
- package/src/raycast3d.js +0 -146
- package/src/richnodes.js +0 -436
- package/src/scene3d.js +0 -683
package/src/node.d.ts
ADDED
|
@@ -0,0 +1,597 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `react-x11/node` — the base class a registered element subclasses.
|
|
3
|
+
*
|
|
4
|
+
* Typed as the surface a subclass legitimately uses. It is deliberately
|
|
5
|
+
* narrower than the runtime class: everything underscore-prefixed is
|
|
6
|
+
* internal and may change in a patch release. docs/extending.md is the
|
|
7
|
+
* contract in prose.
|
|
8
|
+
*/
|
|
9
|
+
import type {
|
|
10
|
+
Rect,
|
|
11
|
+
NtkApp,
|
|
12
|
+
TextPosition,
|
|
13
|
+
TextSelectionSnapshot,
|
|
14
|
+
} from './types/nodes.js';
|
|
15
|
+
import type {
|
|
16
|
+
FontStyle,
|
|
17
|
+
FontWeight,
|
|
18
|
+
Style,
|
|
19
|
+
TextRendering,
|
|
20
|
+
} from './types/style.js';
|
|
21
|
+
import type {
|
|
22
|
+
CompositionEvent,
|
|
23
|
+
KeyboardEvent,
|
|
24
|
+
MouseEvent,
|
|
25
|
+
WheelEvent,
|
|
26
|
+
} from './types/events.js';
|
|
27
|
+
|
|
28
|
+
/** ntk's 2d context. Typed loosely — it is ntk's API, not ours. */
|
|
29
|
+
export type Context2D = unknown;
|
|
30
|
+
|
|
31
|
+
/** How an axis is bounded when layout asks an element for its size.
|
|
32
|
+
* `'exactly'` — the style decided this axis; `'at-most'` — that many pixels
|
|
33
|
+
* are on offer; `'unconstrained'` — nothing bounds it. */
|
|
34
|
+
export type MeasureMode = 'exactly' | 'at-most' | 'unconstrained';
|
|
35
|
+
|
|
36
|
+
/** The question `measureContent` answers. */
|
|
37
|
+
export interface MeasureConstraints {
|
|
38
|
+
/** Pixels on offer across, per `widthMode`. `Infinity` when unbounded, so
|
|
39
|
+
* `Math.min(preferred, width)` is right in every mode. */
|
|
40
|
+
width: number;
|
|
41
|
+
/** Pixels on offer down, per `heightMode`. `Infinity` when unbounded. */
|
|
42
|
+
height: number;
|
|
43
|
+
widthMode: MeasureMode;
|
|
44
|
+
heightMode: MeasureMode;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/** What `measureContent` answers with. */
|
|
48
|
+
export interface MeasuredSize {
|
|
49
|
+
width: number;
|
|
50
|
+
height: number;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* A resolved text style — the base style `app.fonts.layout` takes, which is
|
|
55
|
+
* ntk's vocabulary rather than the style vocabulary: `family` for
|
|
56
|
+
* `fontFamily`, `variations` for `fontVariationSettings`.
|
|
57
|
+
*/
|
|
58
|
+
export interface TextStyle {
|
|
59
|
+
/** A CSS-style family list, as `fontFamily` is written. */
|
|
60
|
+
family: string;
|
|
61
|
+
size: number;
|
|
62
|
+
weight: FontWeight;
|
|
63
|
+
style: FontStyle;
|
|
64
|
+
/** A variable font's axes, `{ wght: 460 }` — undefined unless a style or
|
|
65
|
+
* the cascade above it named one. */
|
|
66
|
+
variations: Record<string, number> | undefined;
|
|
67
|
+
textRendering: TextRendering | undefined;
|
|
68
|
+
color: string;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* What an element holding text tells an assistive technology
|
|
73
|
+
* (`a11yTextState`). Offsets are **code points**, counted the way
|
|
74
|
+
* `Array.from(value).length` counts, and index `value` — the string the
|
|
75
|
+
* element *draws*, an open composition included.
|
|
76
|
+
*/
|
|
77
|
+
export interface A11yTextState {
|
|
78
|
+
/** The text as drawn. */
|
|
79
|
+
value: string;
|
|
80
|
+
/** Where the caret is. Defaults to `selectionEnd`. */
|
|
81
|
+
caret?: number;
|
|
82
|
+
/** The selected range; equal offsets mean a bare caret. Default 0. */
|
|
83
|
+
selectionStart?: number;
|
|
84
|
+
selectionEnd?: number;
|
|
85
|
+
/** Whether this is text the user edits — an editor rather than a viewer.
|
|
86
|
+
* Sets the EDITABLE state and, with `a11yReplaceText`, the AT-SPI
|
|
87
|
+
* EditableText interface. */
|
|
88
|
+
editable?: boolean;
|
|
89
|
+
/** One line or many. Left unsaid, neither state is claimed rather than
|
|
90
|
+
* guessed from the current value. */
|
|
91
|
+
multiline?: boolean;
|
|
92
|
+
/** The part of `value` that is an open composition — a dead key, a
|
|
93
|
+
* half-typed Compose sequence — so a reader can tell it from the
|
|
94
|
+
* character it commits. `offset` is where it starts in `value`. */
|
|
95
|
+
preedit?: { offset: number; text: string } | null;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
/**
|
|
99
|
+
* One thing an element drew, as an assistive technology should meet it
|
|
100
|
+
* (`a11yScene`). Everything but `id` and `rect` is optional, and what is
|
|
101
|
+
* left out is simply not claimed.
|
|
102
|
+
*/
|
|
103
|
+
export interface A11ySceneItem {
|
|
104
|
+
/** This item's name for the whole time it is on screen. Identity is
|
|
105
|
+
* matched on it frame to frame, so a fresh id per frame is a child that
|
|
106
|
+
* is destroyed and recreated under every screen reader holding it. */
|
|
107
|
+
id: string;
|
|
108
|
+
/** Where it is drawn, in the owning window's coordinates — the same
|
|
109
|
+
* space as `abs` and a mouse event's `x`/`y`. Where AT focus draws and
|
|
110
|
+
* what a magnifier follows. */
|
|
111
|
+
rect: Rect;
|
|
112
|
+
/** The ARIA role it plays. `'group'` when it says none, which is
|
|
113
|
+
* audible and promises nothing. A role that promises activation
|
|
114
|
+
* (`button`, `option`, `treeitem`, …) gives it an AT-SPI action, and so
|
|
115
|
+
* does the element implementing `a11ySceneAction`. */
|
|
116
|
+
role?: string;
|
|
117
|
+
/** What a screen reader says. Anything unnamed is announced as having no
|
|
118
|
+
* accessible name, which is the defect being loud rather than hidden. */
|
|
119
|
+
name?: string;
|
|
120
|
+
description?: string;
|
|
121
|
+
/** Whether an AT may put its focus here. Default true. */
|
|
122
|
+
focusable?: boolean;
|
|
123
|
+
states?: {
|
|
124
|
+
selected?: boolean;
|
|
125
|
+
checked?: boolean | 'mixed';
|
|
126
|
+
expanded?: boolean;
|
|
127
|
+
disabled?: boolean;
|
|
128
|
+
busy?: boolean;
|
|
129
|
+
/** The element's own keyboard cursor — the item arrow keys would act
|
|
130
|
+
* on. Element-internal focus never reaches the window's focus manager,
|
|
131
|
+
* so this is the only way it is reported. */
|
|
132
|
+
focused?: boolean;
|
|
133
|
+
};
|
|
134
|
+
/** Anything else this item would carry as an element: `aria-level`,
|
|
135
|
+
* `aria-posinset`/`aria-setsize` (Orca's "3 of 7"), `aria-valuenow`,
|
|
136
|
+
* `aria-keyshortcuts`, `aria-hidden`. Read exactly as they are on a
|
|
137
|
+
* `<box>`; the fields above win where they overlap. */
|
|
138
|
+
props?: Record<string, unknown>;
|
|
139
|
+
/** A scene with structure — series and points, groups and nodes. Ids are
|
|
140
|
+
* matched within their parent, so they only have to be unique there. */
|
|
141
|
+
children?: A11ySceneItem[];
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
/** What an assistive technology asks an element to do with one of the
|
|
145
|
+
* things it drew. */
|
|
146
|
+
export type A11ySceneAction = 'activate' | 'focus' | 'scroll';
|
|
147
|
+
|
|
148
|
+
/**
|
|
149
|
+
* The `measureContent` body for content with a natural size and an aspect
|
|
150
|
+
* ratio to keep — `<image>` and `<svg>` are written on it:
|
|
151
|
+
*
|
|
152
|
+
* ```js
|
|
153
|
+
* measureContent(constraints) {
|
|
154
|
+
* return intrinsicSize({ width: 320, height: 200 }, constraints);
|
|
155
|
+
* }
|
|
156
|
+
* ```
|
|
157
|
+
*/
|
|
158
|
+
export declare function intrinsicSize(
|
|
159
|
+
natural: MeasuredSize,
|
|
160
|
+
constraints: MeasureConstraints,
|
|
161
|
+
): MeasuredSize;
|
|
162
|
+
|
|
163
|
+
/**
|
|
164
|
+
* How long a caret stays in each of its two states, in milliseconds — what
|
|
165
|
+
* `<textinput>` blinks at. An element that draws its own caret uses this
|
|
166
|
+
* rather than a number of its own, so two carets on one screen are in step.
|
|
167
|
+
*/
|
|
168
|
+
export declare const CARET_BLINK_MS: number;
|
|
169
|
+
|
|
170
|
+
export declare class Node {
|
|
171
|
+
constructor(
|
|
172
|
+
kind: string,
|
|
173
|
+
props: Record<string, unknown>,
|
|
174
|
+
app: NtkApp,
|
|
175
|
+
options?: { yoga?: boolean },
|
|
176
|
+
);
|
|
177
|
+
|
|
178
|
+
/** Element name. Must equal the name it was registered under. */
|
|
179
|
+
readonly kind: string;
|
|
180
|
+
/** The current props. Replaced wholesale by `applyProps`. */
|
|
181
|
+
readonly props: Record<string, unknown>;
|
|
182
|
+
/** The ntk connection this tree renders through. */
|
|
183
|
+
readonly app: NtkApp;
|
|
184
|
+
readonly parent: Node | null;
|
|
185
|
+
readonly children: Node[];
|
|
186
|
+
/** The owning `<window>` node, once attached. */
|
|
187
|
+
readonly root: Node | null;
|
|
188
|
+
readonly destroyed: boolean;
|
|
189
|
+
/** Position and size within the owning window, valid after layout. */
|
|
190
|
+
readonly abs: Rect;
|
|
191
|
+
/** `abs` inset by the border and the padding — where the content goes,
|
|
192
|
+
* and where every built-in draws. The insets come off the layout, which
|
|
193
|
+
* is where percentages and the per-side overrides have already been
|
|
194
|
+
* resolved, so this is not arithmetic to redo from `style`. */
|
|
195
|
+
contentBox(): Rect;
|
|
196
|
+
/** The text style this node resolves to, in the shape `app.fonts.layout`
|
|
197
|
+
* takes: the style's font properties over what the palette says text
|
|
198
|
+
* with none of its own is set in. An element that draws text inherits
|
|
199
|
+
* exactly what `<text>` inherits by asking. */
|
|
200
|
+
resolvedTextStyle(): TextStyle;
|
|
201
|
+
/** The flattened `style` prop with the active state blocks overlaid.
|
|
202
|
+
* Everything that paints or lays out reads this, never `props`. */
|
|
203
|
+
readonly style: Style;
|
|
204
|
+
/** The nearest `theme` at or above this node. */
|
|
205
|
+
readonly theme: Record<string, unknown> | null;
|
|
206
|
+
/** Which way this node reads, resolved — `'ltr'` or `'rtl'`, never
|
|
207
|
+
* `'inherit'`. Yoga has already mirrored the boxes, so this is for what an
|
|
208
|
+
* element draws *inside* one: which side a mark sits on, which way a
|
|
209
|
+
* chevron points, what a pointer coordinate means. */
|
|
210
|
+
readonly direction: 'ltr' | 'rtl';
|
|
211
|
+
/** Style names this element owns as its own semantics. Registered
|
|
212
|
+
* elements declare these to `registerElement` instead of overriding. */
|
|
213
|
+
readonly semanticNames: ReadonlySet<string>;
|
|
214
|
+
/** Prop names whose damage this element's own `applyProps` claims, and
|
|
215
|
+
* which `paintChanged` therefore does not damage the whole node for.
|
|
216
|
+
* Empty unless declared — registered elements declare theirs to
|
|
217
|
+
* `registerElement`, so the common case needs no subclass. */
|
|
218
|
+
readonly selfDamagedProps: ReadonlySet<string>;
|
|
219
|
+
|
|
220
|
+
// --- the text this element answers for (docs/extending.md) ---------------
|
|
221
|
+
//
|
|
222
|
+
// Four questions in one index space and one coordinate space: characters
|
|
223
|
+
// are **code points**, rectangles are in the owning window's coordinates —
|
|
224
|
+
// the same ones `abs`, `contentBox()` and a mouse event's `x`/`y` use.
|
|
225
|
+
// An element that answers them can be selected across by a `selectable`
|
|
226
|
+
// ancestor with no registration of any kind.
|
|
227
|
+
|
|
228
|
+
/** This element's text, or null when it has none. The default. */
|
|
229
|
+
textContent(): string | null;
|
|
230
|
+
/** The character boundary nearest a point. Clamps to the ends. */
|
|
231
|
+
textIndexAt(x: number, y: number): number;
|
|
232
|
+
/** Where a caret at this index stands — a zero-width rect from the top of
|
|
233
|
+
* the glyphs to the bottom of them. */
|
|
234
|
+
textCaretRect(index: number): Rect | null;
|
|
235
|
+
/** The bands a highlight over `[start, end)` fills: one per line, and one
|
|
236
|
+
* per direction run within a line — a range that crosses from Latin into
|
|
237
|
+
* Arabic is two stretches of pixels, not the span between them. */
|
|
238
|
+
textRangeRects(start: number, end: number): Rect[];
|
|
239
|
+
/** The part of this element's text the document selection covers, or
|
|
240
|
+
* null. An element that paints its own text fills `textRangeRects` with
|
|
241
|
+
* `selectionColor` under the glyphs while this is set; that is the whole
|
|
242
|
+
* contract for taking part in a selection. */
|
|
243
|
+
readonly selectionRange: { start: number; end: number } | null;
|
|
244
|
+
/** What to fill those rectangles with while `selectionRange` is set. */
|
|
245
|
+
readonly selectionColor: string | null;
|
|
246
|
+
/** An element with a selection of its own — an editor. A `selectable`
|
|
247
|
+
* document around it skips its subtree whole and leaves its presses
|
|
248
|
+
* alone. `<textinput>` sets it. */
|
|
249
|
+
hasOwnSelection: boolean;
|
|
250
|
+
|
|
251
|
+
// --- being a selection surface -------------------------------------------
|
|
252
|
+
//
|
|
253
|
+
// The base class implements these for every node, which is what lets a
|
|
254
|
+
// registered element be passed anywhere a `DrawnNode` is taken — the
|
|
255
|
+
// interface in `types/nodes.d.ts` lists them, so leaving them out here
|
|
256
|
+
// made a subclass stop being one.
|
|
257
|
+
|
|
258
|
+
/** The selection this element owns, or null when it is not `selectable`.
|
|
259
|
+
* A snapshot: read it again after a change. */
|
|
260
|
+
readonly textSelection: TextSelectionSnapshot | null;
|
|
261
|
+
/** Select everything in this surface, and take PRIMARY with it. */
|
|
262
|
+
selectAll(): this;
|
|
263
|
+
/** Drop the selection. PRIMARY is left where it is: the text stays
|
|
264
|
+
* pasteable, which is what every other X client does. */
|
|
265
|
+
clearSelection(): this;
|
|
266
|
+
/** What a copy would put on the clipboard. */
|
|
267
|
+
selectedText(): string;
|
|
268
|
+
/** Set both ends by hand. `setSelection(null)` clears. */
|
|
269
|
+
setSelection(anchor: TextPosition | null, focus?: TextPosition | null): this;
|
|
270
|
+
|
|
271
|
+
/** Draw. A subclass calls `super.paint(ctx)` first, for the background,
|
|
272
|
+
* border and clip, then draws inside `this.abs`. */
|
|
273
|
+
paint(ctx: Context2D): void;
|
|
274
|
+
/**
|
|
275
|
+
* The rect this paint pass is repainting, or null when it is repainting
|
|
276
|
+
* the whole window — and null outside a paint, which means the same
|
|
277
|
+
* thing: nothing is bounding you, so draw everything.
|
|
278
|
+
*
|
|
279
|
+
* An element whose node is one node never needs it; being painted at all
|
|
280
|
+
* means it is inside the pass. An element that draws a **scene** into one
|
|
281
|
+
* node culls against it the way core culls the tree, instead of redrawing
|
|
282
|
+
* the scene into a clip that throws most of it away. Window coordinates,
|
|
283
|
+
* the same space as `abs`; read-only.
|
|
284
|
+
*/
|
|
285
|
+
paintDamage(): Rect | null;
|
|
286
|
+
/**
|
|
287
|
+
* "The pixels in `rect` moved by (dx, dy); the rest of it is new" — for an
|
|
288
|
+
* element with a viewport of its own, whose pan is a scroll in every way
|
|
289
|
+
* but the bookkeeping.
|
|
290
|
+
*
|
|
291
|
+
* Claims `rect`, and arms the frame to blit the surviving band inside the
|
|
292
|
+
* backing store instead — after which the claim is narrowed to the band
|
|
293
|
+
* the shift exposed, which is what `paintDamage()` hands the paint. The
|
|
294
|
+
* element draws the strip and nothing else, without asking whether the
|
|
295
|
+
* blit happened.
|
|
296
|
+
*
|
|
297
|
+
* `dx`/`dy` are how far the **pixels** moved, the sense `Surface.copyWithin`
|
|
298
|
+
* uses rather than a scroll offset's, and whole. `rect` is in window
|
|
299
|
+
* coordinates and inside this node. The return says whether the frame is
|
|
300
|
+
* still a blit candidate; the gates that matter close at frame time, and
|
|
301
|
+
* every one of them falls back to repainting `rect`.
|
|
302
|
+
*/
|
|
303
|
+
scrollContents(rect: Rect, dx: number, dy: number): boolean;
|
|
304
|
+
/**
|
|
305
|
+
* Did anything this node draws change? True damages the whole node, false
|
|
306
|
+
* contributes no damage at all, and the default answers true for any prop
|
|
307
|
+
* that is not identical to the one it replaced — conservative, because a
|
|
308
|
+
* wrong "no" is a stale pixel nothing comes back to fix.
|
|
309
|
+
*
|
|
310
|
+
* Overridden by an element that claims its own damage and can say so only
|
|
311
|
+
* by looking at the values; an element that can say so by *name* declares
|
|
312
|
+
* `selfDamagedProps` instead. Either way, call `super.paintChanged` for
|
|
313
|
+
* everything the element does not know about — `style` is compared by the
|
|
314
|
+
* caller and is never yours to excuse.
|
|
315
|
+
*/
|
|
316
|
+
paintChanged(
|
|
317
|
+
nextProps: Record<string, unknown>,
|
|
318
|
+
prevProps: Record<string, unknown>,
|
|
319
|
+
): boolean;
|
|
320
|
+
/**
|
|
321
|
+
* Implemented by an element whose size comes from its content — a gauge, a
|
|
322
|
+
* chart, a terminal, an editor. Called during layout whenever the box's
|
|
323
|
+
* size is the element's to give, and by the content-floor pass behind
|
|
324
|
+
* `minWidth: 'auto'` with `{ width: 0, widthMode: 'at-most' }`, whose
|
|
325
|
+
* answer is the smallest size the content can be drawn at.
|
|
326
|
+
*
|
|
327
|
+
* Must be a **method on the class**: the base constructor is what wires it
|
|
328
|
+
* to layout. An element that implements it may not have children, and it
|
|
329
|
+
* has to answer from what it can read at any time (props, loaded data) —
|
|
330
|
+
* never from `this.abs`, which is the result of the layout doing the
|
|
331
|
+
* asking. Call `invalidateMeasure()` when the answer would change.
|
|
332
|
+
*/
|
|
333
|
+
measureContent?(constraints: MeasureConstraints): MeasuredSize;
|
|
334
|
+
/** The inputs to `measureContent` changed — a prop it reads, data that
|
|
335
|
+
* arrived — so the next layout has to ask again. `reason` joins the closed
|
|
336
|
+
* set the diagnostics print. */
|
|
337
|
+
invalidateMeasure(reason?: string): void;
|
|
338
|
+
/**
|
|
339
|
+
* The element's own behaviour for a key, run **after** the application's
|
|
340
|
+
* `onKeyDown` handlers and not at all if one of them called
|
|
341
|
+
* `preventDefault()` — the ordering that lets an app veto or extend an
|
|
342
|
+
* interactive element without knowing how it is built.
|
|
343
|
+
*
|
|
344
|
+
* Tab arrives here like any other key. Consuming it — an editor that
|
|
345
|
+
* indents — means calling `ev.preventDefault()`, which suppresses the
|
|
346
|
+
* default action left after this one: the focus cycle. An element that
|
|
347
|
+
* takes Tab owes the user a way back out; see docs/extending.md.
|
|
348
|
+
*/
|
|
349
|
+
defaultKeyDown?(ev: KeyboardEvent): void;
|
|
350
|
+
/**
|
|
351
|
+
* Text the user is still typing: a dead key waiting for its letter, or a
|
|
352
|
+
* Compose sequence half entered. `ev.type` is `compositionStart`,
|
|
353
|
+
* `compositionUpdate` or `compositionEnd`, and `ev.data` is what to show
|
|
354
|
+
* — or, at the end, the text that was committed.
|
|
355
|
+
*
|
|
356
|
+
* An element that implements this shows the preedit at its caret and
|
|
357
|
+
* inserts only what the end carries; the keys that made it never reach
|
|
358
|
+
* `defaultKeyDown`. See docs/extending.md.
|
|
359
|
+
*/
|
|
360
|
+
defaultComposition?(ev: CompositionEvent): void;
|
|
361
|
+
/**
|
|
362
|
+
* The element's own behaviour for a press, after `onMouseDown` handlers:
|
|
363
|
+
* placing a caret, grabbing a scrollbar thumb, arming a drag.
|
|
364
|
+
*
|
|
365
|
+
* The base class implements this (and the two below, and `defaultKeyDown`)
|
|
366
|
+
* to hand the gesture to the nearest `selectable` ancestor, so a press on
|
|
367
|
+
* anything inside a document reaches the selection. An element that
|
|
368
|
+
* overrides it and does not call `super` is, by that alone, not part of
|
|
369
|
+
* one — which is right for anything that edits, and wrong for anything
|
|
370
|
+
* that only draws.
|
|
371
|
+
*/
|
|
372
|
+
defaultMouseDown?(ev: MouseEvent): void;
|
|
373
|
+
/** Pointer motion while this element holds the press — it keeps receiving
|
|
374
|
+
* these wherever the pointer goes, as `onMouseMove` does not. */
|
|
375
|
+
defaultMouseDrag?(ev: MouseEvent): void;
|
|
376
|
+
/** The press this element received has been released. */
|
|
377
|
+
defaultMouseUp?(ev: MouseEvent): void;
|
|
378
|
+
/**
|
|
379
|
+
* Plain pointer motion over this element, with no button down — the hook
|
|
380
|
+
* for an element that paints its own hover state, a scene where the node
|
|
381
|
+
* or handle under the pointer lights up.
|
|
382
|
+
*
|
|
383
|
+
* The element under the pointer gets it, so the first one after the
|
|
384
|
+
* pointer arrives is also the enter. Not delivered while a pointer
|
|
385
|
+
* capture is in force: that motion belongs to the gesture, and
|
|
386
|
+
* `defaultMouseDrag` is where it goes.
|
|
387
|
+
*/
|
|
388
|
+
defaultMouseMove?(ev: MouseEvent): void;
|
|
389
|
+
/** The pointer left this element — clear what `defaultMouseMove` lit. A
|
|
390
|
+
* node that unmounts while hovered is *forgotten* rather than left, the
|
|
391
|
+
* way focus is, so a subtree torn down under the pointer never sees it. */
|
|
392
|
+
defaultMouseLeave?(ev: MouseEvent): void;
|
|
393
|
+
/**
|
|
394
|
+
* The wheel over this element, before the scroll chain gets it: a pane
|
|
395
|
+
* whose wheel is a zoom about the pointer rather than a scroll, which
|
|
396
|
+
* needs `ev.x`/`ev.y` and the modifiers as much as the deltas.
|
|
397
|
+
*
|
|
398
|
+
* `ev.preventDefault()` consumes it, and the chain then never runs — the
|
|
399
|
+
* answer for a gesture that is handled whether or not anything moved. An
|
|
400
|
+
* element whose wheel really is a scroll implements `canScroll`/`scrollBy`
|
|
401
|
+
* instead and joins the chain. Deltas are pixels, fractional where the
|
|
402
|
+
* device measured a fraction: the whole-pixel rule is the chain's.
|
|
403
|
+
*/
|
|
404
|
+
defaultWheel?(ev: WheelEvent): void;
|
|
405
|
+
/** Right-click, after `onContextMenu` handlers: open the element's own
|
|
406
|
+
* menu. Separate from the press so suppressing the menu does not also
|
|
407
|
+
* give up the caret placement `defaultMouseDown` did. */
|
|
408
|
+
defaultContextMenu?(ev: MouseEvent): void;
|
|
409
|
+
/** This element became the focused node, or its window regained the X
|
|
410
|
+
* focus while it was: start a caret blinking, arm an IME. No event —
|
|
411
|
+
* focus is a state, and `onFocus` is where the app hears about it. */
|
|
412
|
+
defaultFocus?(): void;
|
|
413
|
+
/** Focus left, or the window lost it: stop whatever `defaultFocus`
|
|
414
|
+
* started. A node that unmounts while focused is *forgotten* rather than
|
|
415
|
+
* blurred, so anything with a lifetime — a blink timer — is released in
|
|
416
|
+
* `destroySubtree` as well, the way `<textinput>` does. */
|
|
417
|
+
defaultBlur?(): void;
|
|
418
|
+
/** Whether this element is a tab stop and a focus target with nothing in
|
|
419
|
+
* the props saying so — `<textinput>` is, a `<box>` with something to
|
|
420
|
+
* scroll is. `focusable`/`tabIndex` props override it either way. An
|
|
421
|
+
* element with default actions for keys has to set this, or nothing will
|
|
422
|
+
* ever focus it. */
|
|
423
|
+
focusableByDefault?: boolean;
|
|
424
|
+
/** Whether dead keys and Compose run while this element has focus.
|
|
425
|
+
* Defaults to on. Set it false for an element that forwards raw key
|
|
426
|
+
* events to something with an input method of its own — `<foreign>` does,
|
|
427
|
+
* and composing on this side would swallow the dead key on its way to the
|
|
428
|
+
* embedded client. */
|
|
429
|
+
composes?: boolean;
|
|
430
|
+
/** The cursor to show over this element when nothing in the style says
|
|
431
|
+
* otherwise — `'text'` for something editable. A `cursor` style wins. */
|
|
432
|
+
defaultCursor?: string;
|
|
433
|
+
/**
|
|
434
|
+
* The ARIA role this element is when the application writes none — the
|
|
435
|
+
* registered-element counterpart of `<textinput>` defaulting to
|
|
436
|
+
* `textbox`. A `role` prop still wins, and an unknown name warns in
|
|
437
|
+
* development. Assign it in the constructor.
|
|
438
|
+
*/
|
|
439
|
+
a11yRole?: string;
|
|
440
|
+
/**
|
|
441
|
+
* What text this element holds, for the AT-SPI `Text` interface and the
|
|
442
|
+
* test spy (docs/accessibility.md). `null` when it holds none. Implement
|
|
443
|
+
* it and an editor, a viewer or a terminal is readable, navigable and
|
|
444
|
+
* announced through the same paths `<textinput>` uses.
|
|
445
|
+
*
|
|
446
|
+
* Called several times per change, so answer from state the element
|
|
447
|
+
* already holds — never a shaping pass or a copy of a buffer.
|
|
448
|
+
*/
|
|
449
|
+
a11yTextState?(): A11yTextState | null;
|
|
450
|
+
/**
|
|
451
|
+
* An assistive technology moved the caret or the selection: `start` and
|
|
452
|
+
* `end` are code-point offsets into the reported `value`, and the caret
|
|
453
|
+
* belongs at `end`. Return false to refuse. Without it an AT can read
|
|
454
|
+
* this element but not navigate it.
|
|
455
|
+
*/
|
|
456
|
+
a11ySetSelection?(start: number, end: number): boolean;
|
|
457
|
+
/**
|
|
458
|
+
* An assistive technology edited the text: replace `[start, end)` with
|
|
459
|
+
* `text`. Insert, delete and replace-everything all arrive here. Only an
|
|
460
|
+
* element that implements this exposes AT-SPI's `EditableText`, so an
|
|
461
|
+
* editor without it is read but never typed into.
|
|
462
|
+
*/
|
|
463
|
+
a11yReplaceText?(start: number, end: number, text: string): boolean;
|
|
464
|
+
/**
|
|
465
|
+
* The text reported by `a11yTextState()` may have moved — an edit, a
|
|
466
|
+
* caret move, a selection change, a composition. Free when no assistive
|
|
467
|
+
* technology is listening, so call it from every path that changes the
|
|
468
|
+
* text rather than guarding it.
|
|
469
|
+
*/
|
|
470
|
+
notifyA11yTextChanged(): void;
|
|
471
|
+
/**
|
|
472
|
+
* The interactive things this element draws, as accessible children
|
|
473
|
+
* (docs/extending.md). Without it a scene of any size is one accessible
|
|
474
|
+
* — "Flow graph, group" — and nothing in it can be found, named or
|
|
475
|
+
* activated.
|
|
476
|
+
*
|
|
477
|
+
* Called once per question asked about this element's children, so
|
|
478
|
+
* answer from state the element already holds: no layout pass, no copy.
|
|
479
|
+
*/
|
|
480
|
+
a11yScene?(): A11ySceneItem[];
|
|
481
|
+
/**
|
|
482
|
+
* An assistive technology acted on one of them: `id` is the one this
|
|
483
|
+
* element gave it. Return `true` to claim the action; anything else
|
|
484
|
+
* falls back to core — a synthetic click at the item's rect for
|
|
485
|
+
* `activate`, focusing the element for `focus`, revealing the element
|
|
486
|
+
* for `scroll` — so an element only answers what it has a better answer
|
|
487
|
+
* for.
|
|
488
|
+
*/
|
|
489
|
+
a11ySceneAction?(id: string, action: A11ySceneAction): boolean | void;
|
|
490
|
+
/**
|
|
491
|
+
* The scene reported by `a11yScene()` has changed — an item added or
|
|
492
|
+
* removed, one selected, the keyboard cursor moved. A commit re-reads it
|
|
493
|
+
* on its own, so this is for what the element does between commits: a
|
|
494
|
+
* drag, an animation, its own arrow keys. Free when nothing is
|
|
495
|
+
* listening.
|
|
496
|
+
*/
|
|
497
|
+
notifyA11ySceneChanged(): void;
|
|
498
|
+
/** Props changed. A subclass calls `super.applyProps(next, prev)`. */
|
|
499
|
+
applyProps(
|
|
500
|
+
nextProps: Record<string, unknown>,
|
|
501
|
+
prevProps: Record<string, unknown>,
|
|
502
|
+
): void;
|
|
503
|
+
/** Take the keyboard focus, as clicking this node would: focus moves
|
|
504
|
+
* here, `onBlur` fires on whatever had it, `onFocus` here. Also pulls the
|
|
505
|
+
* X input focus back to the window if the window manager gave it away.
|
|
506
|
+
* Returns this node, so an element can hand it out of a method. */
|
|
507
|
+
focus(): this;
|
|
508
|
+
/** Give up focus, leaving the window with nothing focused. */
|
|
509
|
+
blur(): this;
|
|
510
|
+
/** Whether this node has the owning window's focus. */
|
|
511
|
+
readonly focused: boolean;
|
|
512
|
+
/** Whether focus is on this node or inside it — CSS `:focus-within`. A
|
|
513
|
+
* `<popup>` counts as inside the node it hangs off in the JSX tree. */
|
|
514
|
+
readonly focusWithin: boolean;
|
|
515
|
+
/** Whether `node` is this node or a descendant of it (DOM `contains`). */
|
|
516
|
+
contains(node: Node | null): boolean;
|
|
517
|
+
/** The deepest node containing the point, or null. */
|
|
518
|
+
hitTest(x: number, y: number): Node | null;
|
|
519
|
+
containsPoint(x: number, y: number): boolean;
|
|
520
|
+
/** Drawn, visible children in paint order. */
|
|
521
|
+
paintOrder(): Node[];
|
|
522
|
+
insertBefore(child: Node, beforeChild: Node | null): void;
|
|
523
|
+
removeChild(child: Node): void;
|
|
524
|
+
destroySubtree(): void;
|
|
525
|
+
/** Ask the owning window to repaint — every node has this; the window
|
|
526
|
+
* node is where it lands. `damage` is what changed: pass `this`, or a
|
|
527
|
+
* rect when you know a tighter one, because an invalidation with no bound
|
|
528
|
+
* repaints the whole window. `reason` joins the closed set the
|
|
529
|
+
* diagnostics print (docs/debugging.md). */
|
|
530
|
+
invalidate(
|
|
531
|
+
layout?: boolean,
|
|
532
|
+
damage?: Node | Rect | null,
|
|
533
|
+
reason?: string,
|
|
534
|
+
): void;
|
|
535
|
+
getClientRects(): Rect[];
|
|
536
|
+
/** React Native's measure contract — position in the parent, size, then
|
|
537
|
+
* position in the window — which DevTools' style editor calls to draw
|
|
538
|
+
* the box model. Calls back with nothing for a node with no laid-out
|
|
539
|
+
* rect. */
|
|
540
|
+
measure(
|
|
541
|
+
callback: (
|
|
542
|
+
x?: number,
|
|
543
|
+
y?: number,
|
|
544
|
+
width?: number,
|
|
545
|
+
height?: number,
|
|
546
|
+
left?: number,
|
|
547
|
+
top?: number,
|
|
548
|
+
) => void,
|
|
549
|
+
): void;
|
|
550
|
+
}
|
|
551
|
+
|
|
552
|
+
/**
|
|
553
|
+
* Scrolling as a mixin: `class Pane extends Scrollable(Node)` gives a
|
|
554
|
+
* registered element the same `overflow: 'scroll'` behaviour `<box>` and
|
|
555
|
+
* `<window>` have — wheel, keys, bars, and the AT-SPI scroll-pane role.
|
|
556
|
+
*
|
|
557
|
+
* An element whose content is **painted rather than laid out** overrides
|
|
558
|
+
* `measureScrollContent`; everything else follows from the numbers it
|
|
559
|
+
* returns. See docs/extending.md.
|
|
560
|
+
*/
|
|
561
|
+
export declare function Scrollable<T extends typeof Node>(
|
|
562
|
+
Base: T,
|
|
563
|
+
): T & {
|
|
564
|
+
new (...args: any[]): {
|
|
565
|
+
scrollX: number;
|
|
566
|
+
scrollY: number;
|
|
567
|
+
contentWidth: number;
|
|
568
|
+
contentHeight: number;
|
|
569
|
+
isScroller(): boolean;
|
|
570
|
+
scrollTo(to: number | { x?: number; y?: number }): void;
|
|
571
|
+
scrollBy(by: number | { x?: number; y?: number }): void;
|
|
572
|
+
/** Chain membership: has this node room to move on the axis the delta
|
|
573
|
+
* names? The wheel asks it before scrolling this node rather than the
|
|
574
|
+
* next one out. */
|
|
575
|
+
canScroll(dx: number, dy: number): boolean;
|
|
576
|
+
/** How far the content reaches. The default walks the children;
|
|
577
|
+
* override it when the content is pixels this element paints. */
|
|
578
|
+
measureScrollContent(): { width: number; height: number };
|
|
579
|
+
scrollIntoView(node: Node): void;
|
|
580
|
+
};
|
|
581
|
+
};
|
|
582
|
+
|
|
583
|
+
export declare class BoxNode extends Node {
|
|
584
|
+
constructor(props: Record<string, unknown>, app: NtkApp);
|
|
585
|
+
}
|
|
586
|
+
|
|
587
|
+
export declare class TextNode extends Node {}
|
|
588
|
+
export declare class ImageNode extends Node {}
|
|
589
|
+
export declare class CanvasNode extends Node {}
|
|
590
|
+
export declare class TextInputNode extends Node {}
|
|
591
|
+
export declare class TextAreaNode extends TextInputNode {}
|
|
592
|
+
export declare class WindowNode extends Node {}
|
|
593
|
+
export declare class PopupNode extends WindowNode {}
|
|
594
|
+
/** The precedents for an element owning a real child X window — a surface of
|
|
595
|
+
* its own, and one holding somebody else's window. */
|
|
596
|
+
export declare class GlAreaNode extends Node {}
|
|
597
|
+
export declare class ForeignNode extends Node {}
|
package/src/node.js
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
// `react-x11/node` — the base class a registered element subclasses, plus
|
|
2
|
+
// the built-in nodes worth extending or reading as worked examples.
|
|
3
|
+
//
|
|
4
|
+
// The contract a subclass has to keep is written down in docs/extending.md.
|
|
5
|
+
// The short version: `Node` already implements the whole reconciler-facing
|
|
6
|
+
// surface (`insertBefore`, `removeChild`, `applyProps`, `destroySubtree`,
|
|
7
|
+
// layout, hit testing, and a `paint` that draws background, border and
|
|
8
|
+
// clip), so an element that only draws needs a constructor that names its
|
|
9
|
+
// kind and a `paint` that calls `super.paint(ctx)` first. An element whose
|
|
10
|
+
// *size* comes from its content adds `measureContent`, and says when that
|
|
11
|
+
// answer moves with `invalidateMeasure`. An element that *behaves* — one
|
|
12
|
+
// that edits, drags a caret or answers chords — adds the `default*` methods:
|
|
13
|
+
// they run after the application's own handlers and not at all if one of
|
|
14
|
+
// those called `preventDefault`, which is the ordering that makes an
|
|
15
|
+
// interactive element composable rather than something to work around.
|
|
16
|
+
export {
|
|
17
|
+
Node,
|
|
18
|
+
// `class MyPane extends Scrollable(Node)` — the same mixin <box> and
|
|
19
|
+
// <window> use, so a registered element can honour `overflow: 'scroll'`
|
|
20
|
+
// with the wheel, the keys, the bars and the a11y role already wired.
|
|
21
|
+
Scrollable,
|
|
22
|
+
// The `measureContent` body of an element whose content has a size of its
|
|
23
|
+
// own and an aspect ratio to keep — what <image> and <svg> answer with.
|
|
24
|
+
intrinsicSize,
|
|
25
|
+
// The cadence a caret blinks at, so an element that draws one is in step
|
|
26
|
+
// with `<textinput>` rather than a few tens of milliseconds beside it.
|
|
27
|
+
CARET_BLINK_MS,
|
|
28
|
+
BoxNode,
|
|
29
|
+
TextNode,
|
|
30
|
+
ImageNode,
|
|
31
|
+
CanvasNode,
|
|
32
|
+
TextInputNode,
|
|
33
|
+
TextAreaNode,
|
|
34
|
+
WindowNode,
|
|
35
|
+
PopupNode,
|
|
36
|
+
} from './nodes.js';
|
|
37
|
+
|
|
38
|
+
// The two precedents for an element that owns a real child X window rather
|
|
39
|
+
// than painting into its parent's: registered with `drawn: false`, realized
|
|
40
|
+
// by the owning WindowNode. docs/extending.md walks through them —
|
|
41
|
+
// `GlAreaNode` for a surface of one's own, `ForeignNode` for one that holds
|
|
42
|
+
// somebody else's window and therefore must never destroy it.
|
|
43
|
+
export { GlAreaNode } from './glnodes.js';
|
|
44
|
+
export { ForeignNode } from './foreignnodes.js';
|