@fusion.dev/helix-headless 0.102.0 → 0.103.1
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/custom-elements.json +78 -0
- package/dist/map/root/map-root.d.ts +68 -0
- package/dist/map/root/map-root.js +62 -36
- package/package.json +5 -5
- package/types/jsx.d.ts +176 -0
- package/types/vue.d.ts +51 -0
package/custom-elements.json
CHANGED
|
@@ -55446,14 +55446,26 @@
|
|
|
55446
55446
|
"description": "**Helix draws no map.** There are no tiles here, no projection and no\nnetwork, and there should not be: a tile renderer is a library, and what a\ndesign system can add to MapLibre or Leaflet is the frame. The consumer slots\ntheir map and this owns the box, the name, the controls and the way out,\nwhich is the shape `VideoPlaylist` uses for a player it never renders.\n\n**The accessibility argument is the reason this exists**, and it was measured\nrather than assumed: a map embedded the ordinary way is a canvas with no role\nand no name, and it has *no node at all* in the accessibility tree. A reader\nusing a screen reader does not walk past it so much as never meet it. A named\nregion with controls in it is the whole of the difference.\n\n**The controls are buttons, and that is a deliberate choice against arrow\nkeys.** Arrows work here too, but what a screen reader does with them is not\nours to decide: macOS passes them through, Windows readers hold them for\ntheir own reading mode unless a page takes `role=\"application\"`, which costs\nthe reader their normal way of reading everything else in the frame. A button\nis findable and operable in every screen reader on every platform without\nthat bargain, so panning and zooming are buttons first and keys second.\n\n**Nothing here moves the map.** Both controls ask, through `helix-map-pan`\nand `helix-map-zoom`, and the consumer answers against whatever they slotted.\nA frame that moved the map would have to know whose map it was.",
|
|
55447
55447
|
"name": "HelixHeadlessMap",
|
|
55448
55448
|
"cssParts": [
|
|
55449
|
+
{
|
|
55450
|
+
"description": "The strip the credit sits in, under the map.",
|
|
55451
|
+
"name": "attribution"
|
|
55452
|
+
},
|
|
55449
55453
|
{
|
|
55450
55454
|
"description": "The group the pan and zoom buttons sit in.",
|
|
55451
55455
|
"name": "controls"
|
|
55452
55456
|
},
|
|
55457
|
+
{
|
|
55458
|
+
"description": "The strip below the map, for what a consumer slots there.",
|
|
55459
|
+
"name": "footer"
|
|
55460
|
+
},
|
|
55453
55461
|
{
|
|
55454
55462
|
"description": "The button that fills the screen.",
|
|
55455
55463
|
"name": "fullscreen"
|
|
55456
55464
|
},
|
|
55465
|
+
{
|
|
55466
|
+
"description": "The strip above the map, for what a consumer slots there.",
|
|
55467
|
+
"name": "header"
|
|
55468
|
+
},
|
|
55457
55469
|
{
|
|
55458
55470
|
"description": "The button that moves the map down.",
|
|
55459
55471
|
"name": "pan-down"
|
|
@@ -55506,6 +55518,26 @@
|
|
|
55506
55518
|
}
|
|
55507
55519
|
],
|
|
55508
55520
|
"members": [
|
|
55521
|
+
{
|
|
55522
|
+
"kind": "field",
|
|
55523
|
+
"name": "controls",
|
|
55524
|
+
"type": {
|
|
55525
|
+
"text": "string | undefined"
|
|
55526
|
+
},
|
|
55527
|
+
"description": "Which of the controls this frame draws, as a list of what to keep.\n\n**A list rather than a switch, because the overlap is not symmetric.**\nEvery map library draws zoom controls and none of them draws pan buttons:\nMapLibre's navigation control is zoom and a compass, Leaflet's is zoom,\nGoogle's is zoom. So a consumer slotting one of those has our zoom twice\nover and our pan pad not at all, and a single switch would make them choose\nbetween a duplicate and nothing.\n\n`none` draws none of them, which is the right answer where the slotted map\nalready has controls a reader can find: what this family argues for is that\n*a* findable control exists, never that it is ours. The methods stay public\neither way, so a consumer drawing their own chrome can still drive the\nframe.\n\nAbsent is all three, which is this library's rule that a resting value is an\nattribute's absence, and it is what the stylesheet asks about: the layout\nrules are written against `[controls]:not([controls~=\"zoom\"])` rather than\nthe bare negation, or a frame that named no list at all would be laid out as\nthough it had dropped everything.",
|
|
55528
|
+
"attribute": "controls",
|
|
55529
|
+
"reflects": true
|
|
55530
|
+
},
|
|
55531
|
+
{
|
|
55532
|
+
"kind": "field",
|
|
55533
|
+
"name": "controlsPlacement",
|
|
55534
|
+
"type": {
|
|
55535
|
+
"text": "'top-start' | 'top-end' | 'bottom-start' | 'bottom-end' | undefined"
|
|
55536
|
+
},
|
|
55537
|
+
"description": "Which corner the controls sit in.\n\n**Configurable because there is no safe default**, and this is a collision\nrather than a taste: MapLibre puts its own controls at the top end, Leaflet\nand OpenLayers at the top start, Google's zoom at the bottom end. Whichever\ncorner this took would land on somebody's, which is why every one of those\nlibraries made it a setting too.\n\nLogical corners rather than left and right, so a right-to-left page moves\nthem without a consumer writing a second rule.\n\nAbsent is the top end, which is this library's rule that a resting value is\nan attribute's absence: a default that reflected would write an attribute\nonto every host that no server sent and nobody asked for.",
|
|
55538
|
+
"attribute": "controls-placement",
|
|
55539
|
+
"reflects": true
|
|
55540
|
+
},
|
|
55509
55541
|
{
|
|
55510
55542
|
"kind": "field",
|
|
55511
55543
|
"name": "fullscreenLabel",
|
|
@@ -55610,6 +55642,25 @@
|
|
|
55610
55642
|
"readonly": true,
|
|
55611
55643
|
"default": "new IdleController( this, () => this.idleDelay, (resting) => { this.resting = resting }, )"
|
|
55612
55644
|
},
|
|
55645
|
+
{
|
|
55646
|
+
"kind": "method",
|
|
55647
|
+
"name": "draws",
|
|
55648
|
+
"privacy": "private",
|
|
55649
|
+
"return": {
|
|
55650
|
+
"type": {
|
|
55651
|
+
"text": "boolean"
|
|
55652
|
+
}
|
|
55653
|
+
},
|
|
55654
|
+
"parameters": [
|
|
55655
|
+
{
|
|
55656
|
+
"name": "group",
|
|
55657
|
+
"type": {
|
|
55658
|
+
"text": "'pan' | 'zoom' | 'fullscreen'"
|
|
55659
|
+
}
|
|
55660
|
+
}
|
|
55661
|
+
],
|
|
55662
|
+
"description": "Whether a named group of controls is one this frame draws."
|
|
55663
|
+
},
|
|
55613
55664
|
{
|
|
55614
55665
|
"kind": "method",
|
|
55615
55666
|
"name": "toggleFullscreen",
|
|
@@ -55691,6 +55742,17 @@
|
|
|
55691
55742
|
],
|
|
55692
55743
|
"description": "What one pan button is called, with the way it goes filled in.\n\nLeft and right rather than start and end, because the label is read aloud\nand a reader knows which way left is. The event keeps the reading-order\nname, which is the one a right-to-left page needs."
|
|
55693
55744
|
},
|
|
55745
|
+
{
|
|
55746
|
+
"kind": "method",
|
|
55747
|
+
"name": "renderControls",
|
|
55748
|
+
"privacy": "private",
|
|
55749
|
+
"return": {
|
|
55750
|
+
"type": {
|
|
55751
|
+
"text": "TemplateResult | typeof nothing"
|
|
55752
|
+
}
|
|
55753
|
+
},
|
|
55754
|
+
"description": "The controls, or nothing where a consumer kept none of them.\n\n**Written out rather than generated**, because a part name behind an\ninterpolation is a part the manifest cannot see: it would publish `pan-`\nand a consumer's `::part(pan-up)` would match nothing. The same cost\n`drawIcon` names for `Trend`."
|
|
55755
|
+
},
|
|
55694
55756
|
{
|
|
55695
55757
|
"kind": "field",
|
|
55696
55758
|
"name": "tier",
|
|
@@ -56035,6 +56097,22 @@
|
|
|
56035
56097
|
}
|
|
56036
56098
|
],
|
|
56037
56099
|
"attributes": [
|
|
56100
|
+
{
|
|
56101
|
+
"name": "controls",
|
|
56102
|
+
"type": {
|
|
56103
|
+
"text": "string | undefined"
|
|
56104
|
+
},
|
|
56105
|
+
"description": "Which of the controls this frame draws, as a list of what to keep.\n\n**A list rather than a switch, because the overlap is not symmetric.**\nEvery map library draws zoom controls and none of them draws pan buttons:\nMapLibre's navigation control is zoom and a compass, Leaflet's is zoom,\nGoogle's is zoom. So a consumer slotting one of those has our zoom twice\nover and our pan pad not at all, and a single switch would make them choose\nbetween a duplicate and nothing.\n\n`none` draws none of them, which is the right answer where the slotted map\nalready has controls a reader can find: what this family argues for is that\n*a* findable control exists, never that it is ours. The methods stay public\neither way, so a consumer drawing their own chrome can still drive the\nframe.\n\nAbsent is all three, which is this library's rule that a resting value is an\nattribute's absence, and it is what the stylesheet asks about: the layout\nrules are written against `[controls]:not([controls~=\"zoom\"])` rather than\nthe bare negation, or a frame that named no list at all would be laid out as\nthough it had dropped everything.",
|
|
56106
|
+
"fieldName": "controls"
|
|
56107
|
+
},
|
|
56108
|
+
{
|
|
56109
|
+
"name": "controls-placement",
|
|
56110
|
+
"type": {
|
|
56111
|
+
"text": "'top-start' | 'top-end' | 'bottom-start' | 'bottom-end' | undefined"
|
|
56112
|
+
},
|
|
56113
|
+
"description": "Which corner the controls sit in.\n\n**Configurable because there is no safe default**, and this is a collision\nrather than a taste: MapLibre puts its own controls at the top end, Leaflet\nand OpenLayers at the top start, Google's zoom at the bottom end. Whichever\ncorner this took would land on somebody's, which is why every one of those\nlibraries made it a setting too.\n\nLogical corners rather than left and right, so a right-to-left page moves\nthem without a consumer writing a second rule.\n\nAbsent is the top end, which is this library's rule that a resting value is\nan attribute's absence: a default that reflected would write an attribute\nonto every host that no server sent and nobody asked for.",
|
|
56114
|
+
"fieldName": "controlsPlacement"
|
|
56115
|
+
},
|
|
56038
56116
|
{
|
|
56039
56117
|
"name": "fullscreen-label",
|
|
56040
56118
|
"type": {
|
|
@@ -2,6 +2,8 @@ import { HelixElement } from '@fusion.dev/helix-core';
|
|
|
2
2
|
import { type PropertyValues, type TemplateResult } from 'lit';
|
|
3
3
|
/** Which way a press or a key asked the map to go. */
|
|
4
4
|
type Way = 'up' | 'down' | 'start' | 'end';
|
|
5
|
+
/** Where the controls sit, in the corner words the rest of the library uses. */
|
|
6
|
+
export type MapControlsPlacement = 'top-start' | 'top-end' | 'bottom-start' | 'bottom-end';
|
|
5
7
|
/**
|
|
6
8
|
* @summary A frame around somebody else's map.
|
|
7
9
|
*
|
|
@@ -44,8 +46,11 @@ type Way = 'up' | 'down' | 'start' | 'end';
|
|
|
44
46
|
* @event {HelixMapPanEvent} helix-map-pan - The reader asked the map to move. Answer it against your own map.
|
|
45
47
|
* @event {HelixMapZoomEvent} helix-map-zoom - The reader asked the map to zoom, by a direction rather than to a level.
|
|
46
48
|
*
|
|
49
|
+
* @csspart attribution - The strip the credit sits in, under the map.
|
|
47
50
|
* @csspart controls - The group the pan and zoom buttons sit in.
|
|
51
|
+
* @csspart footer - The strip below the map, for what a consumer slots there.
|
|
48
52
|
* @csspart fullscreen - The button that fills the screen.
|
|
53
|
+
* @csspart header - The strip above the map, for what a consumer slots there.
|
|
49
54
|
* @csspart pan-down - The button that moves the map down.
|
|
50
55
|
* @csspart pan-end - The button that moves the map the way the text ends, which is right on an English page.
|
|
51
56
|
* @csspart pan-start - The button that moves the map the way the text starts, which is left on an English page.
|
|
@@ -59,6 +64,46 @@ type Way = 'up' | 'down' | 'start' | 'end';
|
|
|
59
64
|
* @cssstate idle - While the reader has been still long enough to hide the chrome.
|
|
60
65
|
*/
|
|
61
66
|
export declare class HelixHeadlessMap extends HelixElement {
|
|
67
|
+
/**
|
|
68
|
+
* Which of the controls this frame draws, as a list of what to keep.
|
|
69
|
+
*
|
|
70
|
+
* **A list rather than a switch, because the overlap is not symmetric.**
|
|
71
|
+
* Every map library draws zoom controls and none of them draws pan buttons:
|
|
72
|
+
* MapLibre's navigation control is zoom and a compass, Leaflet's is zoom,
|
|
73
|
+
* Google's is zoom. So a consumer slotting one of those has our zoom twice
|
|
74
|
+
* over and our pan pad not at all, and a single switch would make them choose
|
|
75
|
+
* between a duplicate and nothing.
|
|
76
|
+
*
|
|
77
|
+
* `none` draws none of them, which is the right answer where the slotted map
|
|
78
|
+
* already has controls a reader can find: what this family argues for is that
|
|
79
|
+
* *a* findable control exists, never that it is ours. The methods stay public
|
|
80
|
+
* either way, so a consumer drawing their own chrome can still drive the
|
|
81
|
+
* frame.
|
|
82
|
+
*
|
|
83
|
+
* Absent is all three, which is this library's rule that a resting value is an
|
|
84
|
+
* attribute's absence, and it is what the stylesheet asks about: the layout
|
|
85
|
+
* rules are written against `[controls]:not([controls~="zoom"])` rather than
|
|
86
|
+
* the bare negation, or a frame that named no list at all would be laid out as
|
|
87
|
+
* though it had dropped everything.
|
|
88
|
+
*/
|
|
89
|
+
controls?: string;
|
|
90
|
+
/**
|
|
91
|
+
* Which corner the controls sit in.
|
|
92
|
+
*
|
|
93
|
+
* **Configurable because there is no safe default**, and this is a collision
|
|
94
|
+
* rather than a taste: MapLibre puts its own controls at the top end, Leaflet
|
|
95
|
+
* and OpenLayers at the top start, Google's zoom at the bottom end. Whichever
|
|
96
|
+
* corner this took would land on somebody's, which is why every one of those
|
|
97
|
+
* libraries made it a setting too.
|
|
98
|
+
*
|
|
99
|
+
* Logical corners rather than left and right, so a right-to-left page moves
|
|
100
|
+
* them without a consumer writing a second rule.
|
|
101
|
+
*
|
|
102
|
+
* Absent is the top end, which is this library's rule that a resting value is
|
|
103
|
+
* an attribute's absence: a default that reflected would write an attribute
|
|
104
|
+
* onto every host that no server sent and nobody asked for.
|
|
105
|
+
*/
|
|
106
|
+
controlsPlacement?: MapControlsPlacement;
|
|
62
107
|
/** What the control that fills the screen is called. */
|
|
63
108
|
fullscreenLabel: string;
|
|
64
109
|
/**
|
|
@@ -100,6 +145,8 @@ export declare class HelixHeadlessMap extends HelixElement {
|
|
|
100
145
|
private filled;
|
|
101
146
|
private readonly fullscreen;
|
|
102
147
|
private readonly idle;
|
|
148
|
+
/** Whether a named group of controls is one this frame draws. */
|
|
149
|
+
private draws;
|
|
103
150
|
/** Fills the screen with the frame, or comes back. */
|
|
104
151
|
toggleFullscreen(): void;
|
|
105
152
|
/** Asks for the map to move, which the consumer answers. */
|
|
@@ -132,6 +179,27 @@ export declare class HelixHeadlessMap extends HelixElement {
|
|
|
132
179
|
* name, which is the one a right-to-left page needs.
|
|
133
180
|
*/
|
|
134
181
|
private named;
|
|
182
|
+
/**
|
|
183
|
+
* The controls, or nothing where a consumer kept none of them.
|
|
184
|
+
*
|
|
185
|
+
* **Written out rather than generated**, because a part name behind an
|
|
186
|
+
* interpolation is a part the manifest cannot see: it would publish `pan-`
|
|
187
|
+
* and a consumer's `::part(pan-up)` would match nothing. The same cost
|
|
188
|
+
* `drawIcon` names for `Trend`.
|
|
189
|
+
*/
|
|
190
|
+
private renderControls;
|
|
191
|
+
/**
|
|
192
|
+
* The frame, with each region in a box of its own.
|
|
193
|
+
*
|
|
194
|
+
* **The boxes are load-bearing rather than tidiness.** A `<slot>` is
|
|
195
|
+
* `display: contents`, so what lands in the grid is whatever a consumer
|
|
196
|
+
* assigned rather than the slot itself: with no header slotted, the viewport
|
|
197
|
+
* took the first row and the attribution took the `1fr`, and the map collapsed
|
|
198
|
+
* to the height of one line of text. Which slots a consumer fills is not
|
|
199
|
+
* something the layout may depend on, so each region is a box that holds its
|
|
200
|
+
* row whether or not anything is in it, and an empty one is a row of no
|
|
201
|
+
* height.
|
|
202
|
+
*/
|
|
135
203
|
protected render(): TemplateResult;
|
|
136
204
|
}
|
|
137
205
|
declare global {
|
|
@@ -5,7 +5,7 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
|
|
|
5
5
|
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
6
6
|
};
|
|
7
7
|
import { customElement, FullscreenController, HelixElement, HelixMapPanEvent, HelixMapZoomEvent, hostAria, IdleController, inlineStep, } from '@fusion.dev/helix-core';
|
|
8
|
-
import { html } from 'lit';
|
|
8
|
+
import { html, nothing } from 'lit';
|
|
9
9
|
import { property, state } from 'lit/decorators.js';
|
|
10
10
|
let HelixHeadlessMap = class HelixHeadlessMap extends HelixElement {
|
|
11
11
|
constructor() {
|
|
@@ -53,6 +53,9 @@ let HelixHeadlessMap = class HelixHeadlessMap extends HelixElement {
|
|
|
53
53
|
}
|
|
54
54
|
};
|
|
55
55
|
}
|
|
56
|
+
draws(group) {
|
|
57
|
+
return this.controls === undefined ? true : this.controls.split(/\s+/).includes(group);
|
|
58
|
+
}
|
|
56
59
|
toggleFullscreen() {
|
|
57
60
|
void this.fullscreen.toggle();
|
|
58
61
|
}
|
|
@@ -76,6 +79,49 @@ let HelixHeadlessMap = class HelixHeadlessMap extends HelixElement {
|
|
|
76
79
|
const spoken = way === 'start' ? 'left' : way === 'end' ? 'right' : way;
|
|
77
80
|
return this.panLabel.replace('{way}', spoken);
|
|
78
81
|
}
|
|
82
|
+
renderControls() {
|
|
83
|
+
const pan = this.draws('pan');
|
|
84
|
+
const zoom = this.draws('zoom');
|
|
85
|
+
const fullscreen = this.draws('fullscreen');
|
|
86
|
+
if (!pan && !zoom && !fullscreen) {
|
|
87
|
+
return nothing;
|
|
88
|
+
}
|
|
89
|
+
return html `<div part="controls" role="group" aria-label="Map controls">
|
|
90
|
+
${pan
|
|
91
|
+
? html `<button part="pan-up" aria-label=${this.named('up')} type="button" @click=${() => this.pan('up')}>
|
|
92
|
+
↑
|
|
93
|
+
</button>
|
|
94
|
+
<button part="pan-start" aria-label=${this.named('start')} type="button" @click=${() => this.pan('start')}>
|
|
95
|
+
←
|
|
96
|
+
</button>
|
|
97
|
+
<button part="pan-end" aria-label=${this.named('end')} type="button" @click=${() => this.pan('end')}>
|
|
98
|
+
→
|
|
99
|
+
</button>
|
|
100
|
+
<button part="pan-down" aria-label=${this.named('down')} type="button" @click=${() => this.pan('down')}>
|
|
101
|
+
↓
|
|
102
|
+
</button>`
|
|
103
|
+
: nothing}
|
|
104
|
+
${zoom
|
|
105
|
+
? html `<button part="zoom-in" aria-label=${this.zoomInLabel} type="button" @click=${() => this.zoom(1)}>
|
|
106
|
+
+
|
|
107
|
+
</button>
|
|
108
|
+
<button part="zoom-out" aria-label=${this.zoomOutLabel} type="button" @click=${() => this.zoom(-1)}>
|
|
109
|
+
−
|
|
110
|
+
</button>`
|
|
111
|
+
: nothing}
|
|
112
|
+
${fullscreen
|
|
113
|
+
? html `<button
|
|
114
|
+
part="fullscreen"
|
|
115
|
+
aria-label=${this.fullscreenLabel}
|
|
116
|
+
aria-pressed=${this.filled ? 'true' : 'false'}
|
|
117
|
+
type="button"
|
|
118
|
+
@click=${this.toggleFullscreen}
|
|
119
|
+
>
|
|
120
|
+
⤢
|
|
121
|
+
</button>`
|
|
122
|
+
: nothing}
|
|
123
|
+
</div>`;
|
|
124
|
+
}
|
|
79
125
|
render() {
|
|
80
126
|
return html `<div
|
|
81
127
|
part="region"
|
|
@@ -86,48 +132,28 @@ let HelixHeadlessMap = class HelixHeadlessMap extends HelixElement {
|
|
|
86
132
|
@pointerleave=${this.idle.leave}
|
|
87
133
|
@pointermove=${this.idle.stir}
|
|
88
134
|
>
|
|
89
|
-
<
|
|
135
|
+
<div part="header">
|
|
136
|
+
<slot name="header"></slot>
|
|
137
|
+
</div>
|
|
90
138
|
<div part="viewport">
|
|
91
139
|
<slot></slot>
|
|
92
140
|
</div>
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
<
|
|
99
|
-
↑
|
|
100
|
-
</button>
|
|
101
|
-
<button part="pan-start" aria-label=${this.named('start')} type="button" @click=${() => this.pan('start')}>
|
|
102
|
-
←
|
|
103
|
-
</button>
|
|
104
|
-
<button part="pan-end" aria-label=${this.named('end')} type="button" @click=${() => this.pan('end')}>
|
|
105
|
-
→
|
|
106
|
-
</button>
|
|
107
|
-
<button part="pan-down" aria-label=${this.named('down')} type="button" @click=${() => this.pan('down')}>
|
|
108
|
-
↓
|
|
109
|
-
</button>
|
|
110
|
-
<button part="zoom-in" aria-label=${this.zoomInLabel} type="button" @click=${() => this.zoom(1)}>
|
|
111
|
-
+
|
|
112
|
-
</button>
|
|
113
|
-
<button part="zoom-out" aria-label=${this.zoomOutLabel} type="button" @click=${() => this.zoom(-1)}>
|
|
114
|
-
−
|
|
115
|
-
</button>
|
|
116
|
-
<button
|
|
117
|
-
part="fullscreen"
|
|
118
|
-
aria-label=${this.fullscreenLabel}
|
|
119
|
-
aria-pressed=${this.filled ? 'true' : 'false'}
|
|
120
|
-
type="button"
|
|
121
|
-
@click=${this.toggleFullscreen}
|
|
122
|
-
>
|
|
123
|
-
⤢
|
|
124
|
-
</button>
|
|
141
|
+
${this.renderControls()}
|
|
142
|
+
<div part="footer">
|
|
143
|
+
<slot name="footer"></slot>
|
|
144
|
+
</div>
|
|
145
|
+
<div part="attribution">
|
|
146
|
+
<slot name="attribution"></slot>
|
|
125
147
|
</div>
|
|
126
|
-
<slot name="footer"></slot>
|
|
127
|
-
<slot name="attribution"></slot>
|
|
128
148
|
</div>`;
|
|
129
149
|
}
|
|
130
150
|
};
|
|
151
|
+
__decorate([
|
|
152
|
+
property({ reflect: true })
|
|
153
|
+
], HelixHeadlessMap.prototype, "controls", void 0);
|
|
154
|
+
__decorate([
|
|
155
|
+
property({ attribute: 'controls-placement', reflect: true })
|
|
156
|
+
], HelixHeadlessMap.prototype, "controlsPlacement", void 0);
|
|
131
157
|
__decorate([
|
|
132
158
|
property({ attribute: 'fullscreen-label' })
|
|
133
159
|
], HelixHeadlessMap.prototype, "fullscreenLabel", void 0);
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@fusion.dev/helix-headless",
|
|
3
3
|
"description": "Headless component tier. Structure, accessibility, state, and form participation. No styling.",
|
|
4
|
-
"version": "0.
|
|
4
|
+
"version": "0.103.1",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "Ross Sheppard <ross.sheppard@fusion.dev>",
|
|
7
7
|
"repository": {
|
|
@@ -46,13 +46,13 @@
|
|
|
46
46
|
},
|
|
47
47
|
"bugs": "https://github.com/project-fusion/fusion/issues",
|
|
48
48
|
"dependencies": {
|
|
49
|
-
"@fusion.dev/helix-core": "0.
|
|
50
|
-
"@fusion.dev/helix-icons": "0.
|
|
49
|
+
"@fusion.dev/helix-core": "0.103.1",
|
|
50
|
+
"@fusion.dev/helix-icons": "0.103.1",
|
|
51
51
|
"uqr": "^0.1.3"
|
|
52
52
|
},
|
|
53
53
|
"devDependencies": {
|
|
54
|
-
"@fusion.dev/helix-cem": "0.
|
|
55
|
-
"@fusion.dev/helix-testing": "0.
|
|
54
|
+
"@fusion.dev/helix-cem": "0.103.1",
|
|
55
|
+
"@fusion.dev/helix-testing": "0.103.1",
|
|
56
56
|
"@fusion.dev/scripts": "0.0.0-dev",
|
|
57
57
|
"@happy-dom/global-registrator": "^20.0.0",
|
|
58
58
|
"@lit-labs/ssr": "^4.1.0",
|
package/types/jsx.d.ts
CHANGED
|
@@ -9396,6 +9396,57 @@ export type HelixHeadlessMapHelixMapZoomElementEvent =
|
|
|
9396
9396
|
HelixHeadlessMapElementEvent<HelixMapZoomEvent>;
|
|
9397
9397
|
|
|
9398
9398
|
export type HelixHeadlessMapProps = {
|
|
9399
|
+
/** Which of the controls this frame draws, as a list of what to keep.
|
|
9400
|
+
|
|
9401
|
+
**A list rather than a switch, because the overlap is not symmetric.**
|
|
9402
|
+
Every map library draws zoom controls and none of them draws pan buttons:
|
|
9403
|
+
MapLibre's navigation control is zoom and a compass, Leaflet's is zoom,
|
|
9404
|
+
Google's is zoom. So a consumer slotting one of those has our zoom twice
|
|
9405
|
+
over and our pan pad not at all, and a single switch would make them choose
|
|
9406
|
+
between a duplicate and nothing.
|
|
9407
|
+
|
|
9408
|
+
`none` draws none of them, which is the right answer where the slotted map
|
|
9409
|
+
already has controls a reader can find: what this family argues for is that
|
|
9410
|
+
*a* findable control exists, never that it is ours. The methods stay public
|
|
9411
|
+
either way, so a consumer drawing their own chrome can still drive the
|
|
9412
|
+
frame.
|
|
9413
|
+
|
|
9414
|
+
Absent is all three, which is this library's rule that a resting value is an
|
|
9415
|
+
attribute's absence, and it is what the stylesheet asks about: the layout
|
|
9416
|
+
rules are written against `[controls]:not([controls~="zoom"])` rather than
|
|
9417
|
+
the bare negation, or a frame that named no list at all would be laid out as
|
|
9418
|
+
though it had dropped everything. */
|
|
9419
|
+
controls?: (HelixHeadlessMap["controls"]) | undefined;
|
|
9420
|
+
/** Which corner the controls sit in.
|
|
9421
|
+
|
|
9422
|
+
**Configurable because there is no safe default**, and this is a collision
|
|
9423
|
+
rather than a taste: MapLibre puts its own controls at the top end, Leaflet
|
|
9424
|
+
and OpenLayers at the top start, Google's zoom at the bottom end. Whichever
|
|
9425
|
+
corner this took would land on somebody's, which is why every one of those
|
|
9426
|
+
libraries made it a setting too.
|
|
9427
|
+
|
|
9428
|
+
Logical corners rather than left and right, so a right-to-left page moves
|
|
9429
|
+
them without a consumer writing a second rule.
|
|
9430
|
+
|
|
9431
|
+
Absent is the top end, which is this library's rule that a resting value is
|
|
9432
|
+
an attribute's absence: a default that reflected would write an attribute
|
|
9433
|
+
onto every host that no server sent and nobody asked for. */
|
|
9434
|
+
"controls-placement"?: (HelixHeadlessMap["controlsPlacement"]) | undefined;
|
|
9435
|
+
/** Which corner the controls sit in.
|
|
9436
|
+
|
|
9437
|
+
**Configurable because there is no safe default**, and this is a collision
|
|
9438
|
+
rather than a taste: MapLibre puts its own controls at the top end, Leaflet
|
|
9439
|
+
and OpenLayers at the top start, Google's zoom at the bottom end. Whichever
|
|
9440
|
+
corner this took would land on somebody's, which is why every one of those
|
|
9441
|
+
libraries made it a setting too.
|
|
9442
|
+
|
|
9443
|
+
Logical corners rather than left and right, so a right-to-left page moves
|
|
9444
|
+
them without a consumer writing a second rule.
|
|
9445
|
+
|
|
9446
|
+
Absent is the top end, which is this library's rule that a resting value is
|
|
9447
|
+
an attribute's absence: a default that reflected would write an attribute
|
|
9448
|
+
onto every host that no server sent and nobody asked for. */
|
|
9449
|
+
controlsPlacement?: (HelixHeadlessMap["controlsPlacement"]) | undefined;
|
|
9399
9450
|
/** What the control that fills the screen is called. */
|
|
9400
9451
|
"fullscreen-label"?: (HelixHeadlessMap["fullscreenLabel"]) | undefined;
|
|
9401
9452
|
/** What the control that fills the screen is called. */
|
|
@@ -9452,6 +9503,57 @@ multiply by their own. */
|
|
|
9452
9503
|
};
|
|
9453
9504
|
|
|
9454
9505
|
export type HelixHeadlessMapSolidJsProps = {
|
|
9506
|
+
/** Which of the controls this frame draws, as a list of what to keep.
|
|
9507
|
+
|
|
9508
|
+
**A list rather than a switch, because the overlap is not symmetric.**
|
|
9509
|
+
Every map library draws zoom controls and none of them draws pan buttons:
|
|
9510
|
+
MapLibre's navigation control is zoom and a compass, Leaflet's is zoom,
|
|
9511
|
+
Google's is zoom. So a consumer slotting one of those has our zoom twice
|
|
9512
|
+
over and our pan pad not at all, and a single switch would make them choose
|
|
9513
|
+
between a duplicate and nothing.
|
|
9514
|
+
|
|
9515
|
+
`none` draws none of them, which is the right answer where the slotted map
|
|
9516
|
+
already has controls a reader can find: what this family argues for is that
|
|
9517
|
+
*a* findable control exists, never that it is ours. The methods stay public
|
|
9518
|
+
either way, so a consumer drawing their own chrome can still drive the
|
|
9519
|
+
frame.
|
|
9520
|
+
|
|
9521
|
+
Absent is all three, which is this library's rule that a resting value is an
|
|
9522
|
+
attribute's absence, and it is what the stylesheet asks about: the layout
|
|
9523
|
+
rules are written against `[controls]:not([controls~="zoom"])` rather than
|
|
9524
|
+
the bare negation, or a frame that named no list at all would be laid out as
|
|
9525
|
+
though it had dropped everything. */
|
|
9526
|
+
"prop:controls"?: (HelixHeadlessMap["controls"]) | undefined;
|
|
9527
|
+
/** Which corner the controls sit in.
|
|
9528
|
+
|
|
9529
|
+
**Configurable because there is no safe default**, and this is a collision
|
|
9530
|
+
rather than a taste: MapLibre puts its own controls at the top end, Leaflet
|
|
9531
|
+
and OpenLayers at the top start, Google's zoom at the bottom end. Whichever
|
|
9532
|
+
corner this took would land on somebody's, which is why every one of those
|
|
9533
|
+
libraries made it a setting too.
|
|
9534
|
+
|
|
9535
|
+
Logical corners rather than left and right, so a right-to-left page moves
|
|
9536
|
+
them without a consumer writing a second rule.
|
|
9537
|
+
|
|
9538
|
+
Absent is the top end, which is this library's rule that a resting value is
|
|
9539
|
+
an attribute's absence: a default that reflected would write an attribute
|
|
9540
|
+
onto every host that no server sent and nobody asked for. */
|
|
9541
|
+
"attr:controls-placement"?: (HelixHeadlessMap["controlsPlacement"]) | undefined;
|
|
9542
|
+
/** Which corner the controls sit in.
|
|
9543
|
+
|
|
9544
|
+
**Configurable because there is no safe default**, and this is a collision
|
|
9545
|
+
rather than a taste: MapLibre puts its own controls at the top end, Leaflet
|
|
9546
|
+
and OpenLayers at the top start, Google's zoom at the bottom end. Whichever
|
|
9547
|
+
corner this took would land on somebody's, which is why every one of those
|
|
9548
|
+
libraries made it a setting too.
|
|
9549
|
+
|
|
9550
|
+
Logical corners rather than left and right, so a right-to-left page moves
|
|
9551
|
+
them without a consumer writing a second rule.
|
|
9552
|
+
|
|
9553
|
+
Absent is the top end, which is this library's rule that a resting value is
|
|
9554
|
+
an attribute's absence: a default that reflected would write an attribute
|
|
9555
|
+
onto every host that no server sent and nobody asked for. */
|
|
9556
|
+
"prop:controlsPlacement"?: (HelixHeadlessMap["controlsPlacement"]) | undefined;
|
|
9455
9557
|
/** What the control that fills the screen is called. */
|
|
9456
9558
|
"attr:fullscreen-label"?: (HelixHeadlessMap["fullscreenLabel"]) | undefined;
|
|
9457
9559
|
/** What the control that fills the screen is called. */
|
|
@@ -27514,6 +27616,40 @@ export type CustomElements = {
|
|
|
27514
27616
|
*
|
|
27515
27617
|
* Component attributes and properties that can be applied to the element or by using JavaScript.
|
|
27516
27618
|
*
|
|
27619
|
+
* - `controls`: Which of the controls this frame draws, as a list of what to keep.
|
|
27620
|
+
*
|
|
27621
|
+
* **A list rather than a switch, because the overlap is not symmetric.**
|
|
27622
|
+
* Every map library draws zoom controls and none of them draws pan buttons:
|
|
27623
|
+
* MapLibre's navigation control is zoom and a compass, Leaflet's is zoom,
|
|
27624
|
+
* Google's is zoom. So a consumer slotting one of those has our zoom twice
|
|
27625
|
+
* over and our pan pad not at all, and a single switch would make them choose
|
|
27626
|
+
* between a duplicate and nothing.
|
|
27627
|
+
*
|
|
27628
|
+
* `none` draws none of them, which is the right answer where the slotted map
|
|
27629
|
+
* already has controls a reader can find: what this family argues for is that
|
|
27630
|
+
* *a* findable control exists, never that it is ours. The methods stay public
|
|
27631
|
+
* either way, so a consumer drawing their own chrome can still drive the
|
|
27632
|
+
* frame.
|
|
27633
|
+
*
|
|
27634
|
+
* Absent is all three, which is this library's rule that a resting value is an
|
|
27635
|
+
* attribute's absence, and it is what the stylesheet asks about: the layout
|
|
27636
|
+
* rules are written against `[controls]:not([controls~="zoom"])` rather than
|
|
27637
|
+
* the bare negation, or a frame that named no list at all would be laid out as
|
|
27638
|
+
* though it had dropped everything.
|
|
27639
|
+
* - `controls-placement`/`controlsPlacement`: Which corner the controls sit in.
|
|
27640
|
+
*
|
|
27641
|
+
* **Configurable because there is no safe default**, and this is a collision
|
|
27642
|
+
* rather than a taste: MapLibre puts its own controls at the top end, Leaflet
|
|
27643
|
+
* and OpenLayers at the top start, Google's zoom at the bottom end. Whichever
|
|
27644
|
+
* corner this took would land on somebody's, which is why every one of those
|
|
27645
|
+
* libraries made it a setting too.
|
|
27646
|
+
*
|
|
27647
|
+
* Logical corners rather than left and right, so a right-to-left page moves
|
|
27648
|
+
* them without a consumer writing a second rule.
|
|
27649
|
+
*
|
|
27650
|
+
* Absent is the top end, which is this library's rule that a resting value is
|
|
27651
|
+
* an attribute's absence: a default that reflected would write an attribute
|
|
27652
|
+
* onto every host that no server sent and nobody asked for.
|
|
27517
27653
|
* - `fullscreen-label`/`fullscreenLabel`: What the control that fills the screen is called.
|
|
27518
27654
|
* - `idle-delay`/`idleDelay`: How long the reader may be still before the chrome hides, in milliseconds.
|
|
27519
27655
|
*
|
|
@@ -27583,8 +27719,11 @@ export type CustomElements = {
|
|
|
27583
27719
|
*
|
|
27584
27720
|
* Custom selectors for styling elements within the component.
|
|
27585
27721
|
*
|
|
27722
|
+
* - `attribution`: The strip the credit sits in, under the map.
|
|
27586
27723
|
* - `controls`: The group the pan and zoom buttons sit in.
|
|
27724
|
+
* - `footer`: The strip below the map, for what a consumer slots there.
|
|
27587
27725
|
* - `fullscreen`: The button that fills the screen.
|
|
27726
|
+
* - `header`: The strip above the map, for what a consumer slots there.
|
|
27588
27727
|
* - `pan-down`: The button that moves the map down.
|
|
27589
27728
|
* - `pan-end`: The button that moves the map the way the text ends, which is right on an English page.
|
|
27590
27729
|
* - `pan-start`: The button that moves the map the way the text starts, which is left on an English page.
|
|
@@ -45982,6 +46121,40 @@ export type CustomElementsSolidJs = {
|
|
|
45982
46121
|
*
|
|
45983
46122
|
* Component attributes and properties that can be applied to the element or by using JavaScript.
|
|
45984
46123
|
*
|
|
46124
|
+
* - `controls`: Which of the controls this frame draws, as a list of what to keep.
|
|
46125
|
+
*
|
|
46126
|
+
* **A list rather than a switch, because the overlap is not symmetric.**
|
|
46127
|
+
* Every map library draws zoom controls and none of them draws pan buttons:
|
|
46128
|
+
* MapLibre's navigation control is zoom and a compass, Leaflet's is zoom,
|
|
46129
|
+
* Google's is zoom. So a consumer slotting one of those has our zoom twice
|
|
46130
|
+
* over and our pan pad not at all, and a single switch would make them choose
|
|
46131
|
+
* between a duplicate and nothing.
|
|
46132
|
+
*
|
|
46133
|
+
* `none` draws none of them, which is the right answer where the slotted map
|
|
46134
|
+
* already has controls a reader can find: what this family argues for is that
|
|
46135
|
+
* *a* findable control exists, never that it is ours. The methods stay public
|
|
46136
|
+
* either way, so a consumer drawing their own chrome can still drive the
|
|
46137
|
+
* frame.
|
|
46138
|
+
*
|
|
46139
|
+
* Absent is all three, which is this library's rule that a resting value is an
|
|
46140
|
+
* attribute's absence, and it is what the stylesheet asks about: the layout
|
|
46141
|
+
* rules are written against `[controls]:not([controls~="zoom"])` rather than
|
|
46142
|
+
* the bare negation, or a frame that named no list at all would be laid out as
|
|
46143
|
+
* though it had dropped everything.
|
|
46144
|
+
* - `controls-placement`/`controlsPlacement`: Which corner the controls sit in.
|
|
46145
|
+
*
|
|
46146
|
+
* **Configurable because there is no safe default**, and this is a collision
|
|
46147
|
+
* rather than a taste: MapLibre puts its own controls at the top end, Leaflet
|
|
46148
|
+
* and OpenLayers at the top start, Google's zoom at the bottom end. Whichever
|
|
46149
|
+
* corner this took would land on somebody's, which is why every one of those
|
|
46150
|
+
* libraries made it a setting too.
|
|
46151
|
+
*
|
|
46152
|
+
* Logical corners rather than left and right, so a right-to-left page moves
|
|
46153
|
+
* them without a consumer writing a second rule.
|
|
46154
|
+
*
|
|
46155
|
+
* Absent is the top end, which is this library's rule that a resting value is
|
|
46156
|
+
* an attribute's absence: a default that reflected would write an attribute
|
|
46157
|
+
* onto every host that no server sent and nobody asked for.
|
|
45985
46158
|
* - `fullscreen-label`/`fullscreenLabel`: What the control that fills the screen is called.
|
|
45986
46159
|
* - `idle-delay`/`idleDelay`: How long the reader may be still before the chrome hides, in milliseconds.
|
|
45987
46160
|
*
|
|
@@ -46051,8 +46224,11 @@ export type CustomElementsSolidJs = {
|
|
|
46051
46224
|
*
|
|
46052
46225
|
* Custom selectors for styling elements within the component.
|
|
46053
46226
|
*
|
|
46227
|
+
* - `attribution`: The strip the credit sits in, under the map.
|
|
46054
46228
|
* - `controls`: The group the pan and zoom buttons sit in.
|
|
46229
|
+
* - `footer`: The strip below the map, for what a consumer slots there.
|
|
46055
46230
|
* - `fullscreen`: The button that fills the screen.
|
|
46231
|
+
* - `header`: The strip above the map, for what a consumer slots there.
|
|
46056
46232
|
* - `pan-down`: The button that moves the map down.
|
|
46057
46233
|
* - `pan-end`: The button that moves the map the way the text ends, which is right on an English page.
|
|
46058
46234
|
* - `pan-start`: The button that moves the map the way the text starts, which is left on an English page.
|
package/types/vue.d.ts
CHANGED
|
@@ -4808,6 +4808,57 @@ export type HelixHeadlessMapHelixMapZoomElementEvent =
|
|
|
4808
4808
|
HelixHeadlessMapElementEvent<HelixMapZoomEvent>;
|
|
4809
4809
|
|
|
4810
4810
|
export type HelixHeadlessMapVueProps = {
|
|
4811
|
+
/** Which of the controls this frame draws, as a list of what to keep.
|
|
4812
|
+
|
|
4813
|
+
**A list rather than a switch, because the overlap is not symmetric.**
|
|
4814
|
+
Every map library draws zoom controls and none of them draws pan buttons:
|
|
4815
|
+
MapLibre's navigation control is zoom and a compass, Leaflet's is zoom,
|
|
4816
|
+
Google's is zoom. So a consumer slotting one of those has our zoom twice
|
|
4817
|
+
over and our pan pad not at all, and a single switch would make them choose
|
|
4818
|
+
between a duplicate and nothing.
|
|
4819
|
+
|
|
4820
|
+
`none` draws none of them, which is the right answer where the slotted map
|
|
4821
|
+
already has controls a reader can find: what this family argues for is that
|
|
4822
|
+
*a* findable control exists, never that it is ours. The methods stay public
|
|
4823
|
+
either way, so a consumer drawing their own chrome can still drive the
|
|
4824
|
+
frame.
|
|
4825
|
+
|
|
4826
|
+
Absent is all three, which is this library's rule that a resting value is an
|
|
4827
|
+
attribute's absence, and it is what the stylesheet asks about: the layout
|
|
4828
|
+
rules are written against `[controls]:not([controls~="zoom"])` rather than
|
|
4829
|
+
the bare negation, or a frame that named no list at all would be laid out as
|
|
4830
|
+
though it had dropped everything. */
|
|
4831
|
+
controls?: (HelixHeadlessMap["controls"]) | undefined;
|
|
4832
|
+
/** Which corner the controls sit in.
|
|
4833
|
+
|
|
4834
|
+
**Configurable because there is no safe default**, and this is a collision
|
|
4835
|
+
rather than a taste: MapLibre puts its own controls at the top end, Leaflet
|
|
4836
|
+
and OpenLayers at the top start, Google's zoom at the bottom end. Whichever
|
|
4837
|
+
corner this took would land on somebody's, which is why every one of those
|
|
4838
|
+
libraries made it a setting too.
|
|
4839
|
+
|
|
4840
|
+
Logical corners rather than left and right, so a right-to-left page moves
|
|
4841
|
+
them without a consumer writing a second rule.
|
|
4842
|
+
|
|
4843
|
+
Absent is the top end, which is this library's rule that a resting value is
|
|
4844
|
+
an attribute's absence: a default that reflected would write an attribute
|
|
4845
|
+
onto every host that no server sent and nobody asked for. */
|
|
4846
|
+
"controls-placement"?: (HelixHeadlessMap["controlsPlacement"]) | undefined;
|
|
4847
|
+
/** Which corner the controls sit in.
|
|
4848
|
+
|
|
4849
|
+
**Configurable because there is no safe default**, and this is a collision
|
|
4850
|
+
rather than a taste: MapLibre puts its own controls at the top end, Leaflet
|
|
4851
|
+
and OpenLayers at the top start, Google's zoom at the bottom end. Whichever
|
|
4852
|
+
corner this took would land on somebody's, which is why every one of those
|
|
4853
|
+
libraries made it a setting too.
|
|
4854
|
+
|
|
4855
|
+
Logical corners rather than left and right, so a right-to-left page moves
|
|
4856
|
+
them without a consumer writing a second rule.
|
|
4857
|
+
|
|
4858
|
+
Absent is the top end, which is this library's rule that a resting value is
|
|
4859
|
+
an attribute's absence: a default that reflected would write an attribute
|
|
4860
|
+
onto every host that no server sent and nobody asked for. */
|
|
4861
|
+
controlsPlacement?: (HelixHeadlessMap["controlsPlacement"]) | undefined;
|
|
4811
4862
|
/** What the control that fills the screen is called. */
|
|
4812
4863
|
"fullscreen-label"?: (HelixHeadlessMap["fullscreenLabel"]) | undefined;
|
|
4813
4864
|
/** What the control that fills the screen is called. */
|