html-combobox-element 0.0.2-beta.5 → 0.0.2-beta.7

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.
@@ -15,41 +15,70 @@ class HTMLComboboxElement extends HTMLElement {
15
15
  #observer;
16
16
  #markup;
17
17
  #values = new Set;
18
+ #prevValue = '';
19
+ #changed = false;
18
20
  constructor() {
19
21
  super();
20
22
  this.#internals = this.attachInternals();
21
23
  this.#internals.role = "combobox";
22
24
  this.#internals.ariaHasPopup = "dialog";
23
- this.shadowRoot = this.attachShadow({ mode: 'closed', delegatesFocus: true });
25
+ this.shadowRoot = this.attachShadow({ mode: 'open', delegatesFocus: true }); //delegatesFocus: true
24
26
  this.#markup = new Combobox_markup_js_1.ComboboxMarkup(this.shadowRoot, this.#internals);
25
27
  this.shadowRoot.innerHTML = Combobox_markup_js_1.ComboboxMarkup.template;
26
28
  this.shadowRoot.adoptedStyleSheets = _a.styleSheet;
27
29
  this.#observer = new MutationObserver(this.#onOptionsChanges);
30
+ this.#markup.connect();
28
31
  }
29
32
  // Lifecycle callbacks
30
33
  connectedCallback() {
31
- this.#markup.connect();
32
- this.#initialAttributesSynchronization();
34
+ // super.setAttribute('tabindex', '0');
35
+ this.shadowRoot.addEventListener('optionselectedstatechange', this.#onOptionSelectedStateChanges);
36
+ this.shadowRoot.addEventListener('tagcleared', this.#onClearTag);
33
37
  this.#onOptionsChanges([{ addedNodes: Array.from(this.children) }]);
38
+ this.#initialAttributesSynchronization();
34
39
  this.#observer.observe(this, _a.observerOptions);
35
- this.#markup.clearAllButton.addEventListener('click', this.#onClear);
40
+ this.addEventListener('keydown', this.#onKeyDown);
41
+ this.#markup.clearAllButton.addEventListener('click', this.#onClearAll);
36
42
  this.#markup.searchInput.addEventListener('input', this.#onInput);
43
+ this.#markup.dropdown.addEventListener('toggle', this.#onPickerToggle);
44
+ this.#setValidityAndFormValue();
45
+ }
46
+ insertBefore = (node, referenceNode) => {
47
+ // Since we just move options to the #markup.optionsContainer, they are no more part of this children
48
+ // next time, when someone is calling this(combo-box).insertBefore, an error will be thrown:
49
+ // Failed to execute 'insertBefore' on 'Node': The node before which the new node is to be inserted is not a child of this node.
50
+ // Here we overwrite this method, and if new node is HTMLComboboxOptionElement,
51
+ // we just delegate this job to the real option parent: optionsContainer
52
+ if (node instanceof HTML_combobox_option_element_js_1.HTMLComboboxOptionElement || node instanceof HTMLOptGroupElement) {
53
+ this.#markup.optionsContainer?.insertBefore(node, referenceNode);
54
+ }
55
+ else {
56
+ super.insertBefore(node, referenceNode);
57
+ }
58
+ return node;
59
+ };
60
+ get changed() {
61
+ return this.#changed;
37
62
  }
38
63
  disconnectedCallback() {
39
64
  this.#observer.disconnect();
40
65
  this.#markup.disconnect();
41
- this.#markup.clearAllButton.removeEventListener('click', this.#onClear);
66
+ this.removeEventListener('keydown', this.#onKeyDown);
67
+ this.#markup.clearAllButton.removeEventListener('click', this.#onClearAll);
42
68
  this.#markup.searchInput.removeEventListener('input', this.#onInput);
69
+ this.#markup.dropdown.removeEventListener('toggle', this.#onPickerToggle);
70
+ this.shadowRoot.removeEventListener('optionselectedstatechange', this.#onOptionSelectedStateChanges);
71
+ this.shadowRoot.removeEventListener('tagcleared', this.#onClearTag);
43
72
  }
44
73
  formResetCallback() {
45
- this.#values = new Set;
46
74
  this.selectedOptions.forEach(option => option.selected = false);
47
- this.#markup.tagsContainer.replaceChildren();
48
- this.#setValidityAndFormValue();
49
- this.dispatchEvent(new Event('change'));
75
+ this.dispatchEvent(new Event('reset'));
76
+ requestAnimationFrame(() => this.#markup.searchInput?.focus());
50
77
  }
51
- formDisabledCallback(isDisabled) {
52
- this.disabled = isDisabled;
78
+ formDisabledCallback() {
79
+ // toDo
80
+ // when inside fieldset, this callback is only invoked for the first time
81
+ // isDisabled: boolean
53
82
  }
54
83
  // Instance properties
55
84
  // <combo-box> specific properties
@@ -66,22 +95,17 @@ class HTMLComboboxElement extends HTMLElement {
66
95
  value = '';
67
96
  value = String(value);
68
97
  super.setAttribute('query', value);
69
- if (this.#markup.connected) {
70
- this.#markup.searchInput.value = value;
71
- }
98
+ this.#markup?.setInputValue(value);
72
99
  }
73
100
  get placeholder() {
74
101
  return this.getAttribute('placeholder');
75
102
  }
76
103
  set placeholder(value) {
77
104
  if (value == null)
78
- value = '';
105
+ value = ' ';
79
106
  value = String(value);
80
107
  super.setAttribute('placeholder', value);
81
- if (this.#markup.connected) {
82
- this.#markup.placeholder.innerText = value;
83
- this.#markup.searchInput.placeholder = value;
84
- }
108
+ this.#markup?.setPlaceholder(value);
85
109
  }
86
110
  get clearable() {
87
111
  return this.hasAttribute('clearable');
@@ -107,7 +131,9 @@ class HTMLComboboxElement extends HTMLElement {
107
131
  }
108
132
  set disabled(value) {
109
133
  this.#internals.ariaDisabled = String(value);
110
- super.toggleAttribute('disabled', (0, Boolean_attribute_value_normalizer_js_1.toBoolean)(value));
134
+ value = (0, Boolean_attribute_value_normalizer_js_1.toBoolean)(value);
135
+ super.toggleAttribute('disabled', value);
136
+ super.toggleAttribute('inert', value);
111
137
  }
112
138
  get form() {
113
139
  return this.#internals.form;
@@ -158,34 +184,11 @@ class HTMLComboboxElement extends HTMLElement {
158
184
  set value(value) {
159
185
  if (this.value === value || typeof value !== 'string')
160
186
  return;
161
- const prevValue = new Set(this.#values);
162
- this.#values = new Set;
163
187
  const values = value.split(',').filter(Boolean);
164
- Promise.resolve(values)
165
- .then(values => {
166
- if (values.length) {
167
- if (!this.multiple) {
168
- if (this.#values.size === 0) {
169
- values.length = 1;
170
- }
171
- else {
172
- values.length = 0;
173
- }
174
- }
175
- for (const key of values) {
176
- const option = this.#markup.getOptionByValue(key);
177
- if (option)
178
- this.#selectOption(option);
179
- }
180
- }
181
- for (const key of prevValue) {
182
- if (this.#values.has(key))
183
- continue;
184
- const option = this.#markup.getOptionByValue(key);
185
- const tag = this.#markup.getTagByValue(key);
186
- tag?.remove();
187
- option?.toggleAttribute('selected', false);
188
- }
188
+ this.#values = new Set(values);
189
+ this.#markup.options.forEach(option => {
190
+ const value = option.value;
191
+ option.selected = this.#values.has(value);
189
192
  });
190
193
  }
191
194
  // Instance methods
@@ -232,64 +235,38 @@ class HTMLComboboxElement extends HTMLElement {
232
235
  }
233
236
  }
234
237
  // Internal
235
- #onInput = (event) => {
236
- if (!this.searchable && this.filterable) {
237
- if (event.target && event.target instanceof HTMLInputElement) {
238
- this.#markup.sort(event.target.value);
239
- }
240
- }
241
- };
242
238
  #onOptionsChanges = (records) => {
243
239
  records.forEach(record => {
244
240
  record.addedNodes.forEach(node => {
245
- if (node instanceof HTML_combobox_option_element_js_1.HTMLComboboxOptionElement) {
246
- node.addEventListener('click', this.#onSelectOption);
247
- if (node.selected) {
248
- if (this.multiple) {
249
- this.#selectOption(node);
250
- }
251
- else if (this.#values.size === 0) {
252
- this.#selectOption(node);
253
- }
254
- }
255
- }
256
241
  if (node instanceof HTML_combobox_option_element_js_1.HTMLComboboxOptionElement || node instanceof HTMLOptGroupElement) {
257
242
  this.#markup.optionsContainer.append(node);
258
243
  }
259
244
  });
260
245
  });
261
- this.#markup.invalidateOptionsCache();
262
- this.#setValidityAndFormValue();
263
246
  };
264
- #selectOption(option) {
265
- if (this.#values.has(option.value))
266
- return;
247
+ #onOptionSelectedStateChanges = (event) => {
248
+ const option = event.target;
267
249
  const value = option.value;
268
- this.#values.add(value);
269
- option.toggleAttribute('selected', true);
270
- const control = this.#markup.createAndAppendTag(option);
271
- control?.addEventListener('click', this.#onClearTag);
272
- if (!this.multiple) {
273
- this.#markup.closeDropdown();
250
+ if (option.selected) {
251
+ if (!this.multiple) {
252
+ this.#values.forEach(value => {
253
+ const prevOption = this.#markup.getOptionByValue(value);
254
+ if (prevOption)
255
+ prevOption.selected = false;
256
+ });
257
+ }
258
+ if (!this.#values.has(value)) {
259
+ this.#values.add(value);
260
+ this.#markup.createAndAppendTag(option);
261
+ this.#setValidityAndFormValue();
262
+ this.dispatchEvent(new Event('change'));
263
+ }
274
264
  }
275
- }
276
- #onSelectOption = (event) => {
277
- const target = event.target;
278
- if (target) {
279
- const option = target.closest('box-option');
280
- if (option) {
281
- if (this.#values.has(option.value))
282
- return;
283
- if (!this.multiple) {
284
- event.stopPropagation();
285
- this.#values.forEach(value => {
286
- this.#markup.getTagByValue(value)?.remove();
287
- this.#markup.getOptionByValue(value)?.toggleAttribute('selected', false);
288
- });
289
- this.#values.clear();
290
- this.#markup.tagsContainer.replaceChildren();
291
- }
292
- this.#selectOption(option);
265
+ else {
266
+ if (this.#values.has(value)) {
267
+ this.#values.delete(value);
268
+ const control = this.#markup.getTagByValue(value);
269
+ control?.remove();
293
270
  this.#setValidityAndFormValue();
294
271
  this.dispatchEvent(new Event('change'));
295
272
  }
@@ -298,25 +275,90 @@ class HTMLComboboxElement extends HTMLElement {
298
275
  #onClearTag = (event) => {
299
276
  const target = event.target;
300
277
  if (target) {
301
- const tag = target.closest('box-tag');
302
- if (tag) {
303
- const value = tag.getAttribute('value');
304
- const option = this.#markup.getOptionByValue(value);
305
- option.removeAttribute('selected');
306
- this.#values.delete(value);
307
- tag.remove();
308
- this.#setValidityAndFormValue();
309
- this.dispatchEvent(new Event('change'));
310
- }
278
+ const option = this.#markup.getOptionByValue(target.value);
279
+ if (option)
280
+ option.selected = false;
281
+ requestAnimationFrame(() => {
282
+ if (this.#values.size) {
283
+ this.focus();
284
+ }
285
+ else if (this.searchable || this.filterable) {
286
+ this.#markup.searchInput?.focus();
287
+ }
288
+ else {
289
+ this.focus();
290
+ }
291
+ });
311
292
  }
312
293
  };
313
- #onClear = () => {
294
+ #onClearAll = () => {
314
295
  this.formResetCallback();
315
296
  };
297
+ #onPickerToggle = (event) => {
298
+ const state = Reflect.get(event, 'newState');
299
+ const oldState = Reflect.get(event, 'oldState');
300
+ if (state === oldState)
301
+ return;
302
+ if (state === 'open') {
303
+ this.#prevValue = this.value;
304
+ this.#changed = true;
305
+ }
306
+ else {
307
+ this.#changed = this.#prevValue !== this.value;
308
+ this.dispatchEvent(new Event('close'));
309
+ }
310
+ };
311
+ #onKeyDown = (event) => {
312
+ if (this.#internals.ariaExpanded !== 'true')
313
+ return;
314
+ const activeElement = this.shadowRoot.activeElement;
315
+ if (!activeElement) {
316
+ // ??? how we should react ???
317
+ return;
318
+ }
319
+ if (activeElement === this.#markup.searchInput && event.key === 'Enter') {
320
+ event.stopPropagation();
321
+ if (!this.searchable && this.filterable) {
322
+ this.#markup.sort(this.#markup.searchInput.value);
323
+ }
324
+ if (this.searchable) {
325
+ this.dispatchEvent(new Event('search'));
326
+ }
327
+ return;
328
+ }
329
+ if (event.key === 'Enter' && activeElement instanceof HTML_combobox_option_element_js_1.HTMLComboboxOptionElement) {
330
+ if (!activeElement.selected) {
331
+ event.stopPropagation();
332
+ return;
333
+ }
334
+ }
335
+ if (event.key === 'Enter' && activeElement instanceof HTMLElement && activeElement.part.contains('clear-tag')) {
336
+ activeElement.click();
337
+ return;
338
+ }
339
+ if (event.key === 'Escape' || event.key === 'Enter') {
340
+ this.#markup.closeDropdown();
341
+ this.blur();
342
+ }
343
+ };
344
+ #onInput = () => {
345
+ this.query = this.#markup.searchInput.value;
346
+ if (!this.searchable && this.filterable) {
347
+ this.#markup.sort(this.#markup.searchInput?.value || '');
348
+ }
349
+ };
316
350
  #setValidityAndFormValue() {
351
+ this.#markup.clearAllButton?.toggleAttribute('disabled', !Boolean(this.#values.size));
352
+ let empty = false;
353
+ if (this.#values.size === 0)
354
+ empty = true;
355
+ if (this.#values.size > 0 && !this.clearable && !this.multiple && (this.searchable || this.filterable)) {
356
+ empty = true;
357
+ }
358
+ this.#markup.searchInput?.toggleAttribute('autofocus', empty);
317
359
  this.#internals.setFormValue(this.value);
318
360
  if (this.required && this.value === '') {
319
- this.#internals.setValidity({ valueMissing: true });
361
+ this.#internals.setValidity({ valueMissing: true }, 'Value missing');
320
362
  }
321
363
  else {
322
364
  this.#internals.setValidity({});
@@ -324,6 +366,7 @@ class HTMLComboboxElement extends HTMLElement {
324
366
  }
325
367
  #initialAttributesSynchronization() {
326
368
  for (const key of _a.OWN_IDL) {
369
+ // @ts-ignore
327
370
  this[key] = this.getAttribute(key);
328
371
  }
329
372
  }
@@ -4,16 +4,57 @@ Object.defineProperty(exports, "__esModule", { value: true });
4
4
  exports.HTMLComboboxOptionElement = void 0;
5
5
  const Boolean_attribute_value_normalizer_js_1 = require("./Boolean.attribute.value.normalizer.js");
6
6
  class HTMLComboboxOptionElement extends HTMLElement {
7
- static OWN_IDL = new Set(['value', 'label', 'selected']);
7
+ static OWN_IDL = new Set(['value', 'label', 'selected', 'disabled']);
8
+ static EventInit = { bubbles: true, cancelable: true, composed: true };
9
+ static captureFocus(event) {
10
+ if (event.relatedTarget && event.relatedTarget instanceof _a) {
11
+ event.stopPropagation();
12
+ event.preventDefault();
13
+ }
14
+ }
15
+ static onNavigate(event) {
16
+ if (!event.target ||
17
+ !(event.target instanceof _a) ||
18
+ event.key === 'Tab' ||
19
+ event.key === 'Enter')
20
+ return;
21
+ event.preventDefault();
22
+ if (event.key === 'ArrowDown') {
23
+ const next = event.target.nextElementSibling;
24
+ if (next && next instanceof _a) {
25
+ next.focus();
26
+ }
27
+ }
28
+ if (event.key === 'ArrowUp') {
29
+ const prev = event.target.previousElementSibling;
30
+ if (prev && prev instanceof _a) {
31
+ prev.focus();
32
+ }
33
+ }
34
+ }
8
35
  connectedCallback() {
36
+ this.addEventListener('keydown', _a.onNavigate);
37
+ this.addEventListener('focusout', _a.captureFocus);
38
+ this.addEventListener('click', this.#toggleSelection);
9
39
  this.#initialAttributesSynchronization();
10
40
  this.part.add('option');
11
41
  super.setAttribute('tabindex', "0");
12
42
  super.setAttribute('role', "option");
13
- if (!this.value) {
14
- this.value = this.textContent;
15
- }
43
+ if (!this.value)
44
+ this.value = this.label;
45
+ if (!this.textContent)
46
+ this.textContent = this.value;
47
+ this.dispatchEvent(new Event('optionselectedstatechange', _a.EventInit));
16
48
  }
49
+ disconnectedCallback() {
50
+ this.removeEventListener('click', this.#toggleSelection);
51
+ this.removeEventListener('keydown', _a.onNavigate);
52
+ this.removeEventListener('focusout', _a.captureFocus);
53
+ }
54
+ #toggleSelection = (event) => {
55
+ event.stopPropagation();
56
+ this.selected = !this.selected;
57
+ };
17
58
  get value() {
18
59
  return this.getAttribute('value');
19
60
  }
@@ -34,15 +75,34 @@ class HTMLComboboxOptionElement extends HTMLElement {
34
75
  return this.hasAttribute('selected');
35
76
  }
36
77
  set selected(value) {
37
- super.toggleAttribute('selected', (0, Boolean_attribute_value_normalizer_js_1.toBoolean)(value));
78
+ const prev = this.selected;
79
+ const force = (0, Boolean_attribute_value_normalizer_js_1.toBoolean)(value);
80
+ if (prev === force)
81
+ return;
82
+ super.toggleAttribute('selected', force);
83
+ this.part.toggle('selected', force);
84
+ if (this.isConnected) {
85
+ this.dispatchEvent(new Event('optionselectedstatechange', _a.EventInit));
86
+ }
87
+ }
88
+ get disabled() {
89
+ return this.hasAttribute('disabled');
90
+ }
91
+ set disabled(value) {
92
+ const force = (0, Boolean_attribute_value_normalizer_js_1.toBoolean)(value);
93
+ super.toggleAttribute('disabled', force);
94
+ this.part.toggle('disabled', force);
95
+ super.toggleAttribute('inert', force);
38
96
  }
39
97
  #initialAttributesSynchronization() {
40
98
  for (const key of _a.OWN_IDL) {
99
+ // @ts-ignore
41
100
  this[key] = this.getAttribute(key);
42
101
  }
43
102
  }
44
103
  setAttribute(name, value) {
45
104
  if (_a.OWN_IDL.has(name)) {
105
+ // @ts-ignore
46
106
  this[name] = value;
47
107
  }
48
108
  else {
@@ -51,12 +111,18 @@ class HTMLComboboxOptionElement extends HTMLElement {
51
111
  }
52
112
  removeAttribute(name) {
53
113
  if (_a.OWN_IDL.has(name)) {
114
+ // @ts-ignore
54
115
  this[name] = null;
55
116
  }
56
117
  else {
57
118
  super.removeAttribute(name);
58
119
  }
59
120
  }
121
+ toggleAttribute(name, force) {
122
+ if (name === 'selected')
123
+ this.part.toggle(name, force);
124
+ return super.toggleAttribute(name, force);
125
+ }
60
126
  }
61
127
  exports.HTMLComboboxOptionElement = HTMLComboboxOptionElement;
62
128
  _a = HTMLComboboxOptionElement;
@@ -2,19 +2,38 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.HTMLComboboxTagElement = void 0;
4
4
  class HTMLComboboxTagElement extends HTMLElement {
5
- constructor() {
6
- super();
5
+ static EventInit = { bubbles: true, cancelable: true, composed: true };
6
+ get value() {
7
+ return this.getAttribute('value') || '';
7
8
  }
8
9
  connectedCallback() {
9
10
  this.part.add('tag');
10
- if (this.parentElement) {
11
- if (this.parentElement.hasAttribute('multiple')) {
12
- if (!this.querySelector('[part*="clear-tag"]')) {
13
- throw new Error(`A <button> with part="clear-tag" is required for <combo-box> with multiple attribute`);
14
- }
11
+ const control = this.querySelector('[part*="clear-tag"]');
12
+ if (!control?.checkVisibility()) {
13
+ super.setAttribute('tabindex', '0');
14
+ }
15
+ control?.addEventListener('focusout', HTMLComboboxTagElement.captureFocus);
16
+ control?.addEventListener('click', HTMLComboboxTagElement.onClearTag);
17
+ const root = this.getRootNode();
18
+ if (root?.host.hasAttribute('multiple')) {
19
+ if (!control) {
20
+ throw new Error(`A <button> with part="clear-tag" is required for <combo-box> with multiple attribute`);
15
21
  }
16
22
  }
17
23
  }
24
+ disconnectedCallback() {
25
+ const control = this.querySelector('[part*="clear-tag"]');
26
+ control?.removeEventListener('focusout', HTMLComboboxTagElement.captureFocus);
27
+ control?.removeEventListener('click', HTMLComboboxTagElement.onClearTag);
28
+ }
29
+ static onClearTag(event) {
30
+ const target = event.target;
31
+ target?.parentElement?.dispatchEvent(new Event('tagcleared', HTMLComboboxTagElement.EventInit));
32
+ }
33
+ static captureFocus(event) {
34
+ event.stopPropagation();
35
+ event.preventDefault();
36
+ }
18
37
  }
19
38
  exports.HTMLComboboxTagElement = HTMLComboboxTagElement;
20
39
  if (!window.customElements.get('box-tag')) {
package/dist/cjs/index.js CHANGED
@@ -19,65 +19,3 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
19
19
  };
20
20
  Object.defineProperty(exports, "__esModule", { value: true });
21
21
  __exportStar(require("./combobox/index.js"), exports);
22
- // declare global {
23
- // namespace React {
24
- // namespace JSX {
25
- // interface IntrinsicElements {
26
- // 'combo-box': React.DetailedHTMLProps<Omit<React.HTMLAttributes<HTMLComboboxElement>, 'defaultValue'>,
27
- // HTMLComboboxElement
28
- // > & ComboboxJsxAttributes;
29
- //
30
- // 'box-option': React.DetailedHTMLProps<
31
- // React.HTMLAttributes<HTMLComboboxOptionElement>,
32
- // HTMLComboboxOptionElement>
33
- // & ComboboxOptionJsxAttributes;
34
- //
35
- // 'box-tag': React.DetailedHTMLProps<React.HTMLAttributes<HTMLComboboxTagElement>, HTMLComboboxTagElement>;
36
- // }
37
- // }
38
- // }
39
- //
40
- //
41
- // namespace preact {
42
- // namespace JSX {
43
- // interface IntrinsicElements {
44
- // 'combo-box': preact.HTMLAttributes<HTMLComboboxElement> & ComboboxJsxAttributes;
45
- // 'box-option': preact.HTMLAttributes<HTMLComboboxOptionElement> & ComboboxOptionJsxAttributes;
46
- // 'box-tag': preact.HTMLAttributes<HTMLComboboxTagElement>;
47
- // }
48
- // }
49
- // }
50
- //
51
- // }
52
- //
53
- // declare module 'preact' {
54
- // namespace JSX {
55
- // interface IntrinsicElements {
56
- // 'combo-box': preact.HTMLAttributes<HTMLComboboxElement> & ComboboxJsxAttributes;
57
- // 'box-option': preact.HTMLAttributes<HTMLComboboxOptionElement> & ComboboxOptionJsxAttributes;
58
- // 'box-tag': preact.HTMLAttributes<HTMLComboboxTagElement>;
59
- // }
60
- // }
61
- // }
62
- //
63
- // // Solid
64
- // declare module 'solid-js' {
65
- // namespace JSX {
66
- // interface IntrinsicElements {
67
- // 'combo-box': HTMLAttributes<HTMLComboboxElement> & ComboboxJsxAttributes
68
- // 'box-option': HTMLAttributes<HTMLComboboxOptionElement> & ComboboxOptionJsxAttributes
69
- // 'box-tag': HTMLAttributes<HTMLElement>
70
- // }
71
- // }
72
- // }
73
- //
74
- //
75
- // declare global {
76
- // namespace JSX {
77
- // interface IntrinsicElements {
78
- // 'combo-box': ComboboxJsxAttributes;
79
- // 'box-option': ComboboxOptionJsxAttributes;
80
- // 'box-tag': HTMLElement;
81
- // }
82
- // }
83
- // }