@react-x11/components 0.7.1 → 0.8.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 +214 -31
- package/dist/color-picker/ColorPicker.d.ts.map +1 -1
- package/dist/color-picker/ColorPicker.js +43 -33
- package/dist/color-picker/ColorPicker.js.map +1 -1
- package/dist/internal/scroll.d.ts.map +1 -1
- package/dist/internal/scroll.js +32 -15
- package/dist/internal/scroll.js.map +1 -1
- package/dist/internal/units.d.ts +2 -0
- package/dist/internal/units.d.ts.map +1 -0
- package/dist/internal/units.js +35 -0
- package/dist/internal/units.js.map +1 -0
- package/dist/internal/window.d.ts.map +1 -1
- package/dist/internal/window.js +4 -2
- package/dist/internal/window.js.map +1 -1
- package/dist/table/index.d.ts.map +1 -1
- package/dist/table/index.js +14 -5
- package/dist/table/index.js.map +1 -1
- package/dist/terminal/vt/node.d.ts +56 -3
- package/dist/terminal/vt/node.d.ts.map +1 -1
- package/dist/terminal/vt/node.js +106 -26
- package/dist/terminal/vt/node.js.map +1 -1
- package/dist/terminal/vt/renderer.d.ts +4 -0
- package/dist/terminal/vt/renderer.d.ts.map +1 -1
- package/dist/terminal/vt/renderer.js +14 -5
- package/dist/terminal/vt/renderer.js.map +1 -1
- package/dist/tree/index.d.ts.map +1 -1
- package/dist/tree/index.js +6 -4
- package/dist/tree/index.js.map +1 -1
- package/package.json +3 -3
- package/src/color-picker/ColorPicker.ts +107 -81
- package/src/internal/scroll.ts +34 -15
- package/src/internal/units.ts +34 -0
- package/src/internal/window.ts +4 -2
- package/src/table/index.ts +14 -5
- package/src/terminal/vt/node.ts +128 -29
- package/src/terminal/vt/renderer.ts +27 -5
- package/src/tree/index.ts +6 -4
package/README.md
CHANGED
|
@@ -11,10 +11,10 @@ needs a change to core to exist, and core does not grow to carry it.
|
|
|
11
11
|
reference page per component, rendered from [`docs/`](docs/README.md). This
|
|
12
12
|
README is the tour; that is the detail.
|
|
13
13
|
|
|
14
|
-
> **Installable now.**
|
|
15
|
-
>
|
|
16
|
-
>
|
|
17
|
-
>
|
|
14
|
+
> **Installable now.** The published release is `0.7.1`, and the react-x11
|
|
15
|
+
> range it declares resolves off the registry, so `npm install` just works.
|
|
16
|
+
> `master` carries what has landed since, so use a checkout if you want
|
|
17
|
+
> something not in that release yet.
|
|
18
18
|
|
|
19
19
|
## What is here, and what is in core
|
|
20
20
|
|
|
@@ -36,10 +36,49 @@ This package carries it when **all** of these hold:
|
|
|
36
36
|
So `<box>`, `<text>`, `<window>`, buttons, menus, dialogs and the rest of the
|
|
37
37
|
widget set are core. Heavier, more specialised things live here.
|
|
38
38
|
|
|
39
|
-
The line can also fall inside a single feature. `<glarea>` is core —
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
and it belongs
|
|
39
|
+
The line can also fall inside a single feature. `<glarea>` is core — a real
|
|
40
|
+
child surface on a GL visual, created in the commit phase, which is renderer
|
|
41
|
+
internals whichever backend is under it. A Three.js-shaped scene graph drawn
|
|
42
|
+
into it is not: that is composition over a public element, and it belongs
|
|
43
|
+
here.
|
|
44
|
+
|
|
45
|
+
## Two backends, and the three components that only run on one
|
|
46
|
+
|
|
47
|
+
react-x11 has two backend families now — X11, and a native macOS one that
|
|
48
|
+
speaks to Cocoa with no X server anywhere (`createRoot({ backend })`, or
|
|
49
|
+
`REACT_X11_BACKEND`). **Almost everything in this package is neutral about
|
|
50
|
+
which**, because almost everything here is either composition over core's
|
|
51
|
+
host elements or a registered element that draws through core's 2D context,
|
|
52
|
+
and both are backend contracts rather than X ones. `<Map>`, the vt terminal,
|
|
53
|
+
`<Flow>`, `<Html>`, `<Markdown>`, the charts and the rest render on either.
|
|
54
|
+
|
|
55
|
+
The exceptions are the components built on **XEmbed**, and they are
|
|
56
|
+
exceptions because cross-process window embedding does not exist on macOS at
|
|
57
|
+
all — there is no `<foreign>` to build on, which react-x11's own
|
|
58
|
+
[`docs/macos.md`](https://github.com/sidorares/react-x11/blob/master/docs/macos.md)
|
|
59
|
+
names this package in as much:
|
|
60
|
+
|
|
61
|
+
| Component | On the Cocoa backend |
|
|
62
|
+
| --------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
63
|
+
| `<Terminal>`, embedded backends (xterm, urxvt, alacritty) | No equivalent. Pin `backend="vt"`, which is native and needs no emulator installed anyway. |
|
|
64
|
+
| `<MediaPlayer>` | No equivalent — mpv's and VLC's `--wid` embedding is an X mechanism. |
|
|
65
|
+
| `<TrayHost>` | Reports `status: 'unavailable'` and renders `fallback`; there is no manager selection to take. Putting an icon _in_ a Mac's status bar is the other direction, and is core's `useTray()`. |
|
|
66
|
+
|
|
67
|
+
`<Three>` is the one that looks like it should be on that list and is not: it
|
|
68
|
+
draws through `<glarea>`, which the Cocoa backend implements as GL into a
|
|
69
|
+
CALayer, so the scene graph runs there too — on a third GL path rather than
|
|
70
|
+
none. [Its reference](docs/components/three.md) has the table.
|
|
71
|
+
|
|
72
|
+
One sharp edge worth knowing: `<Terminal backend="auto">` probes `PATH`, and
|
|
73
|
+
a `PATH` probe cannot see which backend the app is running on. On a Mac with
|
|
74
|
+
XQuartz installed it will still choose that xterm, which the Cocoa backend
|
|
75
|
+
then cannot embed. Say `backend="vt"` outright in an app that runs on both.
|
|
76
|
+
|
|
77
|
+
The other X-shaped behaviour to know about is **PRIMARY**: selecting text
|
|
78
|
+
publishing to the X PRIMARY selection, and middle-click pasting it, are what
|
|
79
|
+
X11 desktops do and what this package's document surfaces take part in. On
|
|
80
|
+
macOS there is one pasteboard and no such convention, so what is described
|
|
81
|
+
as PRIMARY below is the X11 backend's half of the story.
|
|
43
82
|
|
|
44
83
|
## Install
|
|
45
84
|
|
|
@@ -51,8 +90,14 @@ npm install @react-x11/components react react-x11
|
|
|
51
90
|
host element mutates state inside react-x11, so a second copy of the renderer
|
|
52
91
|
would leave you with an element that lays out correctly and never paints.
|
|
53
92
|
|
|
54
|
-
Core must be **2.
|
|
55
|
-
|
|
93
|
+
Core must be **2.11.0 or newer**. The floor is a running one rather than a
|
|
94
|
+
one-time gate — it moves whenever a component here adopts something core
|
|
95
|
+
just landed, and the last few moves were the Cocoa glyph-run seams
|
|
96
|
+
(`^2.5.0`), the chunked Cocoa stroke `<Map>` wanted (`^2.6.1`), the desktop
|
|
97
|
+
calendar's move into core (`^2.9.1`) and the eyedropper's macOS rung
|
|
98
|
+
(`^2.11.0`). The subpaths this package imports are `react-x11` itself plus
|
|
99
|
+
`/host`, `/node`, `/style`, `/keysyms`, `/ntk`, `/yoga` and
|
|
100
|
+
`/jsx-runtime`.
|
|
56
101
|
|
|
57
102
|
## Usage
|
|
58
103
|
|
|
@@ -124,14 +169,18 @@ import type { CodeEditorProps } from '@react-x11/components';
|
|
|
124
169
|
| `Code` | `@react-x11/components/code` | A static code block: highlighted, selectable. |
|
|
125
170
|
| `CodeEditor` | `@react-x11/components/code-editor` | Multiline code editing: highlighting, completion. |
|
|
126
171
|
| `Flow` | `@react-x11/components/flow` | A directed-graph editor: nodes, edges, pan and zoom. |
|
|
172
|
+
| `Formula` | `@react-x11/components/formula` | TeX mathematics: KaTeX layout, native ink, selectable. |
|
|
127
173
|
| `Html` | `@react-x11/components/html` | A static HTML + CSS document, selectable, with seams. |
|
|
128
174
|
| `Map` | `@react-x11/components/maps` | A 2D vector-tile map: pan, zoom, markers, overlays. |
|
|
129
175
|
| `Markdown` | `@react-x11/components/markdown` | Streaming-friendly GFM with cross-block selection. |
|
|
130
176
|
| `MediaPlayer` | `@react-x11/components/media-player` | mpv or VLC, embedded, with real transport control. |
|
|
177
|
+
| `QmlView` | `@react-x11/components/qml` | Qt's QML language as an authoring layer. No Qt. |
|
|
131
178
|
| `ReorderList` … | `@react-x11/components/reorder` | A drag-and-drop list, over core's own drag and drop. |
|
|
132
179
|
| `Table` | `@react-x11/components/table` | A data table: sortable, virtualized, any row height. |
|
|
180
|
+
| `Tabs` … | `@react-x11/components/tabs` | One visible panel at a time, five strip styles. |
|
|
133
181
|
| `Terminal` | `@react-x11/components/terminal` | A real terminal: an embedded emulator, or its own. |
|
|
134
182
|
| `TerminalOutput` | `@react-x11/components/terminal-output` | A captured session, rendered. `<Terminal>`'s static sibling. |
|
|
183
|
+
| `Canvas` … | `@react-x11/components/three` | A three-fiber-shaped 3D scene over either GL backend. |
|
|
135
184
|
| `Timeline` … | `@react-x11/components/timeline` | A run of events: a mark per step, a line between. |
|
|
136
185
|
| `TrayHost` | `@react-x11/components/tray-host` | The system tray: applications dock their icons in. |
|
|
137
186
|
| `Tree` | `@react-x11/components/tree` | A disclosure tree: seams throughout, and virtualized. |
|
|
@@ -147,7 +196,7 @@ spawn, watch and hand-back lifecycle both XEmbed wrappers are built on).
|
|
|
147
196
|
Selecting text is **core's**, not this package's: a `<box selectable>` is
|
|
148
197
|
a surface, everything under it that answers for its own text is in the
|
|
149
198
|
selection, and the drag, the word and block granularities, Ctrl+A, Ctrl+C
|
|
150
|
-
and PRIMARY come with it (react-x11#291). `<Markdown>` and `<Code>` set
|
|
199
|
+
and (on X11) PRIMARY come with it (react-x11#291). `<Markdown>` and `<Code>` set
|
|
151
200
|
that prop and say which parts are chrome; the elements underneath answer
|
|
152
201
|
`textContent`/`textIndexAt`/`textCaretRect`/`textRangeRects`, which is all
|
|
153
202
|
an element of your own has to do to join a document.
|
|
@@ -218,9 +267,10 @@ What "put a lot of effort into performance" means here, concretely:
|
|
|
218
267
|
a per-pixel-column min/max index (a pyramid over the data, built lazily
|
|
219
268
|
and extended on append), so a million points in a 90px cell cost ~90
|
|
220
269
|
rectangles. A million points that fall on one pixel render one pixel.
|
|
221
|
-
- **
|
|
222
|
-
|
|
223
|
-
|
|
270
|
+
- **Drawing commands by default, pixels when they win.** A dense line goes
|
|
271
|
+
out as one batched `fillRects` — on X11 that is a `FillRectangles` at
|
|
272
|
+
~8 bytes per pixel column, and the wire cost `onFrameStats` reports is
|
|
273
|
+
that one; a sparse line goes as a real antialiased path. The one place a pixel
|
|
224
274
|
push wins — a scatter covering most of the plot — is detected by
|
|
225
275
|
comparing the actual byte costs, and flips to one composited density
|
|
226
276
|
image.
|
|
@@ -278,8 +328,8 @@ markdown→HTML pass anywhere — and is exported (`parseMarkdown`) with the
|
|
|
278
328
|
AST types.
|
|
279
329
|
|
|
280
330
|
**Selection is the point.** Text selects across every block — drag,
|
|
281
|
-
double-click a word, triple-click a block, Ctrl+A, Ctrl+C — and a
|
|
282
|
-
with a selection takes the
|
|
331
|
+
double-click a word, triple-click a block, Ctrl+A, Ctrl+C — and on X11 a
|
|
332
|
+
mouse-up with a selection takes the PRIMARY selection, so middle-click paste
|
|
283
333
|
works everywhere. All of that is core's `selectable` (react-x11#291); what
|
|
284
334
|
this component adds is which parts are chrome, so copied text is clean:
|
|
285
335
|
list markers stay behind, and the separators come from the layout, which
|
|
@@ -372,6 +422,26 @@ explicit `language={…}`) and the look is shared with `<Markdown>`'s fenced
|
|
|
372
422
|
blocks, so the two agree in one window. Selection and copy are core's; the
|
|
373
423
|
line-number gutter is `selectable={false}`, so copied code pastes clean.
|
|
374
424
|
|
|
425
|
+
## Mathematics
|
|
426
|
+
|
|
427
|
+
```jsx
|
|
428
|
+
import { Formula } from '@react-x11/components/formula';
|
|
429
|
+
|
|
430
|
+
<Formula tex="x = \frac{-b \pm \sqrt{b^2-4ac}}{2a}" display selectable />;
|
|
431
|
+
```
|
|
432
|
+
|
|
433
|
+
TeX, rendered natively. KaTeX — an optional dependency — parses the source
|
|
434
|
+
into its virtual DOM, and this package's `formula` element lays that tree out
|
|
435
|
+
and draws it through the app's font manager, using KaTeX's own faces. Every
|
|
436
|
+
glyph answers core's four text accessors, so the mathematics is **part of the
|
|
437
|
+
selection** rather than an opaque picture: on its own with `selectable`, or as
|
|
438
|
+
one block inside any `selectable` document. `partial` holds the last tree that
|
|
439
|
+
parsed while more source is still arriving, which is what makes it safe to
|
|
440
|
+
append to a formula a model is still writing. A ` ```math ` fence in a
|
|
441
|
+
document becomes one through `<Markdown>`'s `fences` map, which is opt-in —
|
|
442
|
+
that seam is how `<Markdown>` hosts a component without importing it.
|
|
443
|
+
[The reference](docs/components/formula.md) has the rest.
|
|
444
|
+
|
|
375
445
|
## A terminal session you already have: `<TerminalOutput>`
|
|
376
446
|
|
|
377
447
|
The static sibling of `<Terminal>`, exactly as `<Code>` is `<CodeEditor>`'s.
|
|
@@ -473,6 +543,40 @@ pipeline beside galleries of the sizes and variants;
|
|
|
473
543
|
[the reference](docs/components/timeline.md) has the rest, including why
|
|
474
544
|
every indicator's chip is opaque.
|
|
475
545
|
|
|
546
|
+
## Tabs
|
|
547
|
+
|
|
548
|
+
One visible panel at a time. The API is
|
|
549
|
+
[Chakra UI's Tabs](https://chakra-ui.com/docs/components/tabs) with its parts
|
|
550
|
+
spelled flat, exactly as `<Timeline>` spells its own:
|
|
551
|
+
|
|
552
|
+
```jsx
|
|
553
|
+
import {
|
|
554
|
+
Tabs,
|
|
555
|
+
TabsList,
|
|
556
|
+
TabsTrigger,
|
|
557
|
+
TabsContent,
|
|
558
|
+
} from '@react-x11/components/tabs';
|
|
559
|
+
|
|
560
|
+
<Tabs defaultValue="members">
|
|
561
|
+
<TabsList>
|
|
562
|
+
<TabsTrigger value="members">Members</TabsTrigger>
|
|
563
|
+
<TabsTrigger value="projects">Projects</TabsTrigger>
|
|
564
|
+
</TabsList>
|
|
565
|
+
<TabsContent value="members">…</TabsContent>
|
|
566
|
+
<TabsContent value="projects">…</TabsContent>
|
|
567
|
+
</Tabs>;
|
|
568
|
+
```
|
|
569
|
+
|
|
570
|
+
The vocabulary is Chakra's too — `value`/`defaultValue`/`onValueChange`, five
|
|
571
|
+
strip variants (`line`, `subtle`, `enclosed`, `outline`, `plain`), `size`,
|
|
572
|
+
`orientation`, `activationMode`, `fitted`, `lazyMount` — so a snippet from
|
|
573
|
+
their docs is the same tree with the dots removed. It supersedes core's tabs
|
|
574
|
+
the way `<Tree>` supersedes core's tree: the keyboard and RTL behaviour a
|
|
575
|
+
user has already learnt, without the items-array API. The one prop Chakra has
|
|
576
|
+
no counterpart for is `overflow`: a horizontal strip that runs out of room
|
|
577
|
+
puts the tabs that do not fit in a menu at its end rather than off its own
|
|
578
|
+
edge. [The reference](docs/components/tabs.md) has the rest.
|
|
579
|
+
|
|
476
580
|
## A drag-and-drop list
|
|
477
581
|
|
|
478
582
|
`<ReorderList>` is a list the user reorders by dragging its items — or by
|
|
@@ -617,8 +721,8 @@ import {
|
|
|
617
721
|
```
|
|
618
722
|
|
|
619
723
|
Editing is the full expected set: selection (keyboard and mouse, word and
|
|
620
|
-
line variants), undo/redo with coalescing,
|
|
621
|
-
and middle-click paste
|
|
724
|
+
line variants), undo/redo with coalescing, the system clipboard — including
|
|
725
|
+
PRIMARY and middle-click paste on X11 — auto-indent, Tab/Shift+Tab indentation, Ctrl+/
|
|
622
726
|
comment toggling, bracket matching, and LSP-shaped `diagnostics` squiggles.
|
|
623
727
|
Escape then Tab leaves the field. Ctrl+Space asks for completions.
|
|
624
728
|
|
|
@@ -857,6 +961,71 @@ architecture.
|
|
|
857
961
|
|
|
858
962
|
[mvt]: https://github.com/mapbox/vector-tile-spec
|
|
859
963
|
|
|
964
|
+
## A 3D scene
|
|
965
|
+
|
|
966
|
+
A [react-three-fiber](https://docs.pmnd.rs/react-three-fiber)-shaped scene
|
|
967
|
+
graph over core's `<glarea>`. There is no three.js and no WebGL underneath —
|
|
968
|
+
the element names, the prop shapes, `attach`, dashed paths, `useFrame` /
|
|
969
|
+
`useThree` and `extend()` follow r3f, and what differs is the pipeline.
|
|
970
|
+
|
|
971
|
+
```jsx
|
|
972
|
+
import { Canvas, useFrame } from '@react-x11/components/three';
|
|
973
|
+
|
|
974
|
+
<Canvas camera={{ position: [3, 3, 6], fov: 50 }} style={{ flexGrow: 1 }}>
|
|
975
|
+
<ambientLight intensity={0.4} />
|
|
976
|
+
<pointLight position={[5, 6, 6]} />
|
|
977
|
+
<mesh position={[0, 0.5, 0]}>
|
|
978
|
+
<boxGeometry args={[1, 1, 1]} />
|
|
979
|
+
<meshStandardMaterial color="hotpink" />
|
|
980
|
+
</mesh>
|
|
981
|
+
</Canvas>;
|
|
982
|
+
```
|
|
983
|
+
|
|
984
|
+
This is the worked example at the top of this file of a boundary running
|
|
985
|
+
_through_ a feature: `<glarea>` is a real GL surface created in the commit
|
|
986
|
+
phase, which is renderer internals and stayed in core; the scene graph over it
|
|
987
|
+
is composition, and it is here.
|
|
988
|
+
|
|
989
|
+
Which pipeline draws is the connection's business, not the scene's. **Indirect
|
|
990
|
+
GLX** encodes GL 1.x into the X connection and survives a network hop, at the
|
|
991
|
+
cost of shaders and post-processing — the protocol encodes neither. **Direct**
|
|
992
|
+
rendering (the `x11-dri` addon: DRI3 on Linux, Apple-DRI under XQuartz, CGL
|
|
993
|
+
into a CALayer on the native macOS backend) is OpenGL ES 2 on the GPU, and it
|
|
994
|
+
is where `<shaderMaterial>` and `<effectComposer>` work. The same JSX renders
|
|
995
|
+
on all of them; the two direct-only families throw at creation naming the
|
|
996
|
+
reason rather than showing a blank surface, so a scene that would rather
|
|
997
|
+
degrade can branch. [The reference](docs/components/three.md) is the table,
|
|
998
|
+
including the JSX pragma the intrinsic element names want.
|
|
999
|
+
|
|
1000
|
+
## QML, without Qt
|
|
1001
|
+
|
|
1002
|
+
Qt's declarative UI language as an authoring layer — the parser, the reactive
|
|
1003
|
+
binding graph and the object model are this package's own, with zero
|
|
1004
|
+
dependencies and no Qt anywhere:
|
|
1005
|
+
|
|
1006
|
+
```jsx
|
|
1007
|
+
import { QmlView } from '@react-x11/components/qml';
|
|
1008
|
+
|
|
1009
|
+
<QmlView
|
|
1010
|
+
source={`
|
|
1011
|
+
import QtQuick 2.15
|
|
1012
|
+
Rectangle {
|
|
1013
|
+
width: 300; height: 120; color: "#101418"
|
|
1014
|
+
property int count: 0
|
|
1015
|
+
Text { anchors.centerIn: parent; color: "white"; text: "clicks: " + count }
|
|
1016
|
+
MouseArea { anchors.fill: parent; onClicked: count++ }
|
|
1017
|
+
}
|
|
1018
|
+
`}
|
|
1019
|
+
/>;
|
|
1020
|
+
```
|
|
1021
|
+
|
|
1022
|
+
Everything visible is an ordinary `<box>`, `<text>` or `<image>` committed
|
|
1023
|
+
through the renderer, so theming, damage tracking, accessibility and the test
|
|
1024
|
+
harness all apply to QML content without knowing it is QML. It registers no
|
|
1025
|
+
host element; the one import-time side effect is populating the family's own
|
|
1026
|
+
QtQuick type registry, which touches no core state and shakes out with the
|
|
1027
|
+
family. [The reference](docs/components/qml.md) has the rest.
|
|
1028
|
+
|
|
860
1029
|
## The user's real calendar
|
|
861
1030
|
|
|
862
1031
|
`<Calendar dayContent>` is the seam the desktop's own events hang off, and
|
|
@@ -901,9 +1070,9 @@ handed, so nothing sits between the two — **that string format is the whole
|
|
|
901
1070
|
contract between the two packages**, and it is why the grid never had to know
|
|
902
1071
|
what an event is.
|
|
903
1072
|
|
|
904
|
-
This package shipped the D-Bus half
|
|
1073
|
+
This package shipped the D-Bus half through 0.6.0, as
|
|
905
1074
|
`@react-x11/components/desktop-calendar`. It moved to core in react-x11 2.9.1
|
|
906
|
-
and the subpath
|
|
1075
|
+
and 0.7.0 deleted the subpath: a calendar is one of the things an app does _outside_
|
|
907
1076
|
its own windows, like notifications, the tray and the file dialog, and every
|
|
908
1077
|
one of those is a ladder in core with a freedesktop rung and a macOS one — the
|
|
909
1078
|
macOS rung here reaches EventKit through `@windowkit/appkit`, which only core
|
|
@@ -924,6 +1093,12 @@ These two are the same component twice, and they are what core's `<foreign>`
|
|
|
924
1093
|
element was added for: a react-x11 app can now **host** another X client
|
|
925
1094
|
rather than only drawing its own pixels.
|
|
926
1095
|
|
|
1096
|
+
**Both are X11-only**, and the heading says why: an X client is what they
|
|
1097
|
+
host. macOS has no cross-process window embedding to build the same thing
|
|
1098
|
+
on, so on the Cocoa backend `<Terminal backend="vt">` is the terminal and
|
|
1099
|
+
`<MediaPlayer>` has no counterpart — see
|
|
1100
|
+
[Two backends](#two-backends-and-the-three-components-that-only-run-on-one).
|
|
1101
|
+
|
|
927
1102
|
```jsx
|
|
928
1103
|
import { Terminal } from '@react-x11/components';
|
|
929
1104
|
|
|
@@ -993,9 +1168,10 @@ without an xterm in CI.
|
|
|
993
1168
|
|
|
994
1169
|
One prop changes the terminal from a hosted X client into a native element: a
|
|
995
1170
|
pty (through a pluggable `PtyHost`), [`@xterm/headless`][xterm-headless] as
|
|
996
|
-
the escape-sequence state machine, and a cell-grid renderer that draws
|
|
997
|
-
|
|
998
|
-
|
|
1171
|
+
the escape-sequence state machine, and a cell-grid renderer that draws glyph
|
|
1172
|
+
runs into a retained offscreen surface, scrolls it in place, and coalesces
|
|
1173
|
+
onto react-x11's frame clock. One renderer, both backends: XRender runs and a
|
|
1174
|
+
server-side copy on X11, CoreText runs into a CG bitmap on macOS.
|
|
999
1175
|
|
|
1000
1176
|
```jsx
|
|
1001
1177
|
<Terminal
|
|
@@ -1056,8 +1232,8 @@ Keyboard, mouse and selection are what a terminal user expects: xterm-compatible
|
|
|
1056
1232
|
key encoding (application cursor/keypad modes, the modifier parameter
|
|
1057
1233
|
scheme, `Alt` as an ESC prefix), mouse reporting in the tracking mode the
|
|
1058
1234
|
program asked for (with Shift as the universal "let me select instead"
|
|
1059
|
-
override), char/word/line selection that publishes PRIMARY,
|
|
1060
|
-
paste, Ctrl+Shift+C/V, bracketed paste, and OSC 52 clipboard **writes** —
|
|
1235
|
+
override), char/word/line selection that publishes PRIMARY on X11,
|
|
1236
|
+
middle-click paste, Ctrl+Shift+C/V, bracketed paste, and OSC 52 clipboard **writes** —
|
|
1061
1237
|
never reads, which are answered with nothing whatever a program asks for.
|
|
1062
1238
|
|
|
1063
1239
|
Escape arms one pass-through Tab, so the terminal is not a keyboard trap;
|
|
@@ -1125,7 +1301,11 @@ The same protocol as the two above, pointed the other way. `<Terminal>` and
|
|
|
1125
1301
|
`<MediaPlayer>` spawn a program into a container they own; a tray is handed
|
|
1126
1302
|
windows by applications that were already running, and the
|
|
1127
1303
|
[system tray spec](http://specifications.freedesktop.org/systemtray/latest/)
|
|
1128
|
-
is XEmbed's biggest surviving consumer.
|
|
1304
|
+
is XEmbed's biggest surviving consumer. **X11-only**, for the same reason the
|
|
1305
|
+
two above are: on the Cocoa backend there is no manager selection to take, so
|
|
1306
|
+
it reports `status: 'unavailable'` and renders `fallback` — the same posture
|
|
1307
|
+
it has against the headless test server. Putting an icon _in_ a Mac's status
|
|
1308
|
+
bar is the other direction and is core's `useTray()`.
|
|
1129
1309
|
|
|
1130
1310
|
```jsx
|
|
1131
1311
|
import { TrayHost } from '@react-x11/components';
|
|
@@ -1184,9 +1364,6 @@ rather than inside it.
|
|
|
1184
1364
|
|
|
1185
1365
|
Candidates to move here:
|
|
1186
1366
|
|
|
1187
|
-
- The 3D scene graph and a Three.js / react-three-fiber-shaped layer, with
|
|
1188
|
-
`<glarea>` itself staying in core.
|
|
1189
|
-
- `<Tabs>`, undecided — it may well stay in core.
|
|
1190
1367
|
- The inline half of MDX — a component in the middle of a sentence, which is
|
|
1191
1368
|
gated on a `<richtext>` run that can reserve advance width for an embedded
|
|
1192
1369
|
element. Block-position components and expressions have shipped;
|
|
@@ -1196,8 +1373,14 @@ Candidates to move here:
|
|
|
1196
1373
|
`dbusmenu.js`, and a complete panel wants both.
|
|
1197
1374
|
|
|
1198
1375
|
`<Table>` above supersedes core's `<Table>` the way `<Tree>` supersedes
|
|
1199
|
-
core's tree
|
|
1200
|
-
|
|
1376
|
+
core's tree, and `<Tabs>` supersedes core's tabs the same way; whether core's
|
|
1377
|
+
remainder in each case is stripped down or removed outright is core's
|
|
1378
|
+
decision, still open — `docs/prd-table.md` records the table's contract.
|
|
1379
|
+
|
|
1380
|
+
The 3D scene graph landed while this list still called it a candidate:
|
|
1381
|
+
`@react-x11/components/three` is the react-three-fiber-shaped layer, and
|
|
1382
|
+
`<glarea>` stayed in core exactly as planned. That is the worked example at
|
|
1383
|
+
the top of this file of a boundary running _through_ a feature.
|
|
1201
1384
|
|
|
1202
1385
|
`<Markdown>` above **replaces** core's ntk-backed `<markdown>` element, and
|
|
1203
1386
|
`<Html>` now replaces `HtmlView` and core's `<html>` (ntk's document widgets
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ColorPicker.d.ts","sourceRoot":"","sources":["../../src/color-picker/ColorPicker.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"ColorPicker.d.ts","sourceRoot":"","sources":["../../src/color-picker/ColorPicker.ts"],"names":[],"mappings":"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"}
|
|
@@ -296,7 +296,16 @@ export function ColorPicker(props) {
|
|
|
296
296
|
const setHsv = (h, sat, v, done = false) => emit(channelsFromHsv(h, sat, v, model.a), done);
|
|
297
297
|
// --- pointer ------------------------------------------------------------
|
|
298
298
|
const fractionIn = (node, ev) => {
|
|
299
|
-
|
|
299
|
+
// `getClientRects()`, not `abs`. `abs` is **device** pixels and an
|
|
300
|
+
// event's `x`/`y` are **logical** — react-x11's docs/scale.md — so
|
|
301
|
+
// subtracting one from the other is only right at scale 1. On a retina
|
|
302
|
+
// panel a press at the middle of this box read as a press a quarter of
|
|
303
|
+
// the way in from its corner: the thumb sat near the corner however the
|
|
304
|
+
// pointer moved, and the far side of every axis was unreachable. The
|
|
305
|
+
// client rect is the same box already divided by the node's scale,
|
|
306
|
+
// which is the unit the pointer arrives in, so the arithmetic below is
|
|
307
|
+
// the arithmetic it always was.
|
|
308
|
+
const [box] = node?.getClientRects() ?? [];
|
|
300
309
|
if (!box?.width || !box.height)
|
|
301
310
|
return null;
|
|
302
311
|
return {
|
|
@@ -450,21 +459,38 @@ export function ColorPicker(props) {
|
|
|
450
459
|
onBlur: () => setFocused(false),
|
|
451
460
|
onKeyDown: focusable ? handleKey : undefined,
|
|
452
461
|
});
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
462
|
+
/**
|
|
463
|
+
* The gradient and its border, as one element *under* the thumb.
|
|
464
|
+
*
|
|
465
|
+
* Core paints a node's children first and its border after them, so a
|
|
466
|
+
* border on the box the thumb lives in is painted across the thumb — the
|
|
467
|
+
* grey line over the white handle. On a sibling below it, the thumb wins,
|
|
468
|
+
* which is the order a handle wants: it is the thing being pointed at.
|
|
469
|
+
*
|
|
470
|
+
* It fixes the geometry too. An absolutely positioned child is laid out
|
|
471
|
+
* from its parent's *padding* box, so a border on the axis box shifted
|
|
472
|
+
* every thumb by its width — a strip handle overhung the top by 1px and
|
|
473
|
+
* the bottom by 3, and sat 1px right of the colour it was naming. Here
|
|
474
|
+
* the thumb's parent has no border, so `left` and `top` mean what they
|
|
475
|
+
* say: the same outer box `fractionIn` measures a press against.
|
|
476
|
+
*/
|
|
477
|
+
const framed = (axis, pane) => hx('box', {
|
|
478
|
+
key: 'frame',
|
|
457
479
|
style: [
|
|
458
|
-
s.
|
|
480
|
+
s.pane,
|
|
459
481
|
{
|
|
460
482
|
borderWidth: theme.borderWidth,
|
|
461
|
-
borderColor: cursorShown && active ===
|
|
462
|
-
? theme.borderFocus
|
|
463
|
-
: theme.border,
|
|
483
|
+
borderColor: cursorShown && active === axis ? theme.borderFocus : theme.border,
|
|
464
484
|
},
|
|
465
485
|
],
|
|
486
|
+
}, pane);
|
|
487
|
+
const renderArea = () => hx('box', {
|
|
488
|
+
key: 'area',
|
|
489
|
+
ref: areaRef,
|
|
490
|
+
...axisProps('area', 'Saturation and brightness', `saturation ${Math.round(model.s * 100)}%, brightness ${Math.round(model.v * 100)}%`, model.s * 100, 100),
|
|
491
|
+
style: s.area,
|
|
466
492
|
...track('area', areaTo),
|
|
467
|
-
}, hx('canvas', {
|
|
493
|
+
}, framed('area', hx('canvas', {
|
|
468
494
|
style: s.pane,
|
|
469
495
|
// Everything the drawing reads: the hue, and the size, which is a
|
|
470
496
|
// constant here precisely so this key can name it.
|
|
@@ -485,7 +511,7 @@ export function ColorPicker(props) {
|
|
|
485
511
|
ctx.fillStyle = black;
|
|
486
512
|
ctx.fillRect(0, 0, width, height);
|
|
487
513
|
},
|
|
488
|
-
}), hx('box', {
|
|
514
|
+
})), hx('box', {
|
|
489
515
|
style: [
|
|
490
516
|
s.areaThumb,
|
|
491
517
|
{
|
|
@@ -499,17 +525,9 @@ export function ColorPicker(props) {
|
|
|
499
525
|
key: 'hue',
|
|
500
526
|
ref: hueRef,
|
|
501
527
|
...axisProps('hue', 'Hue', `hue ${Math.round(model.h)} degrees`, model.h, 360),
|
|
502
|
-
style:
|
|
503
|
-
s.strip,
|
|
504
|
-
{
|
|
505
|
-
borderWidth: theme.borderWidth,
|
|
506
|
-
borderColor: cursorShown && active === 'hue'
|
|
507
|
-
? theme.borderFocus
|
|
508
|
-
: theme.border,
|
|
509
|
-
},
|
|
510
|
-
],
|
|
528
|
+
style: s.strip,
|
|
511
529
|
...track('hue', hueTo),
|
|
512
|
-
}, hx('canvas', {
|
|
530
|
+
}, framed('hue', hx('canvas', {
|
|
513
531
|
style: s.pane,
|
|
514
532
|
cacheKey: `hue:${CONTENT}x${STRIP_H}`,
|
|
515
533
|
onDraw: (ctx, { width, height }) => {
|
|
@@ -520,7 +538,7 @@ export function ColorPicker(props) {
|
|
|
520
538
|
ctx.fillStyle = ramp;
|
|
521
539
|
ctx.fillRect(0, 0, width, height);
|
|
522
540
|
},
|
|
523
|
-
}), hx('box', {
|
|
541
|
+
})), hx('box', {
|
|
524
542
|
style: [
|
|
525
543
|
s.stripThumb,
|
|
526
544
|
{ left: (model.h / 360) * CONTENT - 4, backgroundColor: hue },
|
|
@@ -530,17 +548,9 @@ export function ColorPicker(props) {
|
|
|
530
548
|
key: 'alpha',
|
|
531
549
|
ref: alphaRef,
|
|
532
550
|
...axisProps('alpha', 'Opacity', `opacity ${Math.round(model.a * 100)}%`, model.a * 100, 100),
|
|
533
|
-
style:
|
|
534
|
-
s.strip,
|
|
535
|
-
{
|
|
536
|
-
borderWidth: theme.borderWidth,
|
|
537
|
-
borderColor: cursorShown && active === 'alpha'
|
|
538
|
-
? theme.borderFocus
|
|
539
|
-
: theme.border,
|
|
540
|
-
},
|
|
541
|
-
],
|
|
551
|
+
style: s.strip,
|
|
542
552
|
...track('alpha', alphaTo),
|
|
543
|
-
}, hx('canvas', {
|
|
553
|
+
}, framed('alpha', hx('canvas', {
|
|
544
554
|
style: s.pane,
|
|
545
555
|
cacheKey: `alpha:${opaqueHex(model)}:${CONTENT}x${STRIP_H}`,
|
|
546
556
|
onDraw: (ctx, { width, height }) => {
|
|
@@ -552,7 +562,7 @@ export function ColorPicker(props) {
|
|
|
552
562
|
ctx.fillStyle = ramp;
|
|
553
563
|
ctx.fillRect(0, 0, width, height);
|
|
554
564
|
},
|
|
555
|
-
}), hx('box', {
|
|
565
|
+
})), hx('box', {
|
|
556
566
|
style: [
|
|
557
567
|
s.stripThumb,
|
|
558
568
|
{ left: model.a * CONTENT - 4, backgroundColor: opaqueHex(model) },
|