html-combobox-element 0.0.7 → 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.
@@ -1,91 +1,86 @@
1
1
  import { HTMLComboboxElement as ComboboxElementClass } from './combobox/HTML.combobox.element.js';
2
2
  import type { HTMLComboboxOptionsCollection } from './combobox/HTML.combobox.options.collection.js';
3
3
  export * from './combobox/index.js';
4
- /**
5
- * The `<combo-box>` constructor, typed the way lib.dom types built-in elements
6
- * (`interface HTMLSelectElement` + `declare var HTMLSelectElement: { prototype; new() }`):
7
- * the same `HTMLComboboxElement` type is what `document.createElement('combo-box')`,
8
- * `querySelector('combo-box')`, `event.target`, refs and `instanceof HTMLComboboxElement` give.
9
- *
10
- * Runtime-wise this is the very same class object that `export *` exported before.
11
- */
12
4
  export declare const HTMLComboboxElement: Omit<typeof ComboboxElementClass, 'prototype'> & {
13
5
  prototype: HTMLComboboxElement;
14
6
  new (): HTMLComboboxElement;
15
7
  };
16
- interface HTMLComboboxTagElement extends HTMLElement {
17
- }
18
- interface HTMLComboboxOptionElement extends HTMLOptionElement {
19
- value: string;
20
- label: string;
21
- }
22
- export interface HTMLComboboxElement extends HTMLSelectElement {
23
- /** List of selected options value attribute */
24
- valueAsArray: string[];
25
- /** Whether the value differs from when the picker opened (read it in a `close` listener). */
26
- readonly changed: boolean;
27
- /** A live `HTMLOptionsCollection`-compatible collection (not `instanceof HTMLOptionsCollection`). */
28
- readonly options: HTMLOptionsCollection & HTMLComboboxOptionsCollection;
29
- multiple: boolean;
30
- /** The value of internal input
31
- *
32
- * Internal input is visible when either "searchable" or "filterable" attribute is presented */
33
- query: string;
34
- /** The placeholder of internal input
35
- *
36
- * Internal input is visible when either "searchable" or "filterable" attribute is presented
37
- *
38
- * When <combo-box> is empty, this value is also shown as <combo-box> placeholder itself
39
- * */
40
- placeholder: string;
41
- /** When is true, the clear-all-button is shown in the <combo-box> itself,
42
- * and the clear-button is shown for each selected tag.
43
- *
44
- * If multiple attribute is set to "true", this is also enabled.
45
- *
46
- * If multiple attribute is set to "false", i.e. the <combo-box> is used as a <select>,
47
- * then setting this attribute to "true" will make the clear-button of selected tag visible
48
- * */
49
- clearable: boolean;
50
- /** When is true, the internal input is shown.
51
- *
52
- * When user type something, available options are not filtered by this query.
53
- * You have to set an "input" listener to the <combo-box> and filter options by yourself
54
- *
55
- * Setting both "searchable" and "filterable" make no sense, the "searchable" will have priority
56
- * */
57
- searchable: boolean;
58
- /** When is true, the internal input is shown.
59
- *
60
- * When user type something, available options are filtered by this query.
61
- *
62
- * Setting both "filterable" and "searchable" make no sense, the "searchable" will have priority
63
- * */
64
- filterable: boolean;
65
- selectedOptions: HTMLCollectionOf<HTMLComboboxOptionElement>;
66
- addEventListener<K extends keyof ComboboxEventMap>(type: K, listener: (this: HTMLComboboxElement, ev: ComboboxEventMap[K]) => any, options?: boolean | AddEventListenerOptions): void;
67
- addEventListener<K extends keyof HTMLElementEventMap>(type: K, listener: (this: HTMLComboboxElement, ev: HTMLElementEventMap[K]) => any, options?: boolean | AddEventListenerOptions): void;
68
- addEventListener(type: string, listener: EventListenerOrEventListenerObject, options?: boolean | AddEventListenerOptions): void;
69
- removeEventListener<K extends keyof ComboboxEventMap>(type: K, listener: (this: HTMLComboboxElement, ev: ComboboxEventMap[K]) => any, options?: boolean | EventListenerOptions): void;
70
- removeEventListener<K extends keyof HTMLElementEventMap>(type: K, listener: (this: HTMLComboboxElement, ev: HTMLElementEventMap[K]) => any, options?: boolean | EventListenerOptions): void;
71
- removeEventListener(type: string, listener: EventListenerOrEventListenerObject, options?: boolean | EventListenerOptions): void;
72
- }
73
- interface ComboboxEventMap extends HTMLElementEventMap {
74
- "change": ComboboxEvent;
75
- "blur": ComboboxFocusEvent;
76
- "focus": ComboboxFocusEvent;
77
- "focusin": ComboboxFocusEvent;
78
- "focusout": ComboboxFocusEvent;
79
- "input": ComboboxInputEvent;
80
- "invalid": ComboboxEvent;
81
- "selectionchange": ComboboxEvent;
82
- "selectstart": ComboboxEvent;
83
- /** The picker closed (read `event.target.changed`) */
84
- "close": ComboboxEvent;
85
- /** Enter was pressed in the search field */
86
- "search": ComboboxEvent;
87
- /** The owner form was reset */
88
- "reset": ComboboxEvent;
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
+ }
89
84
  }
