wj-elements 0.1.105 → 0.1.108

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.
@@ -238,7 +238,7 @@ class InfiniteScroll extends WJElement {
238
238
  } else {
239
239
  response = await this.getPages(page);
240
240
  }
241
- this.totalPages = response.totalPages;
241
+ this.totalPages = response == null ? void 0 : response.totalPages;
242
242
  this.currentPage = page;
243
243
  this.placementObj = this;
244
244
  if (this.hasAttribute("placement"))
@@ -252,7 +252,7 @@ class InfiniteScroll extends WJElement {
252
252
  this.endingEl.classList.add("show");
253
253
  }
254
254
  } catch (error) {
255
- console.log(error.message);
255
+ console.log(error);
256
256
  } finally {
257
257
  this.hideLoader();
258
258
  }
@@ -619,11 +619,12 @@ const _WJElement = class _WJElement extends HTMLElement {
619
619
  setUpAccessors() {
620
620
  let attrs = this.getAttributeNames();
621
621
  attrs.forEach((name) => {
622
+ var _a, _b;
622
623
  const sanitizedName = this.sanitizeName(name);
623
624
  if (this[sanitizedName] == void 0) {
624
625
  Object.defineProperty(this, sanitizedName, {
625
- set: (value) => this.setAttribute(name, value),
626
- get: (_) => {
626
+ set: Object.getOwnPropertyDescriptors(this.__proto__).hasOwnProperty(sanitizedName) ? (_a = Object.getOwnPropertyDescriptors(this.__proto__)) == null ? void 0 : _a[sanitizedName].set : (value) => this.setAttribute(name, value),
627
+ get: Object.getOwnPropertyDescriptors(this.__proto__).hasOwnProperty(sanitizedName) ? (_b = Object.getOwnPropertyDescriptors(this.__proto__)) == null ? void 0 : _b[sanitizedName].get : (_) => {
627
628
  return this.getAttribute(name);
628
629
  }
629
630
  });
@@ -84,7 +84,10 @@ function isValidFileType(file, acceptedFileTypes) {
84
84
  }
85
85
  return false;
86
86
  }
87
- function upload(url, chunkSize = 1024 * 1024) {
87
+ function upload(url, chunkSize = 1024 * 1024, wholeFile = false) {
88
+ if (wholeFile) {
89
+ return (file, preview) => uploadWholeFile(url, file, preview);
90
+ }
88
91
  return (file, preview) => uploadFileInChunks(url, chunkSize, file, preview);
89
92
  }
90
93
  async function uploadFileInChunks(url, chunkSize = 1024 * 1024, file, preview) {
@@ -134,6 +137,20 @@ async function uploadFileInChunks(url, chunkSize = 1024 * 1024, file, preview) {
134
137
  console.log("File upload complete!");
135
138
  return partResponses.at(-1).json();
136
139
  }
140
+ function uploadWholeFile(url, file, preview) {
141
+ const formData = new FormData();
142
+ formData.append("file", file);
143
+ return fetch(url, {
144
+ method: "POST",
145
+ body: formData
146
+ }).then((response) => response.json()).then((data) => {
147
+ console.log(data);
148
+ preview.setAttribute("uploaded", file.size);
149
+ return data;
150
+ }).catch((error) => {
151
+ console.error("Error:", error);
152
+ });
153
+ }
137
154
  const styles = '/*\r\n[ WJ File Upload ]\r\n*/\r\n\r\n:host {\r\n width: 100%;\r\n}\r\n\r\n.native-file-upload {\r\n width: 100%;\r\n}\r\n\r\n.file-label {\r\n background: var(--wje-color-contrast-0);\r\n border: 1px dashed var(--wje-border-color);\r\n border-radius: var(--wje-border-radius-medium);\r\n align-items: center;\r\n justify-content: center;\r\n display: flex;\r\n padding: 1rem;\r\n margin-bottom: .5rem;\r\n flex-direction: column;\r\n}\r\n\r\n.file-preview {\r\n display: grid;\r\n grid-template-columns: auto 1fr 1fr;\r\n grid-template-rows: auto auto auto;\r\n gap: 0 0;\r\n grid-template-areas:\r\n "image name name"\r\n "image size size"\r\n "progress progress progress";\r\n}\r\n\r\n.file-image {\r\n grid-area: image;\r\n align-items: center;\r\n display: flex;\r\n}\r\n\r\n.file-name {\r\n grid-area: name;\r\n white-space: nowrap;\r\n overflow: hidden;\r\n text-overflow: ellipsis;\r\n}\r\n\r\n.file-size {\r\n grid-area: size;\r\n display: flex;\r\n}\r\n\r\n.file-progress { grid-area: progress; }\r\n\r\nwje-icon {\r\n margin-right: .25rem;\r\n}\r\n\r\nwje-img {\r\n margin-right: .25rem;\r\n}\r\n\r\n.file-info > span {\r\n white-space: nowrap;\r\n overflow: hidden;\r\n text-overflow: ellipsis;\r\n}\r\n\r\nwje-slider {\r\n flex-basis: 100%;\r\n margin-top: .5rem;\r\n}\r\n\r\n::part(slider) {\r\n &::-webkit-slider-thumb {\r\n visibility: hidden;\r\n }\r\n\r\n &::-moz-range-thumb {\r\n visibility: hidden;\r\n }\r\n\r\n &::-ms-thumb {\r\n visibility: hidden;\r\n }\r\n}\r\n\r\nwje-img {\r\n width: 50px;\r\n height: 50px;\r\n display: flex;\r\n align-items: center;\r\n padding: .25rem;\r\n border: 1px solid var(--wje-border-color);\r\n border-radius: var(--wje-border-radius-medium);\r\n}';
138
155
  class FileUpload extends WJElement {
139
156
  /**
@@ -262,7 +279,7 @@ class FileUpload extends WJElement {
262
279
  this.isShadowRoot = "open";
263
280
  }
264
281
  beforeDraw() {
265
- this.uploadFunction = upload(this.uploadUrl, this.chunkSize);
282
+ this.uploadFunction = upload(this.uploadUrl, this.chunkSize, true);
266
283
  }
267
284
  /**
268
285
  * Method to draw the component.
@@ -9,7 +9,7 @@ import "./wje-infinite-scroll.js";
9
9
  import Input from "./wje-input.js";
10
10
  import Tooltip from "./wje-tooltip.js";
11
11
  import "./wje-popup.js";
12
- import { I as InfiniteScroll } from "./infinite-scroll.element-7dR-X4sd.js";
12
+ import { I as InfiniteScroll } from "./infinite-scroll.element-BJZCBKDO.js";
13
13
  import { P as Popup } from "./popup.element-Dna4OwCH.js";
14
14
  const styles = "/*\r\n[ Wj Icon Picker ]\r\n*/\r\n\r\n:host {\r\n --wje-icon-picker-radius: var(--wje-border-radius-small);\r\n --wje-icon-picker-icon-size: 1.5rem;\r\n --wje-icon-picker-border-width: 1px;\r\n --wje-icon-picker-border-style: solid;\r\n --wje-icon-picker-border-color: var(--wje-border-color);\r\n --wje-icon-picker-padding: .25rem;\r\n padding: 0 1rem;\r\n}\r\n\r\n.anchor {\r\n width: var(--wje-icon-picker-icon-size);\r\n height: var(--wje-icon-picker-icon-size);\r\n padding: var(--wje-icon-picker-padding);\r\n border-width: var(--wje-icon-picker-border-width);\r\n border-style: var(--wje-icon-picker-border-style);\r\n border-color: var(--wje-icon-picker-border-color);\r\n box-sizing: border-box;\r\n border-radius: var(--wje-icon-picker-radius);\r\n}\r\n\r\n.picker {\r\n width: 320px;\r\n height: 271px;\r\n box-shadow: 0 0 5px rgba(0,0,0,.05), 0 5px 20px rgba(0,0,0,.1);\r\n border-radius: var(--wje-icon-picker-radius);\r\n border-width: var(--wje-icon-picker-border-width);\r\n border-style: var(--wje-icon-picker-border-style);\r\n border-color: var(--wje-icon-picker-border-color);\r\n overflow: auto;\r\n padding: 1rem;\r\n background: var(--wje-background);\r\n}\r\n\r\n.icon-items {\r\n --icon-min-width: 2rem;\r\n display: grid;\r\n grid-gap: .5rem;\r\n grid-template-columns: repeat(auto-fit,minmax(var(--icon-min-width),1fr));\r\n}\r\n\r\n.icon-item {\r\n box-sizing: border-box;\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n text-align: center;\r\n color: inherit;\r\n padding: .25rem;\r\n min-height: var(--wje-icon-picker-icon-size);\r\n min-width: var(--wje-icon-picker-icon-size);\r\n text-decoration: none;\r\n\r\n &:hover {\r\n border-radius: .25rem;\r\n background: var(--wje-border-color);\r\n }\r\n}\r\n\r\n.wje-size {\r\n --wje-icon-size: 24px !important;\r\n}\r\n\r\nicon-item svg {\r\n width: var(--wje-icon-picker-icon-size);\r\n height: var(--wje-icon-picker-icon-size);\r\n}\r\n\r\nwje-input {\r\n --wje-input-border-radius: 4px;\r\n --wje-input-margin-bottom: 0;\r\n}\r\n\r\nwje-infinite-scroll {\r\n margin-top: 1rem;\r\n}\r\n\r\nwje-select {\r\n --wje-select-border-width: 0 0 1px 0 !important;\r\n --wje-select-border-radius: 0 !important;\r\n margin-bottom: 1rem;\r\n}\r\n\r\n.anchor wje-icon {\r\n --wje-icon-size: 100% !important;\r\n}";
15
15
  class IconPicker extends WJElement {
@@ -1,4 +1,4 @@
1
- import { I as InfiniteScroll } from "./infinite-scroll.element-7dR-X4sd.js";
1
+ import { I as InfiniteScroll } from "./infinite-scroll.element-BJZCBKDO.js";
2
2
  InfiniteScroll.define("wje-infinite-scroll", InfiniteScroll);
3
3
  export {
4
4
  InfiniteScroll as default
@@ -99,7 +99,7 @@ import { default as default84 } from "./wje-tooltip.js";
99
99
  import { default as default85 } from "./wje-visually-hidden.js";
100
100
  import { default as default86 } from "./wje-sliding-container.js";
101
101
  import { L } from "./list.element-BkOOqBtW.js";
102
- import { I } from "./infinite-scroll.element-7dR-X4sd.js";
102
+ import { I } from "./infinite-scroll.element-BJZCBKDO.js";
103
103
  import { P } from "./popup.element-Dna4OwCH.js";
104
104
  function formatDate(input, format) {
105
105
  let date;
@@ -29,7 +29,7 @@ class Option extends WJElement {
29
29
  * @param {boolean} value - The value to set.
30
30
  */
31
31
  set selected(value) {
32
- return value ? this.setAttribute("selected", "") : this.removeAttribute("selected");
32
+ value ? this.setAttribute("selected", "") : this.removeAttribute("selected");
33
33
  }
34
34
  /**
35
35
  * Sets the value attribute of the option.
@@ -5,7 +5,7 @@ var __publicField = (obj, key, value) => {
5
5
  return value;
6
6
  };
7
7
  import WJElement, { event } from "./wje-element.js";
8
- import { I as InfiniteScroll } from "./infinite-scroll.element-7dR-X4sd.js";
8
+ import { I as InfiniteScroll } from "./infinite-scroll.element-BJZCBKDO.js";
9
9
  import { L as List } from "./list.element-BkOOqBtW.js";
10
10
  import Option from "./wje-option.js";
11
11
  class Options extends WJElement {
@@ -30,10 +30,17 @@ class Options extends WJElement {
30
30
  */
31
31
  __publicField(this, "htmlItem", (item) => {
32
32
  let option = document.createElement("wje-option");
33
- option.setAttribute("value", item[this.itemValue] || item.value);
34
- option.innerText = item[this.itemText] || item.text;
33
+ if (item[this.itemValue] == null) {
34
+ console.warn(`The item ${JSON.stringify(item)} does not have the property ${this.itemValue}`);
35
+ }
36
+ if (item[this.itemText] == null) {
37
+ console.warn(`The item ${JSON.stringify(item)} does not have the property ${this.itemText}`);
38
+ }
39
+ option.setAttribute("value", item[this.itemValue] ?? "");
40
+ option.innerText = item[this.itemText] ?? "";
35
41
  return option;
36
42
  });
43
+ this._loadedOptions = [];
37
44
  }
38
45
  /**
39
46
  * Returns the list of attributes to observe for changes.
@@ -86,11 +93,16 @@ class Options extends WJElement {
86
93
  set lazy(value) {
87
94
  this.setAttribute("lazy", value);
88
95
  }
96
+ get options() {
97
+ var _a;
98
+ return (_a = this._loadedOptions) == null ? void 0 : _a.flat();
99
+ }
89
100
  /**
90
101
  * Lifecycle method, called whenever an observed property changes
91
102
  */
92
- attributeChangedCallback(name, old, newName) {
93
- if (this.infiniteScroll) {
103
+ attributeChangedCallback(name, oldValue, newValue) {
104
+ if (this.infiniteScroll && name === "search" && oldValue !== newValue) {
105
+ this._loadedOptions = [];
94
106
  this.infiniteScroll.placementObj.innerHTML = "";
95
107
  this.infiniteScroll.totalPages = 0;
96
108
  this.infiniteScroll.refresh();
@@ -122,13 +134,18 @@ class Options extends WJElement {
122
134
  infiniteScroll.dataToHtml = this.htmlItem;
123
135
  infiniteScroll.setCustomData = async (page, signal) => {
124
136
  let res = await this.service.get(`${this.url}${this.search ? `/${this.search}` : ""}?page=${page}&size=${this.lazyLoadSize}`, null, false, signal);
125
- return res;
137
+ const filteredOptions = this.filterOutDrawnOptions(res);
138
+ this._loadedOptions.push(...this.processData(filteredOptions));
139
+ return filteredOptions;
126
140
  };
127
141
  this.contains(infiniteScroll) || this.appendChild(infiniteScroll);
128
142
  this.infiniteScroll = infiniteScroll;
129
143
  } else {
130
144
  this.response = await this.getPages();
131
- this.append(...this.processData(this.response).map(this.htmlItem));
145
+ let optionsData = this.filterOutDrawnOptions(this.response);
146
+ optionsData = this.processData(optionsData);
147
+ this._loadedOptions.push(...optionsData);
148
+ this.append(...optionsData.map(this.htmlItem));
132
149
  }
133
150
  fragment.appendChild(slot);
134
151
  return fragment;
@@ -141,12 +158,32 @@ class Options extends WJElement {
141
158
  */
142
159
  processData(data) {
143
160
  var _a;
144
- const splittedOptionArrayPath = (_a = this.optionArrayPath) == null ? void 0 : _a.split(".");
161
+ const splittedOptionArrayPath = this.optionArrayPath ? (_a = this.optionArrayPath) == null ? void 0 : _a.split(".") : null;
145
162
  let options = data;
146
163
  splittedOptionArrayPath == null ? void 0 : splittedOptionArrayPath.forEach((path) => {
147
164
  options = options[path];
148
165
  });
149
- return options;
166
+ return options ?? [];
167
+ }
168
+ /**
169
+ * Filters out drawn options from the response.
170
+ *
171
+ * @param {any} response - The response to filter.
172
+ * @returns {any} - The filtered response.
173
+ */
174
+ filterOutDrawnOptions(response) {
175
+ var _a;
176
+ const splittedOptionArrayPath = this.optionArrayPath ? (_a = this.optionArrayPath) == null ? void 0 : _a.split(".") : [];
177
+ let filteredResponse = structuredClone(response);
178
+ const recursiveUpdate = (object, pathToProperty) => {
179
+ if (pathToProperty.length > 1) {
180
+ recursiveUpdate(object[pathToProperty[0]], pathToProperty.slice(1));
181
+ } else {
182
+ object[pathToProperty[0]] = object[pathToProperty[0]].filter((option) => !this._loadedOptions.some((loadedOption) => loadedOption[this.itemValue] === option[this.itemValue]));
183
+ }
184
+ };
185
+ recursiveUpdate(filteredResponse, splittedOptionArrayPath);
186
+ return filteredResponse;
150
187
  }
151
188
  /**
152
189
  * Fetches the pages from the provided URL.
@@ -163,6 +200,36 @@ class Options extends WJElement {
163
200
  const data = await response.json();
164
201
  return data;
165
202
  }
203
+ /**
204
+ * Finds the selected option data based on the given selected option values.
205
+ *
206
+ * @param {Array} selectedOptionValues - The array of selected option values.
207
+ * @returns {Array} - The array of option data that matches the selected option values.
208
+ */
209
+ findSelectedOptionData(selectedOptionValues = []) {
210
+ return this.options.filter((option) => selectedOptionValues.includes(option[this.itemValue]));
211
+ }
212
+ /**
213
+ * Adds an option to the element.
214
+ *
215
+ * @param {Object} optionData - The data of the option to be added.
216
+ */
217
+ addOption(optionData) {
218
+ if (this._loadedOptions.some((option) => option[this.itemValue] === optionData[this.itemValue])) {
219
+ return;
220
+ }
221
+ this.appendChild(this.htmlItem(optionData));
222
+ this._loadedOptions.push(optionData);
223
+ }
224
+ /**
225
+ * Adds options to the element.
226
+ *
227
+ * @param {Array} optionsData - The array of option data to be added.
228
+ * @param {boolean} [silent=false] - Whether to suppress events triggered by adding options.
229
+ */
230
+ addOptions(optionsData = [], silent = false) {
231
+ Array.isArray(optionsData) ? optionsData == null ? void 0 : optionsData.forEach((optionData) => this.addOption(optionData, silent)) : this.addOption(optionsData, silent);
232
+ }
166
233
  }
167
234
  Options.define("wje-options", Options);
168
235
  export {
@@ -14,7 +14,7 @@ import Input from "./wje-input.js";
14
14
  import Option from "./wje-option.js";
15
15
  import Options from "./wje-options.js";
16
16
  import { P as Popup } from "./popup.element-Dna4OwCH.js";
17
- const styles = "/*\r\n[ WJ Select ]\r\n*/\r\n\r\n:host {\r\n --wje-select-border-width: 1px;\r\n --wje-select-border-style: solid;\r\n --wje-select-border-color: var(--wje-border-color);\r\n\r\n --wje-select-options-border-width: 1px;\r\n --wje-select-options-border-style: var(--wje-border-style);\r\n --wje-select-options-border-color: var(--wje-border-color);\r\n\r\n --wje-select-background: var(--wje-background);\r\n --wje-select-line-height: 20px;\r\n --wje-select-color: var(--wje-color);\r\n --wje-select-border-radius: var(--wje-border-radius-medium);\r\n\r\n width: 100%;\r\n display: block;\r\n [slot=arrow] {\r\n transform: rotate(0deg);\r\n transition: all .2s ease-in;\r\n }\r\n}\r\n\r\n.native-select {\r\n &.default{\r\n .wrapper {\r\n display: block;\r\n border-width: var(--wje-select-border-width);\r\n border-style: var(--wje-select-border-style);\r\n border-color: var(--wje-select-border-color);\r\n border-radius: var(--wje-select-border-radius);\r\n padding-inline: .5rem;\r\n padding-top: 0.125rem;\r\n padding-bottom: 0.125rem;\r\n }\r\n .input-wrapper {\r\n padding: 0;\r\n min-height: 28px;\r\n margin-top: -4px;\r\n }\r\n &.focused {\r\n wje-label {\r\n opacity: 0.67;\r\n font-size: 12px;\r\n letter-spacing: normal;\r\n }\r\n }\r\n wje-label {\r\n margin: 0;\r\n display: block;\r\n opacity: 1;\r\n cursor: text;\r\n transition: opacity 0.2s ease 0s;\r\n line-height: var(--wje-select-line-height);\r\n &.fade {\r\n opacity: 0.5;\r\n font-size: 12px;\r\n letter-spacing: normal;\r\n }\r\n }\r\n }\r\n &.standard {\r\n .wrapper {\r\n background-color: var(--wje-select-background);\r\n border-width: var(--wje-select-border-width);\r\n border-style: var(--wje-select-border-style);\r\n border-color: var(--wje-select-border-color);\r\n border-radius: var(--wje-select-border-radius);\r\n }\r\n .input-wrapper {\r\n background: transparent;\r\n width: 100%;\r\n }\r\n }\r\n}\r\n\r\n.wrapper {\r\n display: flex;\r\n width: 100%;\r\n}\r\n\r\n.input-wrapper {\r\n display: grid;\r\n grid-template-columns: auto 1fr auto auto auto;\r\n align-items: center;\r\n background-color: var(--wje-select-background);\r\n min-height: 28px;\r\n color: var(--wje-select-color);\r\n line-height: var(--wje-select-line-height);\r\n appearance: none;\r\n padding: 2px .5rem;\r\n font-size: 14px !important;\r\n font-weight: normal;\r\n vertical-align: middle;\r\n}\r\n\r\ninput {\r\n color: var(--wje-select-color);\r\n line-height: var(--wje-select-line-height);\r\n font-size: 14px !important;\r\n font-weight: 400;\r\n letter-spacing: .01em;\r\n border: medium;\r\n height: 25px;\r\n min-height: 25px;\r\n padding: 0;\r\n background: none;\r\n box-shadow: none;\r\n width: 100%;\r\n outline: 0;\r\n font-size: 14px !important;\r\n}\r\n\r\n::placeholder {\r\n opacity: 1;\r\n}\r\n\r\n:host [active] {\r\n .wrapper {\r\n border-radius: var(--wje-select-border-radius) var(--wje-select-border-radius) 0 0;\r\n }\r\n [slot=arrow] {\r\n transform: rotate(180deg);\r\n transition: all .2s ease-in;\r\n }\r\n}\r\n\r\n.options-wrapper {\r\n border-width: var(--wje-select-options-border-width);\r\n border-style: var(--wje-select-options-border-style);\r\n border-color: var(--wje-select-options-border-color);\r\n border-radius: 0 0 var(--wje-select-border-radius) var(--wje-select-border-radius);\r\n margin-top: calc(0px - var(--wje-select-border-width));\r\n background: var(--wje-select-background);\r\n overflow: hidden;\r\n\r\n}\r\n\r\n.find {\r\n --wje-input-border-radius: 0;\r\n --wje-input-border-width: 0 0 1px 0;\r\n}\r\n\r\n.list {\r\n overflow: auto;\r\n height: 100%;\r\n}\r\n\r\n.options-wrapper:has(.find) .list {\r\n height: calc(100% - 32px - .5rem);\r\n}\r\n\r\n:host([multiple]) input {\r\n position: absolute;\r\n z-index: -1;\r\n top: 0;\r\n left: 0;\r\n width: 0;\r\n height: 0;\r\n opacity: 0;\r\n}\r\n\r\n:host([multiple]) .chips {\r\n display: flex;\r\n flex: 1;\r\n align-items: center;\r\n flex-wrap: wrap;\r\n}\r\n\r\n:host([disabled]) .input-wrapper{\r\n opacity: 0.5;\r\n pointer-events: none;\r\n cursor: not-allowed;\r\n}\r\n\r\n.counter {\r\n padding-inline: .5rem;\r\n}\r\n\r\nwje-chip {\r\n --wje-chip-margin: 0 .25rem 0 0;\r\n}\r\n\r\nwje-button {\r\n --wje-padding-top: .25rem;\r\n --wje-padding-start: .25rem;\r\n --wje-padding-end: .25rem;\r\n --wje-padding-bottom: .25rem;\r\n --wje-button-margin-inline: 0 .25rem;\r\n}\r\n\r\n.slot-start, .slot-end {\r\n &:not(:empty) {\r\n margin-right: .5rem;\r\n }\r\n}\r\n";
17
+ const styles = "/*\r\n[ WJ Select ]\r\n*/\r\n\r\n:host {\r\n --wje-select-border-width: 1px;\r\n --wje-select-border-style: solid;\r\n --wje-select-border-color: var(--wje-border-color);\r\n\r\n --wje-select-options-border-width: 1px;\r\n --wje-select-options-border-style: var(--wje-border-style);\r\n --wje-select-options-border-color: var(--wje-border-color);\r\n\r\n --wje-select-background: var(--wje-background);\r\n --wje-select-line-height: 20px;\r\n --wje-select-color: var(--wje-color);\r\n --wje-select-border-radius: var(--wje-border-radius-medium);\r\n\r\n --wje-select-margin-bottom: .5rem;\r\n margin-bottom: var(--wje-select-margin-bottom);\r\n\r\n width: 100%;\r\n display: block;\r\n [slot=arrow] {\r\n transform: rotate(0deg);\r\n transition: all .2s ease-in;\r\n }\r\n}\r\n\r\n.native-select {\r\n &.default{\r\n .wrapper {\r\n display: block;\r\n border-width: var(--wje-select-border-width);\r\n border-style: var(--wje-select-border-style);\r\n border-color: var(--wje-select-border-color);\r\n border-radius: var(--wje-select-border-radius);\r\n padding-inline: .5rem;\r\n padding-top: 0.125rem;\r\n padding-bottom: 0.125rem;\r\n }\r\n .input-wrapper {\r\n padding: 0;\r\n min-height: 28px;\r\n margin-top: -4px;\r\n }\r\n &.focused {\r\n wje-label {\r\n opacity: 0.67;\r\n font-size: 12px;\r\n letter-spacing: normal;\r\n }\r\n }\r\n wje-label {\r\n margin: 0;\r\n display: block;\r\n opacity: 1;\r\n cursor: text;\r\n transition: opacity 0.2s ease 0s;\r\n line-height: var(--wje-select-line-height);\r\n &.fade {\r\n opacity: 0.5;\r\n font-size: 12px;\r\n letter-spacing: normal;\r\n }\r\n }\r\n }\r\n &.standard {\r\n .wrapper {\r\n background-color: var(--wje-select-background);\r\n border-width: var(--wje-select-border-width);\r\n border-style: var(--wje-select-border-style);\r\n border-color: var(--wje-select-border-color);\r\n border-radius: var(--wje-select-border-radius);\r\n }\r\n .input-wrapper {\r\n background: transparent;\r\n width: 100%;\r\n }\r\n }\r\n}\r\n\r\n.wrapper {\r\n display: flex;\r\n width: 100%;\r\n}\r\n\r\n.input-wrapper {\r\n display: grid;\r\n grid-template-columns: auto 1fr auto auto auto;\r\n align-items: center;\r\n background-color: var(--wje-select-background);\r\n min-height: 28px;\r\n color: var(--wje-select-color);\r\n line-height: var(--wje-select-line-height);\r\n appearance: none;\r\n padding: 2px .5rem;\r\n font-size: 14px !important;\r\n font-weight: normal;\r\n vertical-align: middle;\r\n}\r\n\r\ninput {\r\n color: var(--wje-select-color);\r\n line-height: var(--wje-select-line-height);\r\n font-size: 14px !important;\r\n font-weight: 400;\r\n letter-spacing: .01em;\r\n border: medium;\r\n height: 25px;\r\n min-height: 25px;\r\n padding: 0;\r\n background: none;\r\n box-shadow: none;\r\n width: 100%;\r\n outline: 0;\r\n font-size: 14px !important;\r\n}\r\n\r\n::placeholder {\r\n opacity: 1;\r\n}\r\n\r\n:host [active] {\r\n .wrapper {\r\n border-radius: var(--wje-select-border-radius) var(--wje-select-border-radius) 0 0;\r\n }\r\n [slot=arrow] {\r\n transform: rotate(180deg);\r\n transition: all .2s ease-in;\r\n }\r\n}\r\n\r\n.options-wrapper {\r\n border-width: var(--wje-select-options-border-width);\r\n border-style: var(--wje-select-options-border-style);\r\n border-color: var(--wje-select-options-border-color);\r\n border-radius: 0 0 var(--wje-select-border-radius) var(--wje-select-border-radius);\r\n margin-top: calc(0px - var(--wje-select-border-width));\r\n background: var(--wje-select-background);\r\n overflow: hidden;\r\n\r\n}\r\n\r\n.find {\r\n --wje-input-border-radius: 0;\r\n --wje-input-border-width: 0 0 1px 0;\r\n}\r\n\r\n.list {\r\n overflow: auto;\r\n height: 100%;\r\n}\r\n\r\n.options-wrapper:has(.find) .list {\r\n height: calc(100% - 32px - .5rem);\r\n}\r\n\r\n:host([multiple]) input {\r\n position: absolute;\r\n z-index: -1;\r\n top: 0;\r\n left: 0;\r\n width: 0;\r\n height: 0;\r\n opacity: 0;\r\n}\r\n\r\n:host([multiple]) .chips {\r\n display: flex;\r\n flex: 1;\r\n align-items: center;\r\n flex-wrap: wrap;\r\n}\r\n\r\n:host([disabled]) .input-wrapper{\r\n opacity: 0.5;\r\n pointer-events: none;\r\n cursor: not-allowed;\r\n}\r\n\r\n.counter {\r\n padding-inline: .5rem;\r\n}\r\n\r\nwje-chip {\r\n --wje-chip-margin: 0 .25rem 0 0;\r\n}\r\n\r\nwje-button {\r\n --wje-padding-top: .25rem;\r\n --wje-padding-start: .25rem;\r\n --wje-padding-end: .25rem;\r\n --wje-padding-bottom: .25rem;\r\n --wje-button-margin-inline: 0 .25rem;\r\n}\r\n\r\n.slot-start, .slot-end {\r\n &:not(:empty) {\r\n margin-right: .5rem;\r\n }\r\n}\r\n";
18
18
  class Select extends WJElement {
19
19
  /**
20
20
  * Creates an instance of Select.
@@ -49,8 +49,7 @@ class Select extends WJElement {
49
49
  this.popup.removeAttribute("active");
50
50
  }
51
51
  e.target.selected = !e.target.hasAttribute("selected");
52
- this.selections(e.target);
53
- event.dispatchCustomEvent(this, "wje-select:change");
52
+ this.selections();
54
53
  });
55
54
  /**
56
55
  * Handles the chip remove event.
@@ -62,7 +61,7 @@ class Select extends WJElement {
62
61
  option.selected = false;
63
62
  option.removeAttribute("selected");
64
63
  e.target.parentNode.removeChild(e.target);
65
- this.selections(null, 0);
64
+ this.selections();
66
65
  });
67
66
  this._selected = [];
68
67
  this.counterEl = null;
@@ -353,7 +352,7 @@ class Select extends WJElement {
353
352
  this.selections();
354
353
  e.stopPropagation();
355
354
  });
356
- this.selections();
355
+ this.selections(true);
357
356
  this.list.addEventListener("wje-options:load", (e) => {
358
357
  this.list.scrollTo(0, 0);
359
358
  });
@@ -449,7 +448,7 @@ class Select extends WJElement {
449
448
  *
450
449
  * @param {Element} option - The option to select.
451
450
  */
452
- selections(option) {
451
+ selections(silence = false) {
453
452
  let options = this.getSelectedOptions();
454
453
  this.selectedOptions = Array.isArray(options) ? options : Array.from(options);
455
454
  if (this.selectedOptions.length >= +this.maxOptions) {
@@ -457,12 +456,15 @@ class Select extends WJElement {
457
456
  }
458
457
  this.chips.innerHTML = "";
459
458
  if (this.selectedOptions.length > 0) {
460
- this.selectedOptions.forEach((option2, index) => {
461
- this.selectionChanged(option2, ++index);
459
+ this.selectedOptions.forEach((option, index) => {
460
+ this.selectionChanged(option, ++index);
462
461
  });
463
462
  } else {
464
463
  this.selectionChanged();
465
464
  }
465
+ if (silence)
466
+ return;
467
+ event.dispatchCustomEvent(this, "wje-select:change");
466
468
  }
467
469
  /**
468
470
  * Handles the counter.
@@ -496,6 +498,95 @@ class Select extends WJElement {
496
498
  chip.appendChild(label);
497
499
  return chip;
498
500
  }
501
+ /**
502
+ * Generates an HTML option element based on the provided item and mapping.
503
+ *
504
+ * @param {Object} item - The item to generate the option for.
505
+ * @param {Object} [map] - The mapping object that specifies the properties of the item to use for the option's value and text.
506
+ * @param {string} [map.value="value"] - The property of the item to use for the option's value.
507
+ * @param {string} [map.text="text"] - The property of the item to use for the option's text.
508
+ * @returns {HTMLElement} The generated HTML option element.
509
+ */
510
+ htmlOption(item, map = { value: "value", text: "text" }) {
511
+ let option = document.createElement("wje-option");
512
+ if (item[map.value] == null) {
513
+ console.warn(`The item ${JSON.stringify(item)} does not have the property ${map.value}`);
514
+ }
515
+ if (item[map.text] == null) {
516
+ console.warn(`The item ${JSON.stringify(item)} does not have the property ${map.text}`);
517
+ }
518
+ option.setAttribute("value", item[map.value] ?? "");
519
+ option.innerText = item[map.text] ?? "";
520
+ return option;
521
+ }
522
+ /**
523
+ * Adds an option to the select element.
524
+ *
525
+ * @param {any} optionData - The data for the option to be added.
526
+ * @param {boolean} [silent=false] - Whether to suppress any events triggered by the addition of the option.
527
+ * @param {object} [map={ value: "value", text: "text" }] - The mapping object specifying the properties of the option data to be used for the value and text of the option.
528
+ */
529
+ addOption(optionData, silent = false, map = { value: "value", text: "text" }) {
530
+ if (!optionData)
531
+ return;
532
+ const optionsElement = this.querySelector("wje-options");
533
+ if (optionsElement) {
534
+ optionsElement.addOption(optionData, silent, map);
535
+ return;
536
+ }
537
+ let option = this.htmlOption(optionData, map);
538
+ this.appendChild(option);
539
+ }
540
+ /**
541
+ * Adds options to the select element.
542
+ *
543
+ * @param {Array|Object} optionsData - The options data to be added. Can be an array of objects or a single object.
544
+ * @param {boolean} [silent=false] - Indicates whether to trigger events when adding options. Default is false.
545
+ * @param {Object} [map] - The mapping object that specifies the properties of the options data object. Default is { value: "value", text: "text" }.
546
+ */
547
+ addOptions(optionsData, silent = false, map = { value: "value", text: "text" }) {
548
+ if (!Array.isArray(optionsData)) {
549
+ this.addOption(optionsData, silent, map);
550
+ } else {
551
+ const optionsElement = this.querySelector("wje-options");
552
+ if (optionsElement) {
553
+ optionsElement.addOptions(optionsData, silent, map);
554
+ return;
555
+ }
556
+ optionsData.forEach((item) => {
557
+ this.addOption(item, silent, map);
558
+ });
559
+ }
560
+ }
561
+ /**
562
+ * Selects an option with the specified value.
563
+ *
564
+ * @param {string} value - The value of the option to be selected.
565
+ * @param {boolean} [silent=false] - Whether to suppress firing events.
566
+ */
567
+ selectOption(value, silent = false) {
568
+ if (!value)
569
+ return;
570
+ let option = this.querySelector(`wje-option[value="${value}"]`);
571
+ if (option) {
572
+ option.selected = true;
573
+ }
574
+ }
575
+ /**
576
+ * Selects one or multiple options in the select element.
577
+ *
578
+ * @param {Array|any} values - The value(s) of the option(s) to be selected.
579
+ * @param {boolean} [silent=false] - Whether to trigger the change event or not.
580
+ */
581
+ selectOptions(values, silent = false) {
582
+ if (!Array.isArray(values)) {
583
+ this.selectOption(values, silent);
584
+ } else {
585
+ values.forEach((value) => {
586
+ this.selectOption(value, silent);
587
+ });
588
+ }
589
+ }
499
590
  /**
500
591
  * @summary Callback function that is called when the custom element is associated with a form.
501
592
  * This function adds an event listener to the form's submit event, which validates the input and propagates the validation.
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "wj-elements",
3
3
  "description": "WebJET Elements is a modern set of user interface tools harnessing the power of web components designed to simplify web application development.",
4
- "version": "0.1.105",
4
+ "version": "0.1.108",
5
5
  "homepage": "https://github.com/lencys/wj-elements",
6
6
  "author": "Lukáš Ondrejček <lukas.ondrejcek@gmail.com>",
7
7
  "license": "MIT",