@fusion.dev/helix-headless 0.151.0 → 0.153.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/custom-elements.json +1332 -37
- package/dist/app-header/root/app-header-root.d.ts +75 -0
- package/dist/app-header/root/app-header-root.js +140 -5
- package/dist/area-chart/root/area-chart-root.d.ts +16 -1
- package/dist/area-chart/root/area-chart-root.js +3 -3
- package/dist/bar-chart/root/bar-chart-root.d.ts +16 -1
- package/dist/bar-chart/root/bar-chart-root.js +3 -3
- package/dist/breadcrumbs/breadcrumb/breadcrumb.d.ts +11 -2
- package/dist/breadcrumbs/breadcrumb/breadcrumb.js +11 -2
- package/dist/breadcrumbs/root/breadcrumbs-root.d.ts +14 -2
- package/dist/breadcrumbs/root/breadcrumbs-root.js +16 -3
- package/dist/dialog/description.d.ts +10 -0
- package/dist/dialog/description.js +22 -8
- package/dist/dialog/root/dialog-root.d.ts +17 -1
- package/dist/dialog/root/dialog-root.js +2 -2
- package/dist/drawer/root/drawer-root.d.ts +38 -2
- package/dist/drawer/root/drawer-root.js +33 -6
- package/dist/heatmap/root/heatmap-root.d.ts +3 -0
- package/dist/heatmap/root/heatmap-root.js +2 -8
- package/dist/lightbox/root/lightbox-root.d.ts +44 -6
- package/dist/lightbox/root/lightbox-root.js +59 -11
- package/dist/lightbox/zoom-controller.d.ts +5 -0
- package/dist/lightbox/zoom-controller.js +8 -0
- package/dist/line-chart/root/line-chart-root.d.ts +16 -1
- package/dist/line-chart/root/line-chart-root.js +3 -3
- package/dist/loader/root/loader-root.d.ts +5 -0
- package/dist/menu/root/menu-root.js +2 -0
- package/dist/navigation/root/navigation-root.d.ts +11 -1
- package/dist/navigation/root/navigation-root.js +10 -5
- package/dist/notifications/root/notifications-root.d.ts +17 -0
- package/dist/notifications/root/notifications-root.js +21 -1
- package/dist/popover/root/popover-root.d.ts +18 -7
- package/dist/popover/root/popover-root.js +8 -1
- package/dist/progress/root/progress-root.d.ts +16 -1
- package/dist/progress/root/progress-root.js +12 -4
- package/dist/scatter-chart/root/scatter-chart-root.d.ts +16 -1
- package/dist/scatter-chart/root/scatter-chart-root.js +3 -3
- package/dist/splitter/root/splitter-root.d.ts +41 -0
- package/dist/splitter/root/splitter-root.js +77 -0
- package/dist/tabs/root/tabs-root.d.ts +25 -0
- package/dist/tabs/root/tabs-root.js +28 -1
- package/dist/tour/naming.d.ts +9 -3
- package/dist/tour/naming.js +9 -3
- package/dist/tour/root/tour-root.d.ts +29 -5
- package/dist/tour/root/tour-root.js +13 -1
- package/dist/tour/stop/tour-stop.d.ts +2 -1
- package/dist/tour/stop/tour-stop.js +4 -1
- package/dist/tree/root/tree-root.d.ts +13 -0
- package/dist/tree/root/tree-root.js +42 -2
- package/lint.json +1 -1
- package/package.json +5 -5
- package/types/jsx.d.ts +1456 -36
- package/types/vue.d.ts +277 -24
- package/types/words.d.ts +64 -0
|
@@ -19,6 +19,20 @@ import { type PropertyValues, type TemplateResult } from 'lit';
|
|
|
19
19
|
* The page is the window unless `scroller` names the element that scrolls, for
|
|
20
20
|
* an app shell whose content scrolls inside a container.
|
|
21
21
|
*
|
|
22
|
+
* **Set `hide-on-scroll` for a bar that moves out of the way.** Scrolling down
|
|
23
|
+
* past the bar's own height hides it, and scrolling up shows it again, as does
|
|
24
|
+
* focus moving into it. The custom state `hidden` is on the host while it is
|
|
25
|
+
* hidden, and the styled tier slides a `sticky` bar up out of view.
|
|
26
|
+
*
|
|
27
|
+
* **Set `fold-below` to fold the middle region on a narrow screen.** Below that
|
|
28
|
+
* many pixels of the bar's own width, the middle region is hidden behind a
|
|
29
|
+
* toggle at the end of the bar, named by `menu-label`. The toggle says whether
|
|
30
|
+
* the region is open with `aria-expanded`, and the region opens below the row.
|
|
31
|
+
* Escape closes it and puts focus back on the toggle. The custom state
|
|
32
|
+
* `folded` is on the host while the bar is that narrow, and `open` while the
|
|
33
|
+
* folded region is open. A server serves the bar unfolded, and the browser
|
|
34
|
+
* folds it once it has measured it.
|
|
35
|
+
*
|
|
22
36
|
* The host is the page's `banner` landmark. Placed inside `main`, `article`,
|
|
23
37
|
* `aside`, `nav` or `section`, it is a plain box instead, as a native
|
|
24
38
|
* `<header>` is there, so a header inside a card or a pane does not add a
|
|
@@ -36,6 +50,7 @@ import { type PropertyValues, type TemplateResult } from 'lit';
|
|
|
36
50
|
*
|
|
37
51
|
* @slot - The middle region, usually a `Navigation`.
|
|
38
52
|
* @slot end - Trailing content.
|
|
53
|
+
* @slot menu-icon - Replaces the glyph inside the toggle that opens a folded middle region.
|
|
39
54
|
* @slot start - Leading content, usually a wordmark.
|
|
40
55
|
*
|
|
41
56
|
* @event {HelixScrolledEvent} helix-scrolled - Fired when the page crosses the
|
|
@@ -48,10 +63,20 @@ import { type PropertyValues, type TemplateResult } from 'lit';
|
|
|
48
63
|
* @csspart end - The trailing region.
|
|
49
64
|
* @csspart row - The centered row inside the banner.
|
|
50
65
|
* @csspart start - The leading region.
|
|
66
|
+
* @csspart toggle - The control that opens and closes the folded middle region, drawn while the bar is narrower than `fold-below`.
|
|
67
|
+
* @csspart toggle-mark - The glyph on the toggle, where none is slotted.
|
|
51
68
|
*
|
|
69
|
+
* @cssstate folded - While the bar is narrower than `fold-below`, and the middle region is behind the toggle.
|
|
70
|
+
* @cssstate hidden - While `hide-on-scroll` has the bar out of the way, after a scroll down.
|
|
71
|
+
* @cssstate open - While the folded middle region is open.
|
|
52
72
|
* @cssstate scrolled - While the page is scrolled down from the top, which is when the bar lifts off it.
|
|
53
73
|
*/
|
|
54
74
|
export declare class HelixHeadlessAppHeader extends HelixElement {
|
|
75
|
+
/**
|
|
76
|
+
* The key this family's words are registered under, its styled tag:
|
|
77
|
+
* `registerWords('de', { 'helix-app-header': { menuLabel: 'Menü' } })`.
|
|
78
|
+
*/
|
|
79
|
+
static words: string;
|
|
55
80
|
/**
|
|
56
81
|
* Where the middle region sits in the bar.
|
|
57
82
|
*
|
|
@@ -68,6 +93,47 @@ export declare class HelixHeadlessAppHeader extends HelixElement {
|
|
|
68
93
|
* the property carries the part's name, `content`.
|
|
69
94
|
*/
|
|
70
95
|
contentAlign?: 'start';
|
|
96
|
+
/**
|
|
97
|
+
* The width of the bar, in pixels, below which the middle region folds behind
|
|
98
|
+
* a toggle. Unset, it never folds.
|
|
99
|
+
*/
|
|
100
|
+
foldBelow?: number;
|
|
101
|
+
/**
|
|
102
|
+
* Hides the bar as the page scrolls down past it, and shows it again as the
|
|
103
|
+
* page scrolls up.
|
|
104
|
+
*/
|
|
105
|
+
hideOnScroll: boolean;
|
|
106
|
+
/** Whether the bar is narrower than `fold-below`, which only the observer sets. */
|
|
107
|
+
private folded;
|
|
108
|
+
/** Whether the folded middle region is open. */
|
|
109
|
+
private unfolded;
|
|
110
|
+
/** Watches the bar's own width while `fold-below` is set. */
|
|
111
|
+
private widths;
|
|
112
|
+
/** Starts or stops watching the width, according to `fold-below`. */
|
|
113
|
+
private watchWidth;
|
|
114
|
+
/** Folds the middle region where the bar is narrower than `fold-below`. */
|
|
115
|
+
private fold;
|
|
116
|
+
/** Opens or closes the folded middle region. */
|
|
117
|
+
private readonly handleToggle;
|
|
118
|
+
/** Escape in the open region closes it and puts focus back on the toggle. */
|
|
119
|
+
private readonly handleKeydown;
|
|
120
|
+
/** Whether the bar is out of the way, under `hide-on-scroll`. */
|
|
121
|
+
private away;
|
|
122
|
+
/** Where the page was last scrolled to, to tell down from up. */
|
|
123
|
+
private lastY;
|
|
124
|
+
/** Shows a hidden bar again when focus moves into it. */
|
|
125
|
+
private readonly handleFocusIn;
|
|
126
|
+
/** Hides the bar or shows it again, under `hide-on-scroll`. */
|
|
127
|
+
private hide;
|
|
128
|
+
/**
|
|
129
|
+
* Hides the bar on a scroll down past its own height, and shows it on a
|
|
130
|
+
* scroll up. A few pixels either way are not a direction, so a bar does not
|
|
131
|
+
* flicker under a hand resting on a trackpad. Not while focus is in the bar
|
|
132
|
+
* or its folded region is open, which a reader is using.
|
|
133
|
+
*/
|
|
134
|
+
private follow;
|
|
135
|
+
/** The name of the toggle that opens a folded middle region. */
|
|
136
|
+
menuLabel: string;
|
|
71
137
|
/**
|
|
72
138
|
* The id of the element whose scrolling lifts the bar, for an app shell that
|
|
73
139
|
* scrolls a container instead of the window. Unset is the window.
|
|
@@ -111,7 +177,16 @@ export declare class HelixHeadlessAppHeader extends HelixElement {
|
|
|
111
177
|
/** Whether this header is the page's banner, read from where it sits. */
|
|
112
178
|
private readLandmark;
|
|
113
179
|
disconnectedCallback(): void;
|
|
180
|
+
/** The `fold-below` the width watch was started for, so a change is measured at once. */
|
|
181
|
+
private watchedFor;
|
|
182
|
+
protected firstUpdated(changed: PropertyValues): void;
|
|
114
183
|
protected updated(changed: PropertyValues): void;
|
|
184
|
+
/**
|
|
185
|
+
* The glyph on the toggle that opens a folded middle region, behind a seam:
|
|
186
|
+
* slot fallback, so a consumer replaces it by slotting, and a method, so a
|
|
187
|
+
* tier above replaces it by overriding.
|
|
188
|
+
*/
|
|
189
|
+
protected renderMenuIcon(): TemplateResult;
|
|
115
190
|
protected render(): TemplateResult;
|
|
116
191
|
}
|
|
117
192
|
declare global {
|
|
@@ -4,18 +4,41 @@ 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 { customElement, elementById, HelixElement, HelixScrolledEvent, hostAria, } from '@fusion.dev/helix-core';
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
7
|
+
import { customElement, deepActiveElement, deepContains, elementById, HelixElement, HelixScrolledEvent, hostAria, words, } from '@fusion.dev/helix-core';
|
|
8
|
+
import { list } from '@fusion.dev/helix-icons';
|
|
9
|
+
import { html, nothing } from 'lit';
|
|
10
|
+
import { property, state } from 'lit/decorators.js';
|
|
11
|
+
import { unsafeSVG } from 'lit/directives/unsafe-svg.js';
|
|
10
12
|
import { inSectioningContent } from '../sectioning.js';
|
|
11
13
|
let HelixHeadlessAppHeader = class HelixHeadlessAppHeader extends HelixElement {
|
|
12
14
|
constructor() {
|
|
13
15
|
super(...arguments);
|
|
16
|
+
this.hideOnScroll = false;
|
|
17
|
+
this.folded = false;
|
|
18
|
+
this.unfolded = false;
|
|
19
|
+
this.handleToggle = () => {
|
|
20
|
+
this.unfolded = !this.unfolded;
|
|
21
|
+
};
|
|
22
|
+
this.handleKeydown = (event) => {
|
|
23
|
+
if (event.key !== 'Escape' || !this.unfolded || event.defaultPrevented) {
|
|
24
|
+
return;
|
|
25
|
+
}
|
|
26
|
+
event.preventDefault();
|
|
27
|
+
this.unfolded = false;
|
|
28
|
+
void this.updateComplete.then(() => this.partNamed('toggle')?.focus());
|
|
29
|
+
};
|
|
30
|
+
this.away = false;
|
|
31
|
+
this.lastY = 0;
|
|
32
|
+
this.handleFocusIn = () => {
|
|
33
|
+
this.hide(false);
|
|
34
|
+
};
|
|
35
|
+
this.menuLabel = 'Menu';
|
|
14
36
|
this.landmark = 'banner';
|
|
15
37
|
this.scrolled = false;
|
|
16
38
|
this.handleScroll = () => {
|
|
17
39
|
const source = this.source ?? window;
|
|
18
40
|
const y = source instanceof Element ? source.scrollTop : window.scrollY;
|
|
41
|
+
this.follow(y);
|
|
19
42
|
const next = this.scrolled ? y > 2 : y > 8;
|
|
20
43
|
if (next === this.scrolled) {
|
|
21
44
|
return;
|
|
@@ -25,6 +48,57 @@ let HelixHeadlessAppHeader = class HelixHeadlessAppHeader extends HelixElement {
|
|
|
25
48
|
this.dispatchEvent(new HelixScrolledEvent({ scrolled: next }));
|
|
26
49
|
};
|
|
27
50
|
}
|
|
51
|
+
static { this.words = 'helix-app-header'; }
|
|
52
|
+
watchWidth() {
|
|
53
|
+
if (!this.foldBelow || typeof ResizeObserver === 'undefined') {
|
|
54
|
+
this.widths?.disconnect();
|
|
55
|
+
this.widths = undefined;
|
|
56
|
+
this.folded = false;
|
|
57
|
+
return;
|
|
58
|
+
}
|
|
59
|
+
if (this.widths) {
|
|
60
|
+
return;
|
|
61
|
+
}
|
|
62
|
+
this.widths = new ResizeObserver(([entry]) => {
|
|
63
|
+
const width = entry?.borderBoxSize?.[0]?.inlineSize ?? entry?.contentRect.width ?? 0;
|
|
64
|
+
if (width > 0) {
|
|
65
|
+
this.fold(width);
|
|
66
|
+
}
|
|
67
|
+
});
|
|
68
|
+
this.widths.observe(this);
|
|
69
|
+
}
|
|
70
|
+
fold(width) {
|
|
71
|
+
const folded = this.foldBelow !== undefined && width < this.foldBelow;
|
|
72
|
+
if (folded !== this.folded) {
|
|
73
|
+
this.folded = folded;
|
|
74
|
+
this.unfolded = false;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
hide(away) {
|
|
78
|
+
if (away === this.away) {
|
|
79
|
+
return;
|
|
80
|
+
}
|
|
81
|
+
this.away = away;
|
|
82
|
+
this.toggleState('hidden', away);
|
|
83
|
+
}
|
|
84
|
+
follow(y) {
|
|
85
|
+
const moved = y - this.lastY;
|
|
86
|
+
this.lastY = y;
|
|
87
|
+
if (!this.hideOnScroll) {
|
|
88
|
+
this.hide(false);
|
|
89
|
+
return;
|
|
90
|
+
}
|
|
91
|
+
const height = this.getBoundingClientRect().height;
|
|
92
|
+
if (y <= height) {
|
|
93
|
+
this.hide(false);
|
|
94
|
+
}
|
|
95
|
+
else if (moved > 4 && !this.unfolded && !deepContains(this, deepActiveElement())) {
|
|
96
|
+
this.hide(true);
|
|
97
|
+
}
|
|
98
|
+
else if (moved < -4) {
|
|
99
|
+
this.hide(false);
|
|
100
|
+
}
|
|
101
|
+
}
|
|
28
102
|
findSource() {
|
|
29
103
|
return (this.scroller ? elementById(this, this.scroller) : null) ?? window;
|
|
30
104
|
}
|
|
@@ -44,6 +118,8 @@ let HelixHeadlessAppHeader = class HelixHeadlessAppHeader extends HelixElement {
|
|
|
44
118
|
willUpdate(changed) {
|
|
45
119
|
super.willUpdate(changed);
|
|
46
120
|
hostAria(this.internals, { role: this.landmark });
|
|
121
|
+
this.toggleState('folded', this.folded);
|
|
122
|
+
this.toggleState('open', this.folded && this.unfolded);
|
|
47
123
|
}
|
|
48
124
|
connectedCallback() {
|
|
49
125
|
super.connectedCallback();
|
|
@@ -54,6 +130,11 @@ let HelixHeadlessAppHeader = class HelixHeadlessAppHeader extends HelixElement {
|
|
|
54
130
|
}
|
|
55
131
|
});
|
|
56
132
|
this.listen();
|
|
133
|
+
this.addEventListener('focusin', this.handleFocusIn);
|
|
134
|
+
this.addEventListener('keydown', this.handleKeydown);
|
|
135
|
+
if (this.hasUpdated) {
|
|
136
|
+
this.watchWidth();
|
|
137
|
+
}
|
|
57
138
|
}
|
|
58
139
|
readLandmark() {
|
|
59
140
|
this.landmark = inSectioningContent(this) ? '' : 'banner';
|
|
@@ -63,19 +144,57 @@ let HelixHeadlessAppHeader = class HelixHeadlessAppHeader extends HelixElement {
|
|
|
63
144
|
super.disconnectedCallback();
|
|
64
145
|
this.source?.removeEventListener('scroll', this.handleScroll);
|
|
65
146
|
this.source = undefined;
|
|
147
|
+
this.removeEventListener('focusin', this.handleFocusIn);
|
|
148
|
+
this.removeEventListener('keydown', this.handleKeydown);
|
|
149
|
+
this.widths?.disconnect();
|
|
150
|
+
this.widths = undefined;
|
|
151
|
+
}
|
|
152
|
+
firstUpdated(changed) {
|
|
153
|
+
super.firstUpdated(changed);
|
|
154
|
+
this.watchedFor = this.foldBelow;
|
|
155
|
+
this.watchWidth();
|
|
66
156
|
}
|
|
67
157
|
updated(changed) {
|
|
68
158
|
super.updated(changed);
|
|
69
159
|
if (changed.has('scroller') && this.isConnected) {
|
|
70
160
|
this.listen();
|
|
71
161
|
}
|
|
162
|
+
if (this.foldBelow !== this.watchedFor) {
|
|
163
|
+
this.watchedFor = this.foldBelow;
|
|
164
|
+
this.watchWidth();
|
|
165
|
+
const width = this.getBoundingClientRect().width;
|
|
166
|
+
if (this.widths && width > 0) {
|
|
167
|
+
this.fold(width);
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
if (changed.has('hideOnScroll') && !this.hideOnScroll) {
|
|
171
|
+
this.hide(false);
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
renderMenuIcon() {
|
|
175
|
+
return html `<slot name="menu-icon">
|
|
176
|
+
<svg part="toggle-mark" fill="currentColor" viewBox=${list.viewBox} aria-hidden="true">
|
|
177
|
+
${unsafeSVG(list.content)}
|
|
178
|
+
</svg>
|
|
179
|
+
</slot>`;
|
|
72
180
|
}
|
|
73
181
|
render() {
|
|
74
182
|
return html `
|
|
75
183
|
<div part="row">
|
|
76
184
|
<div part="start"><slot name="start"></slot></div>
|
|
77
|
-
<div part="content"><slot></slot></div>
|
|
78
|
-
<div part="end"><slot name="end"></slot
|
|
185
|
+
<div part="content" id="content" ?hidden=${this.folded && !this.unfolded}><slot></slot></div>
|
|
186
|
+
<div part="end"><slot name="end"></slot>${this.folded
|
|
187
|
+
? html `<button
|
|
188
|
+
part="toggle"
|
|
189
|
+
type="button"
|
|
190
|
+
aria-controls="content"
|
|
191
|
+
aria-expanded=${this.unfolded ? 'true' : 'false'}
|
|
192
|
+
aria-label=${this.menuLabel}
|
|
193
|
+
@click=${this.handleToggle}
|
|
194
|
+
>
|
|
195
|
+
${this.renderMenuIcon()}
|
|
196
|
+
</button>`
|
|
197
|
+
: nothing}</div>
|
|
79
198
|
</div>
|
|
80
199
|
`;
|
|
81
200
|
}
|
|
@@ -83,6 +202,22 @@ let HelixHeadlessAppHeader = class HelixHeadlessAppHeader extends HelixElement {
|
|
|
83
202
|
__decorate([
|
|
84
203
|
property({ attribute: 'content-align', reflect: true })
|
|
85
204
|
], HelixHeadlessAppHeader.prototype, "contentAlign", void 0);
|
|
205
|
+
__decorate([
|
|
206
|
+
property({ attribute: 'fold-below', type: Number })
|
|
207
|
+
], HelixHeadlessAppHeader.prototype, "foldBelow", void 0);
|
|
208
|
+
__decorate([
|
|
209
|
+
property({ attribute: 'hide-on-scroll', type: Boolean })
|
|
210
|
+
], HelixHeadlessAppHeader.prototype, "hideOnScroll", void 0);
|
|
211
|
+
__decorate([
|
|
212
|
+
state()
|
|
213
|
+
], HelixHeadlessAppHeader.prototype, "folded", void 0);
|
|
214
|
+
__decorate([
|
|
215
|
+
state()
|
|
216
|
+
], HelixHeadlessAppHeader.prototype, "unfolded", void 0);
|
|
217
|
+
__decorate([
|
|
218
|
+
words,
|
|
219
|
+
property({ attribute: 'menu-label' })
|
|
220
|
+
], HelixHeadlessAppHeader.prototype, "menuLabel", void 0);
|
|
86
221
|
__decorate([
|
|
87
222
|
property()
|
|
88
223
|
], HelixHeadlessAppHeader.prototype, "scroller", void 0);
|
|
@@ -17,7 +17,7 @@ export interface AreaStack {
|
|
|
17
17
|
/** Each column's own reading, not yet summed. */
|
|
18
18
|
values: number[][];
|
|
19
19
|
}
|
|
20
|
-
declare const HelixHeadlessAreaChart_base: typeof HelixElement & (new (...args: any[]) => import("@fusion.dev/helix-core").MixinChartSourceInterface);
|
|
20
|
+
declare const HelixHeadlessAreaChart_base: typeof HelixElement & (new (...args: any[]) => import("@fusion.dev/helix-core").MixinChartSourceInterface) & (new (...args: any[]) => import("@fusion.dev/helix-core").MixinChartStatusInterface);
|
|
21
21
|
/**
|
|
22
22
|
* @summary A chart that shows how a total is made up over time, as bands stacked on one another.
|
|
23
23
|
*
|
|
@@ -73,24 +73,39 @@ declare const HelixHeadlessAreaChart_base: typeof HelixElement & (new (...args:
|
|
|
73
73
|
* tap or key, and `helix-reading-press` says a reading was clicked, tapped, or
|
|
74
74
|
* pressed with Enter or Space, for a page that opens what a reading stands for.
|
|
75
75
|
*
|
|
76
|
+
* **`data` takes the readings as data** where the page has no table to point
|
|
77
|
+
* `for` at, in a table's shape: the column headings, then one row per reading
|
|
78
|
+
* with its label first. A table is still the better source where the page can
|
|
79
|
+
* show one, since it reads before any script runs.
|
|
80
|
+
*
|
|
81
|
+
* **A chart with nothing to draw says so.** A table with no readings shows
|
|
82
|
+
* `empty-text`, "No readings", in the plot, and `loading` shows `loading-text`
|
|
83
|
+
* there until readings arrive. The `empty` and `loading` slots take markup in
|
|
84
|
+
* their place, such as a link to add the first reading.
|
|
85
|
+
*
|
|
76
86
|
* @since 0.1.0
|
|
77
87
|
* @status stable
|
|
78
88
|
* @category charts
|
|
79
89
|
* @aliases Stacked Area Chart, Composition Chart, Banded Chart
|
|
80
90
|
* @documentation https://fusion.dev/helix/components/area-chart
|
|
81
91
|
*
|
|
92
|
+
* @slot empty - Content shown in place of the drawing when the table has no readings, such as a link to add the first. Falls back to `empty-text`.
|
|
93
|
+
* @slot loading - Content shown in place of the drawing while `loading` is set and there are no readings yet. Falls back to `loading-text`.
|
|
94
|
+
*
|
|
82
95
|
* @event {HelixReadingChangeEvent} helix-reading-change - The reading shown moved, or was put away: `index` is the row, or `-1` for none, with its `label`, the `series` the keys rest on, and the `pointerType` that moved it.
|
|
83
96
|
* @event {HelixReadingPressEvent} helix-reading-press - A reading was clicked, tapped, or pressed with Enter or Space, with the same detail as `helix-reading-change`.
|
|
84
97
|
*
|
|
85
98
|
* @csspart area - One part's band.
|
|
86
99
|
* @csspart axis - The numbers of the scale beside the plot, under `value-axis`.
|
|
87
100
|
* @csspart baseline - The rule at zero, which is the floor of the drawing.
|
|
101
|
+
* @csspart empty - The words in place of the drawing when the table has no readings: the `empty` slot, falling back to `empty-text`. Not drawn while the table cannot be read yet, on the server and during hydration.
|
|
88
102
|
* @csspart gridline - One rule across the plot, under `gridlines`.
|
|
89
103
|
* @csspart guide - A rule down the reading a pointer is resting on.
|
|
90
104
|
* @csspart label - One reading's name.
|
|
91
105
|
* @csspart labels - The row of reading names.
|
|
92
106
|
* @csspart line - The top edge of one part's band.
|
|
93
107
|
* @csspart live - The readout: a polite live region that says the reading the keys moved to. Hide it visually.
|
|
108
|
+
* @csspart loading - The words in place of the drawing while `loading` is set and there are no readings: the `loading` slot, falling back to `loading-text`.
|
|
94
109
|
* @csspart mark - The invisible point the tooltip is anchored to.
|
|
95
110
|
* @csspart plot - The drawing, which takes focus to be read by key.
|
|
96
111
|
* @csspart summary - The total and each part's share at the latest reading, written as a sentence for screen readers.
|
|
@@ -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 { CHART_PLOT, customElement, drawTooltip, drawValueAxis, formatNumbers, formatWords, HelixElement, HelixReadingChangeEvent, HelixReadingPressEvent, linear, linePath, MixinChartSource, PLOT_HEIGHT, PLOT_WIDTH, reportRuntime, seriesIndex, ticks, words, wordsLocale, } from '@fusion.dev/helix-core';
|
|
7
|
+
import { CHART_PLOT, customElement, drawTooltip, drawValueAxis, formatNumbers, formatWords, HelixElement, HelixReadingChangeEvent, HelixReadingPressEvent, linear, linePath, MixinChartSource, MixinChartStatus, PLOT_HEIGHT, PLOT_WIDTH, reportRuntime, seriesIndex, ticks, words, wordsLocale, } from '@fusion.dev/helix-core';
|
|
8
8
|
import { html, nothing, svg } from 'lit';
|
|
9
9
|
import { property } from 'lit/decorators.js';
|
|
10
10
|
import '../../tooltip/index.js';
|
|
@@ -20,7 +20,7 @@ const percentIn = (locale) => {
|
|
|
20
20
|
}
|
|
21
21
|
return found;
|
|
22
22
|
};
|
|
23
|
-
let HelixHeadlessAreaChart = class HelixHeadlessAreaChart extends MixinChartSource(HelixElement) {
|
|
23
|
+
let HelixHeadlessAreaChart = class HelixHeadlessAreaChart extends MixinChartStatus(MixinChartSource(HelixElement)) {
|
|
24
24
|
constructor() {
|
|
25
25
|
super(...arguments);
|
|
26
26
|
this.overlap = false;
|
|
@@ -96,7 +96,7 @@ let HelixHeadlessAreaChart = class HelixHeadlessAreaChart extends MixinChartSour
|
|
|
96
96
|
const rows = this.sourceRows;
|
|
97
97
|
const stack = this.stack;
|
|
98
98
|
if (rows.length === 0 || stack.columns.length === 0) {
|
|
99
|
-
return html `<div id=${CHART_PLOT} part="plot"
|
|
99
|
+
return html `<div id=${CHART_PLOT} part="plot">${this.renderStatus()}</div>`;
|
|
100
100
|
}
|
|
101
101
|
const top = this.overlap
|
|
102
102
|
? Math.max(0, ...stack.layers.flat())
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { HelixElement, type Series } from '@fusion.dev/helix-core';
|
|
2
2
|
import { nothing, type PropertyValues, type TemplateResult } from 'lit';
|
|
3
3
|
import '../../tooltip/index.js';
|
|
4
|
-
declare const HelixHeadlessBarChart_base: typeof HelixElement & (new (...args: any[]) => import("@fusion.dev/helix-core").MixinChartSourceInterface);
|
|
4
|
+
declare const HelixHeadlessBarChart_base: typeof HelixElement & (new (...args: any[]) => import("@fusion.dev/helix-core").MixinChartSourceInterface) & (new (...args: any[]) => import("@fusion.dev/helix-core").MixinChartStatusInterface);
|
|
5
5
|
/**
|
|
6
6
|
* @summary A chart that draws a table's categories as columns.
|
|
7
7
|
*
|
|
@@ -35,12 +35,25 @@ declare const HelixHeadlessBarChart_base: typeof HelixElement & (new (...args: a
|
|
|
35
35
|
* tap or key, and `helix-reading-press` says a reading was clicked, tapped, or
|
|
36
36
|
* pressed with Enter or Space, for a page that opens what a reading stands for.
|
|
37
37
|
*
|
|
38
|
+
* **`data` takes the readings as data** where the page has no table to point
|
|
39
|
+
* `for` at, in a table's shape: the column headings, then one row per reading
|
|
40
|
+
* with its label first. A table is still the better source where the page can
|
|
41
|
+
* show one, since it reads before any script runs.
|
|
42
|
+
*
|
|
43
|
+
* **A chart with nothing to draw says so.** A table with no readings shows
|
|
44
|
+
* `empty-text`, "No readings", in the plot, and `loading` shows `loading-text`
|
|
45
|
+
* there until readings arrive. The `empty` and `loading` slots take markup in
|
|
46
|
+
* their place, such as a link to add the first reading.
|
|
47
|
+
*
|
|
38
48
|
* @since 0.1.0
|
|
39
49
|
* @status stable
|
|
40
50
|
* @category charts
|
|
41
51
|
* @aliases Column Chart, Categorical Chart
|
|
42
52
|
* @documentation https://fusion.dev/helix/components/bar-chart
|
|
43
53
|
*
|
|
54
|
+
* @slot empty - Content shown in place of the drawing when the table has no readings, such as a link to add the first. Falls back to `empty-text`.
|
|
55
|
+
* @slot loading - Content shown in place of the drawing while `loading` is set and there are no readings yet. Falls back to `loading-text`.
|
|
56
|
+
*
|
|
44
57
|
* @event {HelixReadingChangeEvent} helix-reading-change - The reading shown moved, or was put away: `index` is the row, or `-1` for none, with its `label`, the `series` the keys rest on, and the `pointerType` that moved it.
|
|
45
58
|
* @event {HelixReadingPressEvent} helix-reading-press - A reading was clicked, tapped, or pressed with Enter or Space, with the same detail as `helix-reading-change`.
|
|
46
59
|
*
|
|
@@ -50,6 +63,7 @@ declare const HelixHeadlessBarChart_base: typeof HelixElement & (new (...args: a
|
|
|
50
63
|
* @csspart bar-wash-end - The far stop of a bar's gradient, where one is used.
|
|
51
64
|
* @csspart bar-wash-start - The stop of a bar's gradient at its base.
|
|
52
65
|
* @csspart baseline - The line the columns stand on.
|
|
66
|
+
* @csspart empty - The words in place of the drawing when the table has no readings: the `empty` slot, falling back to `empty-text`. Not drawn while the table cannot be read yet, on the server and during hydration.
|
|
53
67
|
* @csspart gridline - One gridline across the plot, drawn when `gridlines` is set.
|
|
54
68
|
* @csspart group - One category's columns, together.
|
|
55
69
|
* @csspart group-active - The group the tooltip describes. Set together with `group`.
|
|
@@ -57,6 +71,7 @@ declare const HelixHeadlessBarChart_base: typeof HelixElement & (new (...args: a
|
|
|
57
71
|
* @csspart labels - The row of category names.
|
|
58
72
|
* @csspart line - A series drawn as a line, named in `lines`.
|
|
59
73
|
* @csspart live - The readout: a polite live region that says the reading the keys moved to. Hide it visually.
|
|
74
|
+
* @csspart loading - The words in place of the drawing while `loading` is set and there are no readings: the `loading` slot, falling back to `loading-text`.
|
|
60
75
|
* @csspart mark - The invisible point the tooltip is anchored to.
|
|
61
76
|
* @csspart plot - The drawing, which takes focus to be read by key.
|
|
62
77
|
* @csspart summary - The chart's name and each series' highest reading, written as a sentence for screen readers. Hide it visually.
|
|
@@ -4,12 +4,12 @@ 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 { byRow, CHART_PLOT, customElement, drawTooltip, extent, formatNumbers, formatWords, HelixElement, HelixReadingChangeEvent, HelixReadingPressEvent, linear, linePath, MixinChartSource, PLOT_HEIGHT, PLOT_WIDTH, seriesIndex, seriesKey, seriesNames, ticks, unbroken, words, wordsLocale, } from '@fusion.dev/helix-core';
|
|
7
|
+
import { byRow, CHART_PLOT, customElement, drawTooltip, extent, formatNumbers, formatWords, HelixElement, HelixReadingChangeEvent, HelixReadingPressEvent, linear, linePath, MixinChartSource, MixinChartStatus, PLOT_HEIGHT, PLOT_WIDTH, seriesIndex, seriesKey, seriesNames, ticks, unbroken, words, wordsLocale, } from '@fusion.dev/helix-core';
|
|
8
8
|
import { html, nothing, svg } from 'lit';
|
|
9
9
|
import { property } from 'lit/decorators.js';
|
|
10
10
|
import { stackEnds, stackedReadings, stackSpans } from '../stack.js';
|
|
11
11
|
import '../../tooltip/index.js';
|
|
12
|
-
let HelixHeadlessBarChart = class HelixHeadlessBarChart extends MixinChartSource(HelixElement) {
|
|
12
|
+
let HelixHeadlessBarChart = class HelixHeadlessBarChart extends MixinChartStatus(MixinChartSource(HelixElement)) {
|
|
13
13
|
constructor() {
|
|
14
14
|
super(...arguments);
|
|
15
15
|
this.highestLabel = 'Highest';
|
|
@@ -44,7 +44,7 @@ let HelixHeadlessBarChart = class HelixHeadlessBarChart extends MixinChartSource
|
|
|
44
44
|
const series = this.series;
|
|
45
45
|
const categories = series.length === 0 ? [] : this.sourceRows.map((row) => row.label);
|
|
46
46
|
if (categories.length === 0) {
|
|
47
|
-
return html `<div id=${CHART_PLOT} part="plot"
|
|
47
|
+
return html `<div id=${CHART_PLOT} part="plot">${this.renderStatus()}</div>`;
|
|
48
48
|
}
|
|
49
49
|
const scaled = this.scaled;
|
|
50
50
|
const own = (one) => scaled.has(seriesKey(one.name));
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { HelixElement } from '@fusion.dev/helix-core';
|
|
2
|
-
import { type PropertyValues, type TemplateResult } from 'lit';
|
|
2
|
+
import { type CSSResultGroup, type PropertyValues, type TemplateResult } from 'lit';
|
|
3
3
|
/**
|
|
4
4
|
* @summary One step in a breadcrumb trail.
|
|
5
5
|
*
|
|
@@ -18,7 +18,10 @@ import { type PropertyValues, type TemplateResult } from 'lit';
|
|
|
18
18
|
* including your own anchor.
|
|
19
19
|
*
|
|
20
20
|
* The current page is plain text, and `aria-current="page"` on the host conveys
|
|
21
|
-
* the position.
|
|
21
|
+
* the position. In a trail where no crumb is `current`, the last one is said
|
|
22
|
+
* to be the current page, and keeps its link. An `aria-current` you write on
|
|
23
|
+
* the host, such as `aria-current="location"`, replaces the one the crumb
|
|
24
|
+
* gives itself.
|
|
22
25
|
*
|
|
23
26
|
* @since 0.1.0
|
|
24
27
|
* @status stable
|
|
@@ -42,6 +45,7 @@ import { type PropertyValues, type TemplateResult } from 'lit';
|
|
|
42
45
|
* the label and what follows it into one control.
|
|
43
46
|
*/
|
|
44
47
|
export declare class HelixHeadlessBreadcrumb extends HelixElement {
|
|
48
|
+
static styles: CSSResultGroup;
|
|
45
49
|
/**
|
|
46
50
|
* Marks this item as the page you are on.
|
|
47
51
|
*/
|
|
@@ -65,6 +69,11 @@ export declare class HelixHeadlessBreadcrumb extends HelixElement {
|
|
|
65
69
|
* of `breadcrumbs/links` lost its padding at once.
|
|
66
70
|
*/
|
|
67
71
|
href?: string;
|
|
72
|
+
/**
|
|
73
|
+
* @internal Set by the trail: this is its last crumb and no crumb is
|
|
74
|
+
* `current`, so this one is said to be the current page.
|
|
75
|
+
*/
|
|
76
|
+
implied: boolean;
|
|
68
77
|
/**
|
|
69
78
|
* The link's `rel` value, which describes how the linked page relates to this
|
|
70
79
|
* one.
|
|
@@ -6,23 +6,29 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
|
|
|
6
6
|
};
|
|
7
7
|
import { customElement, HelixElement, hostAria, slotFilled, slotNamed, } from '@fusion.dev/helix-core';
|
|
8
8
|
import { caretRight } from '@fusion.dev/helix-icons';
|
|
9
|
-
import { html, nothing } from 'lit';
|
|
9
|
+
import { css, html, nothing, } from 'lit';
|
|
10
10
|
import { property } from 'lit/decorators.js';
|
|
11
11
|
import { unsafeSVG } from 'lit/directives/unsafe-svg.js';
|
|
12
12
|
let HelixHeadlessBreadcrumb = class HelixHeadlessBreadcrumb extends HelixElement {
|
|
13
13
|
constructor() {
|
|
14
14
|
super(...arguments);
|
|
15
15
|
this.current = false;
|
|
16
|
+
this.implied = false;
|
|
16
17
|
this.rel = '';
|
|
17
18
|
this.target = '';
|
|
18
19
|
this.handleEnd = () => {
|
|
19
20
|
this.markEnd();
|
|
20
21
|
};
|
|
21
22
|
}
|
|
23
|
+
static { this.styles = css `
|
|
24
|
+
:host(:first-child) [part='separator'] {
|
|
25
|
+
display: none;
|
|
26
|
+
}
|
|
27
|
+
`; }
|
|
22
28
|
willUpdate(changed) {
|
|
23
29
|
super.willUpdate(changed);
|
|
24
30
|
hostAria(this.internals, { role: 'listitem' });
|
|
25
|
-
this.internals.ariaCurrent = this.current ? 'page' : null;
|
|
31
|
+
this.internals.ariaCurrent = this.current || this.implied ? 'page' : null;
|
|
26
32
|
}
|
|
27
33
|
updated(changed) {
|
|
28
34
|
super.updated(changed);
|
|
@@ -60,6 +66,9 @@ __decorate([
|
|
|
60
66
|
__decorate([
|
|
61
67
|
property({ reflect: true })
|
|
62
68
|
], HelixHeadlessBreadcrumb.prototype, "href", void 0);
|
|
69
|
+
__decorate([
|
|
70
|
+
property({ attribute: false })
|
|
71
|
+
], HelixHeadlessBreadcrumb.prototype, "implied", void 0);
|
|
63
72
|
__decorate([
|
|
64
73
|
property()
|
|
65
74
|
], HelixHeadlessBreadcrumb.prototype, "rel", void 0);
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { HelixElement } from '@fusion.dev/helix-core';
|
|
2
2
|
import { nothing, type PropertyValues, type TemplateResult } from 'lit';
|
|
3
|
-
import '../breadcrumb/breadcrumb.js';
|
|
4
3
|
/** One step of a trail written as data, for `items`. */
|
|
5
4
|
export interface BreadcrumbItem {
|
|
6
5
|
/** The URL the step links to. The last step is the current page and takes none. */
|
|
@@ -26,7 +25,8 @@ export interface BreadcrumbItem {
|
|
|
26
25
|
* markers.
|
|
27
26
|
*
|
|
28
27
|
* The items are slotted directly, so they are `<ol>` children in the flat tree,
|
|
29
|
-
* and each item sets `role="listitem"` on itself.
|
|
28
|
+
* and each item sets `role="listitem"` on itself. Where no slotted crumb is
|
|
29
|
+
* `current`, the last one is said to be the current page.
|
|
30
30
|
*
|
|
31
31
|
* The trail does not measure itself, and you write its overflow in markup: put
|
|
32
32
|
* the crumb that holds the folded items where the gap should appear.
|
|
@@ -41,6 +41,11 @@ export interface BreadcrumbItem {
|
|
|
41
41
|
* to the first crumb it brought back. A new `items` folds again. Slotted crumbs
|
|
42
42
|
* do not fold; write the folded crumb where the gap should be.
|
|
43
43
|
*
|
|
44
|
+
* **Keyboard.** Each crumb with an `href` is a link and one tab stop, and
|
|
45
|
+
* Enter follows it. The current page and the separators are not in the tab
|
|
46
|
+
* order. In a folded trail, Enter or Space on the fold's button shows the
|
|
47
|
+
* whole trail and moves focus to the first crumb it brought back.
|
|
48
|
+
*
|
|
44
49
|
* @since 0.1.0
|
|
45
50
|
* @status stable
|
|
46
51
|
* @category navigation
|
|
@@ -96,8 +101,15 @@ export declare class HelixHeadlessBreadcrumbs extends HelixElement {
|
|
|
96
101
|
/** Shows the whole trail and moves focus to the first crumb it brought back. */
|
|
97
102
|
private readonly expand;
|
|
98
103
|
protected willUpdate(changed: PropertyValues): void;
|
|
104
|
+
protected updated(changed: PropertyValues): void;
|
|
99
105
|
/** How many crumbs drawn from `items` are folded away, or 0. */
|
|
100
106
|
private get folded();
|
|
107
|
+
/**
|
|
108
|
+
* Says the last slotted crumb is the current page where none is marked
|
|
109
|
+
* `current`, as React Aria's trail does. Through a property the crumb does
|
|
110
|
+
* not reflect, so nothing is written onto your markup.
|
|
111
|
+
*/
|
|
112
|
+
private readonly markLast;
|
|
101
113
|
/** The crumbs `items` describes, each a crumb of this tier. */
|
|
102
114
|
protected renderItems(): TemplateResult | typeof nothing;
|
|
103
115
|
protected render(): TemplateResult;
|
|
@@ -4,12 +4,12 @@ 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 { customElement, formatWords, HelixElement, hostAria, words } from '@fusion.dev/helix-core';
|
|
7
|
+
import { customElement, formatWords, HelixElement, hostAria, whenHydrated, words, } from '@fusion.dev/helix-core';
|
|
8
8
|
import { nothing } from 'lit';
|
|
9
9
|
import { property, state } from 'lit/decorators.js';
|
|
10
10
|
import { repeat } from 'lit/directives/repeat.js';
|
|
11
11
|
import { html } from 'lit/static-html.js';
|
|
12
|
-
import '../breadcrumb/breadcrumb.js';
|
|
12
|
+
import { HelixHeadlessBreadcrumb } from '../breadcrumb/breadcrumb.js';
|
|
13
13
|
let HelixHeadlessBreadcrumbs = class HelixHeadlessBreadcrumbs extends HelixElement {
|
|
14
14
|
constructor() {
|
|
15
15
|
super(...arguments);
|
|
@@ -24,6 +24,15 @@ let HelixHeadlessBreadcrumbs = class HelixHeadlessBreadcrumbs extends HelixEleme
|
|
|
24
24
|
crumb?.shadowRoot?.querySelector('a, [part="link"]')?.focus();
|
|
25
25
|
});
|
|
26
26
|
};
|
|
27
|
+
this.markLast = () => {
|
|
28
|
+
const crumbs = (this.renderRoot.querySelector('slot:not([name])')?.assignedElements() ?? []).filter((one) => one instanceof HelixHeadlessBreadcrumb);
|
|
29
|
+
const marked = crumbs.some((one) => one.current);
|
|
30
|
+
crumbs.forEach((crumb, index) => {
|
|
31
|
+
whenHydrated(crumb, () => {
|
|
32
|
+
crumb.implied = !marked && this.items.length === 0 && index === crumbs.length - 1;
|
|
33
|
+
});
|
|
34
|
+
});
|
|
35
|
+
};
|
|
27
36
|
}
|
|
28
37
|
static { this.words = 'helix-breadcrumbs'; }
|
|
29
38
|
willUpdate(changed) {
|
|
@@ -33,6 +42,10 @@ let HelixHeadlessBreadcrumbs = class HelixHeadlessBreadcrumbs extends HelixEleme
|
|
|
33
42
|
this.expanded = false;
|
|
34
43
|
}
|
|
35
44
|
}
|
|
45
|
+
updated(changed) {
|
|
46
|
+
super.updated(changed);
|
|
47
|
+
this.markLast();
|
|
48
|
+
}
|
|
36
49
|
get folded() {
|
|
37
50
|
const most = this.maxItems ?? 0;
|
|
38
51
|
const count = this.items.length;
|
|
@@ -77,7 +90,7 @@ let HelixHeadlessBreadcrumbs = class HelixHeadlessBreadcrumbs extends HelixEleme
|
|
|
77
90
|
}
|
|
78
91
|
render() {
|
|
79
92
|
return html `<ol part="list" role="list">
|
|
80
|
-
${this.renderItems()}<slot></slot>
|
|
93
|
+
${this.renderItems()}<slot @slotchange=${this.markLast}></slot>
|
|
81
94
|
</ol>`;
|
|
82
95
|
}
|
|
83
96
|
};
|
|
@@ -1,3 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The elements at the start of a list that hold words and no control, up to the
|
|
3
|
+
* first one that is or holds a control.
|
|
4
|
+
*
|
|
5
|
+
* `skip` is an element whose words are said elsewhere, such as the heading
|
|
6
|
+
* that names a panel. It is left out, and an element holding it is read for
|
|
7
|
+
* its other children, so a card's title names the panel and the card's text
|
|
8
|
+
* describes it.
|
|
9
|
+
*/
|
|
10
|
+
export declare const wordsAmong: (elements: readonly Element[], skip?: Element | null) => Element[];
|
|
1
11
|
/**
|
|
2
12
|
* The elements at the start of a slot that hold words and no control, up to the
|
|
3
13
|
* first one that is or holds a control.
|