@fusion.dev/helix-headless 0.218.0 → 0.220.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/api.json +1 -1
- package/custom-elements.json +1 -1
- package/dist/breadcrumbs/breadcrumb/breadcrumb.d.ts +13 -2
- package/dist/breadcrumbs/breadcrumb/breadcrumb.js +19 -9
- package/dist/breadcrumbs/root/breadcrumbs-root.d.ts +16 -1
- package/dist/breadcrumbs/root/breadcrumbs-root.js +6 -0
- package/dist/button/root/button-root.d.ts +33 -0
- package/dist/button/root/button-root.js +13 -3
- package/dist/canvas/root/canvas-root.d.ts +11 -0
- package/dist/canvas/root/canvas-root.js +1 -0
- package/dist/chat/composer/chat-composer.d.ts +221 -6
- package/dist/chat/composer/chat-composer.js +249 -19
- package/dist/chat/message/chat-message.d.ts +7 -0
- package/dist/chat/message/chat-message.js +2 -1
- package/dist/chat/root/chat-root.d.ts +1 -0
- package/dist/chat/root/chat-root.js +1 -1
- package/dist/code-editor/root/code-editor-root.d.ts +48 -51
- package/dist/code-editor/root/code-editor-root.js +67 -249
- package/dist/copy-button/root/copy-button-root.js +3 -3
- package/dist/device-screen/root/device-screen-root.d.ts +11 -0
- package/dist/device-screen/root/device-screen-root.js +22 -10
- package/dist/dialog/root/dialog-root.js +6 -1
- package/dist/drilldown/item/drilldown-item.js +1 -1
- package/dist/element-events.generated.js +4 -1
- package/dist/filter-input/root/filter-input-root.d.ts +4 -3
- package/dist/filter-input/root/filter-input-root.js +1 -20
- package/dist/find/index.d.ts +1 -0
- package/dist/find/index.js +1 -0
- package/dist/find/root/find-root.d.ts +314 -0
- package/dist/find/root/find-root.js +577 -0
- package/dist/graph/root/graph-root.d.ts +11 -0
- package/dist/graph/root/graph-root.js +4 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/input/root/input-root.d.ts +6 -0
- package/dist/input/root/input-root.js +7 -0
- package/dist/lightbox/root/lightbox-root.d.ts +4 -1
- package/dist/lightbox/root/lightbox-root.js +10 -8
- package/dist/listbox/root/listbox-root.d.ts +21 -0
- package/dist/listbox/root/listbox-root.js +37 -2
- package/dist/log/group/log-group.d.ts +18 -3
- package/dist/log/group/log-group.js +31 -4
- package/dist/log/root/log-root.d.ts +13 -3
- package/dist/log/root/log-root.js +5 -2
- package/dist/map/root/map-root.d.ts +11 -0
- package/dist/map/root/map-root.js +28 -12
- package/dist/menu/root/menu-root.d.ts +8 -0
- package/dist/menu/root/menu-root.js +22 -1
- package/dist/menu/section/menu-section.d.ts +10 -0
- package/dist/menu/section/menu-section.js +10 -0
- package/dist/meter/index.d.ts +1 -0
- package/dist/meter/index.js +1 -0
- package/dist/meter/root/meter-root.d.ts +16 -1
- package/dist/meter/root/meter-root.js +27 -11
- package/dist/meter/segment/meter-segment.d.ts +74 -0
- package/dist/meter/segment/meter-segment.js +47 -0
- package/dist/scroll-area/root/scroll-area-root.d.ts +20 -3
- package/dist/scroll-area/root/scroll-area-root.js +23 -4
- package/dist/spatial-bar-chart/bars.d.ts +125 -5
- package/dist/spatial-bar-chart/bars.js +194 -17
- package/dist/spatial-bar-chart/root/spatial-bar-chart-root.d.ts +148 -6
- package/dist/spatial-bar-chart/root/spatial-bar-chart-root.js +285 -16
- package/dist/splitter/root/splitter-root.js +1 -0
- package/dist/tabs/root/tabs-root.d.ts +4 -0
- package/dist/tabs/tab/tab.d.ts +1 -0
- package/dist/tabs/tab/tab.js +2 -2
- package/dist/tag/root/tag-root.d.ts +1 -1
- package/dist/terminal/root/terminal-root.d.ts +60 -32
- package/dist/terminal/root/terminal-root.js +82 -178
- package/dist/toolbar/root/toolbar-root.d.ts +4 -1
- package/dist/tooltip/root/tooltip-root.d.ts +23 -1
- package/dist/tooltip/root/tooltip-root.js +28 -5
- package/dist/tour/root/tour-root.d.ts +1 -0
- package/dist/tour/root/tour-root.js +4 -1
- package/dist/tour/stop/tour-stop.js +1 -0
- package/dist/tree/item/tree-item.d.ts +11 -0
- package/dist/tree/item/tree-item.js +19 -1
- package/examples.json +1 -1
- package/lint.json +1 -1
- package/package.json +5 -5
- package/types/jsx.d.ts +2222 -118
- package/types/svelte.d.ts +2 -0
- package/types/vue.d.ts +468 -19
- package/types/words.d.ts +96 -1
|
@@ -0,0 +1,577 @@
|
|
|
1
|
+
import { __decorate } from "tslib";
|
|
2
|
+
import { customElement, deepActiveElement, deepContains, drawIcon, elementById, findPattern, formatWords, HelixElement, HelixFoundEvent, MIRROR_RULE, MixinControllerOpen, matchesChord, onApple, stopPress, textFinder, words, } from '@fusion.dev/helix-core';
|
|
3
|
+
import { asterisk, caretDown, caretRight, caretUp, textAa, textAUnderline, x, } from '@fusion.dev/helix-icons';
|
|
4
|
+
import { nothing } from 'lit';
|
|
5
|
+
import { property, state } from 'lit/decorators.js';
|
|
6
|
+
import { keyed } from 'lit/directives/keyed.js';
|
|
7
|
+
import { live } from 'lit/directives/live.js';
|
|
8
|
+
import { html } from 'lit/static-html.js';
|
|
9
|
+
import '../../button/index.js';
|
|
10
|
+
import '../../icon-button/index.js';
|
|
11
|
+
import '../../toolbar/index.js';
|
|
12
|
+
const SEARCHED = ['for', 'matchCase', 'open', 'query', 'regex', 'skip', 'wholeWord'];
|
|
13
|
+
let HelixHeadlessFind = class HelixHeadlessFind extends MixinControllerOpen(HelixElement) {
|
|
14
|
+
constructor() {
|
|
15
|
+
super(...arguments);
|
|
16
|
+
this.closeLabel = 'Close find';
|
|
17
|
+
this.controlsLabel = 'Find controls';
|
|
18
|
+
this.for = '';
|
|
19
|
+
this.invalidLabel = 'Not a valid regular expression';
|
|
20
|
+
this.label = 'Find';
|
|
21
|
+
this.matchCase = false;
|
|
22
|
+
this.matchCaseLabel = 'Match case';
|
|
23
|
+
this.matchesLabel = '{count, plural, =0 {No matches} one {{index} of # match} other {{index} of # matches}}';
|
|
24
|
+
this.nextLabel = 'Next match';
|
|
25
|
+
this.options = 'match-case whole-word regex';
|
|
26
|
+
this.previousLabel = 'Previous match';
|
|
27
|
+
this.query = '';
|
|
28
|
+
this.readOnly = false;
|
|
29
|
+
this.regex = false;
|
|
30
|
+
this.regexLabel = 'Use regular expression';
|
|
31
|
+
this.replaceAllLabel = 'Replace all';
|
|
32
|
+
this.replaceFieldLabel = 'Replace with';
|
|
33
|
+
this.replaceLabel = 'Replace';
|
|
34
|
+
this.replacement = '';
|
|
35
|
+
this.replaceToggleLabel = 'Find and replace';
|
|
36
|
+
this.shortcut = 'mod+f';
|
|
37
|
+
this.skip = '';
|
|
38
|
+
this.wholeWord = false;
|
|
39
|
+
this.wholeWordLabel = 'Match whole word';
|
|
40
|
+
this.result = undefined;
|
|
41
|
+
this.replaceOpen = false;
|
|
42
|
+
this.attached = undefined;
|
|
43
|
+
this.announcement = '';
|
|
44
|
+
this.said = 0;
|
|
45
|
+
this.inside = false;
|
|
46
|
+
this.handleWhere = (event) => {
|
|
47
|
+
this.inside = this.within(event);
|
|
48
|
+
};
|
|
49
|
+
this.handleShortcut = (event) => {
|
|
50
|
+
if (event.defaultPrevented ||
|
|
51
|
+
event.isComposing ||
|
|
52
|
+
this.shortcut === '' ||
|
|
53
|
+
!matchesChord(event, this.shortcut, onApple()) ||
|
|
54
|
+
!(this.inside || this.within(event)) ||
|
|
55
|
+
this.finder === undefined) {
|
|
56
|
+
return;
|
|
57
|
+
}
|
|
58
|
+
event.preventDefault();
|
|
59
|
+
void this.show();
|
|
60
|
+
};
|
|
61
|
+
this.handleInput = (event) => {
|
|
62
|
+
this.query = event.target.value;
|
|
63
|
+
};
|
|
64
|
+
this.handleReplaceInput = (event) => {
|
|
65
|
+
this.replacement = event.target.value;
|
|
66
|
+
};
|
|
67
|
+
this.handleKeys = (event) => {
|
|
68
|
+
if (event.defaultPrevented || event.isComposing) {
|
|
69
|
+
return;
|
|
70
|
+
}
|
|
71
|
+
if (event.key === 'Escape') {
|
|
72
|
+
event.preventDefault();
|
|
73
|
+
event.stopPropagation();
|
|
74
|
+
this.hide();
|
|
75
|
+
return;
|
|
76
|
+
}
|
|
77
|
+
if (event.key !== 'Enter') {
|
|
78
|
+
return;
|
|
79
|
+
}
|
|
80
|
+
const origin = event.composedPath()[0];
|
|
81
|
+
if (!(origin instanceof HTMLInputElement)) {
|
|
82
|
+
return;
|
|
83
|
+
}
|
|
84
|
+
event.preventDefault();
|
|
85
|
+
if (origin.getAttribute('part') === 'replace-field') {
|
|
86
|
+
this.replace(event.metaKey || event.ctrlKey);
|
|
87
|
+
}
|
|
88
|
+
else {
|
|
89
|
+
this.search(event.shiftKey ? 'previous' : 'next');
|
|
90
|
+
}
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
static { this.markRules = [MIRROR_RULE]; }
|
|
94
|
+
static { this.words = 'helix-find'; }
|
|
95
|
+
attach(finder) {
|
|
96
|
+
this.endSearch();
|
|
97
|
+
this.attached = finder;
|
|
98
|
+
this.replaceOpen = this.replaceOpen && finder.replace !== undefined;
|
|
99
|
+
if (this.open) {
|
|
100
|
+
queueMicrotask(() => this.search('first'));
|
|
101
|
+
}
|
|
102
|
+
return {
|
|
103
|
+
detach: () => {
|
|
104
|
+
if (this.attached === finder) {
|
|
105
|
+
this.endSearch();
|
|
106
|
+
this.attached = undefined;
|
|
107
|
+
}
|
|
108
|
+
},
|
|
109
|
+
found: (result) => {
|
|
110
|
+
if (this.attached === finder) {
|
|
111
|
+
this.report(result);
|
|
112
|
+
}
|
|
113
|
+
},
|
|
114
|
+
};
|
|
115
|
+
}
|
|
116
|
+
async show() {
|
|
117
|
+
const active = deepActiveElement();
|
|
118
|
+
if (active !== null && !deepContains(this, active)) {
|
|
119
|
+
this.returnTo = active;
|
|
120
|
+
}
|
|
121
|
+
const selected = this.attached ? '' : this.selectedText();
|
|
122
|
+
if (selected !== '') {
|
|
123
|
+
this.query = selected;
|
|
124
|
+
}
|
|
125
|
+
if (!this.requestOpen(true)) {
|
|
126
|
+
return;
|
|
127
|
+
}
|
|
128
|
+
await this.updateComplete;
|
|
129
|
+
const field = this.partNamed('field');
|
|
130
|
+
field?.focus();
|
|
131
|
+
field?.select();
|
|
132
|
+
}
|
|
133
|
+
hide() {
|
|
134
|
+
const active = deepActiveElement();
|
|
135
|
+
const focused = active !== null && deepContains(this, active);
|
|
136
|
+
if (!this.requestOpen(false)) {
|
|
137
|
+
return;
|
|
138
|
+
}
|
|
139
|
+
const back = this.returnTo;
|
|
140
|
+
this.returnTo = undefined;
|
|
141
|
+
if (focused && back?.isConnected) {
|
|
142
|
+
;
|
|
143
|
+
back.focus();
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
next() {
|
|
147
|
+
if (this.open) {
|
|
148
|
+
this.search('next');
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
previous() {
|
|
152
|
+
if (this.open) {
|
|
153
|
+
this.search('previous');
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
refresh() {
|
|
157
|
+
if (this.open) {
|
|
158
|
+
this.search('first');
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
connectedCallback() {
|
|
162
|
+
super.connectedCallback();
|
|
163
|
+
const document = this.ownerDocument;
|
|
164
|
+
document.addEventListener('keydown', this.handleShortcut, true);
|
|
165
|
+
document.addEventListener('pointerdown', this.handleWhere, true);
|
|
166
|
+
document.addEventListener('focusin', this.handleWhere, true);
|
|
167
|
+
}
|
|
168
|
+
disconnectedCallback() {
|
|
169
|
+
super.disconnectedCallback();
|
|
170
|
+
const document = this.ownerDocument;
|
|
171
|
+
document.removeEventListener('keydown', this.handleShortcut, true);
|
|
172
|
+
document.removeEventListener('pointerdown', this.handleWhere, true);
|
|
173
|
+
document.removeEventListener('focusin', this.handleWhere, true);
|
|
174
|
+
this.endSearch();
|
|
175
|
+
}
|
|
176
|
+
firstUpdated(changed) {
|
|
177
|
+
super.firstUpdated(changed);
|
|
178
|
+
this.finishHydration();
|
|
179
|
+
}
|
|
180
|
+
willUpdate(changed) {
|
|
181
|
+
super.willUpdate(changed);
|
|
182
|
+
this.toggleState('replace-open', this.replacing);
|
|
183
|
+
}
|
|
184
|
+
updated(changed) {
|
|
185
|
+
super.updated(changed);
|
|
186
|
+
if (!this.open) {
|
|
187
|
+
if (changed.has('open')) {
|
|
188
|
+
this.endSearch();
|
|
189
|
+
}
|
|
190
|
+
return;
|
|
191
|
+
}
|
|
192
|
+
if (SEARCHED.some((name) => changed.has(name))) {
|
|
193
|
+
queueMicrotask(() => this.search('first'));
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
get target() {
|
|
197
|
+
return this.for === '' ? null : elementById(this, this.for);
|
|
198
|
+
}
|
|
199
|
+
get finder() {
|
|
200
|
+
if (this.attached) {
|
|
201
|
+
return this.attached;
|
|
202
|
+
}
|
|
203
|
+
const root = this.target;
|
|
204
|
+
if (root === null) {
|
|
205
|
+
return undefined;
|
|
206
|
+
}
|
|
207
|
+
if (this.own?.root !== root || this.own.skip !== this.skip) {
|
|
208
|
+
this.own?.finder.end();
|
|
209
|
+
this.own = {
|
|
210
|
+
finder: textFinder(root, { found: (result) => this.report(result), skip: this.skip }),
|
|
211
|
+
root,
|
|
212
|
+
skip: this.skip,
|
|
213
|
+
};
|
|
214
|
+
}
|
|
215
|
+
return this.own.finder;
|
|
216
|
+
}
|
|
217
|
+
get findQuery() {
|
|
218
|
+
return {
|
|
219
|
+
caseSensitive: this.matchCase,
|
|
220
|
+
regex: this.regex,
|
|
221
|
+
replace: this.replacement,
|
|
222
|
+
search: this.query,
|
|
223
|
+
wholeWord: this.wholeWord,
|
|
224
|
+
};
|
|
225
|
+
}
|
|
226
|
+
get readable() {
|
|
227
|
+
return this.query === '' || findPattern(this.findQuery) !== undefined;
|
|
228
|
+
}
|
|
229
|
+
get replaceable() {
|
|
230
|
+
return !this.hydrating && !this.readOnly && this.attached?.replace !== undefined;
|
|
231
|
+
}
|
|
232
|
+
get replacing() {
|
|
233
|
+
return this.replaceOpen && this.replaceable;
|
|
234
|
+
}
|
|
235
|
+
get countText() {
|
|
236
|
+
if (!this.readable) {
|
|
237
|
+
return this.invalidLabel;
|
|
238
|
+
}
|
|
239
|
+
return this.result === undefined
|
|
240
|
+
? ''
|
|
241
|
+
: formatWords(this, 'matchesLabel', {
|
|
242
|
+
count: this.result.count,
|
|
243
|
+
index: Math.max(this.result.index, 0) + 1,
|
|
244
|
+
});
|
|
245
|
+
}
|
|
246
|
+
offers(option) {
|
|
247
|
+
return this.options.split(/\s+/).includes(option);
|
|
248
|
+
}
|
|
249
|
+
selectedText() {
|
|
250
|
+
const selection = this.ownerDocument.getSelection?.();
|
|
251
|
+
const root = this.target;
|
|
252
|
+
const text = selection?.toString() ?? '';
|
|
253
|
+
const anchor = selection?.anchorNode ?? null;
|
|
254
|
+
return root !== null &&
|
|
255
|
+
anchor !== null &&
|
|
256
|
+
root.contains(anchor) &&
|
|
257
|
+
text.trim() !== '' &&
|
|
258
|
+
!/[\r\n]/.test(text)
|
|
259
|
+
? text
|
|
260
|
+
: '';
|
|
261
|
+
}
|
|
262
|
+
search(direction) {
|
|
263
|
+
const finder = this.finder;
|
|
264
|
+
if (!finder) {
|
|
265
|
+
return;
|
|
266
|
+
}
|
|
267
|
+
if (this.marking !== finder) {
|
|
268
|
+
this.endSearch();
|
|
269
|
+
}
|
|
270
|
+
if (this.query === '' || !this.readable) {
|
|
271
|
+
this.endSearch();
|
|
272
|
+
if (!this.readable) {
|
|
273
|
+
this.say(this.invalidLabel);
|
|
274
|
+
}
|
|
275
|
+
return;
|
|
276
|
+
}
|
|
277
|
+
this.marking = finder;
|
|
278
|
+
const result = finder.find(this.findQuery, direction);
|
|
279
|
+
if (result) {
|
|
280
|
+
this.report(result);
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
endSearch() {
|
|
284
|
+
this.marking?.end();
|
|
285
|
+
this.marking = undefined;
|
|
286
|
+
this.result = undefined;
|
|
287
|
+
}
|
|
288
|
+
report(result) {
|
|
289
|
+
if (!this.open) {
|
|
290
|
+
return;
|
|
291
|
+
}
|
|
292
|
+
this.result = result;
|
|
293
|
+
this.say(this.countText);
|
|
294
|
+
this.dispatchEvent(new HelixFoundEvent({ count: result.count, index: result.index }));
|
|
295
|
+
}
|
|
296
|
+
replace(all) {
|
|
297
|
+
const finder = this.finder;
|
|
298
|
+
if (!finder?.replace || this.readOnly || this.query === '' || !this.readable) {
|
|
299
|
+
return;
|
|
300
|
+
}
|
|
301
|
+
const result = finder.replace(this.findQuery, all);
|
|
302
|
+
if (result) {
|
|
303
|
+
this.report(result);
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
say(text) {
|
|
307
|
+
this.announcement = text;
|
|
308
|
+
this.said += 1;
|
|
309
|
+
}
|
|
310
|
+
within(event) {
|
|
311
|
+
const path = event.composedPath();
|
|
312
|
+
const root = this.target;
|
|
313
|
+
return path.includes(this) || (root !== null && path.includes(root));
|
|
314
|
+
}
|
|
315
|
+
toggleOption(option) {
|
|
316
|
+
this[option] = !this[option];
|
|
317
|
+
}
|
|
318
|
+
renderReplaceToggle() {
|
|
319
|
+
if (!this.replaceable) {
|
|
320
|
+
return nothing;
|
|
321
|
+
}
|
|
322
|
+
const button = this.tag('icon-button');
|
|
323
|
+
return html `<${button}
|
|
324
|
+
part="replace-toggle"
|
|
325
|
+
exportparts="button: replace-toggle-button, live: replace-toggle-live, spinner: replace-toggle-spinner, text: replace-toggle-text"
|
|
326
|
+
.expanded=${this.replacing}
|
|
327
|
+
label=${this.replaceToggleLabel}
|
|
328
|
+
@click=${() => {
|
|
329
|
+
this.replaceOpen = !this.replaceOpen;
|
|
330
|
+
}}
|
|
331
|
+
@helix-press=${stopPress}
|
|
332
|
+
>
|
|
333
|
+
${this.replacing ? drawIcon(caretDown) : html `<span data-mirror>${drawIcon(caretRight)}</span>`}
|
|
334
|
+
</${button}>`;
|
|
335
|
+
}
|
|
336
|
+
renderOptionButtons() {
|
|
337
|
+
const button = this.tag('icon-button');
|
|
338
|
+
return html `${this.offers('match-case')
|
|
339
|
+
? html `<${button}
|
|
340
|
+
part="match-case${this.matchCase ? ' match-case-pressed' : ''}"
|
|
341
|
+
exportparts="button: match-case-button, live: match-case-live, spinner: match-case-spinner, text: match-case-text"
|
|
342
|
+
aria-pressed=${this.matchCase ? 'true' : 'false'}
|
|
343
|
+
label=${this.matchCaseLabel}
|
|
344
|
+
@click=${() => this.toggleOption('matchCase')}
|
|
345
|
+
@helix-press=${stopPress}
|
|
346
|
+
>
|
|
347
|
+
<slot name="match-case-icon">${drawIcon(textAa)}</slot>
|
|
348
|
+
</${button}>`
|
|
349
|
+
: nothing}${this.offers('whole-word')
|
|
350
|
+
? html `<${button}
|
|
351
|
+
part="whole-word${this.wholeWord ? ' whole-word-pressed' : ''}"
|
|
352
|
+
exportparts="button: whole-word-button, live: whole-word-live, spinner: whole-word-spinner, text: whole-word-text"
|
|
353
|
+
aria-pressed=${this.wholeWord ? 'true' : 'false'}
|
|
354
|
+
label=${this.wholeWordLabel}
|
|
355
|
+
@click=${() => this.toggleOption('wholeWord')}
|
|
356
|
+
@helix-press=${stopPress}
|
|
357
|
+
>
|
|
358
|
+
<slot name="whole-word-icon">${drawIcon(textAUnderline)}</slot>
|
|
359
|
+
</${button}>`
|
|
360
|
+
: nothing}${this.offers('regex')
|
|
361
|
+
? html `<${button}
|
|
362
|
+
part="regex${this.regex ? ' regex-pressed' : ''}"
|
|
363
|
+
exportparts="button: regex-button, live: regex-live, spinner: regex-spinner, text: regex-text"
|
|
364
|
+
aria-pressed=${this.regex ? 'true' : 'false'}
|
|
365
|
+
label=${this.regexLabel}
|
|
366
|
+
@click=${() => this.toggleOption('regex')}
|
|
367
|
+
@helix-press=${stopPress}
|
|
368
|
+
>
|
|
369
|
+
<slot name="regex-icon">${drawIcon(asterisk)}</slot>
|
|
370
|
+
</${button}>`
|
|
371
|
+
: nothing}`;
|
|
372
|
+
}
|
|
373
|
+
renderControls() {
|
|
374
|
+
const toolbar = this.tag('toolbar');
|
|
375
|
+
const button = this.tag('icon-button');
|
|
376
|
+
const searchable = this.readable && (this.result?.count ?? 0) > 0;
|
|
377
|
+
return html `<${toolbar} part="controls" exportparts="toolbar: controls-toolbar" label=${this.controlsLabel}>
|
|
378
|
+
${this.renderOptionButtons()}
|
|
379
|
+
<slot name="actions" part="actions"></slot>
|
|
380
|
+
<${button}
|
|
381
|
+
part="previous"
|
|
382
|
+
exportparts="button: previous-button, live: previous-live, spinner: previous-spinner, text: previous-text"
|
|
383
|
+
?disabled=${!searchable}
|
|
384
|
+
label=${this.previousLabel}
|
|
385
|
+
@click=${() => this.search('previous')}
|
|
386
|
+
@helix-press=${stopPress}
|
|
387
|
+
>
|
|
388
|
+
<slot name="previous-icon">${drawIcon(caretUp)}</slot>
|
|
389
|
+
</${button}>
|
|
390
|
+
<${button}
|
|
391
|
+
part="next"
|
|
392
|
+
exportparts="button: next-button, live: next-live, spinner: next-spinner, text: next-text"
|
|
393
|
+
?disabled=${!searchable}
|
|
394
|
+
label=${this.nextLabel}
|
|
395
|
+
@click=${() => this.search('next')}
|
|
396
|
+
@helix-press=${stopPress}
|
|
397
|
+
>
|
|
398
|
+
<slot name="next-icon">${drawIcon(caretDown)}</slot>
|
|
399
|
+
</${button}>
|
|
400
|
+
<${button}
|
|
401
|
+
part="close"
|
|
402
|
+
exportparts="button: close-button, live: close-live, spinner: close-spinner, text: close-text"
|
|
403
|
+
label=${this.closeLabel}
|
|
404
|
+
@click=${() => this.hide()}
|
|
405
|
+
@helix-press=${stopPress}
|
|
406
|
+
>
|
|
407
|
+
<slot name="close-icon">${drawIcon(x)}</slot>
|
|
408
|
+
</${button}>
|
|
409
|
+
</${toolbar}>`;
|
|
410
|
+
}
|
|
411
|
+
renderReplace() {
|
|
412
|
+
if (!this.replacing) {
|
|
413
|
+
return nothing;
|
|
414
|
+
}
|
|
415
|
+
const button = this.tag('button');
|
|
416
|
+
const searchable = this.readable && (this.result?.count ?? 0) > 0;
|
|
417
|
+
return html `<input
|
|
418
|
+
part="replace-field"
|
|
419
|
+
aria-label=${this.replaceFieldLabel}
|
|
420
|
+
autocomplete="off"
|
|
421
|
+
placeholder=${this.replaceFieldLabel}
|
|
422
|
+
spellcheck="false"
|
|
423
|
+
type="text"
|
|
424
|
+
.value=${live(this.replacement)}
|
|
425
|
+
@input=${this.handleReplaceInput}
|
|
426
|
+
/>
|
|
427
|
+
<${button}
|
|
428
|
+
part="replace"
|
|
429
|
+
exportparts="button: replace-button, live: replace-live, spinner: replace-spinner, text: replace-text"
|
|
430
|
+
?disabled=${!searchable}
|
|
431
|
+
@click=${() => this.replace(false)}
|
|
432
|
+
@helix-press=${stopPress}
|
|
433
|
+
>
|
|
434
|
+
${this.replaceLabel}
|
|
435
|
+
</${button}>
|
|
436
|
+
<${button}
|
|
437
|
+
part="replace-all"
|
|
438
|
+
exportparts="button: replace-all-button, live: replace-all-live, spinner: replace-all-spinner, text: replace-all-text"
|
|
439
|
+
?disabled=${!searchable}
|
|
440
|
+
@click=${() => this.replace(true)}
|
|
441
|
+
@helix-press=${stopPress}
|
|
442
|
+
>
|
|
443
|
+
${this.replaceAllLabel}
|
|
444
|
+
</${button}>`;
|
|
445
|
+
}
|
|
446
|
+
render() {
|
|
447
|
+
return html `<div
|
|
448
|
+
part="bar"
|
|
449
|
+
role="search"
|
|
450
|
+
aria-label=${this.label}
|
|
451
|
+
?hidden=${!this.open}
|
|
452
|
+
@keydown=${this.handleKeys}
|
|
453
|
+
>
|
|
454
|
+
${this.renderReplaceToggle()}
|
|
455
|
+
<input
|
|
456
|
+
part="field"
|
|
457
|
+
aria-invalid=${this.readable ? nothing : 'true'}
|
|
458
|
+
aria-label=${this.label}
|
|
459
|
+
autocomplete="off"
|
|
460
|
+
placeholder=${this.label}
|
|
461
|
+
spellcheck="false"
|
|
462
|
+
type="search"
|
|
463
|
+
.value=${live(this.query)}
|
|
464
|
+
@input=${this.handleInput}
|
|
465
|
+
/>
|
|
466
|
+
<span part="count" aria-hidden="true">${this.countText || nothing}</span>
|
|
467
|
+
${this.renderControls()}
|
|
468
|
+
${this.renderReplace()}
|
|
469
|
+
</div>
|
|
470
|
+
<span part="live" role="status">${keyed(this.said, this.announcement)}</span>`;
|
|
471
|
+
}
|
|
472
|
+
};
|
|
473
|
+
__decorate([
|
|
474
|
+
words,
|
|
475
|
+
property({ attribute: 'close-label' })
|
|
476
|
+
], HelixHeadlessFind.prototype, "closeLabel", void 0);
|
|
477
|
+
__decorate([
|
|
478
|
+
words,
|
|
479
|
+
property({ attribute: 'controls-label' })
|
|
480
|
+
], HelixHeadlessFind.prototype, "controlsLabel", void 0);
|
|
481
|
+
__decorate([
|
|
482
|
+
property()
|
|
483
|
+
], HelixHeadlessFind.prototype, "for", void 0);
|
|
484
|
+
__decorate([
|
|
485
|
+
words,
|
|
486
|
+
property({ attribute: 'invalid-label' })
|
|
487
|
+
], HelixHeadlessFind.prototype, "invalidLabel", void 0);
|
|
488
|
+
__decorate([
|
|
489
|
+
words,
|
|
490
|
+
property()
|
|
491
|
+
], HelixHeadlessFind.prototype, "label", void 0);
|
|
492
|
+
__decorate([
|
|
493
|
+
property({ attribute: 'match-case', type: Boolean })
|
|
494
|
+
], HelixHeadlessFind.prototype, "matchCase", void 0);
|
|
495
|
+
__decorate([
|
|
496
|
+
words,
|
|
497
|
+
property({ attribute: 'match-case-label' })
|
|
498
|
+
], HelixHeadlessFind.prototype, "matchCaseLabel", void 0);
|
|
499
|
+
__decorate([
|
|
500
|
+
words,
|
|
501
|
+
property({ attribute: 'matches-label' })
|
|
502
|
+
], HelixHeadlessFind.prototype, "matchesLabel", void 0);
|
|
503
|
+
__decorate([
|
|
504
|
+
words,
|
|
505
|
+
property({ attribute: 'next-label' })
|
|
506
|
+
], HelixHeadlessFind.prototype, "nextLabel", void 0);
|
|
507
|
+
__decorate([
|
|
508
|
+
property()
|
|
509
|
+
], HelixHeadlessFind.prototype, "options", void 0);
|
|
510
|
+
__decorate([
|
|
511
|
+
words,
|
|
512
|
+
property({ attribute: 'previous-label' })
|
|
513
|
+
], HelixHeadlessFind.prototype, "previousLabel", void 0);
|
|
514
|
+
__decorate([
|
|
515
|
+
property()
|
|
516
|
+
], HelixHeadlessFind.prototype, "query", void 0);
|
|
517
|
+
__decorate([
|
|
518
|
+
property({ attribute: 'readonly', type: Boolean })
|
|
519
|
+
], HelixHeadlessFind.prototype, "readOnly", void 0);
|
|
520
|
+
__decorate([
|
|
521
|
+
property({ type: Boolean })
|
|
522
|
+
], HelixHeadlessFind.prototype, "regex", void 0);
|
|
523
|
+
__decorate([
|
|
524
|
+
words,
|
|
525
|
+
property({ attribute: 'regex-label' })
|
|
526
|
+
], HelixHeadlessFind.prototype, "regexLabel", void 0);
|
|
527
|
+
__decorate([
|
|
528
|
+
words,
|
|
529
|
+
property({ attribute: 'replace-all-label' })
|
|
530
|
+
], HelixHeadlessFind.prototype, "replaceAllLabel", void 0);
|
|
531
|
+
__decorate([
|
|
532
|
+
words,
|
|
533
|
+
property({ attribute: 'replace-field-label' })
|
|
534
|
+
], HelixHeadlessFind.prototype, "replaceFieldLabel", void 0);
|
|
535
|
+
__decorate([
|
|
536
|
+
words,
|
|
537
|
+
property({ attribute: 'replace-label' })
|
|
538
|
+
], HelixHeadlessFind.prototype, "replaceLabel", void 0);
|
|
539
|
+
__decorate([
|
|
540
|
+
property()
|
|
541
|
+
], HelixHeadlessFind.prototype, "replacement", void 0);
|
|
542
|
+
__decorate([
|
|
543
|
+
words,
|
|
544
|
+
property({ attribute: 'replace-toggle-label' })
|
|
545
|
+
], HelixHeadlessFind.prototype, "replaceToggleLabel", void 0);
|
|
546
|
+
__decorate([
|
|
547
|
+
property()
|
|
548
|
+
], HelixHeadlessFind.prototype, "shortcut", void 0);
|
|
549
|
+
__decorate([
|
|
550
|
+
property()
|
|
551
|
+
], HelixHeadlessFind.prototype, "skip", void 0);
|
|
552
|
+
__decorate([
|
|
553
|
+
property({ attribute: 'whole-word', type: Boolean })
|
|
554
|
+
], HelixHeadlessFind.prototype, "wholeWord", void 0);
|
|
555
|
+
__decorate([
|
|
556
|
+
words,
|
|
557
|
+
property({ attribute: 'whole-word-label' })
|
|
558
|
+
], HelixHeadlessFind.prototype, "wholeWordLabel", void 0);
|
|
559
|
+
__decorate([
|
|
560
|
+
state()
|
|
561
|
+
], HelixHeadlessFind.prototype, "result", void 0);
|
|
562
|
+
__decorate([
|
|
563
|
+
state()
|
|
564
|
+
], HelixHeadlessFind.prototype, "replaceOpen", void 0);
|
|
565
|
+
__decorate([
|
|
566
|
+
state()
|
|
567
|
+
], HelixHeadlessFind.prototype, "attached", void 0);
|
|
568
|
+
__decorate([
|
|
569
|
+
state()
|
|
570
|
+
], HelixHeadlessFind.prototype, "announcement", void 0);
|
|
571
|
+
__decorate([
|
|
572
|
+
state()
|
|
573
|
+
], HelixHeadlessFind.prototype, "said", void 0);
|
|
574
|
+
HelixHeadlessFind = __decorate([
|
|
575
|
+
customElement('helix-headless-find')
|
|
576
|
+
], HelixHeadlessFind);
|
|
577
|
+
export { HelixHeadlessFind };
|
|
@@ -2,6 +2,7 @@ import { type GraphSignalDetail, HelixElement, ToolbarController, type ViewportP
|
|
|
2
2
|
import { nothing, type PropertyValues, type TemplateResult } from 'lit';
|
|
3
3
|
import { type StaticValue } from 'lit/static-html.js';
|
|
4
4
|
import '../../icon-button/index.js';
|
|
5
|
+
import '../../tooltip/index.js';
|
|
5
6
|
import { type GraphLink, type GraphNode } from './graph-model.js';
|
|
6
7
|
declare const HelixHeadlessGraph_base: (new (...args: any[]) => import("@fusion.dev/helix-core").ViewportElement) & (new (...args: any[]) => import("@fusion.dev/helix-core").MixinControllerActiveInterface) & typeof HelixElement;
|
|
7
8
|
/**
|
|
@@ -149,6 +150,16 @@ declare const HelixHeadlessGraph_base: (new (...args: any[]) => import("@fusion.
|
|
|
149
150
|
* @csspart settling - What is said while a layout runs unseen, where the reader asked for less motion or the page paused its motion, over the hidden drawing.
|
|
150
151
|
* @csspart stage - The drawing and its controls.
|
|
151
152
|
* @csspart stop-layout - The button that stops a layout that has run past five seconds, where the notes stand.
|
|
153
|
+
* @csspart tooltip-arrow - The arrow of the tooltip that names each button, forwarded from `Tooltip`.
|
|
154
|
+
* @csspart tooltip-arrow-bottom - The arrow while the bubble is below its button, on the bubble's top edge. Set together with `tooltip-arrow`.
|
|
155
|
+
* @csspart tooltip-arrow-left - The arrow while the bubble is left of its button, on the bubble's right edge. Set together with `tooltip-arrow`.
|
|
156
|
+
* @csspart tooltip-arrow-right - The arrow while the bubble is right of its button, on the bubble's left edge. Set together with `tooltip-arrow`.
|
|
157
|
+
* @csspart tooltip-arrow-top - The arrow while the bubble is above its button, on the bubble's bottom edge. Set together with `tooltip-arrow`.
|
|
158
|
+
* @csspart tooltip-surface - The bubble of the tooltip that names each button, forwarded from `Tooltip`.
|
|
159
|
+
* @csspart tooltip-surface-bottom - The bubble while it is below its button. Set together with `tooltip-surface`.
|
|
160
|
+
* @csspart tooltip-surface-left - The bubble while it is left of its button. Set together with `tooltip-surface`.
|
|
161
|
+
* @csspart tooltip-surface-right - The bubble while it is right of its button. Set together with `tooltip-surface`.
|
|
162
|
+
* @csspart tooltip-surface-top - The bubble while it is above its button. Set together with `tooltip-surface`.
|
|
152
163
|
* @csspart viewport - The box the renderer draws in.
|
|
153
164
|
* @csspart zoom-in - The zoom in button.
|
|
154
165
|
* @csspart zoom-in-button - `zoom-in`'s inner button.
|
|
@@ -5,6 +5,7 @@ import { html, nothing } from 'lit';
|
|
|
5
5
|
import { property, state } from 'lit/decorators.js';
|
|
6
6
|
import { html as staticHtml } from 'lit/static-html.js';
|
|
7
7
|
import '../../icon-button/index.js';
|
|
8
|
+
import '../../tooltip/index.js';
|
|
8
9
|
import { repeat } from 'lit/directives/repeat.js';
|
|
9
10
|
import { unsafeSVG } from 'lit/directives/unsafe-svg.js';
|
|
10
11
|
import { adjacencyOf, cursorAfter, entriesOf, groupsOf, nameOf, sortedOf, within, withoutGroups, } from './graph-model.js';
|
|
@@ -559,9 +560,11 @@ let HelixHeadlessGraph = class HelixHeadlessGraph extends MixinViewport(MixinCon
|
|
|
559
560
|
return nothing;
|
|
560
561
|
}
|
|
561
562
|
const button = this.controlTag;
|
|
563
|
+
const tip = this.tag('tooltip');
|
|
562
564
|
const { material, raised } = this.controlAxes;
|
|
563
565
|
return staticHtml `<${button}
|
|
564
566
|
part="notes-toggle"
|
|
567
|
+
id="notes-toggle"
|
|
565
568
|
exportparts="button: notes-toggle-button, live: notes-toggle-live, spinner: notes-toggle-spinner, text: notes-toggle-text"
|
|
566
569
|
aria-controls="panel"
|
|
567
570
|
.expanded=${this.panelOpen}
|
|
@@ -574,7 +577,7 @@ let HelixHeadlessGraph = class HelixHeadlessGraph extends MixinViewport(MixinCon
|
|
|
574
577
|
<svg aria-hidden="true" fill="currentColor" viewBox=${list.viewBox}>
|
|
575
578
|
${unsafeSVG(list.content)}
|
|
576
579
|
</svg>
|
|
577
|
-
</${button}>`;
|
|
580
|
+
</${button}><${tip} for="notes-toggle" content=${this.notesLabel} exportparts="arrow: tooltip-arrow, arrow-bottom: tooltip-arrow-bottom, arrow-left: tooltip-arrow-left, arrow-right: tooltip-arrow-right, arrow-top: tooltip-arrow-top, surface: tooltip-surface, surface-bottom: tooltip-surface-bottom, surface-left: tooltip-surface-left, surface-right: tooltip-surface-right, surface-top: tooltip-surface-top"></${tip}>`;
|
|
578
581
|
}
|
|
579
582
|
renderFilterIcon() {
|
|
580
583
|
return html `<slot name="filter-icon">
|
package/dist/index.d.ts
CHANGED
|
@@ -50,6 +50,7 @@ export * from './empty/index.js';
|
|
|
50
50
|
export * from './file-input/index.js';
|
|
51
51
|
export * from './filter-input/index.js';
|
|
52
52
|
export * from './filter-input/menu/index.js';
|
|
53
|
+
export * from './find/index.js';
|
|
53
54
|
export * from './format-date/index.js';
|
|
54
55
|
export * from './graph/index.js';
|
|
55
56
|
export * from './heatmap/index.js';
|
package/dist/index.js
CHANGED
|
@@ -41,6 +41,7 @@ export * from './empty/index.js';
|
|
|
41
41
|
export * from './file-input/index.js';
|
|
42
42
|
export * from './filter-input/index.js';
|
|
43
43
|
export * from './filter-input/menu/index.js';
|
|
44
|
+
export * from './find/index.js';
|
|
44
45
|
export * from './format-date/index.js';
|
|
45
46
|
export * from './graph/index.js';
|
|
46
47
|
export * from './heatmap/index.js';
|
|
@@ -99,6 +99,12 @@ export declare class HelixHeadlessInput extends HelixHeadlessInput_base {
|
|
|
99
99
|
* a token like `email` or `bday` to ask for autofill, or to `off` to refuse.
|
|
100
100
|
*/
|
|
101
101
|
autocomplete: string;
|
|
102
|
+
/**
|
|
103
|
+
* Whether the browser corrects words as the reader types, as the platform's
|
|
104
|
+
* `autocorrect`. Turn it off, with `autocorrect="off"`, for text that is not
|
|
105
|
+
* prose, such as an address or a code, which corrections would change.
|
|
106
|
+
*/
|
|
107
|
+
autocorrect: boolean;
|
|
102
108
|
/**
|
|
103
109
|
* Whether the field shows a button that empties it.
|
|
104
110
|
*
|
|
@@ -13,6 +13,7 @@ let HelixHeadlessInput = class HelixHeadlessInput extends MixinVoice(MixinContro
|
|
|
13
13
|
this.announcesInput = true;
|
|
14
14
|
this.autocapitalize = '';
|
|
15
15
|
this.autocomplete = '';
|
|
16
|
+
this.autocorrect = true;
|
|
16
17
|
this.clearable = false;
|
|
17
18
|
this.clearLabel = 'Clear';
|
|
18
19
|
this.enterKeyHint = '';
|
|
@@ -198,6 +199,7 @@ let HelixHeadlessInput = class HelixHeadlessInput extends MixinVoice(MixinContro
|
|
|
198
199
|
inputmode=${this.inputMode || nothing}
|
|
199
200
|
enterkeyhint=${this.enterKeyHint || nothing}
|
|
200
201
|
autocapitalize=${this.autocapitalize || nothing}
|
|
202
|
+
autocorrect=${this.autocorrect ? nothing : 'off'}
|
|
201
203
|
aria-describedby=${this.describedBy ?? nothing}
|
|
202
204
|
aria-invalid=${this.invalidity ?? nothing}
|
|
203
205
|
?disabled=${this.isDisabled}
|
|
@@ -243,6 +245,11 @@ __decorate([
|
|
|
243
245
|
__decorate([
|
|
244
246
|
property()
|
|
245
247
|
], HelixHeadlessInput.prototype, "autocomplete", void 0);
|
|
248
|
+
__decorate([
|
|
249
|
+
property({
|
|
250
|
+
converter: { fromAttribute: (value) => value?.toLowerCase() !== 'off' },
|
|
251
|
+
})
|
|
252
|
+
], HelixHeadlessInput.prototype, "autocorrect", void 0);
|
|
246
253
|
__decorate([
|
|
247
254
|
property({ type: Boolean })
|
|
248
255
|
], HelixHeadlessInput.prototype, "clearable", void 0);
|