@fusion.dev/helix-headless 0.12.2 → 0.13.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 +1424 -76
- package/dist/combobox/root/combobox-root.d.ts +9 -16
- package/dist/combobox/root/combobox-root.js +10 -18
- package/dist/element-events.generated.js +1 -0
- package/dist/filter-input/index.d.ts +1 -0
- package/dist/filter-input/index.js +1 -0
- package/dist/filter-input/root/filter-input-root.d.ts +129 -0
- package/dist/filter-input/root/filter-input-root.js +140 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/package.json +5 -5
- package/types/jsx.d.ts +537 -76
- package/types/svelte.d.ts +1 -0
- package/types/vue.d.ts +96 -26
|
@@ -2,7 +2,7 @@ import { AriaForwardController, HelixFormElement, PopoverController } from '@fus
|
|
|
2
2
|
import { type PropertyValues, type TemplateResult } from 'lit';
|
|
3
3
|
import '../../listbox/index.js';
|
|
4
4
|
import '../../tag/index.js';
|
|
5
|
-
declare const HelixHeadlessCombobox_base: (new (...args: any[]) => import("@fusion.dev/helix-core").MixinControllerOpenInterface) & (new (...args: any[]) => import("@fusion.dev/helix-core").MixinControllerValueInterface) & (new (...args: any[]) => import("@fusion.dev/helix-core").MixinFieldInterface) & typeof HelixFormElement;
|
|
5
|
+
declare const HelixHeadlessCombobox_base: (new (...args: any[]) => import("@fusion.dev/helix-core").MixinControllerOpenInterface) & (new (...args: any[]) => import("@fusion.dev/helix-core").MixinTokensInterface) & (new (...args: any[]) => import("@fusion.dev/helix-core").MixinControllerValueInterface) & (new (...args: any[]) => import("@fusion.dev/helix-core").MixinFieldInterface) & typeof HelixFormElement;
|
|
6
6
|
/**
|
|
7
7
|
* @summary A field that filters a list as it is typed into.
|
|
8
8
|
*
|
|
@@ -121,21 +121,6 @@ export declare class HelixHeadlessCombobox extends HelixHeadlessCombobox_base {
|
|
|
121
121
|
* What the list says while they are on their way.
|
|
122
122
|
*/
|
|
123
123
|
loadingText: string;
|
|
124
|
-
/**
|
|
125
|
-
* How many tags to draw before the rest become a count. `multiple` only.
|
|
126
|
-
*
|
|
127
|
-
* `0` is all of them, and is the default: a cap that guesses is worse than no
|
|
128
|
-
* cap, because the number that fits depends on the width of the field and the
|
|
129
|
-
* length of what is in it, neither of which this element knows. What a cap is
|
|
130
|
-
* genuinely for is a field in a row or a table cell, where a set of twelve
|
|
131
|
-
* choices would push everything below it down a line at a time.
|
|
132
|
-
*
|
|
133
|
-
* The remainder is counted rather than hidden. `+3` is a fact a reader can act
|
|
134
|
-
* on, where a row that silently stops is a field that appears to have lost
|
|
135
|
-
* what was put in it. Date Input and Time Input carry the same property and
|
|
136
|
-
* the same reasoning.
|
|
137
|
-
*/
|
|
138
|
-
maxTags: number;
|
|
139
124
|
/**
|
|
140
125
|
* Whether more than one option can be chosen.
|
|
141
126
|
*
|
|
@@ -295,6 +280,14 @@ export declare class HelixHeadlessCombobox extends HelixHeadlessCombobox_base {
|
|
|
295
280
|
* when you clicked into the middle of your own typing would be unusable.
|
|
296
281
|
*/
|
|
297
282
|
private readonly handleFieldClick;
|
|
283
|
+
/**
|
|
284
|
+
* The last chosen one goes, which is what Backspace on an empty field means.
|
|
285
|
+
*
|
|
286
|
+
* `MixinTokens` owns when this is asked for and this owns what it does: a
|
|
287
|
+
* token here is a chosen option, so it leaves by the same door a dismissed
|
|
288
|
+
* tag does.
|
|
289
|
+
*/
|
|
290
|
+
protected removeLastToken(): void;
|
|
298
291
|
/** One tag asking to be taken out of the set. */
|
|
299
292
|
private readonly handleDismiss;
|
|
300
293
|
/**
|
|
@@ -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 { AriaForwardController, customElement, HelixCreateEvent, HelixFormElement, MixinControllerOpen, MixinControllerValue, MixinField, PopoverController, } from '@fusion.dev/helix-core';
|
|
7
|
+
import { AriaForwardController, customElement, HelixCreateEvent, HelixFormElement, MixinControllerOpen, MixinControllerValue, MixinField, MixinTokens, PopoverController, } from '@fusion.dev/helix-core';
|
|
8
8
|
import { caretDown } from '@fusion.dev/helix-icons';
|
|
9
9
|
import { nothing } from 'lit';
|
|
10
10
|
import { property, state } from 'lit/decorators.js';
|
|
@@ -13,7 +13,7 @@ import { html } from 'lit/static-html.js';
|
|
|
13
13
|
import '../../listbox/index.js';
|
|
14
14
|
import '../../tag/index.js';
|
|
15
15
|
const isInsertion = (event) => !event.inputType?.startsWith('delete');
|
|
16
|
-
let HelixHeadlessCombobox = class HelixHeadlessCombobox extends MixinControllerOpen(MixinControllerValue(MixinField(HelixFormElement))) {
|
|
16
|
+
let HelixHeadlessCombobox = class HelixHeadlessCombobox extends MixinControllerOpen(MixinTokens(MixinControllerValue(MixinField(HelixFormElement)))) {
|
|
17
17
|
constructor() {
|
|
18
18
|
super(...arguments);
|
|
19
19
|
this.aria = new AriaForwardController(this, {
|
|
@@ -26,7 +26,6 @@ let HelixHeadlessCombobox = class HelixHeadlessCombobox extends MixinControllerO
|
|
|
26
26
|
this.listLabel = 'Options';
|
|
27
27
|
this.loading = false;
|
|
28
28
|
this.loadingText = 'Loading';
|
|
29
|
-
this.maxTags = 0;
|
|
30
29
|
this.multiple = false;
|
|
31
30
|
this.placeholder = '';
|
|
32
31
|
this.removeLabel = 'Remove';
|
|
@@ -71,12 +70,7 @@ let HelixHeadlessCombobox = class HelixHeadlessCombobox extends MixinControllerO
|
|
|
71
70
|
}
|
|
72
71
|
return;
|
|
73
72
|
}
|
|
74
|
-
if (
|
|
75
|
-
const last = this.values.at(-1);
|
|
76
|
-
if (last !== undefined) {
|
|
77
|
-
event.preventDefault();
|
|
78
|
-
this.drop(last);
|
|
79
|
-
}
|
|
73
|
+
if (this.multiple && this.tokenKeydown(event, this.typed)) {
|
|
80
74
|
return;
|
|
81
75
|
}
|
|
82
76
|
if (event.key === 'Enter' && this.creation !== '' && !this.showing) {
|
|
@@ -206,6 +200,12 @@ let HelixHeadlessCombobox = class HelixHeadlessCombobox extends MixinControllerO
|
|
|
206
200
|
const match = (this.listbox?.options ?? []).find((option) => !option.hidden && !option.disabled && option.text.toLowerCase().startsWith(needle));
|
|
207
201
|
return match && match.text.length > typed.length ? match.text : '';
|
|
208
202
|
}
|
|
203
|
+
removeLastToken() {
|
|
204
|
+
const last = this.values.at(-1);
|
|
205
|
+
if (last !== undefined) {
|
|
206
|
+
this.drop(last);
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
209
|
sync() {
|
|
210
210
|
this.internals.setFormValue(this.value === '' ? null : this.value);
|
|
211
211
|
this.reportRequired(this.value === '', 'Choose one to continue.', 'control');
|
|
@@ -284,12 +284,7 @@ let HelixHeadlessCombobox = class HelixHeadlessCombobox extends MixinControllerO
|
|
|
284
284
|
<div part="field" @click=${this.handleFieldClick}>
|
|
285
285
|
<slot name="start"></slot>
|
|
286
286
|
${this.multiple && this.chosen.length > 0
|
|
287
|
-
?
|
|
288
|
-
${this.shown.map((option) => this.renderTag(option))}
|
|
289
|
-
${this.restCount > 0
|
|
290
|
-
? html `<span part="rest">${`+${this.restCount}`}</span>`
|
|
291
|
-
: nothing}
|
|
292
|
-
</span>`
|
|
287
|
+
? this.renderTokenRow(this.shown.map((option) => this.renderTag(option)), this.restCount)
|
|
293
288
|
: nothing}
|
|
294
289
|
<input
|
|
295
290
|
part="control"
|
|
@@ -344,9 +339,6 @@ __decorate([
|
|
|
344
339
|
__decorate([
|
|
345
340
|
property({ attribute: 'loading-text' })
|
|
346
341
|
], HelixHeadlessCombobox.prototype, "loadingText", void 0);
|
|
347
|
-
__decorate([
|
|
348
|
-
property({ attribute: 'max-tags', type: Number })
|
|
349
|
-
], HelixHeadlessCombobox.prototype, "maxTags", void 0);
|
|
350
342
|
__decorate([
|
|
351
343
|
property({ type: Boolean })
|
|
352
344
|
], HelixHeadlessCombobox.prototype, "multiple", void 0);
|
|
@@ -52,6 +52,7 @@ registerElementEvents({
|
|
|
52
52
|
'helix-headless-drilldown': ['helix-select'],
|
|
53
53
|
'helix-headless-drilldown-item': ['helix-select'],
|
|
54
54
|
'helix-headless-file-input': ['change', 'helix-before-change', 'input'],
|
|
55
|
+
'helix-headless-filter-input': ['change', 'helix-before-change', 'input'],
|
|
55
56
|
'helix-headless-heatmap': ['helix-resize'],
|
|
56
57
|
'helix-headless-image': ['error', 'load'],
|
|
57
58
|
'helix-headless-input': ['change', 'helix-before-change', 'input'],
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './root/filter-input-root.js';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './root/filter-input-root.js';
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
import { AriaForwardController, HelixFormElement } from '@fusion.dev/helix-core';
|
|
2
|
+
import { type PropertyValues, type TemplateResult } from 'lit';
|
|
3
|
+
declare const HelixHeadlessFilterInput_base: (new (...args: any[]) => import("@fusion.dev/helix-core").MixinTokensInterface) & (new (...args: any[]) => import("@fusion.dev/helix-core").MixinControllerValueInterface) & (new (...args: any[]) => import("@fusion.dev/helix-core").MixinFieldInterface) & typeof HelixFormElement;
|
|
4
|
+
/**
|
|
5
|
+
* @summary A field that narrows something else, beside what is already narrowing it.
|
|
6
|
+
*
|
|
7
|
+
* @description
|
|
8
|
+
* **The tokens are the consumer's own elements, slotted.** What a filter narrows
|
|
9
|
+
* by belongs to the consumer's model rather than to this element: a facet with a
|
|
10
|
+
* prefix, a saved query, a range. So they are slotted rather than rendered from
|
|
11
|
+
* a list of strings, and removing one is a request this element makes rather
|
|
12
|
+
* than a change it applies. Combobox is the other way round, and that is the
|
|
13
|
+
* difference between the two: its tokens are a view of a selection it owns,
|
|
14
|
+
* drawn from options it was handed.
|
|
15
|
+
*
|
|
16
|
+
* **`value` is the text being typed, not the tokens**, which is what makes this
|
|
17
|
+
* a field a consumer can listen to. Every keystroke announces `input` with the
|
|
18
|
+
* text on the element, so a table narrows as the reader types. The tokens need
|
|
19
|
+
* no reporting back, being markup the consumer already holds.
|
|
20
|
+
*
|
|
21
|
+
* Backspace on an empty field asks the last token to go, through the same
|
|
22
|
+
* `helix-dismiss` its own remove control fires, so a consumer who handled the
|
|
23
|
+
* pointer has already handled the keyboard.
|
|
24
|
+
*
|
|
25
|
+
* @since 0.1.0
|
|
26
|
+
* @status experimental
|
|
27
|
+
* @category forms
|
|
28
|
+
* @aliases SearchField, FacetInput, TokenInput
|
|
29
|
+
* @documentation https://helix.fusion.dev/components/filter-input
|
|
30
|
+
*
|
|
31
|
+
* @slot end - After the text, for a count or a control.
|
|
32
|
+
* @slot start - Before the text, for a search icon.
|
|
33
|
+
* @slot tags - What is already narrowing the results, as `Tag`s.
|
|
34
|
+
*
|
|
35
|
+
* @event {Event} change - Relayed from the input once the reader has finished.
|
|
36
|
+
* @event {HelixBeforeChangeEvent} helix-before-change - Fired as the text changes, and cancelable.
|
|
37
|
+
* @event {Event} input - Announced once the text has moved.
|
|
38
|
+
*
|
|
39
|
+
* @csspart clear - The button that empties the field.
|
|
40
|
+
* @csspart control - The input itself.
|
|
41
|
+
* @csspart feedback - What is wrong with it.
|
|
42
|
+
* @csspart field - The box holding everything.
|
|
43
|
+
* @csspart hint - Help under the field, while nothing is wrong.
|
|
44
|
+
* @csspart label - The question, over the field.
|
|
45
|
+
* @csspart rest - How many tokens did not fit.
|
|
46
|
+
* @csspart tags - The row the tokens sit in.
|
|
47
|
+
*/
|
|
48
|
+
export declare class HelixHeadlessFilterInput extends HelixHeadlessFilterInput_base {
|
|
49
|
+
protected readonly aria: AriaForwardController;
|
|
50
|
+
/** Typed, so every keystroke is announced. See `announcesInput`. */
|
|
51
|
+
protected readonly announcesInput = true;
|
|
52
|
+
/**
|
|
53
|
+
* Whether the field offers a button that empties it.
|
|
54
|
+
*
|
|
55
|
+
* The text only. The tokens are the consumer's markup and this element is not
|
|
56
|
+
* entitled to take them out of the document, which is the same reason
|
|
57
|
+
* `hideOverflow` marks the ones over the cap `hidden` rather than removing
|
|
58
|
+
* them.
|
|
59
|
+
*/
|
|
60
|
+
clearable: boolean;
|
|
61
|
+
/**
|
|
62
|
+
* What the clear button is called, since an icon has no name of its own.
|
|
63
|
+
*/
|
|
64
|
+
clearLabel: string;
|
|
65
|
+
/**
|
|
66
|
+
* Shown while the field is empty.
|
|
67
|
+
*
|
|
68
|
+
* Not a label: it goes when typing starts.
|
|
69
|
+
*/
|
|
70
|
+
placeholder: string;
|
|
71
|
+
/** How many tokens did not fit, which is what the row's count renders. */
|
|
72
|
+
private over;
|
|
73
|
+
/**
|
|
74
|
+
* The caret, held across a value the consumer wrote rather than the reader.
|
|
75
|
+
*
|
|
76
|
+
* Set in `willUpdate` and spent in `updated`, because Lit's `.value` binding
|
|
77
|
+
* lands between the two and takes the selection with it. See `holdCaret`.
|
|
78
|
+
*/
|
|
79
|
+
private releaseCaret;
|
|
80
|
+
/** Focus is delegated to the input, so the host is never the focus target. */
|
|
81
|
+
static shadowRootOptions: ShadowRootInit;
|
|
82
|
+
private get control();
|
|
83
|
+
private get tokens();
|
|
84
|
+
/** Whether there is a clear button on screen right now. */
|
|
85
|
+
private get showsClear();
|
|
86
|
+
/**
|
|
87
|
+
* Every keystroke, cancelable, and put back where it is refused.
|
|
88
|
+
*
|
|
89
|
+
* Stopped for the reason `Input` gives: `input` is composed, so the inner
|
|
90
|
+
* control's own would arrive beside the one the mixin announces and a consumer
|
|
91
|
+
* would hear one keystroke twice, once carrying the value from before it.
|
|
92
|
+
*/
|
|
93
|
+
private readonly handleInput;
|
|
94
|
+
/** Relayed, because `change` does not cross a shadow boundary on its own. */
|
|
95
|
+
private readonly handleChange;
|
|
96
|
+
/**
|
|
97
|
+
* Empties the text and gives the caret back.
|
|
98
|
+
*
|
|
99
|
+
* Focus returns to the input rather than staying on a button that is about to
|
|
100
|
+
* disappear, which would otherwise land on the body.
|
|
101
|
+
*/
|
|
102
|
+
private readonly handleClear;
|
|
103
|
+
private readonly handleKeydown;
|
|
104
|
+
/** The row again, whenever what is in it changes. */
|
|
105
|
+
private readonly handleTokens;
|
|
106
|
+
/**
|
|
107
|
+
* Asks the last token to go, rather than taking it.
|
|
108
|
+
*
|
|
109
|
+
* `dismiss()` is the tag's own, so this is the code path its remove control
|
|
110
|
+
* already runs on a press: the consumer hears one `helix-dismiss`, cancels it
|
|
111
|
+
* or removes the element, and never learns which of the two asked. A slotted
|
|
112
|
+
* node that is not a `Tag` has no such method and is left alone, because
|
|
113
|
+
* hiding a consumer's element on Backspace would be this element deciding
|
|
114
|
+
* something it was never given.
|
|
115
|
+
*/
|
|
116
|
+
protected removeLastToken(): void;
|
|
117
|
+
protected willUpdate(changed: PropertyValues): void;
|
|
118
|
+
protected firstUpdated(changed: PropertyValues): void;
|
|
119
|
+
protected updated(changed: PropertyValues): void;
|
|
120
|
+
/** Puts the caret in the field, the way a label pointing at one would. */
|
|
121
|
+
focus(options?: FocusOptions): void;
|
|
122
|
+
protected render(): TemplateResult;
|
|
123
|
+
}
|
|
124
|
+
declare global {
|
|
125
|
+
interface HTMLElementTagNameMap {
|
|
126
|
+
'helix-headless-filter-input': HelixHeadlessFilterInput;
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
export {};
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
2
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
3
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
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
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
6
|
+
};
|
|
7
|
+
import { AriaForwardController, customElement, drawIcon, HelixFormElement, holdCaret, MixinControllerValue, MixinField, MixinTokens, restoreValue, } from '@fusion.dev/helix-core';
|
|
8
|
+
import { x } from '@fusion.dev/helix-icons';
|
|
9
|
+
import { html, nothing } from 'lit';
|
|
10
|
+
import { property, state } from 'lit/decorators.js';
|
|
11
|
+
const asksToGo = (node) => typeof node?.dismiss === 'function';
|
|
12
|
+
let HelixHeadlessFilterInput = class HelixHeadlessFilterInput extends MixinTokens(MixinControllerValue(MixinField(HelixFormElement))) {
|
|
13
|
+
constructor() {
|
|
14
|
+
super(...arguments);
|
|
15
|
+
this.aria = new AriaForwardController(this, {
|
|
16
|
+
target: () => this.renderRoot?.querySelector('[part="control"]') ?? null,
|
|
17
|
+
});
|
|
18
|
+
this.announcesInput = true;
|
|
19
|
+
this.clearable = false;
|
|
20
|
+
this.clearLabel = 'Clear';
|
|
21
|
+
this.placeholder = '';
|
|
22
|
+
this.over = 0;
|
|
23
|
+
this.handleInput = (event) => {
|
|
24
|
+
event.stopPropagation();
|
|
25
|
+
const control = event.target;
|
|
26
|
+
this.requestValue(control.value);
|
|
27
|
+
restoreValue(control, this.value);
|
|
28
|
+
};
|
|
29
|
+
this.handleChange = (event) => {
|
|
30
|
+
event.stopPropagation();
|
|
31
|
+
this.dispatchEvent(new Event('change', { bubbles: true, composed: false }));
|
|
32
|
+
};
|
|
33
|
+
this.handleClear = () => {
|
|
34
|
+
this.requestValue('');
|
|
35
|
+
const control = this.control;
|
|
36
|
+
if (control) {
|
|
37
|
+
restoreValue(control, this.value);
|
|
38
|
+
control.focus();
|
|
39
|
+
}
|
|
40
|
+
};
|
|
41
|
+
this.handleKeydown = (event) => {
|
|
42
|
+
this.tokenKeydown(event, this.value);
|
|
43
|
+
};
|
|
44
|
+
this.handleTokens = () => {
|
|
45
|
+
this.over = this.hideOverflow(this.tokens);
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
static { this.shadowRootOptions = {
|
|
49
|
+
...HelixFormElement.shadowRootOptions,
|
|
50
|
+
delegatesFocus: true,
|
|
51
|
+
}; }
|
|
52
|
+
get control() {
|
|
53
|
+
return this.renderRoot.querySelector('[part="control"]');
|
|
54
|
+
}
|
|
55
|
+
get tokens() {
|
|
56
|
+
return this.renderRoot?.querySelector('slot[name="tags"]') ?? null;
|
|
57
|
+
}
|
|
58
|
+
get showsClear() {
|
|
59
|
+
return this.clearable && this.value !== '' && !this.isDisabled;
|
|
60
|
+
}
|
|
61
|
+
removeLastToken() {
|
|
62
|
+
const last = this.tokens?.assignedElements({ flatten: true }).at(-1);
|
|
63
|
+
if (asksToGo(last)) {
|
|
64
|
+
last.dismiss();
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
willUpdate(changed) {
|
|
68
|
+
super.willUpdate(changed);
|
|
69
|
+
if (!this.hasUpdated) {
|
|
70
|
+
return;
|
|
71
|
+
}
|
|
72
|
+
const control = this.control;
|
|
73
|
+
if (changed.has('value') && control && this.shadowRoot?.activeElement === control) {
|
|
74
|
+
this.releaseCaret = holdCaret(control);
|
|
75
|
+
}
|
|
76
|
+
this.handleTokens();
|
|
77
|
+
}
|
|
78
|
+
firstUpdated(changed) {
|
|
79
|
+
super.firstUpdated(changed);
|
|
80
|
+
this.handleTokens();
|
|
81
|
+
}
|
|
82
|
+
updated(changed) {
|
|
83
|
+
super.updated(changed);
|
|
84
|
+
this.releaseCaret?.();
|
|
85
|
+
this.releaseCaret = undefined;
|
|
86
|
+
this.internals.setFormValue(this.value);
|
|
87
|
+
}
|
|
88
|
+
focus(options) {
|
|
89
|
+
this.control?.focus(options);
|
|
90
|
+
}
|
|
91
|
+
render() {
|
|
92
|
+
return html `${this.renderLabel()}
|
|
93
|
+
<div part="field">
|
|
94
|
+
<slot name="start"></slot>
|
|
95
|
+
${this.renderTokenRow(html `<slot name="tags" @slotchange=${this.handleTokens}></slot>`, this.over)}
|
|
96
|
+
<input
|
|
97
|
+
part="control"
|
|
98
|
+
id="control"
|
|
99
|
+
type="text"
|
|
100
|
+
.value=${this.value}
|
|
101
|
+
name=${this.name || nothing}
|
|
102
|
+
placeholder=${this.placeholder || nothing}
|
|
103
|
+
aria-describedby=${this.describedBy ?? nothing}
|
|
104
|
+
?disabled=${this.isDisabled}
|
|
105
|
+
?required=${this.required}
|
|
106
|
+
@input=${this.handleInput}
|
|
107
|
+
@change=${this.handleChange}
|
|
108
|
+
@keydown=${this.handleKeydown}
|
|
109
|
+
/>
|
|
110
|
+
<slot name="end"></slot>
|
|
111
|
+
${this.showsClear
|
|
112
|
+
? html `<button
|
|
113
|
+
part="clear"
|
|
114
|
+
type="button"
|
|
115
|
+
aria-label=${this.clearLabel}
|
|
116
|
+
@click=${this.handleClear}
|
|
117
|
+
>
|
|
118
|
+
${drawIcon(x)}
|
|
119
|
+
</button>`
|
|
120
|
+
: nothing}
|
|
121
|
+
</div>
|
|
122
|
+
${this.renderHint()}${this.renderFeedback()}`;
|
|
123
|
+
}
|
|
124
|
+
};
|
|
125
|
+
__decorate([
|
|
126
|
+
property({ type: Boolean })
|
|
127
|
+
], HelixHeadlessFilterInput.prototype, "clearable", void 0);
|
|
128
|
+
__decorate([
|
|
129
|
+
property({ attribute: 'clear-label' })
|
|
130
|
+
], HelixHeadlessFilterInput.prototype, "clearLabel", void 0);
|
|
131
|
+
__decorate([
|
|
132
|
+
property()
|
|
133
|
+
], HelixHeadlessFilterInput.prototype, "placeholder", void 0);
|
|
134
|
+
__decorate([
|
|
135
|
+
state()
|
|
136
|
+
], HelixHeadlessFilterInput.prototype, "over", void 0);
|
|
137
|
+
HelixHeadlessFilterInput = __decorate([
|
|
138
|
+
customElement('helix-headless-filter-input')
|
|
139
|
+
], HelixHeadlessFilterInput);
|
|
140
|
+
export { HelixHeadlessFilterInput };
|
package/dist/index.d.ts
CHANGED
|
@@ -42,6 +42,7 @@ export * from './drawer/index.js';
|
|
|
42
42
|
export * from './drilldown/index.js';
|
|
43
43
|
export * from './empty/index.js';
|
|
44
44
|
export * from './file-input/index.js';
|
|
45
|
+
export * from './filter-input/index.js';
|
|
45
46
|
export * from './format-date/index.js';
|
|
46
47
|
export * from './heatmap/index.js';
|
|
47
48
|
export * from './icon/index.js';
|
package/dist/index.js
CHANGED
|
@@ -33,6 +33,7 @@ export * from './drawer/index.js';
|
|
|
33
33
|
export * from './drilldown/index.js';
|
|
34
34
|
export * from './empty/index.js';
|
|
35
35
|
export * from './file-input/index.js';
|
|
36
|
+
export * from './filter-input/index.js';
|
|
36
37
|
export * from './format-date/index.js';
|
|
37
38
|
export * from './heatmap/index.js';
|
|
38
39
|
export * from './icon/index.js';
|
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.13.0",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "Ross Sheppard <ross.sheppard@fusion.dev>",
|
|
7
7
|
"repository": {
|
|
@@ -45,14 +45,14 @@
|
|
|
45
45
|
},
|
|
46
46
|
"bugs": "https://github.com/project-fusion/fusion/issues",
|
|
47
47
|
"dependencies": {
|
|
48
|
-
"@fusion.dev/helix-core": "0.
|
|
49
|
-
"@fusion.dev/helix-icons": "0.
|
|
48
|
+
"@fusion.dev/helix-core": "0.13.0",
|
|
49
|
+
"@fusion.dev/helix-icons": "0.13.0",
|
|
50
50
|
"uqr": "^0.1.3"
|
|
51
51
|
},
|
|
52
52
|
"devDependencies": {
|
|
53
53
|
"@custom-elements-manifest/analyzer": "^0.11.0",
|
|
54
|
-
"@fusion.dev/helix-cem": "0.
|
|
55
|
-
"@fusion.dev/helix-testing": "0.
|
|
54
|
+
"@fusion.dev/helix-cem": "0.13.0",
|
|
55
|
+
"@fusion.dev/helix-testing": "0.13.0",
|
|
56
56
|
"@fusion.dev/scripts": "0.0.0-dev",
|
|
57
57
|
"@happy-dom/global-registrator": "^20.0.0",
|
|
58
58
|
"@lit-labs/ssr": "^3.3.0",
|