@fusion.dev/helix-headless 0.177.2 → 0.179.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.
@@ -20,6 +20,23 @@ declare const HelixHeadlessGraph_base: (new (...args: any[]) => import("@fusion.
20
20
  * Set `depth` to show the local graph: only the notes within that many links
21
21
  * of the selected one.
22
22
  *
23
+ * The search field is a combobox over the list. Down and Up move through the
24
+ * notes while the focus stays in the field, and Enter selects one.
25
+ *
26
+ * **Walk the links with Alt and the arrow keys**, in the list or in the
27
+ * search field once its keys are on a note. The note the keys are on is
28
+ * marked in the drawing.
29
+ *
30
+ * | Key | What it does |
31
+ * |---|---|
32
+ * | Alt+Right | Follows a link, to the first note the one the keys are on links to or from. |
33
+ * | Alt+Down, Alt+Up | Moves to the next or the previous note linked to the one the step came from, wrapping. |
34
+ * | Alt+Left | Goes back along the links walked. |
35
+ *
36
+ * Right and Left swap on a right-to-left page. Each step says the note, how it
37
+ * stands to the note it came from, and its place among that note's links,
38
+ * such as "Hiring plan. Linked from Roadmap. 2 of 3". Enter selects the note.
39
+ *
23
40
  * Set `legend` to name the groups over the drawing, each a button that shows
24
41
  * or hides its notes. `hiddenGroups` holds the groups turned off, and the
25
42
  * list holds only what the drawing shows. The legend is a toolbar and one tab
@@ -59,7 +76,7 @@ declare const HelixHeadlessGraph_base: (new (...args: any[]) => import("@fusion.
59
76
  * @event {HelixGraphFilterEvent} helix-graph-filter - A group in the legend was pressed, to show or hide its notes. The detail's `hidden` is every group that would be hidden. Cancelable: cancel it to keep the groups as they were, or to set `hiddenGroups` yourself.
60
77
  * @event {HelixGraphLayoutEvent} helix-graph-layout - A layout settled, with where it put each note, sent by `laidOut()`. Keep the positions and pass them back as each note's `x` and `y`, and `z` where a renderer draws in three dimensions.
61
78
  * @event {HelixGraphPanEvent} helix-graph-pan - A pan button or arrow key was pressed. `connectGraph` moves the drawing, then calls `moved()`.
62
- * @event {HelixGraphPartChangeEvent} helix-graph-part-change - The notes, the links, the selection, the depth or the gestures changed. Used by `connectGraph`; pages do not need to listen for it.
79
+ * @event {HelixGraphPartChangeEvent} helix-graph-part-change - The notes, the links, the selection, the depth, the note the keys are on, or the gestures changed. Used by `connectGraph`; pages do not need to listen for it.
63
80
  * @event {HelixGraphReadyEvent} helix-graph-ready - The graph has been drawn whole, laid out and settled. Sent each time `drawn()` says it is drawn after it was not.
64
81
  * @event {HelixGraphSignalEvent} helix-graph-signal - Something passed between two notes, sent by `signal()`. Used by `connectGraph`; pages do not need to listen for it.
65
82
  * @event {HelixGraphZoomEvent} helix-graph-zoom - A zoom button or key was pressed. `connectGraph` zooms the drawing, then calls `moved()`.
@@ -166,6 +183,12 @@ export declare class HelixHeadlessGraph extends HelixHeadlessGraph_base {
166
183
  legend: boolean;
167
184
  /** The legend's name, read by screen readers. */
168
185
  legendLabel: string;
186
+ /**
187
+ * What screen readers hear when a walk along the links reaches a note that
188
+ * has no link to follow, or goes back to a note: `{note}` for its name and
189
+ * `{count}` for how many notes the list holds that it links to or from.
190
+ */
191
+ linkCountLabel: string;
169
192
  /** How a note linked both to and from the selected one is described, with `{note}`. */
170
193
  linkedBothLabel: string;
171
194
  /** How a note the selected one links to is described, with `{note}`, the selected note's name. */
@@ -231,6 +254,13 @@ export declare class HelixHeadlessGraph extends HelixHeadlessGraph_base {
231
254
  twoFingerHintLabel: string;
232
255
  /** The line shown while the graph, with `gestures="activate"`, has the gestures. */
233
256
  usingLabel: string;
257
+ /**
258
+ * What screen readers hear when a walk along the links moves to a note:
259
+ * `{note}` for its name, `{relation}` for how it stands to the note the
260
+ * step came from, such as "Linked from Roadmap", and `{index}` and `{count}`
261
+ * for its place among that note's links.
262
+ */
263
+ walkLabel: string;
234
264
  /**
235
265
  * The hint shown when the wheel scrolls past the graph with
236
266
  * `gestures="cooperative"`. `{key}` is ⌘ on a Mac and Ctrl elsewhere.
@@ -246,6 +276,22 @@ export declare class HelixHeadlessGraph extends HelixHeadlessGraph_base {
246
276
  private cursor;
247
277
  /** Whether the search and the list are open over the drawing, with `no-panel`. */
248
278
  private panelOpen;
279
+ /**
280
+ * Whether the search field's arrow keys have moved onto a note, which the
281
+ * field then names as its `aria-activedescendant` while the focus stays in
282
+ * it. Typing, Left, Right, Escape, and leaving the field let it go.
283
+ */
284
+ private fieldKeys;
285
+ /** Whether the list has the focus, so the drawing marks the note its keys are on. */
286
+ private listKeys;
287
+ /**
288
+ * The notes a walk along the links stepped from, by `id`, the last the one
289
+ * the note the keys are on was reached from. Empty when the keys moved some
290
+ * other way.
291
+ */
292
+ private trail;
293
+ /** The note the drawing last heard the keys are on, so it hears each move once. */
294
+ private keyedSent;
249
295
  /** Which notes link to and from each, read again when `links` changes. */
250
296
  private adjacency;
251
297
  /** The notes in the order of their names, read again when `nodes` changes. */
@@ -292,6 +338,18 @@ export declare class HelixHeadlessGraph extends HelixHeadlessGraph_base {
292
338
  * within `depth` of the selected note, or `undefined` for every note.
293
339
  */
294
340
  get shown(): ReadonlySet<string> | undefined;
341
+ /**
342
+ * @internal The note the keys are on, while the list or the search field
343
+ * has them, which `connectGraph` marks in the drawing as it marks the note
344
+ * under the pointer. `walked` is true where a walk along the links reached
345
+ * it, which brings it into view.
346
+ */
347
+ get keyed(): {
348
+ id: string;
349
+ walked: boolean;
350
+ } | undefined;
351
+ /** The `id` of the note the keys are on, or `undefined` where neither the list nor the field has them. */
352
+ private keyedId;
295
353
  /** Whether the graph has been drawn whole. For code that runs after `helix-graph-ready`. */
296
354
  get ready(): boolean;
297
355
  /**
@@ -404,6 +462,33 @@ export declare class HelixHeadlessGraph extends HelixHeadlessGraph_base {
404
462
  * together, and a repeated letter steps through the names that start with it.
405
463
  */
406
464
  private typeahead;
465
+ /**
466
+ * The rows of the notes `id` links to or is linked from, in the list's
467
+ * order, which is the order of their names. Only the notes the list holds:
468
+ * a search, the legend, or `depth` leaves the others out.
469
+ */
470
+ private linkedRows;
471
+ /** How the note `id` stands to the note `from`, in the words the list uses for the selection. */
472
+ private relationFrom;
473
+ /**
474
+ * A walk along the links from the note the keys are on, with Alt and the
475
+ * arrow keys, so a reader follows the lines of the drawing and not only
476
+ * the order of the list. **The same four keys a tree takes**, with Alt,
477
+ * since the list's own arrows already move through it:
478
+ *
479
+ * - Alt+Right follows a link, to the first note the one the keys are on
480
+ * links to or from.
481
+ * - Alt+Down and Alt+Up move to the next and the previous note linked to
482
+ * the one the step came from, wrapping.
483
+ * - Alt+Left goes back along the links walked.
484
+ *
485
+ * Right and Left swap on a right-to-left page. Each step says the note, how
486
+ * it stands to the note it was reached from, and its place among that
487
+ * note's links. Returns whether the key was one of the walk's.
488
+ */
489
+ private walk;
490
+ /** Says the note at row `at` and how many notes in the list it links to or from. */
491
+ private sayLinks;
407
492
  /**
408
493
  * How many rows Page Down and Page Up move: the rows that fit in the list's
409
494
  * box, or in the window where the list does not scroll, less one, so the
@@ -412,10 +497,22 @@ export declare class HelixHeadlessGraph extends HelixHeadlessGraph_base {
412
497
  private pageRows;
413
498
  /**
414
499
  * The search field's keys, which belong to the field and never pan the
415
- * graph. Escape empties a search that has words in it, and passes through
416
- * an empty one to whatever the page does with it.
500
+ * graph.
501
+ *
502
+ * **The field is a combobox over the list**, as React Aria's Autocomplete
503
+ * and the APG combobox are: the focus stays in the field, and Down and Up
504
+ * move the keys through the notes, which the field names as its
505
+ * `aria-activedescendant`. Down starts on the note the keys were last on,
506
+ * the first after a search, and Up on the last. Page Down and Page Up move
507
+ * a page, Enter selects, Alt and the arrows walk the links as in the list,
508
+ * and Left, Right, Home and End go back to the text.
509
+ *
510
+ * Escape lets the note go, then empties a search that has words in it, and
511
+ * passes through an empty one to whatever the page does with it.
417
512
  */
418
513
  private readonly handleSearchKeydown;
514
+ /** Leaving the field lets go of the note its keys were on. */
515
+ private readonly handleSearchBlur;
419
516
  /**
420
517
  * Opens the search and the list over the drawing, or closes them, with
421
518
  * `no-panel`. **Opened, the search field takes the focus**, since finding
@@ -430,6 +527,7 @@ export declare class HelixHeadlessGraph extends HelixHeadlessGraph_base {
430
527
  * the controls after zoom, where the frame leaves them out with `no-panel`.
431
528
  */
432
529
  protected renderMoreControls(): TemplateResult | typeof nothing;
530
+ /** Typing is a new search, read from its top, with no note under the keys until Down. */
433
531
  private readonly handleSearch;
434
532
  /**
435
533
  * The mark in the search field, behind a seam: a slot for the page, and a
@@ -4,7 +4,7 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
4
4
  else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
5
5
  return c > 3 && r && Object.defineProperty(target, key, r), r;
6
6
  };
7
- import { auditName, customElement, focusItemOf, formatWords, HelixElement, HelixGraphFilterEvent, HelixGraphLayoutEvent, HelixGraphPanEvent, HelixGraphPartChangeEvent, HelixGraphReadyEvent, HelixGraphSignalEvent, HelixGraphZoomEvent, KeyboardNavigationController, MixinControllerActive, MixinViewport, scrollItemIntoView, scrollRoom, Typeahead, typeaheadBy, VirtualizeController, words, wordsLocale, } from '@fusion.dev/helix-core';
7
+ import { auditName, customElement, focusItemOf, formatWords, HelixElement, HelixGraphFilterEvent, HelixGraphLayoutEvent, HelixGraphPanEvent, HelixGraphPartChangeEvent, HelixGraphReadyEvent, HelixGraphSignalEvent, HelixGraphZoomEvent, isRtl, KeyboardNavigationController, MixinControllerActive, MixinViewport, scrollItemIntoView, scrollRoom, Typeahead, typeaheadBy, VirtualizeController, words, wordsLocale, } from '@fusion.dev/helix-core';
8
8
  import { list, magnifyingGlass } from '@fusion.dev/helix-icons';
9
9
  import { html, nothing } from 'lit';
10
10
  import { property, state } from 'lit/decorators.js';
@@ -23,6 +23,7 @@ let HelixHeadlessGraph = class HelixHeadlessGraph extends MixinViewport(MixinCon
23
23
  this.label = '';
24
24
  this.legend = false;
25
25
  this.legendLabel = 'Groups';
26
+ this.linkCountLabel = '{note}. {count, plural, =0 {No links} one {# link} other {# links}}';
26
27
  this.linkedBothLabel = 'Linked both ways with {note}';
27
28
  this.linkedFromLabel = 'Linked from {note}';
28
29
  this.links = [];
@@ -42,12 +43,16 @@ let HelixHeadlessGraph = class HelixHeadlessGraph extends MixinViewport(MixinCon
42
43
  this.selectionLabel = '{note}, selected. {count}';
43
44
  this.twoFingerHintLabel = 'Use two fingers to move the graph';
44
45
  this.usingLabel = 'Using the graph. Press Escape to scroll the page again.';
46
+ this.walkLabel = '{note}. {relation}. {index} of {count}';
45
47
  this.wheelHintLabel = 'Use {key} and scroll to zoom the graph';
46
48
  this.zoomedInLabel = 'Zoomed in';
47
49
  this.zoomedOutLabel = 'Zoomed out';
48
50
  this.query = '';
49
51
  this.cursor = 0;
50
52
  this.panelOpen = false;
53
+ this.fieldKeys = false;
54
+ this.listKeys = false;
55
+ this.trail = [];
51
56
  this.adjacency = new Map();
52
57
  this.sorted = [];
53
58
  this.entries = [];
@@ -74,6 +79,9 @@ let HelixHeadlessGraph = class HelixHeadlessGraph extends MixinViewport(MixinCon
74
79
  })),
75
80
  });
76
81
  this.handleListKeydown = (event) => {
82
+ if (this.walk(event)) {
83
+ return;
84
+ }
77
85
  const moves = {
78
86
  ArrowDown: this.cursor + 1,
79
87
  ArrowUp: this.cursor - 1,
@@ -102,19 +110,51 @@ let HelixHeadlessGraph = class HelixHeadlessGraph extends MixinViewport(MixinCon
102
110
  };
103
111
  this.typed = new Typeahead();
104
112
  this.handleSearchKeydown = (event) => {
105
- if (event.key === 'ArrowDown') {
113
+ if (event.isComposing) {
114
+ return;
115
+ }
116
+ if (this.fieldKeys && this.walk(event)) {
117
+ return;
118
+ }
119
+ const last = this.entries.length - 1;
120
+ const moves = this.fieldKeys
121
+ ? {
122
+ ArrowDown: this.cursor + 1,
123
+ ArrowUp: this.cursor - 1,
124
+ PageDown: this.cursor + this.pageRows(),
125
+ PageUp: this.cursor - this.pageRows(),
126
+ }
127
+ : { ArrowDown: this.cursor, ArrowUp: last };
128
+ if (event.key in moves && !event.altKey && last >= 0) {
106
129
  event.preventDefault();
107
- this.partNamed('list')?.focus();
130
+ this.fieldKeys = true;
131
+ this.moveTo(moves[event.key]);
132
+ }
133
+ else if (event.key === 'Enter' && this.fieldKeys) {
134
+ event.preventDefault();
135
+ this.choose(this.cursor);
108
136
  }
109
- if (event.key === 'Escape') {
110
- if (this.query === '') {
137
+ else if (event.key === 'Escape') {
138
+ if (this.fieldKeys) {
139
+ event.preventDefault();
140
+ this.fieldKeys = false;
141
+ }
142
+ else if (this.query === '') {
111
143
  return;
112
144
  }
113
- event.preventDefault();
114
- this.query = '';
145
+ else {
146
+ event.preventDefault();
147
+ this.query = '';
148
+ }
149
+ }
150
+ else if (['ArrowLeft', 'ArrowRight', 'End', 'Home'].includes(event.key)) {
151
+ this.fieldKeys = false;
115
152
  }
116
153
  event.stopPropagation();
117
154
  };
155
+ this.handleSearchBlur = () => {
156
+ this.fieldKeys = false;
157
+ };
118
158
  this.handlePanelKeydown = (event) => {
119
159
  if (event.key === 'Escape' && this.noPanel && this.panelOpen) {
120
160
  event.preventDefault();
@@ -124,12 +164,20 @@ let HelixHeadlessGraph = class HelixHeadlessGraph extends MixinViewport(MixinCon
124
164
  };
125
165
  this.handleSearch = (event) => {
126
166
  this.query = event.target.value;
167
+ this.fieldKeys = false;
127
168
  };
128
169
  }
129
170
  static { this.words = 'helix-graph'; }
130
171
  get shown() {
131
172
  return this.kept;
132
173
  }
174
+ get keyed() {
175
+ const id = this.keyedId();
176
+ return id === undefined ? undefined : { id, walked: this.trail.length > 0 };
177
+ }
178
+ keyedId() {
179
+ return this.listKeys || this.fieldKeys ? this.entries[this.cursor]?.node.id : undefined;
180
+ }
133
181
  get ready() {
134
182
  return this.whole;
135
183
  }
@@ -204,6 +252,7 @@ let HelixHeadlessGraph = class HelixHeadlessGraph extends MixinViewport(MixinCon
204
252
  if (['active', 'depth', 'hiddenGroups', 'query'].some((name) => changed.has(name)) ||
205
253
  !this.hasUpdated) {
206
254
  this.cursor = 0;
255
+ this.trail = [];
207
256
  if (list) {
208
257
  list.scrollTop = 0;
209
258
  }
@@ -230,10 +279,16 @@ let HelixHeadlessGraph = class HelixHeadlessGraph extends MixinViewport(MixinCon
230
279
  updated(changed) {
231
280
  super.updated(changed);
232
281
  this.virtualize.measure();
282
+ const keyed = this.keyedId();
283
+ const rekeyed = keyed !== this.keyedSent;
284
+ this.keyedSent = keyed;
233
285
  if (changed.has('nodes') || changed.has('links')) {
234
286
  this.dispatchEvent(new HelixGraphPartChangeEvent({ kind: 'data' }));
235
287
  }
236
- else if (changed.has('active') || changed.has('depth') || changed.has('hiddenGroups')) {
288
+ else if (changed.has('active') ||
289
+ changed.has('depth') ||
290
+ changed.has('hiddenGroups') ||
291
+ rekeyed) {
237
292
  this.dispatchEvent(new HelixGraphPartChangeEvent({ kind: 'focus' }));
238
293
  }
239
294
  }
@@ -316,7 +371,10 @@ let HelixHeadlessGraph = class HelixHeadlessGraph extends MixinViewport(MixinCon
316
371
  this.requestActive(entry.node.id);
317
372
  }
318
373
  }
319
- moveTo(index) {
374
+ moveTo(index, walking = false) {
375
+ if (!walking) {
376
+ this.trail = [];
377
+ }
320
378
  const last = this.entries.length - 1;
321
379
  this.cursor = Math.min(Math.max(index, 0), Math.max(last, 0));
322
380
  void this.updateComplete.then(() => this.revealCursor());
@@ -352,6 +410,99 @@ let HelixHeadlessGraph = class HelixHeadlessGraph extends MixinViewport(MixinCon
352
410
  this.moveTo(at);
353
411
  }
354
412
  }
413
+ linkedRows(id) {
414
+ const near = this.adjacency.get(id);
415
+ if (!near) {
416
+ return [];
417
+ }
418
+ const rows = [];
419
+ for (const [index, entry] of this.entries.entries()) {
420
+ const other = entry.node.id;
421
+ if (other !== id && (near.to.has(other) || near.from.has(other))) {
422
+ rows.push(index);
423
+ }
424
+ }
425
+ return rows;
426
+ }
427
+ relationFrom(from, id) {
428
+ const near = this.adjacency.get(from);
429
+ const origin = this.nodes.find((node) => node.id === from);
430
+ const note = origin ? nameOf(origin) : from;
431
+ const to = near?.to.has(id) === true;
432
+ const back = near?.from.has(id) === true;
433
+ return formatWords(this, to && back ? 'linkedBothLabel' : to ? 'linkedFromLabel' : 'linksToLabel', { note });
434
+ }
435
+ walk(event) {
436
+ if (!event.altKey || event.ctrlKey || event.metaKey || this.entries.length === 0) {
437
+ return false;
438
+ }
439
+ const flip = isRtl(this);
440
+ const key = event.key === 'ArrowRight'
441
+ ? flip
442
+ ? 'back'
443
+ : 'follow'
444
+ : event.key === 'ArrowLeft'
445
+ ? flip
446
+ ? 'follow'
447
+ : 'back'
448
+ : event.key === 'ArrowDown'
449
+ ? 'next'
450
+ : event.key === 'ArrowUp'
451
+ ? 'previous'
452
+ : undefined;
453
+ if (key === undefined) {
454
+ return false;
455
+ }
456
+ event.preventDefault();
457
+ event.stopPropagation();
458
+ const here = this.entries[this.cursor]?.node.id;
459
+ if (here === undefined) {
460
+ return true;
461
+ }
462
+ if (key === 'back') {
463
+ const back = this.trail.pop();
464
+ const row = back === undefined ? -1 : this.entries.findIndex((entry) => entry.node.id === back);
465
+ const at = row >= 0 ? row : this.cursor;
466
+ this.moveTo(at, true);
467
+ this.sayLinks(at);
468
+ return true;
469
+ }
470
+ const from = key === 'follow' || this.trail.length === 0 ? here : this.trail.at(-1);
471
+ const rows = this.linkedRows(from);
472
+ if (rows.length === 0) {
473
+ this.sayLinks(this.cursor);
474
+ return true;
475
+ }
476
+ let place;
477
+ if (from === here) {
478
+ place = key === 'previous' ? rows.length - 1 : 0;
479
+ this.trail.push(here);
480
+ }
481
+ else {
482
+ const now = rows.indexOf(this.cursor);
483
+ const by = key === 'previous' ? -1 : 1;
484
+ place = now < 0 ? 0 : (now + by + rows.length) % rows.length;
485
+ }
486
+ const at = rows[place];
487
+ this.moveTo(at, true);
488
+ const entry = this.entries[at];
489
+ this.say(formatWords(this, 'walkLabel', {
490
+ count: rows.length,
491
+ index: place + 1,
492
+ note: nameOf(entry.node),
493
+ relation: this.relationFrom(from, entry.node.id),
494
+ }));
495
+ return true;
496
+ }
497
+ sayLinks(at) {
498
+ const entry = this.entries[at];
499
+ if (entry) {
500
+ this.say(formatWords(this, 'linkCountLabel', {
501
+ count: this.linkedRows(entry.node.id).length,
502
+ note: nameOf(entry.node),
503
+ }));
504
+ }
505
+ }
355
506
  pageRows() {
356
507
  const room = scrollRoom(this.partNamed('list'));
357
508
  const tall = this.virtualize.sizeOf(this.cursor) || 32;
@@ -473,11 +624,17 @@ let HelixHeadlessGraph = class HelixHeadlessGraph extends MixinViewport(MixinCon
473
624
  <input
474
625
  part="search-field"
475
626
  type="text"
627
+ role="combobox"
476
628
  autocomplete="off"
477
629
  spellcheck="false"
478
630
  aria-label=${this.searchLabel}
631
+ aria-autocomplete="list"
632
+ aria-controls="note-list"
633
+ aria-expanded=${this.entries.length > 0 ? 'true' : 'false'}
634
+ aria-activedescendant=${this.fieldKeys ? cursor : nothing}
479
635
  placeholder=${this.searchLabel}
480
636
  .value=${this.query}
637
+ @blur=${this.handleSearchBlur}
481
638
  @input=${this.handleSearch}
482
639
  @keydown=${this.handleSearchKeydown}
483
640
  />
@@ -485,12 +642,20 @@ let HelixHeadlessGraph = class HelixHeadlessGraph extends MixinViewport(MixinCon
485
642
  </div>
486
643
  <div
487
644
  part="list"
645
+ id="note-list"
488
646
  role="listbox"
489
647
  tabindex="0"
490
648
  data-scroller
491
649
  aria-label=${this.notesLabel}
492
650
  aria-activedescendant=${cursor}
493
651
  aria-busy=${this.loading ? 'true' : nothing}
652
+ aria-keyshortcuts="Alt+ArrowRight Alt+ArrowLeft Alt+ArrowDown Alt+ArrowUp"
653
+ @blur=${() => {
654
+ this.listKeys = false;
655
+ }}
656
+ @focus=${() => {
657
+ this.listKeys = true;
658
+ }}
494
659
  @keydown=${this.handleListKeydown}
495
660
  @scroll=${() => this.virtualize.measure()}
496
661
  >
@@ -548,6 +713,10 @@ __decorate([
548
713
  words,
549
714
  property({ attribute: 'legend-label' })
550
715
  ], HelixHeadlessGraph.prototype, "legendLabel", void 0);
716
+ __decorate([
717
+ words,
718
+ property({ attribute: 'link-count-label' })
719
+ ], HelixHeadlessGraph.prototype, "linkCountLabel", void 0);
551
720
  __decorate([
552
721
  words,
553
722
  property({ attribute: 'linked-both-label' })
@@ -623,6 +792,10 @@ __decorate([
623
792
  words,
624
793
  property({ attribute: 'using-label' })
625
794
  ], HelixHeadlessGraph.prototype, "usingLabel", void 0);
795
+ __decorate([
796
+ words,
797
+ property({ attribute: 'walk-label' })
798
+ ], HelixHeadlessGraph.prototype, "walkLabel", void 0);
626
799
  __decorate([
627
800
  words,
628
801
  property({ attribute: 'wheel-hint-label' })
@@ -644,6 +817,12 @@ __decorate([
644
817
  __decorate([
645
818
  state()
646
819
  ], HelixHeadlessGraph.prototype, "panelOpen", void 0);
820
+ __decorate([
821
+ state()
822
+ ], HelixHeadlessGraph.prototype, "fieldKeys", void 0);
823
+ __decorate([
824
+ state()
825
+ ], HelixHeadlessGraph.prototype, "listKeys", void 0);
647
826
  __decorate([
648
827
  state()
649
828
  ], HelixHeadlessGraph.prototype, "said", void 0);