90
85
  /** Own attributes/properties of `<combo-box>`, shared by every JSX integration below. */
91
86
  export interface ComboboxJsxAttributes {
@@ -139,9 +134,14 @@ export interface ComboboxJsxAttributes {
139
134
  form?: string;
140
135
  }
141
136
  export interface ComboboxOptionJsxAttributes {
137
+ /** The value submitted and reported (`combobox.value`, `valueAsArray`) when this option is selected. */
142
138
  value: string;
139
+ /** The option's label; defaults to its text content. */
143
140
  label?: string;
141
+ /** Initially selected. `false`, `undefined` or removing the prop deselects it. */
144
142
  selected?: boolean;
143
+ /** Can't be selected by the user. `false`, `undefined` or removing the prop enables it. */
144
+ disabled?: boolean;
145
145
  }
146
146
  /**
147
147
  * Generic HTML/JSX passthrough attributes (class, style, event handlers, `data-*`, `aria-*`, ...).
@@ -153,21 +153,72 @@ export interface ComboboxOptionJsxAttributes {
153
153
  */
154
154
  export interface ComboboxCommonAttributes {
155
155
  id?: string;
156
+ /** CSS classes (Preact, Vue, Solid, React 19). */
156
157
  class?: string;
158
+ /** CSS classes (React). */
157
159
  className?: string;
160
+ /** Inline styles, in the framework's own format (a string or an object). */
158
161
  style?: unknown;
159
162
  slot?: string;
160
163
  title?: string;
161
164
  tabIndex?: number;
162
165
  hidden?: boolean;
163
166
  children?: unknown;
167
+ /** The element: `HTMLElementTagNameMap['combo-box']` (a ref object or callback, per framework). */
164
168
  ref?: unknown;
165
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
+ */
166
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
+ */
167
181
  onInput?: (event: ComboboxInputEvent) => void;
182
+ /** Focus moved into the combobox. Preact, Solid, Vue: the DOM event. React: a SyntheticEvent. */
168
183
  onFocus?: (event: ComboboxFocusEvent) => void;
184
+ /** Focus left the combobox. Preact, Solid, Vue: the DOM event. React: a SyntheticEvent. */
169
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
+ */
170
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;
171
222
  [key: `data-${string}`]: unknown;
172
223
  [key: `aria-${string}`]: unknown;
173
224
  [key: `on${string}`]: ((event: any) => void) | undefined;
@@ -200,46 +251,97 @@ declare global {
200
251
  }
201
252
  }
202
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
203
271
  declare module 'react' {
204
- /** A React event whose `target` is the element (events from the shadow DOM are retargeted to it). */
205
- type ComboboxSyntheticEvent<T, E extends globalThis.Event = globalThis.Event> = import('react').SyntheticEvent<T, E> & {
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;
206
279
  target: EventTarget & T;
207
- };
208
- type ComboboxBaseHTMLAttributes<T> = import('react').HTMLAttributes<T>;
209
- type ComboboxBaseHostAttributes<T> = Omit<import('react').HTMLAttributes<T>, 'onInput'>;
210
- interface ComboboxHTMLAttributes<T> extends ComboboxBaseHostAttributes<T>, ComboboxJsxAttributes {
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;
292
+ }
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;
301
+ }
302
+ type ComboboxBaseHTMLAttributes<T extends EventTarget, Own> = Omit<HTMLAttributes<T>, keyof Own | 'class'> & Own & {
211
303
  class?: string | undefined;
304
+ };
305
+ type ComboboxHTMLAttributes<T extends EventTarget> = ComboboxBaseHTMLAttributes<T, ComboboxJsxAttributes & {
212
306
  /** The user changed the selection (`event.target.value` is the new value). */
213
- onChange?: import('react').EventHandler<ComboboxSyntheticEvent<T>> | undefined;
307
+ onChange?: ComboboxEventHandler<ComboboxSyntheticEvent<T>> | undefined;
214
308
  /** The user typed in the search field (`event.target.query`); `nativeEvent` is its InputEvent. */
215
- onInput?: import('react').EventHandler<ComboboxSyntheticEvent<T, globalThis.InputEvent>> | undefined;
216
- onInvalid?: import('react').EventHandler<ComboboxSyntheticEvent<T>> | undefined;
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;
217
314
  /** Native listener: the picker closed (`event.target.changed`). Lowercase - `onClose` never fires. */
218
315
  onclose?: ((event: ComboboxEvent) => void) | undefined;
219
316
  /** Native listener: Enter in the search field. Lowercase - `onSearch` never fires. */
220
317
  onsearch?: ((event: ComboboxEvent) => void) | undefined;
221
- }
222
- interface ComboboxOptionHTMLAttributes<T> extends ComboboxBaseHTMLAttributes<T>, ComboboxOptionJsxAttributes {
223
- class?: string | undefined;
224
- }
225
- interface ComboboxTagHTMLAttributes<T> extends ComboboxBaseHTMLAttributes<T> {
226
- class?: string | undefined;
227
- }
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, {}>;
228
325
  /**
229
- * @types/react 18 builds React.JSX.IntrinsicElements on top of the global JSX namespace, so
230
- * its entries must stay assignable to the framework-agnostic global ones (catch-all `on*`,
231
- * native event types): with React 18 types the global entries are kept as they are.
232
- * @types/react 19 has no global JSX namespace: React.JSX gets React-typed props.
233
- * (React 18 types declare the HTML elements in the global namespace, React 19 types don't.)
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.)
234
334
  */
235
335
  type ComboboxIntrinsicElement<Global, Typed> = globalThis.JSX.IntrinsicElements extends {
236
336
  div: unknown;
237
- } ? Global : Typed;
337
+ } ? Global : JSX.IntrinsicElements extends {
338
+ div: infer Div;
339
+ } ? ('class' extends keyof Div ? Global : Typed) : Typed;
238
340
  namespace JSX {
239
341
  interface IntrinsicElements {
240
- 'combo-box': ComboboxIntrinsicElement<ComboboxElementAttributes, import('react').ClassAttributes<HTMLComboboxElement> & ComboboxHTMLAttributes<HTMLComboboxElement>>;
241
- 'box-option': ComboboxIntrinsicElement<ComboboxOptionElementAttributes, import('react').ClassAttributes<HTMLComboboxOptionElement> & ComboboxOptionHTMLAttributes<HTMLComboboxOptionElement>>;
242
- 'box-tag': ComboboxIntrinsicElement<ComboboxTagElementAttributes, import('react').ClassAttributes<HTMLComboboxTagElement> & ComboboxTagHTMLAttributes<HTMLComboboxTagElement>>;
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>>;
243
345
  }
244
346
  }
245
347
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "html-combobox-element",
3
- "version": "0.0.7",
3
+ "version": "0.0.8",
4
4
  "description": "The combo-box web-component & customizable select polyfill",
5
5
  "type": "module",
6
6
  "repository": {