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/menuitem.js
ADDED
|
@@ -0,0 +1,223 @@
|
|
|
1
|
+
// The menu item vocabulary, shared by the component that draws menus
|
|
2
|
+
// (`components/Menu.js`) and the one that hands them to the desktop
|
|
3
|
+
// (`dbusmenu.js`).
|
|
4
|
+
//
|
|
5
|
+
// ## Why the names are the desktop's names
|
|
6
|
+
//
|
|
7
|
+
// A `MenuBar` is either drawn by us or drawn by the panel, and the app is not
|
|
8
|
+
// told which — that is the whole point of the feature. So the descriptor has
|
|
9
|
+
// to be equally at home in both, and only one of the two ends gets a vote on
|
|
10
|
+
// what things are called: `com.canonical.dbusmenu` is a wire protocol with a
|
|
11
|
+
// published item vocabulary, and we are one of many exporters.
|
|
12
|
+
//
|
|
13
|
+
// Hence `type: 'separator'` rather than `separator: true`, `enabled: false`
|
|
14
|
+
// rather than `disabled: true`, `toggleType`/`toggleState` rather than a bare
|
|
15
|
+
// `checked`, and `shortcut` as dbusmenu's `aas` rather than a display string.
|
|
16
|
+
// Each one used to be the shape a drawn-only menu would pick; each one now
|
|
17
|
+
// serialises with no translation, which is what keeps `menus` a single
|
|
18
|
+
// authoring model instead of a drawn one and an exported one that drift.
|
|
19
|
+
//
|
|
20
|
+
// The one deliberate exception is `icon`, which stays a react-x11 callback and
|
|
21
|
+
// is **not** serialisable — see `gutterMark` in `components/Menu.js`. The
|
|
22
|
+
// desktop cannot call a function, so `iconName` and `iconData` are what cross
|
|
23
|
+
// the bus, and an item may carry both: the drawing for our own menu, the theme
|
|
24
|
+
// name for the panel's.
|
|
25
|
+
|
|
26
|
+
/** A rule instead of a row. dbusmenu's `type` property, whose only other legal value is `'standard'`. */
|
|
27
|
+
export const isSeparator = (item) => item?.type === 'separator';
|
|
28
|
+
|
|
29
|
+
/** dbusmenu defaults `enabled` and `visible` to true, so absent means yes. */
|
|
30
|
+
export const isEnabled = (item) => item?.enabled !== false;
|
|
31
|
+
export const isVisible = (item) => item?.visible !== false;
|
|
32
|
+
|
|
33
|
+
/** Can the selection land here? Separators and disabled rows cannot take it. */
|
|
34
|
+
export const isSelectable = (item) =>
|
|
35
|
+
Boolean(item) && !isSeparator(item) && isEnabled(item);
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* dbusmenu's `children-display: submenu` — a fact about the children, and
|
|
39
|
+
* about the **visible** ones: a parent whose every child is hidden opens onto
|
|
40
|
+
* nothing, so neither our chevron nor the panel's arrow should promise a
|
|
41
|
+
* submenu that is empty when it arrives.
|
|
42
|
+
*/
|
|
43
|
+
export const hasSubmenu = (item) => (item?.items ?? []).some(isVisible);
|
|
44
|
+
|
|
45
|
+
/** Rows the user can see. A hidden item is not laid out, not just not drawn. */
|
|
46
|
+
export const visibleItems = (items) => (items ?? []).filter(isVisible);
|
|
47
|
+
|
|
48
|
+
// --------------------------------------------------------------------------
|
|
49
|
+
// Shortcuts
|
|
50
|
+
// --------------------------------------------------------------------------
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* How dbusmenu spells the modifiers. The key token is whatever is left over
|
|
54
|
+
* after them, and it comes last.
|
|
55
|
+
*
|
|
56
|
+
* Exported because a chord is now matched as well as drawn (`accelerators.js`,
|
|
57
|
+
* issue #351), and a second copy of this set in the matcher would be a second
|
|
58
|
+
* answer to "is `Super` a modifier or a key called Super".
|
|
59
|
+
*/
|
|
60
|
+
export const MODIFIER_TOKENS = new Set(['Control', 'Alt', 'Shift', 'Super']);
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* One `aas` alternative split into what it means: the modifiers held down,
|
|
64
|
+
* in the order they were written, and the key it ends on (`null` for a chord
|
|
65
|
+
* that is nothing but modifiers, which is not a chord).
|
|
66
|
+
*
|
|
67
|
+
* The single reader of the token list — the row draws from it, the panel's
|
|
68
|
+
* announcement spells it, and the key path matches against it.
|
|
69
|
+
*/
|
|
70
|
+
export function splitChord(chord) {
|
|
71
|
+
const modifiers = new Set();
|
|
72
|
+
let key = null;
|
|
73
|
+
for (const token of chord ?? []) {
|
|
74
|
+
if (MODIFIER_TOKENS.has(token)) modifiers.add(token);
|
|
75
|
+
else key = token;
|
|
76
|
+
}
|
|
77
|
+
return { modifiers, key };
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
// What a person reads. `Control` is the wire spelling and `Ctrl` is the one
|
|
81
|
+
// every desktop puts in front of a user, which is the entire reason this map
|
|
82
|
+
// is not an identity.
|
|
83
|
+
const MODIFIER_LABELS = {
|
|
84
|
+
Control: 'Ctrl',
|
|
85
|
+
Alt: 'Alt',
|
|
86
|
+
Shift: 'Shift',
|
|
87
|
+
Super: 'Super',
|
|
88
|
+
};
|
|
89
|
+
|
|
90
|
+
// Keys whose name and whose printed form differ. libdbusmenu names a key the
|
|
91
|
+
// way GDK does — `gdk_keyval_name()`, so `plus` rather than `+` — and that is
|
|
92
|
+
// what a panel's importer expects to parse. It is not what a menu should
|
|
93
|
+
// print: `Ctrl+plus` is nobody's idea of a shortcut. Only the ones that
|
|
94
|
+
// actually read badly are here; `F1`, `Delete` and `Home` print themselves.
|
|
95
|
+
const KEY_LABELS = {
|
|
96
|
+
plus: '+',
|
|
97
|
+
minus: '-',
|
|
98
|
+
equal: '=',
|
|
99
|
+
comma: ',',
|
|
100
|
+
period: '.',
|
|
101
|
+
slash: '/',
|
|
102
|
+
backslash: '\\',
|
|
103
|
+
bracketleft: '[',
|
|
104
|
+
bracketright: ']',
|
|
105
|
+
semicolon: ';',
|
|
106
|
+
apostrophe: "'",
|
|
107
|
+
grave: '`',
|
|
108
|
+
space: 'Space',
|
|
109
|
+
Return: 'Enter',
|
|
110
|
+
BackSpace: 'Backspace',
|
|
111
|
+
Prior: 'PgUp',
|
|
112
|
+
Next: 'PgDn',
|
|
113
|
+
};
|
|
114
|
+
|
|
115
|
+
/**
|
|
116
|
+
* One `aas` alternative — `['Control', 'S']` — as the string a menu row
|
|
117
|
+
* shows: `Ctrl+S`.
|
|
118
|
+
*
|
|
119
|
+
* A single-character key is upper-cased because that is how every toolkit
|
|
120
|
+
* prints one, and because dbusmenu carries the *key*, not the character it
|
|
121
|
+
* types: `['Control', 's']` and `['Control', 'S']` are the same binding and
|
|
122
|
+
* must not render differently.
|
|
123
|
+
*/
|
|
124
|
+
function formatChord(chord) {
|
|
125
|
+
const { modifiers, key } = splitChord(chord);
|
|
126
|
+
const parts = [...modifiers].map((token) => MODIFIER_LABELS[token]);
|
|
127
|
+
if (key != null) {
|
|
128
|
+
parts.push(KEY_LABELS[key] ?? (key.length === 1 ? key.toUpperCase() : key));
|
|
129
|
+
}
|
|
130
|
+
return parts.join('+');
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
/**
|
|
134
|
+
* `item.shortcut` as the text drawn to the right of a label, or `''`.
|
|
135
|
+
*
|
|
136
|
+
* The prop is dbusmenu's `aas`: a list of **alternatives**, each a list of
|
|
137
|
+
* modifier tokens ending in the key. Only the first alternative is drawn —
|
|
138
|
+
* a row has one shortcut column, and a menu that printed `Ctrl+S / F2` in it
|
|
139
|
+
* would be wider than the menu for the benefit of the rarer binding.
|
|
140
|
+
*/
|
|
141
|
+
export function formatShortcut(shortcut) {
|
|
142
|
+
const first = shortcut?.[0];
|
|
143
|
+
if (!Array.isArray(first) || first.length === 0) return '';
|
|
144
|
+
return formatChord(first);
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
// What UI Events calls the modifiers, which is what `aria-keyshortcuts` is
|
|
148
|
+
// specified in terms of. Only `Super` differs from dbusmenu's spelling.
|
|
149
|
+
const ARIA_MODIFIERS = {
|
|
150
|
+
Control: 'Control',
|
|
151
|
+
Alt: 'Alt',
|
|
152
|
+
Shift: 'Shift',
|
|
153
|
+
Super: 'Meta',
|
|
154
|
+
};
|
|
155
|
+
|
|
156
|
+
/**
|
|
157
|
+
* `item.shortcut` as `aria-keyshortcuts`, or `undefined`.
|
|
158
|
+
*
|
|
159
|
+
* A space-delimited list of `+`-joined chords, which is exactly the shape
|
|
160
|
+
* dbusmenu's `aas` already has — so unlike the drawn menu, **every**
|
|
161
|
+
* alternative is announced rather than only the first: a screen reader is
|
|
162
|
+
* reading them out, not fitting them in a column.
|
|
163
|
+
*/
|
|
164
|
+
export function ariaKeyShortcuts(shortcut) {
|
|
165
|
+
if (!isValidShortcut(shortcut)) return undefined;
|
|
166
|
+
return shortcut
|
|
167
|
+
.map((chord) =>
|
|
168
|
+
chord
|
|
169
|
+
.map((token) =>
|
|
170
|
+
MODIFIER_TOKENS.has(token)
|
|
171
|
+
? ARIA_MODIFIERS[token]
|
|
172
|
+
: (KEY_LABELS[token] ?? token),
|
|
173
|
+
)
|
|
174
|
+
.join('+'),
|
|
175
|
+
)
|
|
176
|
+
.join(' ');
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
/**
|
|
180
|
+
* Is this a well-formed `aas`? Used by the development-time check below, and
|
|
181
|
+
* by the exporter, which must not put a malformed shortcut on the wire —
|
|
182
|
+
* dbus-native would throw mid-marshal, inside a method reply, where the
|
|
183
|
+
* failure surfaces as a panel with no menu rather than as an error here.
|
|
184
|
+
*/
|
|
185
|
+
export function isValidShortcut(shortcut) {
|
|
186
|
+
return (
|
|
187
|
+
Array.isArray(shortcut) &&
|
|
188
|
+
shortcut.length > 0 &&
|
|
189
|
+
shortcut.every(
|
|
190
|
+
(chord) =>
|
|
191
|
+
Array.isArray(chord) &&
|
|
192
|
+
chord.length > 0 &&
|
|
193
|
+
chord.every((token) => typeof token === 'string' && token.length > 0),
|
|
194
|
+
)
|
|
195
|
+
);
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
let warnedAboutShortcut = false;
|
|
199
|
+
|
|
200
|
+
/**
|
|
201
|
+
* The one shape mistake worth catching for the app author, because both of
|
|
202
|
+
* its failure modes are silent: `shortcut: 'Ctrl+S'` is a string, so
|
|
203
|
+
* `shortcut[0]` is `'C'` and the row draws `C` — and the exporter drops it,
|
|
204
|
+
* so the panel shows no shortcut at all and nothing anywhere says why.
|
|
205
|
+
*/
|
|
206
|
+
export function checkShortcut(item) {
|
|
207
|
+
if (process.env.NODE_ENV === 'production') return;
|
|
208
|
+
if (item?.shortcut == null || isValidShortcut(item.shortcut)) return;
|
|
209
|
+
if (warnedAboutShortcut) return;
|
|
210
|
+
warnedAboutShortcut = true;
|
|
211
|
+
console.warn(
|
|
212
|
+
`react-x11: a menu item's \`shortcut\` should be dbusmenu's \`aas\` — a ` +
|
|
213
|
+
'list of alternatives, each a list of modifier tokens ending in the ' +
|
|
214
|
+
`key — but ${JSON.stringify(item.shortcut)} is not one. Write:\n` +
|
|
215
|
+
" { label: 'Save', shortcut: [['Control', 'S']] }\n" +
|
|
216
|
+
'Modifier tokens are Control, Alt, Shift and Super.',
|
|
217
|
+
);
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
/** Test seam: the warning above fires once per process. */
|
|
221
|
+
export function _resetShortcutWarning() {
|
|
222
|
+
warnedAboutShortcut = false;
|
|
223
|
+
}
|