@nectary/components 2.8.6 → 2.8.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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nectary/components",
3
- "version": "2.8.6",
3
+ "version": "2.8.7",
4
4
  "files": [
5
5
  "**/*/*.css",
6
6
  "**/*/*.json",
@@ -41,6 +41,7 @@ defineCustomElement('sinch-select-menu', class extends NectaryElement {
41
41
  this.#$search.addEventListener('-change', this.#onSearchChange, options);
42
42
  this.#$searchClear.addEventListener('-click', this.#onSearchClearClick, options);
43
43
  this.#$optionSlot.addEventListener('slotchange', this.#onOptionSlotChange, options);
44
+ this.addEventListener('-search-change', this.#onSearchChangeReactHandler, options);
44
45
  this.addEventListener('-change', this.#onChangeReactHandler, options);
45
46
  subscribeContext(this, 'keydown', this.#onContextKeyDown, this.#controller.signal);
46
47
  subscribeContext(this, 'visibility', this.#onContextVisibility, this.#controller.signal);
@@ -52,7 +53,7 @@ defineCustomElement('sinch-select-menu', class extends NectaryElement {
52
53
  this.#controller = null;
53
54
  }
54
55
  static get observedAttributes() {
55
- return ['value', 'rows', 'multiple'];
56
+ return ['value', 'rows', 'multiple', 'search-placeholder'];
56
57
  }
57
58
  attributeChangedCallback(name, oldVal, newVal) {
58
59
  switch (name) {
@@ -75,6 +76,11 @@ defineCustomElement('sinch-select-menu', class extends NectaryElement {
75
76
  });
76
77
  break;
77
78
  }
79
+ case 'search-placeholder':
80
+ {
81
+ updateAttribute(this.#$search, 'placeholder', newVal);
82
+ break;
83
+ }
78
84
  }
79
85
  }
80
86
  set value(value) {
@@ -95,6 +101,12 @@ defineCustomElement('sinch-select-menu', class extends NectaryElement {
95
101
  get multiple() {
96
102
  return getBooleanAttribute(this, 'multiple');
97
103
  }
104
+ set 'search-placeholder'(placeholder) {
105
+ updateAttribute(this.#$search, 'placeholder', placeholder);
106
+ }
107
+ get 'search-placeholder'() {
108
+ return getAttribute(this.#$search, 'placeholder', '');
109
+ }
98
110
  get focusable() {
99
111
  return true;
100
112
  }
@@ -128,15 +140,22 @@ defineCustomElement('sinch-select-menu', class extends NectaryElement {
128
140
  };
129
141
  #updateSearch = () => {
130
142
  const searchValue = this.#$search.value.toLowerCase();
131
- const $options = this.#getOptionElements();
132
- let someFound = false;
133
- for (const $opt of $options) {
134
- const isHidden = searchValue.length > 0 && !$opt.matchesSearch(searchValue);
135
- someFound ||= !isHidden;
136
- setClass($opt, 'hidden', isHidden);
143
+ const searchChangedEvent = new CustomEvent('-search-change', {
144
+ detail: searchValue,
145
+ cancelable: true
146
+ });
147
+ this.dispatchEvent(searchChangedEvent);
148
+ if (!searchChangedEvent.defaultPrevented) {
149
+ const $options = this.#getOptionElements();
150
+ let someFound = false;
151
+ for (const $opt of $options) {
152
+ const isHidden = searchValue.length > 0 && !$opt.matchesSearch(searchValue);
153
+ someFound ||= !isHidden;
154
+ setClass($opt, 'hidden', isHidden);
155
+ }
156
+ setClass(this.#$notFound, 'active', !someFound);
157
+ this.#selectOption(null);
137
158
  }
138
- setClass(this.#$notFound, 'active', !someFound);
139
- this.#selectOption(null);
140
159
  };
141
160
  #onContextKeyDown = e => {
142
161
  this.#handleKeydown(e.detail);
@@ -179,7 +198,10 @@ defineCustomElement('sinch-select-menu', class extends NectaryElement {
179
198
  }
180
199
  }
181
200
  #onOptionSlotChange = () => {
182
- const isSearchActive = this.#$optionSlot.assignedElements().length >= NUM_ITEMS_SEARCH;
201
+ const hasSearchableAttribute = this.hasAttribute('searchable');
202
+ const options = this.#$optionSlot.assignedElements();
203
+ const isEnoughOptions = options.length >= NUM_ITEMS_SEARCH;
204
+ const isSearchActive = isEnoughOptions || hasSearchableAttribute;
183
205
  if (!isSearchActive) {
184
206
  updateAttribute(this.#$search, 'value', null);
185
207
  }
@@ -304,4 +326,7 @@ defineCustomElement('sinch-select-menu', class extends NectaryElement {
304
326
  #onChangeReactHandler = e => {
305
327
  getReactEventHandler(this, 'on-change')?.(e);
306
328
  };
329
+ #onSearchChangeReactHandler = e => {
330
+ getReactEventHandler(this, 'on-search-change')?.(e);
331
+ };
307
332
  });
@@ -6,8 +6,14 @@ export type TSinchSelectMenuElement = HTMLElement & {
6
6
  rows: number | null;
7
7
  /** Allows multiple selection */
8
8
  multiple: boolean;
9
+ /** Enforce the search bar appearing, by default it appears above a certain number of options */
10
+ searchable: boolean;
11
+ /** Text for search bar's placeholder */
12
+ 'search-placeholder': string;
9
13
  /** Change value event */
10
14
  addEventListener(type: '-change', listener: (e: CustomEvent<string>) => void): void;
15
+ /** Change value event */
16
+ addEventListener(type: '-search-change', listener: (e: CustomEvent<string>) => void): void;
11
17
  /** Selected value, CSV when multiple */
12
18
  setAttribute(name: 'value', value: string): void;
13
19
  /** How many rows to show and scroll the rest */
@@ -22,8 +28,14 @@ export type TSinchSelectMenuReact = TSinchElementReact<TSinchSelectMenuElement>
22
28
  rows?: number;
23
29
  /** Allows multiple selection */
24
30
  multiple?: boolean;
31
+ /** Enforce the search bar appearing, by default it appears above a certain number of options */
32
+ searchable?: boolean;
33
+ /** Text for search bar's placeholder */
34
+ 'search-placeholder'?: string;
25
35
  /** Label that is used for a11y */
26
36
  'aria-label': string;
27
37
  /** Change value handler */
38
+ 'on-search-change'?: (e: CustomEvent<string>) => void;
39
+ /** Change value handler */
28
40
  'on-change'?: (e: CustomEvent<string>) => void;
29
41
  };