html-combobox-element 0.0.6 → 0.0.8
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/README.md +58 -99
- package/README.md.rej +34 -0
- package/dist/cjs/combobox/Boolean.attribute.value.normalizer.d.ts +14 -1
- package/dist/cjs/combobox/Boolean.attribute.value.normalizer.js +17 -1
- package/dist/cjs/combobox/HTML.combobox.element.js +25 -25
- package/dist/cjs/combobox/HTML.combobox.option.element.js +11 -10
- package/dist/cjs/combobox/HTML.combobox.options.collection.js +2 -4
- package/dist/cjs/index.d.ts +228 -82
- package/dist/cjs/index.js +3 -0
- package/dist/esm/combobox/Boolean.attribute.value.normalizer.js +16 -1
- package/dist/esm/combobox/HTML.combobox.element.js +11 -9
- package/dist/esm/combobox/HTML.combobox.option.element.js +8 -5
- package/dist/esm/index.js +2 -0
- package/dist/types/combobox/Boolean.attribute.value.normalizer.d.ts +14 -1
- package/dist/types/index.d.ts +228 -82
- package/package.json +33 -2
package/dist/cjs/index.d.ts
CHANGED
|
@@ -1,67 +1,86 @@
|
|
|
1
|
+
import { HTMLComboboxElement as ComboboxElementClass } from './combobox/HTML.combobox.element.js';
|
|
2
|
+
import type { HTMLComboboxOptionsCollection } from './combobox/HTML.combobox.options.collection.js';
|
|
1
3
|
export * from './combobox/index.js';
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
interface
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
4
|
+
export declare const HTMLComboboxElement: Omit<typeof ComboboxElementClass, 'prototype'> & {
|
|
5
|
+
prototype: HTMLComboboxElement;
|
|
6
|
+
new (): HTMLComboboxElement;
|
|
7
|
+
};
|
|
8
|
+
export type HTMLComboboxElement = globalThis.HTMLComboboxElement;
|
|
9
|
+
declare global {
|
|
10
|
+
interface HTMLComboboxTagElement extends HTMLElement {
|
|
11
|
+
}
|
|
12
|
+
interface HTMLComboboxOptionElement extends HTMLOptionElement {
|
|
13
|
+
value: string;
|
|
14
|
+
label: string;
|
|
15
|
+
}
|
|
16
|
+
interface HTMLComboboxElement extends HTMLSelectElement {
|
|
17
|
+
/** List of selected options value attribute */
|
|
18
|
+
valueAsArray: string[];
|
|
19
|
+
/** Whether the value differs from when the picker opened (read it in a `close` listener). */
|
|
20
|
+
readonly changed: boolean;
|
|
21
|
+
/** A live `HTMLOptionsCollection`-compatible collection (not `instanceof HTMLOptionsCollection`). */
|
|
22
|
+
readonly options: HTMLOptionsCollection & HTMLComboboxOptionsCollection;
|
|
23
|
+
multiple: boolean;
|
|
24
|
+
/** The value of internal input
|
|
25
|
+
*
|
|
26
|
+
* Internal input is visible when either "searchable" or "filterable" attribute is presented */
|
|
27
|
+
query: string;
|
|
28
|
+
/** The placeholder of internal input
|
|
29
|
+
*
|
|
30
|
+
* Internal input is visible when either "searchable" or "filterable" attribute is presented
|
|
31
|
+
*
|
|
32
|
+
* When <combo-box> is empty, this value is also shown as <combo-box> placeholder itself
|
|
33
|
+
* */
|
|
34
|
+
placeholder: string;
|
|
35
|
+
/** When is true, the clear-all-button is shown in the <combo-box> itself,
|
|
36
|
+
* and the clear-button is shown for each selected tag.
|
|
37
|
+
*
|
|
38
|
+
* If multiple attribute is set to "true", this is also enabled.
|
|
39
|
+
*
|
|
40
|
+
* If multiple attribute is set to "false", i.e. the <combo-box> is used as a <select>,
|
|
41
|
+
* then setting this attribute to "true" will make the clear-button of selected tag visible
|
|
42
|
+
* */
|
|
43
|
+
clearable: boolean;
|
|
44
|
+
/** When is true, the internal input is shown.
|
|
45
|
+
*
|
|
46
|
+
* When user type something, available options are not filtered by this query.
|
|
47
|
+
* You have to set an "input" listener to the <combo-box> and filter options by yourself
|
|
48
|
+
*
|
|
49
|
+
* Setting both "searchable" and "filterable" make no sense, the "searchable" will have priority
|
|
50
|
+
* */
|
|
51
|
+
searchable: boolean;
|
|
52
|
+
/** When is true, the internal input is shown.
|
|
53
|
+
*
|
|
54
|
+
* When user type something, available options are filtered by this query.
|
|
55
|
+
*
|
|
56
|
+
* Setting both "filterable" and "searchable" make no sense, the "searchable" will have priority
|
|
57
|
+
* */
|
|
58
|
+
filterable: boolean;
|
|
59
|
+
selectedOptions: HTMLCollectionOf<HTMLComboboxOptionElement>;
|
|
60
|
+
addEventListener<K extends keyof ComboboxEventMap>(type: K, listener: (this: HTMLComboboxElement, ev: ComboboxEventMap[K]) => any, options?: boolean | AddEventListenerOptions): void;
|
|
61
|
+
addEventListener<K extends keyof HTMLElementEventMap>(type: K, listener: (this: HTMLComboboxElement, ev: HTMLElementEventMap[K]) => any, options?: boolean | AddEventListenerOptions): void;
|
|
62
|
+
addEventListener(type: string, listener: EventListenerOrEventListenerObject, options?: boolean | AddEventListenerOptions): void;
|
|
63
|
+
removeEventListener<K extends keyof ComboboxEventMap>(type: K, listener: (this: HTMLComboboxElement, ev: ComboboxEventMap[K]) => any, options?: boolean | EventListenerOptions): void;
|
|
64
|
+
removeEventListener<K extends keyof HTMLElementEventMap>(type: K, listener: (this: HTMLComboboxElement, ev: HTMLElementEventMap[K]) => any, options?: boolean | EventListenerOptions): void;
|
|
65
|
+
removeEventListener(type: string, listener: EventListenerOrEventListenerObject, options?: boolean | EventListenerOptions): void;
|
|
66
|
+
}
|
|
67
|
+
interface ComboboxEventMap extends HTMLElementEventMap {
|
|
68
|
+
"change": ComboboxEvent;
|
|
69
|
+
"blur": ComboboxFocusEvent;
|
|
70
|
+
"focus": ComboboxFocusEvent;
|
|
71
|
+
"focusin": ComboboxFocusEvent;
|
|
72
|
+
"focusout": ComboboxFocusEvent;
|
|
73
|
+
"input": ComboboxInputEvent;
|
|
74
|
+
"invalid": ComboboxEvent;
|
|
75
|
+
"selectionchange": ComboboxEvent;
|
|
76
|
+
"selectstart": ComboboxEvent;
|
|
77
|
+
/** The picker closed (read `event.target.changed`) */
|
|
78
|
+
"close": ComboboxEvent;
|
|
79
|
+
/** Enter was pressed in the search field */
|
|
80
|
+
"search": ComboboxEvent;
|
|
81
|
+
/** The owner form was reset */
|
|
82
|
+
"reset": ComboboxEvent;
|
|
83
|
+
}
|
|
65
84
|
}
|
|
66
85
|
/** Own attributes/properties of `<combo-box>`, shared by every JSX integration below. */
|
|
67
86
|
export interface ComboboxJsxAttributes {
|
|
@@ -109,11 +128,20 @@ export interface ComboboxJsxAttributes {
|
|
|
109
128
|
/** A Boolean attribute indicating that at least one option must be selected. */
|
|
110
129
|
required?: boolean;
|
|
111
130
|
disabled?: boolean;
|
|
131
|
+
/** The name the value is submitted under (`<combo-box>` is form-associated). */
|
|
132
|
+
name?: string;
|
|
133
|
+
/** The id of the `<form>` this combobox belongs to, when it isn't inside it. */
|
|
134
|
+
form?: string;
|
|
112
135
|
}
|
|
113
136
|
export interface ComboboxOptionJsxAttributes {
|
|
137
|
+
/** The value submitted and reported (`combobox.value`, `valueAsArray`) when this option is selected. */
|
|
114
138
|
value: string;
|
|
139
|
+
/** The option's label; defaults to its text content. */
|
|
115
140
|
label?: string;
|
|
141
|
+
/** Initially selected. `false`, `undefined` or removing the prop deselects it. */
|
|
116
142
|
selected?: boolean;
|
|
143
|
+
/** Can't be selected by the user. `false`, `undefined` or removing the prop enables it. */
|
|
144
|
+
disabled?: boolean;
|
|
117
145
|
}
|
|
118
146
|
/**
|
|
119
147
|
* Generic HTML/JSX passthrough attributes (class, style, event handlers, `data-*`, `aria-*`, ...).
|
|
@@ -125,21 +153,72 @@ export interface ComboboxOptionJsxAttributes {
|
|
|
125
153
|
*/
|
|
126
154
|
export interface ComboboxCommonAttributes {
|
|
127
155
|
id?: string;
|
|
156
|
+
/** CSS classes (Preact, Vue, Solid, React 19). */
|
|
128
157
|
class?: string;
|
|
158
|
+
/** CSS classes (React). */
|
|
129
159
|
className?: string;
|
|
160
|
+
/** Inline styles, in the framework's own format (a string or an object). */
|
|
130
161
|
style?: unknown;
|
|
131
162
|
slot?: string;
|
|
132
163
|
title?: string;
|
|
133
164
|
tabIndex?: number;
|
|
134
165
|
hidden?: boolean;
|
|
135
166
|
children?: unknown;
|
|
167
|
+
/** The element: `HTMLElementTagNameMap['combo-box']` (a ref object or callback, per framework). */
|
|
136
168
|
ref?: unknown;
|
|
137
169
|
key?: string | number;
|
|
170
|
+
/**
|
|
171
|
+
* The user changed the selection; `event.target.value` / `.valueAsArray` is the new value.
|
|
172
|
+
* - Preact, Solid, Vue: called with the DOM event.
|
|
173
|
+
* - React 19: called with a SyntheticEvent (`event.nativeEvent` is the DOM event).
|
|
174
|
+
* - React 18: **never called** - listen with `ref` + `addEventListener('change', ...)`.
|
|
175
|
+
*/
|
|
138
176
|
onChange?: (event: ComboboxEvent) => void;
|
|
177
|
+
/**
|
|
178
|
+
* The user typed in the search field; `event.target.query` is the text.
|
|
179
|
+
* Preact, Solid, Vue: the DOM InputEvent. React 18 and 19: a SyntheticEvent.
|
|
180
|
+
*/
|
|
139
181
|
onInput?: (event: ComboboxInputEvent) => void;
|
|
182
|
+
/** Focus moved into the combobox. Preact, Solid, Vue: the DOM event. React: a SyntheticEvent. */
|
|
140
183
|
onFocus?: (event: ComboboxFocusEvent) => void;
|
|
184
|
+
/** Focus left the combobox. Preact, Solid, Vue: the DOM event. React: a SyntheticEvent. */
|
|
141
185
|
onBlur?: (event: ComboboxFocusEvent) => void;
|
|
186
|
+
/**
|
|
187
|
+
* Validation failed (e.g. `required` and empty) on form submit or `checkValidity()`.
|
|
188
|
+
* - Preact, Solid, Vue: called, in either casing (`onInvalid` or `oninvalid`), with the DOM event.
|
|
189
|
+
* - React 19: only as `oninvalid` (lowercase).
|
|
190
|
+
* - React 18: **never called** - use `ref` + `addEventListener('invalid', ...)`.
|
|
191
|
+
*/
|
|
142
192
|
onInvalid?: (event: ComboboxEvent) => void;
|
|
193
|
+
/** Same event as `onInvalid`. React 19 needs this lowercase spelling; React 18 never calls it. */
|
|
194
|
+
oninvalid?: (event: ComboboxEvent) => void;
|
|
195
|
+
/**
|
|
196
|
+
* The value was reset: the owner `<form>` was reset, or the user cleared all (`clearable`).
|
|
197
|
+
* - Preact, Solid, Vue: called, in either casing (`onReset` or `onreset`), with the DOM event.
|
|
198
|
+
* - React 19: only as `onreset` (lowercase).
|
|
199
|
+
* - React 18: **never called** - use `ref` + `addEventListener('reset', ...)`.
|
|
200
|
+
*/
|
|
201
|
+
onReset?: (event: ComboboxEvent) => void;
|
|
202
|
+
/** Same event as `onReset`. React 19 needs this lowercase spelling; React 18 never calls it. */
|
|
203
|
+
onreset?: (event: ComboboxEvent) => void;
|
|
204
|
+
/**
|
|
205
|
+
* The picker closed; `event.target.changed` tells whether the value changed meanwhile.
|
|
206
|
+
* - Preact, Solid, Vue: called, in either casing (`onClose` or `onclose`), with the DOM event.
|
|
207
|
+
* - React 19: only as `onclose` (lowercase).
|
|
208
|
+
* - React 18: **never called** - use `ref` + `addEventListener('close', ...)`.
|
|
209
|
+
*/
|
|
210
|
+
onClose?: (event: ComboboxEvent) => void;
|
|
211
|
+
/** Same event as `onClose`. React 19 needs this lowercase spelling; React 18 never calls it. */
|
|
212
|
+
onclose?: (event: ComboboxEvent) => void;
|
|
213
|
+
/**
|
|
214
|
+
* Enter was pressed in the search field; `event.target.query` is the text.
|
|
215
|
+
* - Preact, Solid, Vue: called, in either casing, with the DOM event.
|
|
216
|
+
* - React 19: only as `onsearch` (lowercase).
|
|
217
|
+
* - React 18: **never called** - use `ref` + `addEventListener('search', ...)`.
|
|
218
|
+
*/
|
|
219
|
+
onSearch?: (event: ComboboxEvent) => void;
|
|
220
|
+
/** Same event as `onSearch`. React 19 needs this lowercase spelling; React 18 never calls it. */
|
|
221
|
+
onsearch?: (event: ComboboxEvent) => void;
|
|
143
222
|
[key: `data-${string}`]: unknown;
|
|
144
223
|
[key: `aria-${string}`]: unknown;
|
|
145
224
|
[key: `on${string}`]: ((event: any) => void) | undefined;
|
|
@@ -172,30 +251,97 @@ declare global {
|
|
|
172
251
|
}
|
|
173
252
|
}
|
|
174
253
|
}
|
|
254
|
+
// #region react-type-fallbacks
|
|
255
|
+
/*
|
|
256
|
+
* Module-private stand-ins for the React types the augmentation below uses. Inside
|
|
257
|
+
* `declare module 'react'` React's own HTMLAttributes/Key/Ref take precedence; these only resolve
|
|
258
|
+
* when React's types aren't in the program (React not installed, or - on TypeScript 7 - not
|
|
259
|
+
* imported by any checked file). Then the augmentation is inert, and without them a project with
|
|
260
|
+
* `skipLibCheck: false` would get "Cannot find name"/"Cannot find module 'react'" errors from it.
|
|
261
|
+
* (`import('react').X` can't be used for the same reason.)
|
|
262
|
+
* The declaration emitter drops them as unused (React is installed here), so
|
|
263
|
+
* scripts/fix-dual-package.mjs copies this region into the emitted index.d.ts files.
|
|
264
|
+
*/
|
|
265
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
266
|
+
type HTMLAttributes<T> = object;
|
|
267
|
+
type Key = string | number | bigint;
|
|
268
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
269
|
+
type Ref<T> = unknown;
|
|
270
|
+
// #endregion react-type-fallbacks
|
|
175
271
|
declare module 'react' {
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
272
|
+
/**
|
|
273
|
+
* The event React passes to the handlers it manages: React's SyntheticEvent (same members), with
|
|
274
|
+
* `target` being the element (events from the shadow DOM are retargeted to it).
|
|
275
|
+
*/
|
|
276
|
+
interface ComboboxSyntheticEvent<T, E extends globalThis.Event = globalThis.Event> {
|
|
277
|
+
nativeEvent: E;
|
|
278
|
+
currentTarget: EventTarget & T;
|
|
279
|
+
target: EventTarget & T;
|
|
280
|
+
bubbles: boolean;
|
|
281
|
+
cancelable: boolean;
|
|
282
|
+
defaultPrevented: boolean;
|
|
283
|
+
eventPhase: number;
|
|
284
|
+
isTrusted: boolean;
|
|
285
|
+
timeStamp: number;
|
|
286
|
+
type: string;
|
|
287
|
+
preventDefault(): void;
|
|
288
|
+
isDefaultPrevented(): boolean;
|
|
289
|
+
stopPropagation(): void;
|
|
290
|
+
isPropagationStopped(): boolean;
|
|
291
|
+
persist(): void;
|
|
182
292
|
}
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
293
|
+
/** Bivariant like React's EventHandler, so React's own handler types (ChangeEventHandler...) fit. */
|
|
294
|
+
type ComboboxEventHandler<E> = {
|
|
295
|
+
bivarianceHack(event: E): void;
|
|
296
|
+
}['bivarianceHack'];
|
|
297
|
+
/** React's ClassAttributes: `key` and a typed `ref`. */
|
|
298
|
+
interface ComboboxClassAttributes<T> {
|
|
299
|
+
key?: Key | null | undefined;
|
|
300
|
+
ref?: Ref<T> | undefined;
|
|
191
301
|
}
|
|
192
|
-
|
|
193
|
-
|
|
302
|
+
type ComboboxBaseHTMLAttributes<T extends EventTarget, Own> = Omit<HTMLAttributes<T>, keyof Own | 'class'> & Own & {
|
|
303
|
+
class?: string | undefined;
|
|
304
|
+
};
|
|
305
|
+
type ComboboxHTMLAttributes<T extends EventTarget> = ComboboxBaseHTMLAttributes<T, ComboboxJsxAttributes & {
|
|
306
|
+
/** The user changed the selection (`event.target.value` is the new value). */
|
|
307
|
+
onChange?: ComboboxEventHandler<ComboboxSyntheticEvent<T>> | undefined;
|
|
308
|
+
/** The user typed in the search field (`event.target.query`); `nativeEvent` is its InputEvent. */
|
|
309
|
+
onInput?: ComboboxEventHandler<ComboboxSyntheticEvent<T, globalThis.InputEvent>> | undefined;
|
|
310
|
+
/** Never called by React 19 for custom elements (the event doesn't bubble) - use `oninvalid`. */
|
|
311
|
+
onInvalid?: undefined;
|
|
312
|
+
/** Never called by React 19 for custom elements (the event doesn't bubble) - use `onreset`. */
|
|
313
|
+
onReset?: undefined;
|
|
314
|
+
/** Native listener: the picker closed (`event.target.changed`). Lowercase - `onClose` never fires. */
|
|
315
|
+
onclose?: ((event: ComboboxEvent) => void) | undefined;
|
|
316
|
+
/** Native listener: Enter in the search field. Lowercase - `onSearch` never fires. */
|
|
317
|
+
onsearch?: ((event: ComboboxEvent) => void) | undefined;
|
|
318
|
+
/** Native listener: the owner form was reset, or the user cleared all. Lowercase - `onReset` never fires. */
|
|
319
|
+
onreset?: ((event: ComboboxEvent) => void) | undefined;
|
|
320
|
+
/** Native listener: validation failed (e.g. `required` and empty). Lowercase - `onInvalid` never fires. */
|
|
321
|
+
oninvalid?: ((event: ComboboxEvent) => void) | undefined;
|
|
322
|
+
}>;
|
|
323
|
+
type ComboboxOptionHTMLAttributes<T extends EventTarget> = ComboboxBaseHTMLAttributes<T, ComboboxOptionJsxAttributes>;
|
|
324
|
+
type ComboboxTagHTMLAttributes<T extends EventTarget> = ComboboxBaseHTMLAttributes<T, {}>;
|
|
325
|
+
/**
|
|
326
|
+
* Which props to use:
|
|
327
|
+
* - @types/react 19: React-typed props (SyntheticEvents, typed ref, React's attributes).
|
|
328
|
+
* - @types/react 18 builds React.JSX.IntrinsicElements on top of the global JSX namespace, so
|
|
329
|
+
* its entries must stay assignable to the framework-agnostic global ones: those are kept.
|
|
330
|
+
* (React 18 types declare the HTML elements in the global namespace, React 19 types don't.)
|
|
331
|
+
* - preact/compat aliased as 'react': its JSX is Preact's, and Preact passes native DOM events,
|
|
332
|
+
* so the framework-agnostic props - the same ones the 'preact' augmentation declares.
|
|
333
|
+
* (Preact's JSX accepts `class`, React's doesn't.)
|
|
334
|
+
*/
|
|
335
|
+
type ComboboxIntrinsicElement<Global, Typed> = globalThis.JSX.IntrinsicElements extends {
|
|
336
|
+
div: unknown;
|
|
337
|
+
} ? Global : JSX.IntrinsicElements extends {
|
|
338
|
+
div: infer Div;
|
|
339
|
+
} ? ('class' extends keyof Div ? Global : Typed) : Typed;
|
|
194
340
|
namespace JSX {
|
|
195
341
|
interface IntrinsicElements {
|
|
196
|
-
'combo-box': ComboboxElementAttributes
|
|
197
|
-
'box-option': ComboboxOptionElementAttributes
|
|
198
|
-
'box-tag': ComboboxTagElementAttributes
|
|
342
|
+
'combo-box': ComboboxIntrinsicElement<ComboboxElementAttributes, ComboboxClassAttributes<HTMLComboboxElement> & ComboboxHTMLAttributes<HTMLComboboxElement>>;
|
|
343
|
+
'box-option': ComboboxIntrinsicElement<ComboboxOptionElementAttributes, ComboboxClassAttributes<HTMLComboboxOptionElement> & ComboboxOptionHTMLAttributes<HTMLComboboxOptionElement>>;
|
|
344
|
+
'box-tag': ComboboxIntrinsicElement<ComboboxTagElementAttributes, ComboboxClassAttributes<HTMLComboboxTagElement> & ComboboxTagHTMLAttributes<HTMLComboboxTagElement>>;
|
|
199
345
|
}
|
|
200
346
|
}
|
|
201
347
|
}
|
package/dist/cjs/index.js
CHANGED
|
@@ -14,4 +14,7 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
|
14
14
|
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
15
|
};
|
|
16
16
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
exports.HTMLComboboxElement = void 0;
|
|
18
|
+
const HTML_combobox_element_js_1 = require("./combobox/HTML.combobox.element.js");
|
|
17
19
|
__exportStar(require("./combobox/index.js"), exports);
|
|
20
|
+
exports.HTMLComboboxElement = HTML_combobox_element_js_1.HTMLComboboxElement;
|
|
@@ -1,4 +1,8 @@
|
|
|
1
|
-
/**
|
|
1
|
+
/**
|
|
2
|
+
* An ATTRIBUTE value as a boolean: present means true (`multiple=""`, `multiple="multiple"`),
|
|
3
|
+
* absent (`null`) means false. The string "false" also means false, so `multiple="false"` from a
|
|
4
|
+
* template or a framework that stringifies values doesn't turn the feature on.
|
|
5
|
+
*/
|
|
2
6
|
export function toBoolean(value) {
|
|
3
7
|
if (value == null || value === 'false' || value === false)
|
|
4
8
|
value = false;
|
|
@@ -6,3 +10,14 @@ export function toBoolean(value) {
|
|
|
6
10
|
value = true;
|
|
7
11
|
return Boolean(value);
|
|
8
12
|
}
|
|
13
|
+
/**
|
|
14
|
+
* A PROPERTY value as a boolean, like native boolean properties (`select.multiple = ''` is false):
|
|
15
|
+
* JavaScript truthiness, except the string "false", which stays false as with attributes.
|
|
16
|
+
*
|
|
17
|
+
* Frameworks that set properties rely on this: Preact clears a removed or `undefined` prop with
|
|
18
|
+
* `element.multiple = ''`, which must turn the feature off. Attribute values (`setAttribute`,
|
|
19
|
+
* the initial attributes) go through `toBoolean` instead.
|
|
20
|
+
*/
|
|
21
|
+
export function propertyToBoolean(value) {
|
|
22
|
+
return value !== 'false' && Boolean(value);
|
|
23
|
+
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { ComboboxMarkup } from './Combobox.markup.js';
|
|
2
2
|
import { HTMLComboboxOptionElement } from './HTML.combobox.option.element.js';
|
|
3
|
-
import { toBoolean } from './Boolean.attribute.value.normalizer.js';
|
|
3
|
+
import { propertyToBoolean, toBoolean } from './Boolean.attribute.value.normalizer.js';
|
|
4
4
|
import { HTMLComboboxOptionsCollection } from './HTML.combobox.options.collection.js';
|
|
5
5
|
export class HTMLComboboxElement extends HTMLElement {
|
|
6
6
|
static OWN_IDL = new Set(['required', 'disabled', 'clearable', 'multiple', 'filterable', 'searchable', 'value', 'placeholder', 'query']);
|
|
@@ -249,26 +249,26 @@ export class HTMLComboboxElement extends HTMLElement {
|
|
|
249
249
|
return this.hasAttribute('clearable');
|
|
250
250
|
}
|
|
251
251
|
set clearable(value) {
|
|
252
|
-
super.toggleAttribute('clearable',
|
|
252
|
+
super.toggleAttribute('clearable', propertyToBoolean(value));
|
|
253
253
|
}
|
|
254
254
|
get filterable() {
|
|
255
255
|
return this.hasAttribute('filterable');
|
|
256
256
|
}
|
|
257
257
|
set filterable(value) {
|
|
258
|
-
super.toggleAttribute('filterable',
|
|
258
|
+
super.toggleAttribute('filterable', propertyToBoolean(value));
|
|
259
259
|
}
|
|
260
260
|
get searchable() {
|
|
261
261
|
return this.hasAttribute('searchable');
|
|
262
262
|
}
|
|
263
263
|
set searchable(value) {
|
|
264
|
-
super.toggleAttribute('searchable',
|
|
264
|
+
super.toggleAttribute('searchable', propertyToBoolean(value));
|
|
265
265
|
}
|
|
266
266
|
// <select> specific properties (implements HTMLSelectElement)
|
|
267
267
|
get disabled() {
|
|
268
268
|
return this.hasAttribute('disabled');
|
|
269
269
|
}
|
|
270
270
|
set disabled(value) {
|
|
271
|
-
super.toggleAttribute('disabled',
|
|
271
|
+
super.toggleAttribute('disabled', propertyToBoolean(value));
|
|
272
272
|
}
|
|
273
273
|
get form() {
|
|
274
274
|
return this.#internals.form;
|
|
@@ -287,7 +287,7 @@ export class HTMLComboboxElement extends HTMLElement {
|
|
|
287
287
|
return this.hasAttribute('multiple');
|
|
288
288
|
}
|
|
289
289
|
set multiple(value) {
|
|
290
|
-
super.toggleAttribute('multiple',
|
|
290
|
+
super.toggleAttribute('multiple', propertyToBoolean(value));
|
|
291
291
|
}
|
|
292
292
|
/** The options, as a live `HTMLOptionsCollection`-like list (like `select.options`) */
|
|
293
293
|
get options() {
|
|
@@ -301,7 +301,7 @@ export class HTMLComboboxElement extends HTMLElement {
|
|
|
301
301
|
return this.hasAttribute('required');
|
|
302
302
|
}
|
|
303
303
|
set required(value) {
|
|
304
|
-
super.toggleAttribute('required',
|
|
304
|
+
super.toggleAttribute('required', propertyToBoolean(value));
|
|
305
305
|
}
|
|
306
306
|
/** Index of the first selected option, or -1. Setting it selects only that option. */
|
|
307
307
|
get selectedIndex() {
|
|
@@ -393,7 +393,8 @@ export class HTMLComboboxElement extends HTMLElement {
|
|
|
393
393
|
// Overwritten methods
|
|
394
394
|
setAttribute(name, value) {
|
|
395
395
|
if (HTMLComboboxElement.OWN_IDL.has(name)) {
|
|
396
|
-
|
|
396
|
+
// through the setter, with attribute semantics: setAttribute('multiple', '') turns it on
|
|
397
|
+
Reflect.set(this, name, HTMLComboboxElement.#BOOLEAN_ATTRIBUTES.has(name) ? toBoolean(value) : value);
|
|
397
398
|
}
|
|
398
399
|
else {
|
|
399
400
|
super.setAttribute(name, value);
|
|
@@ -834,7 +835,8 @@ export class HTMLComboboxElement extends HTMLElement {
|
|
|
834
835
|
// `value = null` would clear it
|
|
835
836
|
if (key === 'value' && !this.hasAttribute('value'))
|
|
836
837
|
continue;
|
|
837
|
-
|
|
838
|
+
const attribute = this.getAttribute(key);
|
|
839
|
+
Reflect.set(this, key, HTMLComboboxElement.#BOOLEAN_ATTRIBUTES.has(key) ? toBoolean(attribute) : attribute);
|
|
838
840
|
}
|
|
839
841
|
}
|
|
840
842
|
static loadCssFromUrls(urls) {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { toBoolean } from './Boolean.attribute.value.normalizer.js';
|
|
1
|
+
import { propertyToBoolean, toBoolean } from './Boolean.attribute.value.normalizer.js';
|
|
2
2
|
/**
|
|
3
3
|
* The `<option>` of `<combo-box>`.
|
|
4
4
|
*
|
|
@@ -18,6 +18,7 @@ import { toBoolean } from './Boolean.attribute.value.normalizer.js';
|
|
|
18
18
|
*/
|
|
19
19
|
export class HTMLComboboxOptionElement extends HTMLElement {
|
|
20
20
|
static OWN_IDL = new Set(['value', 'label', 'selected', 'disabled']);
|
|
21
|
+
static #BOOLEAN_ATTRIBUTES = new Set(['selected', 'disabled']);
|
|
21
22
|
static observedAttributes = ['selected', 'disabled'];
|
|
22
23
|
static EventInit = { bubbles: true, cancelable: true, composed: true };
|
|
23
24
|
#internals;
|
|
@@ -75,13 +76,13 @@ export class HTMLComboboxOptionElement extends HTMLElement {
|
|
|
75
76
|
}
|
|
76
77
|
// Normalization only: the side effects run in attributeChangedCallback
|
|
77
78
|
set selected(value) {
|
|
78
|
-
super.toggleAttribute('selected',
|
|
79
|
+
super.toggleAttribute('selected', propertyToBoolean(value));
|
|
79
80
|
}
|
|
80
81
|
get disabled() {
|
|
81
82
|
return this.hasAttribute('disabled');
|
|
82
83
|
}
|
|
83
84
|
set disabled(value) {
|
|
84
|
-
super.toggleAttribute('disabled',
|
|
85
|
+
super.toggleAttribute('disabled', propertyToBoolean(value));
|
|
85
86
|
}
|
|
86
87
|
attributeChangedCallback(name, _oldValue, newValue) {
|
|
87
88
|
// A path that skipped the setters can leave a value they'd never write, e.g. selected="false".
|
|
@@ -136,12 +137,14 @@ export class HTMLComboboxOptionElement extends HTMLElement {
|
|
|
136
137
|
}
|
|
137
138
|
#initialAttributesSynchronization() {
|
|
138
139
|
for (const key of HTMLComboboxOptionElement.OWN_IDL) {
|
|
139
|
-
|
|
140
|
+
const attribute = this.getAttribute(key);
|
|
141
|
+
Reflect.set(this, key, HTMLComboboxOptionElement.#BOOLEAN_ATTRIBUTES.has(key) ? toBoolean(attribute) : attribute);
|
|
140
142
|
}
|
|
141
143
|
}
|
|
142
144
|
setAttribute(name, value) {
|
|
143
145
|
if (HTMLComboboxOptionElement.OWN_IDL.has(name)) {
|
|
144
|
-
|
|
146
|
+
// through the setter, with attribute semantics: setAttribute('selected', '') selects
|
|
147
|
+
Reflect.set(this, name, HTMLComboboxOptionElement.#BOOLEAN_ATTRIBUTES.has(name) ? toBoolean(value) : value);
|
|
145
148
|
}
|
|
146
149
|
else {
|
|
147
150
|
super.setAttribute(name, value);
|
package/dist/esm/index.js
CHANGED
|
@@ -1,2 +1,15 @@
|
|
|
1
|
-
/**
|
|
1
|
+
/**
|
|
2
|
+
* An ATTRIBUTE value as a boolean: present means true (`multiple=""`, `multiple="multiple"`),
|
|
3
|
+
* absent (`null`) means false. The string "false" also means false, so `multiple="false"` from a
|
|
4
|
+
* template or a framework that stringifies values doesn't turn the feature on.
|
|
5
|
+
*/
|
|
2
6
|
export declare function toBoolean(value: any): boolean;
|
|
7
|
+
/**
|
|
8
|
+
* A PROPERTY value as a boolean, like native boolean properties (`select.multiple = ''` is false):
|
|
9
|
+
* JavaScript truthiness, except the string "false", which stays false as with attributes.
|
|
10
|
+
*
|
|
11
|
+
* Frameworks that set properties rely on this: Preact clears a removed or `undefined` prop with
|
|
12
|
+
* `element.multiple = ''`, which must turn the feature off. Attribute values (`setAttribute`,
|
|
13
|
+
* the initial attributes) go through `toBoolean` instead.
|
|
14
|
+
*/
|
|
15
|
+
export declare function propertyToBoolean(value: unknown): boolean;
|