@nectary/components 5.31.3 → 5.31.4

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/bundle.js CHANGED
@@ -12975,7 +12975,6 @@ defineCustomElement("sinch-select-menu-option", SelectMenuOption);
12975
12975
  const isSelectMenuOption = (el) => el.localName === "sinch-select-menu-option";
12976
12976
  const templateHTML$h = '<style>:host{display:block;outline:0}#listbox{overflow-y:auto;max-height:var(--sinch-comp-select-menu-font-max-height)}#search{display:none;margin:10px}#search.active{display:block}#search-clear:not(.active){display:none}#not-found{display:flex;align-items:center;justify-content:center;width:100%;height:30px;margin-bottom:10px;pointer-events:none;user-select:none;--sinch-comp-text-font:var(--sinch-comp-select-menu-font-not-found-text);--sinch-global-color-text:var(--sinch-comp-select-menu-color-default-not-found-text-initial)}#not-found:not(.active){display:none}::slotted(.hidden){display:none}::slotted(sinch-title){padding:8px 16px;--sinch-global-color-text:var(--sinch-comp-select-menu-color-default-title-initial)}</style><sinch-input id="search" size="s" placeholder="Search"><sinch-icon icons-version="2" name="magnifying-glass" id="icon-search" slot="icon"></sinch-icon><sinch-button id="search-clear" slot="right"><sinch-icon icons-version="2" name="fa-xmark" slot="icon"></sinch-icon></sinch-button></sinch-input><div id="not-found"><sinch-text type="m">No results</sinch-text></div><div id="listbox" role="presentation"><slot></slot></div>';
12977
12977
  const ITEM_HEIGHT = 40;
12978
- const NUM_ITEMS_SEARCH = 7;
12979
12978
  const template$h = document.createElement("template");
12980
12979
  template$h.innerHTML = templateHTML$h;
