@fusion.dev/helix-headless 0.208.1 → 0.210.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/api.json +1 -1
- package/custom-elements.json +1 -1
- package/dist/canvas/root/canvas-root.d.ts +4 -1
- package/dist/element-events.generated.js +9 -0
- package/dist/graph/root/graph-root.d.ts +11 -10
- package/dist/graph/root/graph-root.js +8 -18
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/legend/root/legend-root.d.ts +9 -15
- package/dist/legend/root/legend-root.js +10 -20
- package/dist/map/root/map-root.d.ts +4 -2
- package/dist/map/root/map-root.js +1 -1
- package/dist/terminal/index.d.ts +3 -0
- package/dist/terminal/index.js +1 -0
- package/dist/terminal/keys.d.ts +14 -0
- package/dist/terminal/keys.js +20 -0
- package/dist/terminal/root/terminal-root.d.ts +489 -0
- package/dist/terminal/root/terminal-root.js +710 -0
- package/dist/toolbar/root/toolbar-root.d.ts +9 -78
- package/dist/toolbar/root/toolbar-root.js +10 -224
- package/examples.json +1 -1
- package/lint.json +1 -1
- package/package.json +5 -5
- package/types/jsx.d.ts +923 -10
- package/types/svelte.d.ts +1 -0
- package/types/vue.d.ts +223 -4
- package/types/words.d.ts +112 -0
|
@@ -50,6 +50,9 @@ declare const HelixHeadlessCanvas_base: (new (...args: any[]) => import("@fusion
|
|
|
50
50
|
* board, where the arrow keys pan it.
|
|
51
51
|
* - Plus and minus zoom the board, on the board and on a card or a
|
|
52
52
|
* connection.
|
|
53
|
+
* - The pan and zoom buttons are a toolbar and one tab stop. The arrow keys
|
|
54
|
+
* move between them by where they sit, Right from the up arrow to zoom in,
|
|
55
|
+
* and Enter or Space presses one.
|
|
53
56
|
* - The arrow keys move through the cards in reading order. The card you land
|
|
54
57
|
* on scrolls into view, and its connections are announced with it.
|
|
55
58
|
* - The card you land on is selected. Control or Command with an arrow key,
|
|
@@ -162,7 +165,7 @@ declare const HelixHeadlessCanvas_base: (new (...args: any[]) => import("@fusion
|
|
|
162
165
|
*
|
|
163
166
|
* @csspart arrow - The arrowhead at an end of a connection that has one.
|
|
164
167
|
* @csspart board - The plane the cards are placed on, which pans and zooms.
|
|
165
|
-
* @csspart controls - The
|
|
168
|
+
* @csspart controls - The toolbar the pan and zoom buttons sit in, one tab stop.
|
|
166
169
|
* @csspart draft - The connection being drawn, before `helix-connect` is sent.
|
|
167
170
|
* @csspart edge - One connector between two cards.
|
|
168
171
|
* @csspart edge-end - An end of a selected connection. Drag it, or click it to pick it up.
|
|
@@ -339,6 +339,15 @@ registerElementEvents({
|
|
|
339
339
|
'helix-headless-tabs': ['helix-activate', 'helix-before-activate', 'helix-select'],
|
|
340
340
|
'helix-headless-tag': ['helix-dismiss'],
|
|
341
341
|
'helix-headless-tag-group': ['change', 'helix-before-change', 'helix-dismiss'],
|
|
342
|
+
'helix-headless-terminal': [
|
|
343
|
+
'helix-copy',
|
|
344
|
+
'helix-terminal-bell',
|
|
345
|
+
'helix-terminal-input',
|
|
346
|
+
'helix-terminal-link',
|
|
347
|
+
'helix-terminal-resize',
|
|
348
|
+
'helix-terminal-restart',
|
|
349
|
+
'helix-terminal-title',
|
|
350
|
+
],
|
|
342
351
|
'helix-headless-textarea': ['change', 'helix-before-change', 'helix-clear', 'input'],
|
|
343
352
|
'helix-headless-time-input': [
|
|
344
353
|
'change',
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { type GraphSignalDetail, HelixElement,
|
|
1
|
+
import { type GraphSignalDetail, HelixElement, ToolbarController, type ViewportPanDetail, type ViewportZoomDetail } from '@fusion.dev/helix-core';
|
|
2
2
|
import { nothing, type PropertyValues, type TemplateResult } from 'lit';
|
|
3
3
|
import { type GraphLink, type GraphNode } from './graph-model.js';
|
|
4
4
|
declare const HelixHeadlessGraph_base: (new (...args: any[]) => import("@fusion.dev/helix-core").ViewportElement) & (new (...args: any[]) => import("@fusion.dev/helix-core").MixinControllerActiveInterface) & typeof HelixElement;
|
|
@@ -43,7 +43,9 @@ declare const HelixHeadlessGraph_base: (new (...args: any[]) => import("@fusion.
|
|
|
43
43
|
* or hides its notes. `hiddenGroups` holds the groups turned off, and the
|
|
44
44
|
* list holds only what the drawing shows. The legend is a toolbar and one tab
|
|
45
45
|
* stop: the arrow keys, Home, End and a group's first letters move between
|
|
46
|
-
* its buttons, and Space or Enter presses one.
|
|
46
|
+
* its buttons, and Space or Enter presses one. The pan and zoom buttons are
|
|
47
|
+
* a toolbar and one tab stop too, the arrow keys moving between them by where
|
|
48
|
+
* they sit on screen.
|
|
47
49
|
*
|
|
48
50
|
* `nodes` and `links` are properties, never markup: a graph of ten thousand
|
|
49
51
|
* notes as ten thousand elements would cost what the renderer exists to save.
|
|
@@ -86,7 +88,7 @@ declare const HelixHeadlessGraph_base: (new (...args: any[]) => import("@fusion.
|
|
|
86
88
|
* @csspart after - The room the notes after those drawn would take, so the list scrolls its whole length.
|
|
87
89
|
* @csspart before - The room the notes before those drawn would take.
|
|
88
90
|
* @csspart body - The drawing beside the list, or above it where the frame is narrow.
|
|
89
|
-
* @csspart controls - The
|
|
91
|
+
* @csspart controls - The toolbar the pan and zoom buttons sit in, one tab stop.
|
|
90
92
|
* @csspart count - How many notes the list holds, which a search narrows, at the end of the search bar.
|
|
91
93
|
* @csspart empty - The box in place of the list when it holds no notes, holding the `empty` slot.
|
|
92
94
|
* @csspart filter-icon - The icon beside the search field.
|
|
@@ -343,15 +345,14 @@ export declare class HelixHeadlessGraph extends HelixHeadlessGraph_base {
|
|
|
343
345
|
* and wrote `active` itself.
|
|
344
346
|
*/
|
|
345
347
|
private selectionAsked;
|
|
346
|
-
/** The legend's button that holds its one tab stop, by place: the one a reader was last on, or the first. */
|
|
347
|
-
private legendStop;
|
|
348
348
|
/**
|
|
349
|
-
* The arrow keys, Home, End and typed
|
|
350
|
-
* so a legend of twelve groups is one tab stop, as
|
|
351
|
-
* toolbar is. Only a press that starts on a legend
|
|
352
|
-
* own arrows pan the drawing, and the list's walk
|
|
349
|
+
* The legend's buttons as one tab stop: the arrow keys, Home, End and typed
|
|
350
|
+
* letters move among them, so a legend of twelve groups is one tab stop, as
|
|
351
|
+
* the `Legend` family's toolbar is. Only a press that starts on a legend
|
|
352
|
+
* button moves: the frame's own arrows pan the drawing, and the list's walk
|
|
353
|
+
* the notes. Both axes, the buttons wrapping onto more lines.
|
|
353
354
|
*/
|
|
354
|
-
protected readonly legendKeys:
|
|
355
|
+
protected readonly legendKeys: ToolbarController;
|
|
355
356
|
private readonly virtualize;
|
|
356
357
|
/**
|
|
357
358
|
* @internal The notes the drawing shows, which `connectGraph` reads: those
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { __decorate } from "tslib";
|
|
2
|
-
import { auditName, customElement,
|
|
2
|
+
import { auditName, customElement, formatWords, HelixElement, HelixGraphFilterEvent, HelixGraphLayoutEvent, HelixGraphPanEvent, HelixGraphPartChangeEvent, HelixGraphReadyEvent, HelixGraphSignalEvent, HelixGraphZoomEvent, isRtl, MixinControllerActive, MixinViewport, numberConverter, SCROLLER_RULE, scrollRoom, scrollWithin, ToolbarController, Typeahead, VIRTUAL_RULE, VirtualizeController, words, wordsLocale, } from '@fusion.dev/helix-core';
|
|
3
3
|
import { list, magnifyingGlass } from '@fusion.dev/helix-icons';
|
|
4
4
|
import { html, nothing } from 'lit';
|
|
5
5
|
import { property, state } from 'lit/decorators.js';
|
|
@@ -59,14 +59,12 @@ let HelixHeadlessGraph = class HelixHeadlessGraph extends MixinViewport(MixinCon
|
|
|
59
59
|
this.whole = false;
|
|
60
60
|
this.said = '';
|
|
61
61
|
this.countAsked = false;
|
|
62
|
-
this.
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
selects: () => false,
|
|
69
|
-
typeahead: typeaheadBy((item) => item.words ?? ''),
|
|
62
|
+
this.legendKeys = new ToolbarController(this, {
|
|
63
|
+
arrows: () => 'both',
|
|
64
|
+
members: () => [...(this.partNamed('legend')?.children ?? [])],
|
|
65
|
+
own: true,
|
|
66
|
+
watch: () => this.renderRoot,
|
|
67
|
+
words: (button) => button.textContent?.trim() ?? '',
|
|
70
68
|
});
|
|
71
69
|
this.virtualize = new VirtualizeController(this, {
|
|
72
70
|
container: () => this.partNamed('list'),
|
|
@@ -373,20 +371,15 @@ let HelixHeadlessGraph = class HelixHeadlessGraph extends MixinViewport(MixinCon
|
|
|
373
371
|
return nothing;
|
|
374
372
|
}
|
|
375
373
|
const hidden = new Set(this.hiddenGroups);
|
|
376
|
-
const stop = Math.min(this.legendStop, this.groups.length - 1);
|
|
377
374
|
return html `<div part="legend" role="toolbar" aria-label=${this.legendLabel}>
|
|
378
|
-
${this.groups.map(({ name, tone }
|
|
375
|
+
${this.groups.map(({ name, tone }) => {
|
|
379
376
|
const shown = !hidden.has(name);
|
|
380
377
|
return html `<button
|
|
381
378
|
part="legend-item${shown ? '' : ' legend-item-hidden'}"
|
|
382
379
|
type="button"
|
|
383
|
-
tabindex=${index === stop ? '0' : '-1'}
|
|
384
380
|
aria-pressed=${shown ? 'true' : 'false'}
|
|
385
381
|
data-tone=${tone ?? nothing}
|
|
386
382
|
@click=${() => this.toggleGroup(name)}
|
|
387
|
-
@focus=${() => {
|
|
388
|
-
this.legendStop = index;
|
|
389
|
-
}}
|
|
390
383
|
>
|
|
391
384
|
<span part="legend-swatch" aria-hidden="true"></span>${name}
|
|
392
385
|
</button>`;
|
|
@@ -882,9 +875,6 @@ __decorate([
|
|
|
882
875
|
__decorate([
|
|
883
876
|
state()
|
|
884
877
|
], HelixHeadlessGraph.prototype, "said", void 0);
|
|
885
|
-
__decorate([
|
|
886
|
-
state()
|
|
887
|
-
], HelixHeadlessGraph.prototype, "legendStop", void 0);
|
|
888
878
|
HelixHeadlessGraph = __decorate([
|
|
889
879
|
customElement('helix-headless-graph')
|
|
890
880
|
], HelixHeadlessGraph);
|
package/dist/index.d.ts
CHANGED
|
@@ -103,6 +103,7 @@ export * from './switch/index.js';
|
|
|
103
103
|
export * from './table/index.js';
|
|
104
104
|
export * from './tabs/index.js';
|
|
105
105
|
export * from './tag/index.js';
|
|
106
|
+
export * from './terminal/index.js';
|
|
106
107
|
export * from './textarea/index.js';
|
|
107
108
|
export * from './time-input/index.js';
|
|
108
109
|
export * from './time-picker/index.js';
|
package/dist/index.js
CHANGED
|
@@ -94,6 +94,7 @@ export * from './switch/index.js';
|
|
|
94
94
|
export * from './table/index.js';
|
|
95
95
|
export * from './tabs/index.js';
|
|
96
96
|
export * from './tag/index.js';
|
|
97
|
+
export * from './terminal/index.js';
|
|
97
98
|
export * from './textarea/index.js';
|
|
98
99
|
export * from './time-input/index.js';
|
|
99
100
|
export * from './time-picker/index.js';
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { HelixElement,
|
|
1
|
+
import { HelixElement, SourceController, ToolbarController } from '@fusion.dev/helix-core';
|
|
2
2
|
import { nothing, type PropertyValues, type TemplateResult } from 'lit';
|
|
3
3
|
/**
|
|
4
4
|
* @summary A list of the series in a chart, each name beside the color it is drawn in.
|
|
@@ -108,17 +108,12 @@ export declare class HelixHeadlessLegend extends HelixElement {
|
|
|
108
108
|
toggles: boolean;
|
|
109
109
|
protected readonly source: SourceController;
|
|
110
110
|
/**
|
|
111
|
-
* The
|
|
112
|
-
*
|
|
111
|
+
* The toggles as one tab stop: the arrow keys, Home, End and typed letters
|
|
112
|
+
* move among them, so a legend of twelve series is one tab stop, as a
|
|
113
|
+
* toolbar of toggle buttons is. Both axes, the entries wrapping onto more
|
|
114
|
+
* lines. Nothing without `toggles`, where there is nothing to press.
|
|
113
115
|
*/
|
|
114
|
-
|
|
115
|
-
/**
|
|
116
|
-
* The arrow keys, Home, End and typed letters among the toggles, so a
|
|
117
|
-
* legend of twelve series is one tab stop, as a toolbar of
|
|
118
|
-
* toggle buttons is. Nothing without `toggles`, where there is nothing to
|
|
119
|
-
* press.
|
|
120
|
-
*/
|
|
121
|
-
protected readonly keys: KeyboardNavigationController;
|
|
116
|
+
protected readonly keys: ToolbarController;
|
|
122
117
|
/** The table this legend last wrote its `hidden-series` to, so leaving undoes it. */
|
|
123
118
|
private wroteTo;
|
|
124
119
|
/** Whether this update writes `hidden-series` to the table, decided before the render. */
|
|
@@ -198,11 +193,10 @@ export declare class HelixHeadlessLegend extends HelixElement {
|
|
|
198
193
|
* The button around a name under `toggles`, behind a seam a tier can move.
|
|
199
194
|
*
|
|
200
195
|
* Pressed while its series is shown, which is the state a reader changes by
|
|
201
|
-
* pressing it: a toggle button says whether its thing is on.
|
|
202
|
-
*
|
|
203
|
-
* the toggle at `index`.
|
|
196
|
+
* pressing it: a toggle button says whether its thing is on. Which toggle
|
|
197
|
+
* holds the one tab stop is `keys`'s to say, so the button names none.
|
|
204
198
|
*/
|
|
205
|
-
protected renderToggle(name: string, off: boolean, index?: number
|
|
199
|
+
protected renderToggle(name: string, off: boolean, index?: number): TemplateResult;
|
|
206
200
|
}
|
|
207
201
|
declare global {
|
|
208
202
|
interface HTMLElementTagNameMap {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { __decorate } from "tslib";
|
|
2
|
-
import { customElement,
|
|
2
|
+
import { customElement, HelixElement, requestValue, SourceController, seriesIndex, seriesKey, ToolbarController, } from '@fusion.dev/helix-core';
|
|
3
3
|
import { html, nothing } from 'lit';
|
|
4
|
-
import { property
|
|
4
|
+
import { property } from 'lit/decorators.js';
|
|
5
5
|
import { isHidden, namesIn, toggledNames } from '../hidden-series.js';
|
|
6
6
|
let HelixHeadlessLegend = class HelixHeadlessLegend extends HelixElement {
|
|
7
7
|
constructor() {
|
|
@@ -11,14 +11,12 @@ let HelixHeadlessLegend = class HelixHeadlessLegend extends HelixElement {
|
|
|
11
11
|
this.label = '';
|
|
12
12
|
this.toggles = false;
|
|
13
13
|
this.source = new SourceController(this);
|
|
14
|
-
this.
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
selects: () => false,
|
|
21
|
-
typeahead: typeaheadBy((item) => item.words ?? ''),
|
|
14
|
+
this.keys = new ToolbarController(this, {
|
|
15
|
+
arrows: () => 'both',
|
|
16
|
+
members: () => (this.toggles ? [...(this.partNamed('list')?.children ?? [])] : []),
|
|
17
|
+
own: true,
|
|
18
|
+
watch: () => this.renderRoot,
|
|
19
|
+
words: (button) => button.textContent?.trim() ?? '',
|
|
22
20
|
});
|
|
23
21
|
this.wroteTo = null;
|
|
24
22
|
this.writes = false;
|
|
@@ -75,7 +73,6 @@ let HelixHeadlessLegend = class HelixHeadlessLegend extends HelixElement {
|
|
|
75
73
|
render() {
|
|
76
74
|
const named = this.label || this.source.element?.querySelector('caption')?.textContent?.trim();
|
|
77
75
|
const names = this.names();
|
|
78
|
-
const stop = Math.min(this.stop, names.length - 1);
|
|
79
76
|
const toolbar = this.toggles;
|
|
80
77
|
return html `<ul
|
|
81
78
|
aria-label=${named || nothing}
|
|
@@ -90,7 +87,7 @@ let HelixHeadlessLegend = class HelixHeadlessLegend extends HelixElement {
|
|
|
90
87
|
style="--chart-series: var(--chart-series-${seriesIndex(index)})"
|
|
91
88
|
role=${toolbar ? 'none' : 'listitem'}
|
|
92
89
|
>
|
|
93
|
-
${this.renderSwatch(name, index)}${toolbar ? this.renderToggle(name, off, index
|
|
90
|
+
${this.renderSwatch(name, index)}${toolbar ? this.renderToggle(name, off, index) : this.renderName(name, index)}
|
|
94
91
|
</li>`;
|
|
95
92
|
})}
|
|
96
93
|
</ul>`;
|
|
@@ -101,16 +98,12 @@ let HelixHeadlessLegend = class HelixHeadlessLegend extends HelixElement {
|
|
|
101
98
|
renderName(name, _index) {
|
|
102
99
|
return html `<span part="name">${name}</span>`;
|
|
103
100
|
}
|
|
104
|
-
renderToggle(name, off, index = 0
|
|
101
|
+
renderToggle(name, off, index = 0) {
|
|
105
102
|
return html `<button
|
|
106
103
|
aria-pressed=${off ? 'false' : 'true'}
|
|
107
104
|
part="toggle"
|
|
108
|
-
tabindex=${holds ? '0' : '-1'}
|
|
109
105
|
type="button"
|
|
110
106
|
@click=${() => this.toggle(name)}
|
|
111
|
-
@focus=${() => {
|
|
112
|
-
this.stop = index;
|
|
113
|
-
}}
|
|
114
107
|
>
|
|
115
108
|
${this.renderName(name, index)}
|
|
116
109
|
</button>`;
|
|
@@ -131,9 +124,6 @@ __decorate([
|
|
|
131
124
|
__decorate([
|
|
132
125
|
property({ reflect: true, type: Boolean })
|
|
133
126
|
], HelixHeadlessLegend.prototype, "toggles", void 0);
|
|
134
|
-
__decorate([
|
|
135
|
-
state()
|
|
136
|
-
], HelixHeadlessLegend.prototype, "stop", void 0);
|
|
137
127
|
HelixHeadlessLegend = __decorate([
|
|
138
128
|
customElement('helix-headless-legend')
|
|
139
129
|
], HelixHeadlessLegend);
|
|
@@ -27,7 +27,9 @@ declare const HelixHeadlessMap_base: (new (...args: any[]) => import("@fusion.de
|
|
|
27
27
|
* map. Dragging is otherwise the only way a pointer moves the map, so add them
|
|
28
28
|
* where the map has to be usable without dragging, as WCAG 2.2 asks at level
|
|
29
29
|
* AA. The arrow keys pan the map and Shift with Left or Right turns it either
|
|
30
|
-
* way.
|
|
30
|
+
* way. The buttons are a toolbar and one tab stop: on them, the arrow keys
|
|
31
|
+
* move between the buttons by where they sit, and Shift with an arrow still
|
|
32
|
+
* turns or tilts the map.
|
|
31
33
|
*
|
|
32
34
|
* The pan and zoom buttons and the arrow keys send `helix-map-pan` and
|
|
33
35
|
* `helix-map-zoom`. Move your map in response, or connect it with
|
|
@@ -98,7 +100,7 @@ declare const HelixHeadlessMap_base: (new (...args: any[]) => import("@fusion.de
|
|
|
98
100
|
*
|
|
99
101
|
* @csspart attribution - The strip under the map that holds the credit.
|
|
100
102
|
* @csspart compass - The compass and the pan and rotate buttons around it.
|
|
101
|
-
* @csspart controls - The column of buttons that move the map.
|
|
103
|
+
* @csspart controls - The column of buttons that move the map, a toolbar and one tab stop.
|
|
102
104
|
* @csspart face-north - The compass: its needle points north as the map turns, and pressing it turns the map to face north.
|
|
103
105
|
* @csspart footer - The strip below the map.
|
|
104
106
|
* @csspart fullscreen - The button that makes the map fill the screen.
|
|
@@ -525,7 +525,7 @@ let HelixHeadlessMap = class HelixHeadlessMap extends MixinViewport(HelixElement
|
|
|
525
525
|
if (!pan && !zoom && !rotate && !tilt && !fullscreen && menu === nothing) {
|
|
526
526
|
return nothing;
|
|
527
527
|
}
|
|
528
|
-
return html `<div part="controls" role="
|
|
528
|
+
return html `<div part="controls" role="toolbar" aria-label=${this.controlsLabel}>
|
|
529
529
|
${fullscreen
|
|
530
530
|
? html `<button
|
|
531
531
|
part="fullscreen"
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { HelixHeadlessTerminal } from './root/terminal-root.js';
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { type ChordPress } from '@fusion.dev/helix-core';
|
|
2
|
+
/** What a terminal frame does with a key press before the program sees it. */
|
|
3
|
+
export type TerminalShortcut = 'copy' | 'find' | 'tab-focus';
|
|
4
|
+
/** The chord for a shortcut on this keyboard, or `undefined` where the frame takes none. */
|
|
5
|
+
export declare const chordOf: (shortcut: TerminalShortcut, apple: boolean) => string | undefined;
|
|
6
|
+
/** Which shortcut a press is, or `null` for a press the program should have. */
|
|
7
|
+
export declare const shortcutOf: (press: ChordPress, apple: boolean) => TerminalShortcut | null;
|
|
8
|
+
/**
|
|
9
|
+
* A chord as a reader says it, such as "Control+Shift+M": the key names
|
|
10
|
+
* `aria-keyshortcuts` uses, which a screen reader reads aloud whole.
|
|
11
|
+
*/
|
|
12
|
+
export declare const spokenChord: (shortcut: TerminalShortcut, apple: boolean) => string;
|
|
13
|
+
/** Whether a press is a bare Tab or Shift+Tab, which moves focus while Tab is set to. */
|
|
14
|
+
export declare const isTab: (press: ChordPress) => boolean;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { ariaChord, matchesChord } from '@fusion.dev/helix-core';
|
|
2
|
+
const CHORDS = {
|
|
3
|
+
apple: { copy: undefined, find: 'cmd+f', 'tab-focus': 'ctrl+shift+m' },
|
|
4
|
+
other: { copy: 'ctrl+shift+c', find: 'ctrl+shift+f', 'tab-focus': 'ctrl+m' },
|
|
5
|
+
};
|
|
6
|
+
export const chordOf = (shortcut, apple) => CHORDS[apple ? 'apple' : 'other'][shortcut];
|
|
7
|
+
export const shortcutOf = (press, apple) => {
|
|
8
|
+
for (const shortcut of ['copy', 'find', 'tab-focus']) {
|
|
9
|
+
const chord = chordOf(shortcut, apple);
|
|
10
|
+
if (chord !== undefined && matchesChord(press, chord, apple)) {
|
|
11
|
+
return shortcut;
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
return null;
|
|
15
|
+
};
|
|
16
|
+
export const spokenChord = (shortcut, apple) => {
|
|
17
|
+
const chord = chordOf(shortcut, apple);
|
|
18
|
+
return chord === undefined ? '' : ariaChord(chord, apple).replace('Meta', 'Command');
|
|
19
|
+
};
|
|
20
|
+
export const isTab = (press) => press.key === 'Tab' && !press.altKey && !press.ctrlKey && !press.metaKey;
|