@fusion.dev/helix-headless 0.210.0 → 0.211.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.
@@ -1,5 +1,7 @@
1
1
  import { type CanvasView, HelixElement, type ViewportPanDetail, type ViewportWay, type ViewportZoomDetail } from '@fusion.dev/helix-core';
2
2
  import { type PropertyValues, type TemplateResult } from 'lit';
3
+ import type { StaticValue } from 'lit/static-html.js';
4
+ import '../../icon-button/index.js';
3
5
  import { type CanvasArrangeOptions } from '../arrange.js';
4
6
  import { type CanvasDocument, type CanvasRoute, type CanvasTone } from './canvas-document.js';
5
7
  export type { CanvasArrangeOptions } from '../arrange.js';
@@ -173,6 +175,10 @@ declare const HelixHeadlessCanvas_base: (new (...args: any[]) => import("@fusion
173
175
  * @csspart edges - A layer the connectors are drawn in: one holding the arrowhead, and one after each card holding the connections leaving it, so they are read in the order the arrows walk them. Give it `z-index: -1` to draw it under the cards.
174
176
  * @csspart footer - The strip below the board.
175
177
  * @csspart fullscreen - The button that makes the board fill the screen.
178
+ * @csspart fullscreen-button - `fullscreen`'s inner button.
179
+ * @csspart fullscreen-live - `fullscreen`'s live region, which speaks while it is pending.
180
+ * @csspart fullscreen-spinner - The ring `fullscreen` turns while it is pending.
181
+ * @csspart fullscreen-text - The box `fullscreen`'s glyph sits in.
176
182
  * @csspart gesture-hint - Words over the board for a moment when it lets a gesture pass to the page, such as how to zoom it.
177
183
  * @csspart gesture-status - The line shown while a board with `gestures="activate"` has the gestures.
178
184
  * @csspart header - The strip above the board.
@@ -184,13 +190,37 @@ declare const HelixHeadlessCanvas_base: (new (...args: any[]) => import("@fusion
184
190
  * @csspart minimap-node - One card in the minimap.
185
191
  * @csspart minimap-view - The frame in the minimap around what is on screen.
186
192
  * @csspart pan-down - The button that moves the board down.
193
+ * @csspart pan-down-button - `pan-down`'s inner button.
194
+ * @csspart pan-down-live - `pan-down`'s live region, which speaks while it is pending.
195
+ * @csspart pan-down-spinner - The ring `pan-down` turns while it is pending.
196
+ * @csspart pan-down-text - The box `pan-down`'s glyph sits in.
187
197
  * @csspart pan-end - The button that moves the board toward the end of a line of text: right in English.
198
+ * @csspart pan-end-button - `pan-end`'s inner button.
199
+ * @csspart pan-end-live - `pan-end`'s live region, which speaks while it is pending.
200
+ * @csspart pan-end-spinner - The ring `pan-end` turns while it is pending.
201
+ * @csspart pan-end-text - The box `pan-end`'s glyph sits in.
188
202
  * @csspart pan-start - The button that moves the board toward the start of a line of text: left in English.
203
+ * @csspart pan-start-button - `pan-start`'s inner button.
204
+ * @csspart pan-start-live - `pan-start`'s live region, which speaks while it is pending.
205
+ * @csspart pan-start-spinner - The ring `pan-start` turns while it is pending.
206
+ * @csspart pan-start-text - The box `pan-start`'s glyph sits in.
189
207
  * @csspart pan-up - The button that moves the board up.
208
+ * @csspart pan-up-button - `pan-up`'s inner button.
209
+ * @csspart pan-up-live - `pan-up`'s live region, which speaks while it is pending.
210
+ * @csspart pan-up-spinner - The ring `pan-up` turns while it is pending.
211
+ * @csspart pan-up-text - The box `pan-up`'s glyph sits in.
190
212
  * @csspart region - The named region the board is drawn in.
191
213
  * @csspart viewport - The box the board is drawn inside.
192
214
  * @csspart zoom-in - The button that zooms in.
215
+ * @csspart zoom-in-button - `zoom-in`'s inner button.
216
+ * @csspart zoom-in-live - `zoom-in`'s live region, which speaks while it is pending.
217
+ * @csspart zoom-in-spinner - The ring `zoom-in` turns while it is pending.
218
+ * @csspart zoom-in-text - The box `zoom-in`'s glyph sits in.
193
219
  * @csspart zoom-out - The button that zooms out.
220
+ * @csspart zoom-out-button - `zoom-out`'s inner button.
221
+ * @csspart zoom-out-live - `zoom-out`'s live region, which speaks while it is pending.
222
+ * @csspart zoom-out-spinner - The ring `zoom-out` turns while it is pending.
223
+ * @csspart zoom-out-text - The box `zoom-out`'s glyph sits in.
194
224
  *
195
225
  * @cssproperty --canvas-zoom - The board's zoom, which the board writes: 1 at the document's own size, 0.5 at half. The cards inherit it, so a card's stylesheet can draw less when the board is far out, such as a border that stays one pixel wide at `calc(1px / var(--canvas-zoom))`.
196
226
  *
@@ -595,6 +625,11 @@ export declare class HelixHeadlessCanvas extends HelixHeadlessCanvas_base {
595
625
  */
596
626
  private readonly sides;
597
627
  private readEdges;
628
+ /**
629
+ * The board's controls, each an Icon Button: named here, where this family's
630
+ * imports register it, though the surface draws most of them.
631
+ */
632
+ protected get controlTag(): StaticValue;
598
633
  /** The events this family names for itself, the surface being shared. */
599
634
  protected panEvent(detail: ViewportPanDetail): Event;
600
635
  protected zoomEvent(detail: ViewportZoomDetail): Event;
@@ -2,6 +2,7 @@ import { __decorate } from "tslib";
2
2
  import { assignSlots, auditName, capturePointer, customElement, formatPercent, formatWords, HelixBeforeMoveEvent, HelixBeforePasteEvent, HelixBeforeReconnectEvent, HelixBeforeRelabelEvent, HelixCanvasEditEvent, HelixCanvasPanEvent, HelixCanvasViewEvent, HelixCanvasZoomEvent, HelixConnectEvent, HelixElement, HelixMoveEvent, HelixPastedEvent, HelixReconnectEvent, HelixRelabelEvent, HelixRemoveEvent, HelixSelectEvent, hostAria, inlineStep, isRtl, MixinViewport, numberConverter, words, wordsConverter, wordsLocale, } from '@fusion.dev/helix-core';
3
3
  import { html, nothing, svg } from 'lit';
4
4
  import { property, state } from 'lit/decorators.js';
5
+ import '../../icon-button/index.js';
5
6
  import { arrangement } from '../arrange.js';
6
7
  import { descriptionOf } from '../describe.js';
7
8
  import { HelixHeadlessCanvasEdge } from '../edge/canvas-edge.js';
@@ -887,6 +888,9 @@ let HelixHeadlessCanvas = class HelixHeadlessCanvas extends MixinViewport(HelixE
887
888
  });
888
889
  });
889
890
  }
891
+ get controlTag() {
892
+ return this.tag('icon-button');
893
+ }
890
894
  panEvent(detail) {
891
895
  return new HelixCanvasPanEvent(detail);
892
896
  }
@@ -1,5 +1,7 @@
1
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
+ import { type StaticValue } from 'lit/static-html.js';
4
+ import '../../icon-button/index.js';
3
5
  import { type GraphLink, type GraphNode } from './graph-model.js';
4
6
  declare const HelixHeadlessGraph_base: (new (...args: any[]) => import("@fusion.dev/helix-core").ViewportElement) & (new (...args: any[]) => import("@fusion.dev/helix-core").MixinControllerActiveInterface) & typeof HelixElement;
5
7
  /**
@@ -95,6 +97,10 @@ declare const HelixHeadlessGraph_base: (new (...args: any[]) => import("@fusion.
95
97
  * @csspart filter-mark - The default icon beside the search field, shown when none is slotted.
96
98
  * @csspart footer - The strip below the graph.
97
99
  * @csspart fullscreen - The button that makes the graph fill the screen.
100
+ * @csspart fullscreen-button - `fullscreen`'s inner button.
101
+ * @csspart fullscreen-live - `fullscreen`'s live region, which speaks while it is pending.
102
+ * @csspart fullscreen-spinner - The ring `fullscreen` turns while it is pending.
103
+ * @csspart fullscreen-text - The box `fullscreen`'s glyph sits in.
98
104
  * @csspart gesture-hint - Words over the graph for a moment when it lets a gesture pass to the page, such as how to zoom it.
99
105
  * @csspart gesture-status - The line shown while a graph with `gestures="activate"` has the gestures.
100
106
  * @csspart header - The strip above the graph.
@@ -112,10 +118,30 @@ declare const HelixHeadlessGraph_base: (new (...args: any[]) => import("@fusion.
112
118
  * @csspart note-relation - How a note stands to the selected one, such as "Linked from Alpha".
113
119
  * @csspart note-selected - The selected note, first in the list.
114
120
  * @csspart notes-toggle - The button among the controls that opens the search and the list over the drawing, with `no-panel`.
121
+ * @csspart notes-toggle-button - `notes-toggle`'s inner button.
122
+ * @csspart notes-toggle-live - `notes-toggle`'s live region, which speaks while it is pending.
123
+ * @csspart notes-toggle-spinner - The ring `notes-toggle` turns while it is pending.
124
+ * @csspart notes-toggle-text - The box `notes-toggle`'s glyph sits in.
115
125
  * @csspart pan-down - The button that moves the graph down.
126
+ * @csspart pan-down-button - `pan-down`'s inner button.
127
+ * @csspart pan-down-live - `pan-down`'s live region, which speaks while it is pending.
128
+ * @csspart pan-down-spinner - The ring `pan-down` turns while it is pending.
129
+ * @csspart pan-down-text - The box `pan-down`'s glyph sits in.
116
130
  * @csspart pan-end - The button that moves the graph toward the end of a line of text: right in English.
131
+ * @csspart pan-end-button - `pan-end`'s inner button.
132
+ * @csspart pan-end-live - `pan-end`'s live region, which speaks while it is pending.
133
+ * @csspart pan-end-spinner - The ring `pan-end` turns while it is pending.
134
+ * @csspart pan-end-text - The box `pan-end`'s glyph sits in.
117
135
  * @csspart pan-start - The button that moves the graph toward the start of a line of text: left in English.
136
+ * @csspart pan-start-button - `pan-start`'s inner button.
137
+ * @csspart pan-start-live - `pan-start`'s live region, which speaks while it is pending.
138
+ * @csspart pan-start-spinner - The ring `pan-start` turns while it is pending.
139
+ * @csspart pan-start-text - The box `pan-start`'s glyph sits in.
118
140
  * @csspart pan-up - The button that moves the graph up.
141
+ * @csspart pan-up-button - `pan-up`'s inner button.
142
+ * @csspart pan-up-live - `pan-up`'s live region, which speaks while it is pending.
143
+ * @csspart pan-up-spinner - The ring `pan-up` turns while it is pending.
144
+ * @csspart pan-up-text - The box `pan-up`'s glyph sits in.
119
145
  * @csspart panel - The search field and the list, beside the drawing or below it, or over the drawing when opened with `no-panel`.
120
146
  * @csspart region - The frame: the drawing, its controls and the list.
121
147
  * @csspart search - The bar holding the icon, the search field and the count.
@@ -125,7 +151,15 @@ declare const HelixHeadlessGraph_base: (new (...args: any[]) => import("@fusion.
125
151
  * @csspart stop-layout - The button that stops a layout that has run past five seconds, where the notes stand.
126
152
  * @csspart viewport - The box the renderer draws in.
127
153
  * @csspart zoom-in - The zoom in button.
154
+ * @csspart zoom-in-button - `zoom-in`'s inner button.
155
+ * @csspart zoom-in-live - `zoom-in`'s live region, which speaks while it is pending.
156
+ * @csspart zoom-in-spinner - The ring `zoom-in` turns while it is pending.
157
+ * @csspart zoom-in-text - The box `zoom-in`'s glyph sits in.
128
158
  * @csspart zoom-out - The zoom out button.
159
+ * @csspart zoom-out-button - `zoom-out`'s inner button.
160
+ * @csspart zoom-out-live - `zoom-out`'s live region, which speaks while it is pending.
161
+ * @csspart zoom-out-spinner - The ring `zoom-out` turns while it is pending.
162
+ * @csspart zoom-out-text - The box `zoom-out`'s glyph sits in.
129
163
  *
130
164
  * @cssstate empty - The list holds no notes: the graph has none, or a search or the groups hid them all.
131
165
  * @cssstate fullscreen - The graph fills the screen.
@@ -442,6 +476,11 @@ export declare class HelixHeadlessGraph extends HelixHeadlessGraph_base {
442
476
  protected firstUpdated(changed: PropertyValues): void;
443
477
  protected willUpdate(changed: PropertyValues): void;
444
478
  protected updated(changed: PropertyValues): void;
479
+ /**
480
+ * The graph's controls, each an Icon Button: named here, where this family's
481
+ * imports register it, though the surface draws most of them.
482
+ */
483
+ protected get controlTag(): StaticValue;
445
484
  /** The pan request, and the side it goes to, which `moved()` then says. */
446
485
  protected panEvent(detail: ViewportPanDetail): Event;
447
486
  /** The zoom request, and which way it goes, which `moved()` then says. */
@@ -3,10 +3,13 @@ import { auditName, customElement, formatWords, HelixElement, HelixGraphFilterEv
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';
6
+ import { html as staticHtml } from 'lit/static-html.js';
7
+ import '../../icon-button/index.js';
6
8
  import { repeat } from 'lit/directives/repeat.js';
7
9
  import { unsafeSVG } from 'lit/directives/unsafe-svg.js';
8
10
  import { adjacencyOf, cursorAfter, entriesOf, groupsOf, nameOf, sortedOf, within, withoutGroups, } from './graph-model.js';
9
11
  const LONG_LAYOUT = 5000;
12
+ const stopPress = (event) => event.stopPropagation();
10
13
  let HelixHeadlessGraph = class HelixHeadlessGraph extends MixinViewport(MixinControllerActive(HelixElement)) {
11
14
  constructor() {
12
15
  super(...arguments);
@@ -324,6 +327,9 @@ let HelixHeadlessGraph = class HelixHeadlessGraph extends MixinViewport(MixinCon
324
327
  this.dispatchEvent(new HelixGraphPartChangeEvent({ kind: 'focus' }));
325
328
  }
326
329
  }
330
+ get controlTag() {
331
+ return this.tag('icon-button');
332
+ }
327
333
  panEvent(detail) {
328
334
  this.asked = this.sideOf(detail.to);
329
335
  return new HelixGraphPanEvent(detail);
@@ -553,18 +559,23 @@ let HelixHeadlessGraph = class HelixHeadlessGraph extends MixinViewport(MixinCon
553
559
  if (!this.noPanel) {
554
560
  return nothing;
555
561
  }
556
- return html `<button
562
+ const button = this.controlTag;
563
+ const { material, raised } = this.controlAxes;
564
+ return staticHtml `<${button}
557
565
  part="notes-toggle"
566
+ exportparts="button: notes-toggle-button, live: notes-toggle-live, spinner: notes-toggle-spinner, text: notes-toggle-text"
558
567
  aria-controls="panel"
559
- aria-expanded=${this.panelOpen ? 'true' : 'false'}
560
- aria-label=${this.notesLabel}
561
- type="button"
568
+ .expanded=${this.panelOpen}
569
+ label=${this.notesLabel}
570
+ material=${material ?? nothing}
571
+ ?raised=${raised}
562
572
  @click=${() => this.togglePanel()}
573
+ @helix-press=${stopPress}
563
574
  >
564
575
  <svg aria-hidden="true" fill="currentColor" viewBox=${list.viewBox}>
565
576
  ${unsafeSVG(list.content)}
566
577
  </svg>
567
- </button>`;
578
+ </${button}>`;
568
579
  }
569
580
  renderFilterIcon() {
570
581
  return html `<slot name="filter-icon">
@@ -1,5 +1,7 @@
1
1
  import { HelixElement, KeyboardNavigationController, type ViewportControlsPlacement, type ViewportPanDetail, type ViewportZoomDetail } from '@fusion.dev/helix-core';
2
2
  import { nothing, type PropertyValues, type TemplateResult } from 'lit';
3
+ import { type StaticValue } from 'lit/static-html.js';
4
+ import '../../icon-button/index.js';
3
5
  /**
4
6
  * What `ViewportControlsPlacement` is called for a map.
5
7
  *
@@ -102,8 +104,16 @@ declare const HelixHeadlessMap_base: (new (...args: any[]) => import("@fusion.de
102
104
  * @csspart compass - The compass and the pan and rotate buttons around it.
103
105
  * @csspart controls - The column of buttons that move the map, a toolbar and one tab stop.
104
106
  * @csspart face-north - The compass: its needle points north as the map turns, and pressing it turns the map to face north.
107
+ * @csspart face-north-button - `face-north`'s inner button.
108
+ * @csspart face-north-live - `face-north`'s live region, which speaks while it is pending.
109
+ * @csspart face-north-spinner - The ring `face-north` turns while it is pending.
110
+ * @csspart face-north-text - The box `face-north`'s glyph sits in.
105
111
  * @csspart footer - The strip below the map.
106
112
  * @csspart fullscreen - The button that makes the map fill the screen.
113
+ * @csspart fullscreen-button - `fullscreen`'s inner button.
114
+ * @csspart fullscreen-live - `fullscreen`'s live region, which speaks while it is pending.
115
+ * @csspart fullscreen-spinner - The ring `fullscreen` turns while it is pending.
116
+ * @csspart fullscreen-text - The box `fullscreen`'s glyph sits in.
107
117
  * @csspart gesture-hint - Words over the map for a moment when it lets a gesture pass to the page, such as how to zoom it.
108
118
  * @csspart gesture-status - The line shown while a map with `gestures="activate"` has the gestures.
109
119
  * @csspart header - The strip above the map.
@@ -115,6 +125,10 @@ declare const HelixHeadlessMap_base: (new (...args: any[]) => import("@fusion.de
115
125
  * @csspart layers - The list of the map's shown layers, such as routes, areas, and points, read by screen readers.
116
126
  * @csspart layers-menu - The menu of the map's layers, which the layers button opens.
117
127
  * @csspart layers-toggle - The button that opens and closes the layers menu.
128
+ * @csspart layers-toggle-button - `layers-toggle`'s inner button.
129
+ * @csspart layers-toggle-live - `layers-toggle`'s live region, which speaks while it is pending.
130
+ * @csspart layers-toggle-spinner - The ring `layers-toggle` turns while it is pending.
131
+ * @csspart layers-toggle-text - The box `layers-toggle`'s glyph sits in.
118
132
  * @csspart live - What screen readers hear after the map moves: the zoom level, the way it faces, its tilt, or the way it moved. Visually hidden in the styled tier.
119
133
  * @csspart map-type - One map type's card in the layers menu: a radio button, its picture, and its name.
120
134
  * @csspart map-type-name - The name on a map type's card.
@@ -122,16 +136,52 @@ declare const HelixHeadlessMap_base: (new (...args: any[]) => import("@fusion.de
122
136
  * @csspart map-types - The map-type cards at the top of the layers menu, where the map has imagery.
123
137
  * @csspart needle - The compass needle, turned to point north.
124
138
  * @csspart pan-down - The button that pans the map down.
139
+ * @csspart pan-down-button - `pan-down`'s inner button.
140
+ * @csspart pan-down-live - `pan-down`'s live region, which speaks while it is pending.
141
+ * @csspart pan-down-spinner - The ring `pan-down` turns while it is pending.
142
+ * @csspart pan-down-text - The box `pan-down`'s glyph sits in.
125
143
  * @csspart pan-end - The button that pans toward the end of a line of text: right in English.
144
+ * @csspart pan-end-button - `pan-end`'s inner button.
145
+ * @csspart pan-end-live - `pan-end`'s live region, which speaks while it is pending.
146
+ * @csspart pan-end-spinner - The ring `pan-end` turns while it is pending.
147
+ * @csspart pan-end-text - The box `pan-end`'s glyph sits in.
126
148
  * @csspart pan-start - The button that pans toward the start of a line of text: left in English.
149
+ * @csspart pan-start-button - `pan-start`'s inner button.
150
+ * @csspart pan-start-live - `pan-start`'s live region, which speaks while it is pending.
151
+ * @csspart pan-start-spinner - The ring `pan-start` turns while it is pending.
152
+ * @csspart pan-start-text - The box `pan-start`'s glyph sits in.
127
153
  * @csspart pan-up - The button that pans the map up.
154
+ * @csspart pan-up-button - `pan-up`'s inner button.
155
+ * @csspart pan-up-live - `pan-up`'s live region, which speaks while it is pending.
156
+ * @csspart pan-up-spinner - The ring `pan-up` turns while it is pending.
157
+ * @csspart pan-up-text - The box `pan-up`'s glyph sits in.
128
158
  * @csspart region - The named region the map sits in.
129
159
  * @csspart rotate-left - The button that turns the map counterclockwise.
160
+ * @csspart rotate-left-button - `rotate-left`'s inner button.
161
+ * @csspart rotate-left-live - `rotate-left`'s live region, which speaks while it is pending.
162
+ * @csspart rotate-left-spinner - The ring `rotate-left` turns while it is pending.
163
+ * @csspart rotate-left-text - The box `rotate-left`'s glyph sits in.
130
164
  * @csspart rotate-right - The button that turns the map clockwise.
165
+ * @csspart rotate-right-button - `rotate-right`'s inner button.
166
+ * @csspart rotate-right-live - `rotate-right`'s live region, which speaks while it is pending.
167
+ * @csspart rotate-right-spinner - The ring `rotate-right` turns while it is pending.
168
+ * @csspart rotate-right-text - The box `rotate-right`'s glyph sits in.
131
169
  * @csspart tilt - The 3D button, which tilts the map and makes it flat again. Pressed while the map is tilted.
170
+ * @csspart tilt-button - `tilt`'s inner button.
171
+ * @csspart tilt-live - `tilt`'s live region, which speaks while it is pending.
172
+ * @csspart tilt-spinner - The ring `tilt` turns while it is pending.
173
+ * @csspart tilt-text - The box `tilt`'s glyph sits in.
132
174
  * @csspart viewport - The box the map is drawn in.
133
175
  * @csspart zoom-in - The button that zooms in.
176
+ * @csspart zoom-in-button - `zoom-in`'s inner button.
177
+ * @csspart zoom-in-live - `zoom-in`'s live region, which speaks while it is pending.
178
+ * @csspart zoom-in-spinner - The ring `zoom-in` turns while it is pending.
179
+ * @csspart zoom-in-text - The box `zoom-in`'s glyph sits in.
134
180
  * @csspart zoom-out - The button that zooms out.
181
+ * @csspart zoom-out-button - `zoom-out`'s inner button.
182
+ * @csspart zoom-out-live - `zoom-out`'s live region, which speaks while it is pending.
183
+ * @csspart zoom-out-spinner - The ring `zoom-out` turns while it is pending.
184
+ * @csspart zoom-out-text - The box `zoom-out`'s glyph sits in.
135
185
  *
136
186
  * @cssproperty --map-needle-turn - How far the needle turns to point north, as an angle. The frame writes it from `bearing`.
137
187
  *
@@ -495,6 +545,11 @@ export declare class HelixHeadlessMap extends HelixHeadlessMap_base {
495
545
  private get keyShortcuts();
496
546
  /** Shift with the arrow keys: left and right rotate, and up and down tilt in steps. */
497
547
  protected handleMoreKeys(event: KeyboardEvent): boolean;
548
+ /**
549
+ * The map's controls, each an Icon Button: named here, where this family's
550
+ * imports register it, though the surface draws most of them.
551
+ */
552
+ protected get controlTag(): StaticValue;
498
553
  /** The events this family names, the surface naming none of its own. */
499
554
  protected panEvent(detail: ViewportPanDetail): Event;
500
555
  protected zoomEvent(detail: ViewportZoomDetail): Event;
@@ -3,6 +3,8 @@ import { auditName, customElement, focusItemOf, formatWords, HelixActivateEvent,
3
3
  import { buildings, cloudRain, dotsNine, leaf, mountains, path, polygon, stack, target, } from '@fusion.dev/helix-icons';
4
4
  import { html, nothing } from 'lit';
5
5
  import { property, state } from 'lit/decorators.js';
6
+ import { html as staticHtml } from 'lit/static-html.js';
7
+ import '../../icon-button/index.js';
6
8
  import { live } from 'lit/directives/live.js';
7
9
  import { unsafeSVG } from 'lit/directives/unsafe-svg.js';
8
10
  const MAP_TYPES = ['standard', 'hybrid', 'satellite'];
@@ -34,6 +36,7 @@ const TILTED = 50;
34
36
  const placed = (marker) => Number.isFinite(marker.lat) && Number.isFinite(marker.lng);
35
37
  const ASK_LAPSES = 3000;
36
38
  const SETTLES = 400;
39
+ const stopPress = (event) => event.stopPropagation();
37
40
  let HelixHeadlessMap = class HelixHeadlessMap extends MixinViewport(HelixElement) {
38
41
  constructor() {
39
42
  super(...arguments);
@@ -398,12 +401,16 @@ let HelixHeadlessMap = class HelixHeadlessMap extends MixinViewport(HelixElement
398
401
  return nothing;
399
402
  }
400
403
  const entries = this.layerEntries;
401
- return html `<button
404
+ const button = this.controlTag;
405
+ const { material, raised } = this.controlAxes;
406
+ return staticHtml `<${button}
402
407
  part="layers-toggle"
408
+ exportparts="button: layers-toggle-button, live: layers-toggle-live, spinner: layers-toggle-spinner, text: layers-toggle-text"
403
409
  aria-controls="layers-menu"
404
- aria-expanded=${this.layersOpen ? 'true' : 'false'}
405
- aria-label=${this.layersLabel}
406
- type="button"
410
+ .expanded=${this.layersOpen}
411
+ label=${this.layersLabel}
412
+ material=${material ?? nothing}
413
+ ?raised=${raised}
407
414
  @click=${() => {
408
415
  this.layersOpen = !this.layersOpen;
409
416
  if (this.layersOpen) {
@@ -411,6 +418,7 @@ let HelixHeadlessMap = class HelixHeadlessMap extends MixinViewport(HelixElement
411
418
  }
412
419
  }}
413
420
  @focusout=${this.handleMenuFocusOut}
421
+ @helix-press=${stopPress}
414
422
  @keydown=${this.handleMenuKeydown}
415
423
  >
416
424
  <slot name="layers-icon">
@@ -418,7 +426,7 @@ let HelixHeadlessMap = class HelixHeadlessMap extends MixinViewport(HelixElement
418
426
  ${unsafeSVG(stack.content)}
419
427
  </svg>
420
428
  </slot>
421
- </button>
429
+ </${button}>
422
430
  <div
423
431
  part="layers-menu"
424
432
  id="layers-menu"
@@ -474,44 +482,98 @@ let HelixHeadlessMap = class HelixHeadlessMap extends MixinViewport(HelixElement
474
482
  }
475
483
  renderCompass(pan, rotate) {
476
484
  const { faceNorthLabel } = this;
477
- return html `<div part="compass">
485
+ const button = this.controlTag;
486
+ const { material, raised } = this.controlAxes;
487
+ const ground = material ?? nothing;
488
+ return staticHtml `<div part="compass">
478
489
  ${rotate
479
- ? html `<button part="rotate-left" aria-label=${this.rotateLeftLabel} type="button" @click=${() => this.rotate(-ROTATE_STEP)}>
490
+ ? staticHtml `<${button}
491
+ part="rotate-left"
492
+ exportparts="button: rotate-left-button, live: rotate-left-live, spinner: rotate-left-spinner, text: rotate-left-text"
493
+ label=${this.rotateLeftLabel}
494
+ material=${ground}
495
+ @click=${() => this.rotate(-ROTATE_STEP)}
496
+ @helix-press=${stopPress}
497
+ >
480
498
  <slot name="rotate-left-icon">↺</slot>
481
- </button>`
499
+ </${button}>`
482
500
  : nothing}
483
501
  ${pan
484
- ? html `<button part="pan-up" aria-label=${this.panLabel('up')} type="button" @click=${() => this.pan('up')}>
502
+ ? staticHtml `<${button}
503
+ part="pan-up"
504
+ exportparts="button: pan-up-button, live: pan-up-live, spinner: pan-up-spinner, text: pan-up-text"
505
+ label=${this.panLabel('up')}
506
+ material=${ground}
507
+ @click=${() => this.pan('up')}
508
+ @helix-press=${stopPress}
509
+ >
485
510
  <slot name="pan-up-icon">${this.panGlyph('up')}</slot>
486
- </button>`
511
+ </${button}>`
487
512
  : nothing}
488
513
  ${rotate
489
- ? html `<button part="rotate-right" aria-label=${this.rotateRightLabel} type="button" @click=${() => this.rotate(ROTATE_STEP)}>
514
+ ? staticHtml `<${button}
515
+ part="rotate-right"
516
+ exportparts="button: rotate-right-button, live: rotate-right-live, spinner: rotate-right-spinner, text: rotate-right-text"
517
+ label=${this.rotateRightLabel}
518
+ material=${ground}
519
+ @click=${() => this.rotate(ROTATE_STEP)}
520
+ @helix-press=${stopPress}
521
+ >
490
522
  <slot name="rotate-right-icon">↻</slot>
491
- </button>`
523
+ </${button}>`
492
524
  : nothing}
493
525
  ${pan
494
- ? html `<button part="pan-start" aria-label=${this.panLabel('start')} type="button" @click=${() => this.pan('start')}>
526
+ ? staticHtml `<${button}
527
+ part="pan-start"
528
+ exportparts="button: pan-start-button, live: pan-start-live, spinner: pan-start-spinner, text: pan-start-text"
529
+ label=${this.panLabel('start')}
530
+ material=${ground}
531
+ @click=${() => this.pan('start')}
532
+ @helix-press=${stopPress}
533
+ >
495
534
  <slot name="pan-start-icon">${this.panGlyph('start')}</slot>
496
- </button>`
535
+ </${button}>`
497
536
  : nothing}
498
- <button part="face-north" aria-label=${faceNorthLabel} type="button" style=${`--map-needle-turn: ${-this.bearing}deg`} @click=${() => this.faceNorth()}>
537
+ <${button}
538
+ part="face-north"
539
+ exportparts="button: face-north-button, live: face-north-live, spinner: face-north-spinner, text: face-north-text"
540
+ label=${faceNorthLabel}
541
+ material=${ground}
542
+ ?raised=${raised}
543
+ style=${`--map-needle-turn: ${-this.bearing}deg`}
544
+ @click=${() => this.faceNorth()}
545
+ @helix-press=${stopPress}
546
+ >
499
547
  <slot name="face-north-icon">
500
548
  <svg part="needle" aria-hidden="true" viewBox="0 0 16 16">
501
549
  <path data-end="north" d="M8 1.5 10.5 8h-5Z" />
502
550
  <path data-end="south" d="M8 14.5 5.5 8h5Z" />
503
551
  </svg>
504
552
  </slot>
505
- </button>
553
+ </${button}>
506
554
  ${pan
507
- ? html `<button part="pan-end" aria-label=${this.panLabel('end')} type="button" @click=${() => this.pan('end')}>
555
+ ? staticHtml `<${button}
556
+ part="pan-end"
557
+ exportparts="button: pan-end-button, live: pan-end-live, spinner: pan-end-spinner, text: pan-end-text"
558
+ label=${this.panLabel('end')}
559
+ material=${ground}
560
+ @click=${() => this.pan('end')}
561
+ @helix-press=${stopPress}
562
+ >
508
563
  <slot name="pan-end-icon">${this.panGlyph('end')}</slot>
509
- </button>`
564
+ </${button}>`
510
565
  : nothing}
511
566
  ${pan
512
- ? html `<button part="pan-down" aria-label=${this.panLabel('down')} type="button" @click=${() => this.pan('down')}>
567
+ ? staticHtml `<${button}
568
+ part="pan-down"
569
+ exportparts="button: pan-down-button, live: pan-down-live, spinner: pan-down-spinner, text: pan-down-text"
570
+ label=${this.panLabel('down')}
571
+ material=${ground}
572
+ @click=${() => this.pan('down')}
573
+ @helix-press=${stopPress}
574
+ >
513
575
  <slot name="pan-down-icon">${this.panGlyph('down')}</slot>
514
- </button>`
576
+ </${button}>`
515
577
  : nothing}
516
578
  </div>`;
517
579
  }
@@ -525,37 +587,62 @@ let HelixHeadlessMap = class HelixHeadlessMap extends MixinViewport(HelixElement
525
587
  if (!pan && !zoom && !rotate && !tilt && !fullscreen && menu === nothing) {
526
588
  return nothing;
527
589
  }
528
- return html `<div part="controls" role="toolbar" aria-label=${this.controlsLabel}>
590
+ const button = this.controlTag;
591
+ const { material, raised } = this.controlAxes;
592
+ const ground = material ?? nothing;
593
+ return staticHtml `<div part="controls" role="toolbar" aria-label=${this.controlsLabel}>
529
594
  ${fullscreen
530
- ? html `<button
595
+ ? staticHtml `<${button}
531
596
  part="fullscreen"
532
- aria-label=${this.fullscreenLabel}
597
+ exportparts="button: fullscreen-button, live: fullscreen-live, spinner: fullscreen-spinner, text: fullscreen-text"
533
598
  aria-pressed=${this.filled ? 'true' : 'false'}
534
- type="button"
599
+ label=${this.fullscreenLabel}
600
+ material=${ground}
601
+ ?raised=${raised}
535
602
  @click=${this.toggleFullscreen}
603
+ @helix-press=${stopPress}
536
604
  >
537
605
  <slot name="fullscreen-icon">⤢</slot>
538
- </button>`
606
+ </${button}>`
539
607
  : nothing}
540
608
  ${menu}
541
609
  ${tilt
542
- ? html `<button
610
+ ? staticHtml `<${button}
543
611
  part="tilt"
544
- aria-label=${this.tiltLabel}
612
+ exportparts="button: tilt-button, live: tilt-live, spinner: tilt-spinner, text: tilt-text"
545
613
  aria-pressed=${this.pitch > 0 ? 'true' : 'false'}
546
- type="button"
614
+ label=${this.tiltLabel}
615
+ material=${ground}
616
+ ?raised=${raised}
547
617
  @click=${() => this.tiltTo(this.pitch > 0 ? 0 : TILTED)}
618
+ @helix-press=${stopPress}
548
619
  >
549
620
  <slot name="tilt-icon">3D</slot>
550
- </button>`
621
+ </${button}>`
551
622
  : nothing}
552
623
  ${zoom
553
- ? html `<button part="zoom-in" aria-label=${this.zoomInLabel} type="button" @click=${() => this.zoom(1)}>
624
+ ? staticHtml `<${button}
625
+ part="zoom-in"
626
+ exportparts="button: zoom-in-button, live: zoom-in-live, spinner: zoom-in-spinner, text: zoom-in-text"
627
+ label=${this.zoomInLabel}
628
+ material=${ground}
629
+ ?raised=${raised}
630
+ @click=${() => this.zoom(1)}
631
+ @helix-press=${stopPress}
632
+ >
554
633
  <slot name="zoom-in-icon">+</slot>
555
- </button>
556
- <button part="zoom-out" aria-label=${this.zoomOutLabel} type="button" @click=${() => this.zoom(-1)}>
634
+ </${button}>
635
+ <${button}
636
+ part="zoom-out"
637
+ exportparts="button: zoom-out-button, live: zoom-out-live, spinner: zoom-out-spinner, text: zoom-out-text"
638
+ label=${this.zoomOutLabel}
639
+ material=${ground}
640
+ ?raised=${raised}
641
+ @click=${() => this.zoom(-1)}
642
+ @helix-press=${stopPress}
643
+ >
557
644
  <slot name="zoom-out-icon">−</slot>
558
- </button>`
645
+ </${button}>`
559
646
  : nothing}
560
647
  ${this.drawsCompass ? this.renderCompass(pan, rotate) : nothing}
561
648
  </div>`;
@@ -590,6 +677,9 @@ let HelixHeadlessMap = class HelixHeadlessMap extends MixinViewport(HelixElement
590
677
  }
591
678
  return false;
592
679
  }
680
+ get controlTag() {
681
+ return this.tag('icon-button');
682
+ }
593
683
  panEvent(detail) {
594
684
  this.ask('pan', this.sideOf(detail.to));
595
685
  return new HelixMapPanEvent(detail);