12981
12980
  class SelectMenu extends NectaryElement {
@@ -13076,6 +13075,7 @@ class SelectMenu extends NectaryElement {
13076
13075
  "value",
13077
13076
  "rows",
13078
13077
  "multiple",
13078
+ "searchable",
13079
13079
  "search-value",
13080
13080
  "search-placeholder",
13081
13081
  "search-autocomplete"
@@ -13093,6 +13093,10 @@ class SelectMenu extends NectaryElement {
13093
13093
  this.#internals.ariaMultiSelectable = isAttrTrue(newVal).toString();
13094
13094
  break;
13095
13095
  }
13096
+ case "searchable": {
13097
+ this.#onOptionSlotChange();
13098
+ break;
13099
+ }
13096
13100
  case "search-autocomplete": {
13097
13101
  updateAttribute(this.#$search, "autocomplete", newVal);
13098
13102
  break;
@@ -13102,13 +13106,7 @@ class SelectMenu extends NectaryElement {
13102
13106
  break;
13103
13107
  }
13104
13108
  case "rows": {
13105
- const numberOfItems = this.#$optionSlot.assignedElements().length;
13106
- const maxNumberOfRows = parseInt(newVal ?? "0", 10);
13107
- this.#$listbox.style.maxHeight = attrValueToPixels(newVal, {
13108
- min: 2,
13109
- itemSizeMultiplier: ITEM_HEIGHT,
13110
- addExtraSpace: numberOfItems > maxNumberOfRows
13111
- });
13109
+ this.#updateListboxMaxHeight();
13112
13110
  break;
13113
13111
  }
13114
13112
  case "search-placeholder": {
@@ -13148,7 +13146,13 @@ class SelectMenu extends NectaryElement {
13148
13146
  return getBooleanAttribute(this, "multiple");
13149
13147
  }
13150
13148
  set searchable(isSearchable) {
13151
- updateBooleanAttribute(this, "searchable", isSearchable);
13149
+ if (isSearchable === false) {
13150
+ this.setAttribute("searchable", "false");
13151
+ } else if (isSearchable === true) {
13152
+ updateBooleanAttribute(this, "searchable", true);
13153
+ } else {
13154
+ this.removeAttribute("searchable");
13155
+ }
13152
13156
  }
13153
13157
  get searchable() {
13154
13158
  const searchableAttribute = this.getAttribute("searchable");
@@ -13234,7 +13238,7 @@ class SelectMenu extends NectaryElement {
13234
13238
  someFound ||= !isHidden;
13235
13239
  setClass($opt, "hidden", isHidden);
13236
13240
  }
13237
- setClass(this.#$notFound, "active", !someFound);
13241
+ setClass(this.#$notFound, "active", searchValue.length > 0 && !someFound);
13238
13242
  this.#selectOption(null);
13239
13243
  };
13240
13244
  #onContextKeyDown = (e) => {
@@ -13282,16 +13286,27 @@ class SelectMenu extends NectaryElement {
13282
13286
  }
13283
13287
  };
13284
13288
  #onOptionSlotChange = () => {
13289
+ if (this.hasAttribute("rows")) {
13290
+ this.#updateListboxMaxHeight();
13291
+ }
13285
13292
  const searchable = this.searchable;
13286
- const options = this.#getOptionElements();
13287
- const isEnoughOptions = options.length >= NUM_ITEMS_SEARCH;
13288
- const isSearchActive = isEnoughOptions && searchable !== false || Boolean(searchable);
13293
+ const isSearchActive = searchable !== false;
13289
13294
  if (!isSearchActive) {
13290
13295
  updateAttribute(this.#$search, "value", null);
13291
13296
  }
13292
13297
  setClass(this.#$search, "active", isSearchActive);
13293
13298
  this.#onValueChange(this.value);
13294
13299
  };
13300
+ #updateListboxMaxHeight = () => {
13301
+ const rowsAttr = this.getAttribute("rows");
13302
+ const numberOfItems = this.#$optionSlot.assignedElements().length;
13303
+ const maxNumberOfRows = parseInt(rowsAttr ?? "0", 10);
13304
+ this.#$listbox.style.maxHeight = attrValueToPixels(rowsAttr, {
13305
+ min: 2,
13306
+ itemSizeMultiplier: ITEM_HEIGHT,
13307
+ addExtraSpace: numberOfItems > maxNumberOfRows
13308
+ });
13309
+ };
13295
13310
  #onValueChange(csv) {
13296
13311
  if (this.multiple) {
13297
13312
  const values = unpackCsv(csv);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nectary/components",
3
- "version": "5.31.3",
3
+ "version": "5.31.4",
4
4
  "files": [
5
5
  "**/*/*.css",
6
6
  "**/*/*.json",
@@ -22,8 +22,8 @@ export declare class SelectMenu extends NectaryElement {
22
22
  get rows(): number | null;
23
23
  set multiple(isMultiple: boolean);
24
24
  get multiple(): boolean;
25
- set searchable(isSearchable: boolean | null);
26
- get searchable(): boolean | null;
25
+ set searchable(isSearchable: boolean | null | undefined);
26
+ get searchable(): boolean | null | undefined;
27
27
  set 'search-autocomplete'(autocomplete: string);
28
28
  get 'search-autocomplete'(): string;
29
29
  set 'search-placeholder'(placeholder: string);
@@ -4,7 +4,7 @@ import "../text/index.js";
4
4
  import { isSelectMenuOption } from "../select-menu-option/utils.js";
5
5
  import { subscribeContext } from "../utils/context.js";
6
6
  import { unpackCsv, getFirstCsvValue, updateCsv } from "../utils/csv.js";
7
- import { getBooleanAttribute, updateAttribute, attrValueToPixels, updateExplicitBooleanAttribute, isAttrTrue, getAttribute, updateIntegerAttribute, getIntegerAttribute, updateBooleanAttribute, hasClass, setClass } from "../utils/dom.js";
7
+ import { getBooleanAttribute, updateAttribute, updateExplicitBooleanAttribute, isAttrTrue, getAttribute, updateIntegerAttribute, getIntegerAttribute, updateBooleanAttribute, hasClass, setClass, attrValueToPixels } from "../utils/dom.js";
8
8
  import { defineCustomElement, NectaryElement } from "../utils/element.js";
9
9
  import { debounceTimeout } from "../utils/debounce.js";
10
10
  import { getReactEventHandler } from "../utils/get-react-event-handler.js";
@@ -12,7 +12,6 @@ import { isTargetEqual } from "../utils/event-target.js";
12
12
  import { setFormValue, CSVToFormData } from "../utils/form.js";
13
13
  const templateHTML = '<style>:host{display:block;outline:0}#listbox{overflow-y:auto;max-height:var(--sinch-comp-select-menu-font-max-height)}#search{display:none;margin:10px}#search.active{display:block}#search-clear:not(.active){display:none}#not-found{display:flex;align-items:center;justify-content:center;width:100%;height:30px;margin-bottom:10px;pointer-events:none;user-select:none;--sinch-comp-text-font:var(--sinch-comp-select-menu-font-not-found-text);--sinch-global-color-text:var(--sinch-comp-select-menu-color-default-not-found-text-initial)}#not-found:not(.active){display:none}::slotted(.hidden){display:none}::slotted(sinch-title){padding:8px 16px;--sinch-global-color-text:var(--sinch-comp-select-menu-color-default-title-initial)}</style><sinch-input id="search" size="s" placeholder="Search"><sinch-icon icons-version="2" name="magnifying-glass" id="icon-search" slot="icon"></sinch-icon><sinch-button id="search-clear" slot="right"><sinch-icon icons-version="2" name="fa-xmark" slot="icon"></sinch-icon></sinch-button></sinch-input><div id="not-found"><sinch-text type="m">No results</sinch-text></div><div id="listbox" role="presentation"><slot></slot></div>';
14
14
  const ITEM_HEIGHT = 40;
15
- const NUM_ITEMS_SEARCH = 7;
16
15
  const template = document.createElement("template");
17
16
  template.innerHTML = templateHTML;
18
17
  class SelectMenu extends NectaryElement {
@@ -113,6 +112,7 @@ class SelectMenu extends NectaryElement {
113
112
  "value",
114
113
  "rows",
115
114
  "multiple",
115
+ "searchable",
116
116
  "search-value",
117
117
  "search-placeholder",
118
118
  "search-autocomplete"
@@ -130,6 +130,10 @@ class SelectMenu extends NectaryElement {
130
130
  this.#internals.ariaMultiSelectable = isAttrTrue(newVal).toString();
131
131
  break;
132
132
  }
133
+ case "searchable": {
134
+ this.#onOptionSlotChange();
135
+ break;
136
+ }
133
137
  case "search-autocomplete": {
134
138
  updateAttribute(this.#$search, "autocomplete", newVal);
135
139
  break;
@@ -139,13 +143,7 @@ class SelectMenu extends NectaryElement {
139
143
  break;
140
144
  }
141
145
  case "rows": {
142
- const numberOfItems = this.#$optionSlot.assignedElements().length;
143
- const maxNumberOfRows = parseInt(newVal ?? "0", 10);
144
- this.#$listbox.style.maxHeight = attrValueToPixels(newVal, {
145
- min: 2,
146
- itemSizeMultiplier: ITEM_HEIGHT,
147
- addExtraSpace: numberOfItems > maxNumberOfRows
148
- });
146
+ this.#updateListboxMaxHeight();
149
147
  break;
150
148
  }
151
149
  case "search-placeholder": {
@@ -185,7 +183,13 @@ class SelectMenu extends NectaryElement {
185
183
  return getBooleanAttribute(this, "multiple");
186
184
  }
187
185
  set searchable(isSearchable) {
188
- updateBooleanAttribute(this, "searchable", isSearchable);
186
+ if (isSearchable === false) {
187
+ this.setAttribute("searchable", "false");
188
+ } else if (isSearchable === true) {
189
+ updateBooleanAttribute(this, "searchable", true);
190
+ } else {
191
+ this.removeAttribute("searchable");
192
+ }
189
193
  }
190
194
  get searchable() {
191
195
  const searchableAttribute = this.getAttribute("searchable");
@@ -271,7 +275,7 @@ class SelectMenu extends NectaryElement {
271
275
  someFound ||= !isHidden;
272
276
  setClass($opt, "hidden", isHidden);
273
277
  }
274
- setClass(this.#$notFound, "active", !someFound);
278
+ setClass(this.#$notFound, "active", searchValue.length > 0 && !someFound);
275
279
  this.#selectOption(null);
276
280
  };
277
281
  #onContextKeyDown = (e) => {
@@ -319,16 +323,27 @@ class SelectMenu extends NectaryElement {
319
323
  }
320
324
  };
321
325
  #onOptionSlotChange = () => {
326
+ if (this.hasAttribute("rows")) {
327
+ this.#updateListboxMaxHeight();
328
+ }
322
329
  const searchable = this.searchable;
323
- const options = this.#getOptionElements();
324
- const isEnoughOptions = options.length >= NUM_ITEMS_SEARCH;
325
- const isSearchActive = isEnoughOptions && searchable !== false || Boolean(searchable);
330
+ const isSearchActive = searchable !== false;
326
331
  if (!isSearchActive) {
327
332
  updateAttribute(this.#$search, "value", null);
328
333
  }
329
334
  setClass(this.#$search, "active", isSearchActive);
330
335
  this.#onValueChange(this.value);
331
336
  };
337
+ #updateListboxMaxHeight = () => {
338
+ const rowsAttr = this.getAttribute("rows");
339
+ const numberOfItems = this.#$optionSlot.assignedElements().length;
340
+ const maxNumberOfRows = parseInt(rowsAttr ?? "0", 10);
341
+ this.#$listbox.style.maxHeight = attrValueToPixels(rowsAttr, {
342
+ min: 2,
343
+ itemSizeMultiplier: ITEM_HEIGHT,
344
+ addExtraSpace: numberOfItems > maxNumberOfRows
345
+ });
346
+ };
332
347
  #onValueChange(csv) {
333
348
  if (this.multiple) {
334
349
  const values = unpackCsv(csv);
@@ -8,7 +8,7 @@ export type TSinchSelectMenuProps = {
8
8
  rows?: number;
9
9
  /** Allows multiple selection */
10
10
  multiple?: boolean;
11
- /** Enforce the search bar appearing, by default it appears above a certain number of options */
11
+ /** Show the search bar, shown by default unless explicitly set to false */
12
12
  searchable?: boolean | null;
13
13
  /** Value for the search input */
14
14
  'search-value'?: string;