@wavelengthusaf/web-components 1.11.0 → 1.14.0

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.
@@ -3183,7 +3183,7 @@ if (!customElements.get("wavelength-progress-bar")) {
3183
3183
  }
3184
3184
 
3185
3185
  // src/web-components/wavelength-input.template.html
3186
- var wavelength_input_template_default = '<style>\n :host {\n display: block;\n width: 100%;\n font-family: sans-serif;\n --wavelength-container-background: #f8f8f8;\n --wavelength-label-background: #ffffff;\n }\n\n .field-wrapper {\n position: relative;\n }\n\n .floating-label {\n position: absolute;\n top: -0.325rem;\n left: 12px;\n font-size: 0.75rem;\n line-height: 1;\n color: var(--wavelength-label-color, #666666);\n padding: 0 4px;\n z-index: 1;\n pointer-events: none;\n user-select: none;\n }\n\n .floating-label::before,\n .floating-label::after {\n content: "";\n position: absolute;\n left: 0;\n width: 100%;\n z-index: -1;\n }\n\n .floating-label::before {\n top: 0;\n height: 50%;\n background: var(--wavelength-container-background, white);\n }\n\n .floating-label::after {\n bottom: 0;\n height: 50%;\n background: var(--wavelength-label-background, #ffffff);\n }\n\n :host([disabled]) .floating-label::before {\n opacity: 0;\n }\n\n input {\n font-size: 16px;\n padding: 16.5px 14px;\n border: 1px solid var(--wavelength-border-color, #cccccc);\n border-radius: 8px;\n width: 100%;\n box-sizing: border-box;\n background-color: var(--wavelength-background, #ffffff);\n transition: border-color 0.2s ease;\n overflow: auto;\n font-family: inherit;\n }\n\n input:focus {\n outline: none;\n }\n\n input:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n }\n\n :host([disabled]) .floating-label::after {\n opacity: 0;\n cursor: not-allowed;\n }\n\n input::placeholder {\n color: #999999;\n }\n\n .helper-message {\n margin-top: 4px;\n font-size: 0.75rem;\n max-width: 100%;\n word-wrap: break-word;\n white-space: normal;\n overflow-wrap: break-word;\n color: #000000;\n padding-left: 14px;\n margin-left: 2px;\n user-select: none;\n }\n\n .required-marker {\n color: red;\n font-weight: lighter;\n font-size: 0.75rem;\n }\n\n .clear-button {\n position: absolute;\n right: 12px;\n top: 50%;\n transform: translateY(-50%);\n font-size: 1.25 rem;\n color: #666666;\n cursor: pointer;\n opacity: 0.5;\n user-select: none;\n transition: opacity 0.2s ease;\n z-index: 2;\n display: none;\n line-height: 1;\n padding: 0 4px;\n }\n\n .clear-button:hover {\n opacity: 1;\n }\n\n :host([disabled]) .clear-button {\n display: none;\n }\n</style>\n<div class="field-wrapper">\n <label class="floating-label" id="floating-label"></label>\n <div class="input-wrapper"></div>\n <div class="clear-button" id="clear-button" title="Clear input">\u2715</div>\n</div>\n<div class="helper-message" id="helper"></div>\n';
3186
+ var wavelength_input_template_default = '<style>\n :host {\n display: block;\n width: 100%;\n font-family: sans-serif;\n --wavelength-container-background: #f8f8f8;\n --wavelength-label-background: #ffffff;\n }\n\n .field-wrapper {\n position: relative;\n width: 100%;\n height: 100%;\n }\n\n .input-wrapper {\n width: 100%;\n height: 100%;\n }\n\n .floating-label {\n position: absolute;\n top: -0.325rem;\n left: 12px;\n font-size: 0.75rem;\n line-height: 1;\n color: var(--wavelength-label-color, #666666);\n padding: 0 4px;\n z-index: 1;\n pointer-events: none;\n user-select: none;\n }\n\n .floating-label::before,\n .floating-label::after {\n content: "";\n position: absolute;\n left: 0;\n width: 100%;\n z-index: -1;\n }\n\n .floating-label::before {\n top: 0;\n height: 50%;\n background: var(--wavelength-container-background, white);\n }\n\n .floating-label::after {\n bottom: 0;\n height: 50%;\n background: var(--wavelength-label-background, #ffffff);\n }\n\n :host([disabled]) .floating-label::before {\n opacity: 0;\n }\n\n input {\n font-size: 16px;\n padding: 16.5px 14px;\n border: 1px solid var(--wavelength-border-color, #cccccc);\n border-radius: 8px;\n width: 100%;\n box-sizing: border-box;\n background-color: var(--wavelength-background, #ffffff);\n transition: border-color 0.2s ease;\n overflow: auto;\n font-family: inherit;\n }\n\n input:focus {\n outline: none;\n }\n\n input:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n }\n\n :host([disabled]) .floating-label::after {\n opacity: 0;\n cursor: not-allowed;\n }\n\n input::placeholder {\n color: #999999;\n }\n\n .helper-message {\n margin-top: 4px;\n font-size: 0.75rem;\n max-width: 100%;\n word-wrap: break-word;\n white-space: normal;\n overflow-wrap: break-word;\n color: #000000;\n padding-left: 14px;\n margin-left: 2px;\n user-select: none;\n }\n\n .required-marker {\n color: red;\n font-weight: lighter;\n font-size: 0.75rem;\n }\n\n .clear-button {\n position: absolute;\n right: 12px;\n top: 50%;\n transform: translateY(-50%);\n font-size: 1.25 rem;\n color: #666666;\n cursor: pointer;\n opacity: 0.5;\n user-select: none;\n transition: opacity 0.2s ease;\n z-index: 2;\n display: none;\n line-height: 1;\n padding: 0 4px;\n }\n\n .clear-button:hover {\n opacity: 1;\n }\n\n :host([disabled]) .clear-button {\n display: none;\n }\n</style>\n<div class="field-wrapper">\n <label class="floating-label" id="floating-label"></label>\n <div class="input-wrapper"></div>\n <div class="clear-button" id="clear-button" title="Clear input">\u2715</div>\n</div>\n<div class="helper-message" id="helper"></div>\n';
3187
3187
 
3188
3188
  // src/web-components/wavelength-input.ts
3189
3189
  function getAncestor(el) {
@@ -3302,7 +3302,9 @@ var BaseWavelengthInput = class extends HTMLElement {
3302
3302
  "max-length",
3303
3303
  "required",
3304
3304
  "force-error",
3305
- "label"
3305
+ "label",
3306
+ "font-size",
3307
+ "font-family"
3306
3308
  ];
3307
3309
  }
3308
3310
  connectedCallback() {
@@ -3430,6 +3432,7 @@ var BaseWavelengthInput = class extends HTMLElement {
3430
3432
  }
3431
3433
  this.helperEl.innerHTML = htmlMessage;
3432
3434
  this.helperEl.classList.add("error");
3435
+ this.helperEl.style.display = "block";
3433
3436
  this.inputEl.style.borderColor = "red";
3434
3437
  this.helperEl.style.color = "red";
3435
3438
  this.inputEl.setAttribute("aria-invalid", "true");
@@ -3442,6 +3445,7 @@ var BaseWavelengthInput = class extends HTMLElement {
3442
3445
  this.helperEl.textContent = helperText;
3443
3446
  this.helperEl.classList.remove("error");
3444
3447
  this.helperEl.style.color = helperColor;
3448
+ this.helperEl.style.display = helperText ? "block" : "none";
3445
3449
  this.inputEl.style.borderColor = borderColor;
3446
3450
  this.inputEl.setAttribute("aria-invalid", "false");
3447
3451
  this.removeAttribute("data-error");
@@ -3519,6 +3523,12 @@ var BaseWavelengthInput = class extends HTMLElement {
3519
3523
  this.inputEl.style.padding = rawPadding;
3520
3524
  this.inputEl.style.height = this.getAttribute("height") || "";
3521
3525
  this.inputEl.style.borderRadius = this.getAttribute("border-radius") || "8px";
3526
+ if (this.hasAttribute("font-size")) {
3527
+ this.inputEl.style.fontSize = this.getAttribute("font-size");
3528
+ }
3529
+ if (this.hasAttribute("font-family")) {
3530
+ this.inputEl.style.fontFamily = this.getAttribute("font-family");
3531
+ }
3522
3532
  this.helperEl.style.width = helperWidth;
3523
3533
  this.helperEl.style.paddingLeft = `${leftPaddingPx}px`;
3524
3534
  }
@@ -3564,6 +3574,7 @@ var BaseWavelengthInput = class extends HTMLElement {
3564
3574
  if (!hasError) {
3565
3575
  this.helperEl.textContent = helper;
3566
3576
  this.helperEl.style.color = helperColor;
3577
+ this.helperEl.style.display = helper ? "block" : "none";
3567
3578
  }
3568
3579
  }
3569
3580
  _applyAccessibility() {
@@ -3588,7 +3599,10 @@ var BaseWavelengthInput = class extends HTMLElement {
3588
3599
  this.inputEl.name = newValue || "";
3589
3600
  break;
3590
3601
  case "label":
3602
+ case "font-size":
3603
+ case "font-family":
3591
3604
  this._applyContent();
3605
+ this._applyLayout();
3592
3606
  break;
3593
3607
  case "helper-message":
3594
3608
  this._applyValidationHint();
@@ -6506,6 +6520,392 @@ if (!customElements.get("wavelength-pagination")) {
6506
6520
  customElements.define("wavelength-pagination", WavelengthPagination);
6507
6521
  }
6508
6522
 
6523
+ // src/web-components/wavelength-search.template.html
6524
+ var wavelength_search_template_default = '<style>\n :host {\n display: block;\n --width: 200px;\n --height: 32px;\n --border-width: 1px;\n --mode: automatic;\n --font-size: 14px;\n --border-radius: 50px;\n --border-color: #000;\n --background-color: #fff;\n --hover-color: #007bff;\n --placeholder-color: #999;\n --placeholder-font: "Montserrat", system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;\n --input-color: #000;\n --input-font: "Montserrat", system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;\n }\n\n :host([height="small"]) {\n --height: 32px;\n }\n\n :host([height="medium"]) {\n --height: 48px;\n }\n\n :host([height="large"]) {\n --height: 64px;\n }\n\n .flex-container {\n display: block;\n flex-direction: column;\n width: fit-content;\n height: fit-content;\n position: relative;\n }\n\n .searchbar-wrapper {\n display: flex;\n flex-direction: row;\n align-items: center;\n border-radius: var(--border-radius);\n border: var(--border-width) solid var(--border-color);\n background-color: var(--background-color);\n width: var(--width);\n height: var(--height);\n margin: 1px;\n }\n\n .searchbar-wrapper:hover {\n border-color: var(--hover-color);\n }\n\n .searchbar-wrapper:focus-within {\n border-width: calc(var(--border-width) + 1px);\n border-color: var(--hover-color);\n margin: 0px;\n }\n\n :host([icon-pos="end"]) .searchbar-wrapper {\n flex-direction: row-reverse;\n }\n\n .search-button {\n width: 40px;\n height: 40px;\n border-radius: 50%;\n border: none;\n background-color: transparent;\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n margin: 0 10px;\n padding: 0;\n transition: background-color 0.2s;\n }\n\n .search-button:hover {\n background-color: rgba(0, 0, 0, 0.05);\n }\n\n .search-icon {\n width: var(--font-size);\n height: var(--font-size);\n fill: currentColor;\n }\n\n .input-container {\n position: relative;\n flex-grow: 1;\n display: flex;\n align-items: center;\n height: 100%;\n }\n\n .animated-placeholder {\n position: absolute;\n left: 14px;\n top: 50%;\n transform: translateY(-50%);\n color: var(--placeholder-color);\n font-family: var(--placeholder-font);\n font-size: var(--font-size);\n pointer-events: none;\n transition: all 0.2s ease;\n background-color: transparent;\n padding: 0 4px;\n border-radius: 4px;\n z-index: 5;\n }\n\n .input-container.focused .animated-placeholder,\n .input-container.has-value .animated-placeholder {\n top: -12px;\n font-size: calc(var(--font-size) * 0.75);\n color: var(--placeholder-color);\n background-color: transparent;\n }\n\n .dropdown {\n position: absolute;\n font-size: var(--font-size);\n font-family: var(--input-font);\n top: calc(100% + 4px);\n left: 0;\n max-height: 200px;\n width: 100%;\n background: white;\n border: 1px solid transparent;\n border-radius: 4px;\n display: none;\n z-index: 10;\n overflow-y: auto;\n overflow-x: hidden;\n box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);\n }\n\n .dropdown-item {\n padding: 8px 14px;\n cursor: pointer;\n border-left: 3px solid transparent;\n transition:\n background-color 0.1s,\n border-color 0.1s;\n }\n .dropdown-item:hover {\n background-color: rgba(0, 0, 0, 0.05);\n }\n .dropdown-item.highlighted {\n background-color: rgba(0, 0, 0, 0.08);\n border-left-color: var(--hover-color);\n }\n\n wavelength-input {\n flex-grow: 1;\n width: 100%;\n height: 100%;\n }\n</style>\n\n<div class="flex-container">\n <div class="searchbar-wrapper">\n <button class="search-button search-icon">\n <svg\n version="1.1"\n id="_x32_"\n xmlns="http://www.w3.org/2000/svg"\n xmlns:xlink="http://www.w3.org/1999/xlink"\n viewBox="0 0 512 512"\n xml:space="preserve"\n fill="#000000"\n style="width: 100%; height: 100%"\n >\n <g id="SVGRepo_bgCarrier" stroke-width="0"></g>\n <g id="SVGRepo_tracerCarrier" stroke-linecap="round" stroke-linejoin="round"></g>\n <g id="SVGRepo_iconCarrier">\n <style type="text/css">\n .st0 {\n fill: #000000;\n }\n </style>\n <g>\n <path\n class="st0"\n d="M312.069,53.445c-71.26-71.26-187.194-71.26-258.454,0c-71.261,71.26-71.261,187.206,0,258.466 c71.26,71.26,187.194,71.26,258.454,0S383.329,124.705,312.069,53.445z M286.694,286.536 c-57.351,57.34-150.353,57.34-207.704-0.011s-57.351-150.353,0-207.693c57.351-57.351,150.342-57.351,207.693,0 S344.045,229.174,286.694,286.536z"\n ></path>\n <path\n class="st0"\n d="M101.911,112.531c-29.357,37.725-31.801,89.631-7.321,129.702c1.877,3.087,5.902,4.048,8.978,2.182 c3.065-1.888,4.037-5.903,2.16-8.978c-21.666-35.456-19.506-81.538,6.469-114.876c2.226-2.837,1.713-6.938-1.135-9.154 C108.227,109.193,104.125,109.695,101.911,112.531z"\n ></path>\n <path\n class="st0"\n d="M498.544,447.722l-132.637-129.2c-7.255-7.07-18.84-6.982-26.008,0.174l-21.033,21.033 c-7.156,7.156-7.234,18.742-0.153,25.986l129.19,132.636c14.346,17.324,35.542,18.35,51.917,1.964 C516.216,483.951,515.857,462.068,498.544,447.722z"\n ></path>\n </g>\n </g>\n </svg>\n </button>\n <div class="input-container" id="inputContainer">\n <label class="animated-placeholder" id="animatedPlaceholder">Search...</label>\n <wavelength-input\n focus-color="transparent"\n background-color="transparent"\n border-color="transparent"\n label=""\n id="searchInput"\n placeholder=""\n validation-type="onBlur"\n min-length="0"\n clearable\n height="100%"\n padding="0 10px"\n ></wavelength-input>\n <div id="dropdown" class="dropdown"></div>\n </div>\n </div>\n</div>\n';
6525
+
6526
+ // src/web-components/wavelength-search.ts
6527
+ var WavelengthSearch = class extends HTMLElement {
6528
+ constructor() {
6529
+ super();
6530
+ this.options = [];
6531
+ this.highlightedIndex = -1;
6532
+ this.styleAttributes = [
6533
+ "width",
6534
+ "height",
6535
+ "font-size",
6536
+ "border-width",
6537
+ "border-radius",
6538
+ "border-color",
6539
+ "background-color",
6540
+ "hover-color",
6541
+ "placeholder-color",
6542
+ "placeholder-font",
6543
+ "input-color",
6544
+ "input-font"
6545
+ ];
6546
+ this.handleFocusIn = () => {
6547
+ this.inputContainer.classList.add("focused");
6548
+ };
6549
+ this.handleFocusOut = () => {
6550
+ this.inputContainer.classList.remove("focused");
6551
+ };
6552
+ this.handleInputChange = (e) => {
6553
+ const mode = this.getAttribute("mode") || "automatic";
6554
+ const value = e.detail.value;
6555
+ if (value) {
6556
+ this.inputContainer.classList.add("has-value");
6557
+ } else {
6558
+ this.inputContainer.classList.remove("has-value");
6559
+ }
6560
+ if (mode === "automatic") {
6561
+ if (this.searchTimeout) {
6562
+ clearTimeout(this.searchTimeout);
6563
+ }
6564
+ this.searchTimeout = setTimeout(() => {
6565
+ this.handleSearch(value);
6566
+ }, 300);
6567
+ }
6568
+ };
6569
+ this.handleKeydown = (e) => {
6570
+ const isDropdownVisible = this.dropdown.style.display === "block";
6571
+ const items = this.dropdown.querySelectorAll(".dropdown-item");
6572
+ if (e.key === "ArrowDown") {
6573
+ e.preventDefault();
6574
+ if (!isDropdownVisible) {
6575
+ this.handleSearch(this.input.value);
6576
+ } else if (items.length > 0) {
6577
+ this.highlightedIndex = (this.highlightedIndex + 1) % items.length;
6578
+ this.updateHighlight(items);
6579
+ }
6580
+ } else if (e.key === "ArrowUp") {
6581
+ e.preventDefault();
6582
+ if (isDropdownVisible && items.length > 0) {
6583
+ this.highlightedIndex = this.highlightedIndex <= 0 ? items.length - 1 : this.highlightedIndex - 1;
6584
+ this.updateHighlight(items);
6585
+ }
6586
+ } else if (e.key === "Escape" || e.key === "Tab") {
6587
+ this.dropdown.style.display = "none";
6588
+ this.highlightedIndex = -1;
6589
+ if (e.key === "Escape") {
6590
+ this.input.focus();
6591
+ }
6592
+ } else if (e.key === "Enter") {
6593
+ if (isDropdownVisible && this.highlightedIndex >= 0 && this.highlightedIndex < items.length) {
6594
+ e.preventDefault();
6595
+ this.selectOption(items[this.highlightedIndex].textContent || "");
6596
+ } else {
6597
+ const value = this.input.value;
6598
+ this.dispatchEvent(new CustomEvent("wavelength-search-submit", { detail: { value }, bubbles: true, composed: true }));
6599
+ this.handleSearch(value);
6600
+ }
6601
+ }
6602
+ };
6603
+ this.handleSearchIconClick = () => {
6604
+ const value = this.input.value;
6605
+ this.dispatchEvent(new CustomEvent("wavelength-search-submit", { detail: { value }, bubbles: true, composed: true }));
6606
+ this.handleSearch(value);
6607
+ };
6608
+ this.handleDocumentClick = (e) => {
6609
+ if (!this.contains(e.target)) {
6610
+ this.dropdown.style.display = "none";
6611
+ this.highlightedIndex = -1;
6612
+ }
6613
+ };
6614
+ this.shadow = this.attachShadow({ mode: "open" });
6615
+ this.shadow.innerHTML = wavelength_search_template_default;
6616
+ }
6617
+ static get observedAttributes() {
6618
+ return [
6619
+ "width",
6620
+ "height",
6621
+ "mode",
6622
+ "font-size",
6623
+ "border-width",
6624
+ "border-radius",
6625
+ "border-color",
6626
+ "background-color",
6627
+ "hover-color",
6628
+ "options",
6629
+ "placeholder",
6630
+ "icon-pos",
6631
+ "placeholder-color",
6632
+ "placeholder-font",
6633
+ "input-color",
6634
+ "input-font"
6635
+ ];
6636
+ }
6637
+ connectedCallback() {
6638
+ this._syncStyles();
6639
+ this.input = this.shadow.getElementById("searchInput");
6640
+ this.dropdown = this.shadow.getElementById("dropdown");
6641
+ this.inputContainer = this.shadow.getElementById("inputContainer");
6642
+ this.animatedPlaceholder = this.shadow.getElementById("animatedPlaceholder");
6643
+ if (!this.hasAttribute("icon-pos")) {
6644
+ this.setAttribute("icon-pos", "end");
6645
+ }
6646
+ if (!this.hasAttribute("height")) {
6647
+ this.setAttribute("height", "small");
6648
+ }
6649
+ const placeholder = this.getAttribute("placeholder") || "Search...";
6650
+ this.animatedPlaceholder.textContent = placeholder;
6651
+ const searchIcon = this.shadow.querySelector(".search-icon");
6652
+ this.input.addEventListener("focusin", this.handleFocusIn);
6653
+ this.input.addEventListener("focusout", this.handleFocusOut);
6654
+ this.input.addEventListener("inputChange", this.handleInputChange);
6655
+ this.input.addEventListener("keydown", this.handleKeydown);
6656
+ if (searchIcon) {
6657
+ searchIcon.addEventListener("click", this.handleSearchIconClick);
6658
+ }
6659
+ document.addEventListener("click", this.handleDocumentClick);
6660
+ }
6661
+ disconnectedCallback() {
6662
+ this.input.removeEventListener("focusin", this.handleFocusIn);
6663
+ this.input.removeEventListener("focusout", this.handleFocusOut);
6664
+ this.input.removeEventListener("inputChange", this.handleInputChange);
6665
+ this.input.removeEventListener("keydown", this.handleKeydown);
6666
+ const searchIcon = this.shadow.querySelector(".search-icon");
6667
+ if (searchIcon) {
6668
+ searchIcon.removeEventListener("click", this.handleSearchIconClick);
6669
+ }
6670
+ document.removeEventListener("click", this.handleDocumentClick);
6671
+ }
6672
+ attributeChangedCallback(name, oldValue, newValue) {
6673
+ if (oldValue === newValue) return;
6674
+ if (this.styleAttributes.includes(name)) {
6675
+ if (name === "height") {
6676
+ if (["small", "medium", "large"].includes(newValue || "")) {
6677
+ this.style.removeProperty("--height");
6678
+ } else if (newValue !== null) {
6679
+ this.style.setProperty("--height", newValue);
6680
+ } else {
6681
+ this.style.removeProperty("--height");
6682
+ }
6683
+ } else {
6684
+ if (newValue !== null) {
6685
+ this.style.setProperty(`--${name}`, newValue);
6686
+ } else {
6687
+ this.style.removeProperty(`--${name}`);
6688
+ }
6689
+ }
6690
+ }
6691
+ if (name === "options" && newValue) {
6692
+ try {
6693
+ this.options = JSON.parse(newValue);
6694
+ } catch (e) {
6695
+ this.options = newValue.split(",").map((s) => s.trim());
6696
+ }
6697
+ } else if (name === "placeholder" && this.animatedPlaceholder) {
6698
+ this.animatedPlaceholder.textContent = newValue || "Search...";
6699
+ } else if (name === "font-size" && this.input) {
6700
+ this.input.setAttribute("font-size", newValue || "");
6701
+ } else if (name === "input-color" && this.input) {
6702
+ this.input.setAttribute("text-color", newValue || "");
6703
+ } else if (name === "input-font" && this.input) {
6704
+ this.input.setAttribute("font-family", newValue || "");
6705
+ }
6706
+ }
6707
+ handleSearch(query) {
6708
+ if (this.searchTimeout) {
6709
+ clearTimeout(this.searchTimeout);
6710
+ this.searchTimeout = null;
6711
+ }
6712
+ if (!query) {
6713
+ this.dropdown.style.display = "none";
6714
+ return;
6715
+ }
6716
+ const results = this.options.filter((option) => option.toLowerCase().includes(query.toLowerCase()));
6717
+ this.highlightedIndex = -1;
6718
+ this.renderDropdown(results);
6719
+ }
6720
+ renderDropdown(results) {
6721
+ if (results.length === 0) {
6722
+ this.dropdown.style.display = "none";
6723
+ return;
6724
+ }
6725
+ this.dropdown.innerHTML = results.map((r) => `<div class="dropdown-item">${r}</div>`).join("");
6726
+ this.dropdown.style.display = "block";
6727
+ const items = this.dropdown.querySelectorAll(".dropdown-item");
6728
+ items.forEach((item, index) => {
6729
+ item.addEventListener("click", () => {
6730
+ this.selectOption(item.textContent || "");
6731
+ });
6732
+ item.addEventListener("mouseenter", () => {
6733
+ this.highlightedIndex = index;
6734
+ this.updateHighlight(items);
6735
+ });
6736
+ });
6737
+ this.updateHighlight(items);
6738
+ }
6739
+ selectOption(value) {
6740
+ this.input.value = value;
6741
+ this.dropdown.style.display = "none";
6742
+ this.highlightedIndex = -1;
6743
+ this.dispatchEvent(new CustomEvent("wavelength-search-select", { detail: { value }, bubbles: true, composed: true }));
6744
+ }
6745
+ // ---- Getters and Setters API ---- //
6746
+ get value() {
6747
+ return this.input.value;
6748
+ }
6749
+ set value(val) {
6750
+ this.input.value = val;
6751
+ }
6752
+ get optionsList() {
6753
+ return this.options;
6754
+ }
6755
+ set optionsList(val) {
6756
+ if (val) {
6757
+ this.options = val;
6758
+ this.setAttribute("options", JSON.stringify(val));
6759
+ }
6760
+ }
6761
+ _syncStyles() {
6762
+ this.styleAttributes.forEach((attr) => {
6763
+ const value = this.getAttribute(attr);
6764
+ if (value) {
6765
+ if (attr === "height" && ["small", "medium", "large"].includes(value)) {
6766
+ } else {
6767
+ this.style.setProperty(`--${attr}`, value);
6768
+ }
6769
+ }
6770
+ });
6771
+ }
6772
+ updateHighlight(items) {
6773
+ items.forEach((item, index) => {
6774
+ const isHighlighted = index === this.highlightedIndex;
6775
+ item.classList.toggle("highlighted", isHighlighted);
6776
+ if (isHighlighted) {
6777
+ item.scrollIntoView({ block: "nearest" });
6778
+ }
6779
+ });
6780
+ }
6781
+ };
6782
+ if (!customElements.get("wavelength-search")) {
6783
+ customElements.define("wavelength-search", WavelengthSearch);
6784
+ }
6785
+
6786
+ // src/web-components/wavelength-switch.template.html
6787
+ var wavelength_switch_template_default = '<style>\n :host {\n display: block;\n --font-color: #333;\n --font-size: 20px;\n --font-family: "Montserrat", system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;\n --switch-color: #2196f3;\n --label-font: "Montserrat", system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;\n\n /* Variable-based sizing */\n --container-width: 60px;\n --container-height: 34px;\n --track-height: 22px;\n --knob-size: 28px;\n\n /* Internal Calculations */\n --track-top: calc((var(--container-height) - var(--track-height)) / 2);\n --knob-top: calc((var(--container-height) - var(--knob-size)) / 2);\n --knob-translate: calc(var(--container-width) - var(--knob-size));\n }\n\n :host([size="small"]) {\n --container-width: 40px;\n --container-height: 24px;\n --track-height: 14px;\n --knob-size: 20px;\n --font-size: 16px;\n }\n\n :host([size="large"]) {\n --container-width: 80px;\n --container-height: 48px;\n --track-height: 30px;\n --knob-size: 40px;\n --font-size: 24px;\n }\n\n /* Switch Base Styles */\n .switch {\n position: relative;\n display: inline-block;\n width: var(--container-width);\n height: var(--container-height);\n }\n\n .switch input {\n opacity: 0;\n width: 0;\n height: 0;\n }\n\n /* Slider (The Track) */\n .slider {\n position: absolute;\n cursor: pointer;\n top: var(--track-top);\n left: 0;\n right: 0;\n bottom: var(--track-top);\n background-color: #ccc;\n -webkit-transition: 0.4s;\n transition: 0.4s;\n border-radius: var(--track-height);\n }\n\n .slider:hover {\n cursor: pointer;\n }\n\n /* Handle (The Slider Portion) */\n .slider:before {\n position: absolute;\n content: "";\n height: var(--knob-size);\n width: var(--knob-size);\n left: 0;\n top: calc((var(--track-height) - var(--knob-size)) / 2);\n background-color: white;\n -webkit-transition: 0.4s;\n transition: 0.4s;\n border-radius: var(--knob-size);\n box-shadow: 0 2px 4px rgba(0, 0, 0, 0.3);\n z-index: 2;\n }\n\n .slider:hover:before {\n box-shadow:\n 0 2px 4px rgba(0, 0, 0, 0.3),\n 0 0 0 8px rgba(0, 0, 0, 0.1);\n }\n\n /* Input Checked State Styles */\n input:checked + .slider {\n background-color: var(--switch-color);\n }\n\n input:focus + .slider {\n box-shadow: 0 0 1px #2196f3;\n }\n\n input:checked + .slider:before {\n -webkit-transform: translateX(var(--knob-translate));\n -ms-transform: translateX(var(--knob-translate));\n transform: translateX(var(--knob-translate));\n }\n\n input:checked + .slider:hover:before {\n box-shadow:\n 0 2px 4px rgba(0, 0, 0, 0.3),\n 0 0 0 8px color-mix(in srgb, var(--switch-color), transparent 80%);\n }\n\n /* Disabled State Styles */\n input:disabled + .slider {\n background-color: #e0e0e0;\n cursor: not-allowed;\n }\n\n input:disabled + .slider:before {\n background-color: #f5f5f5;\n box-shadow: 0 1px 2px rgba(0, 0, 0, 0.15);\n }\n\n input:disabled + .slider:hover:before {\n box-shadow: 0 1px 2px rgba(0, 0, 0, 0.15);\n }\n\n input:disabled:checked + .slider {\n background-color: color-mix(in srgb, var(--switch-color), white 50%);\n opacity: 0.8;\n }\n\n /* Label Styles */\n .label {\n font-size: var(--font-size);\n font-weight: 500;\n color: var(--font-color);\n font-family: var(--label-font);\n }\n\n :host([disabled]) .label {\n color: #9e9e9e;\n }\n\n .flex-container {\n display: flex;\n flex-direction: row;\n align-items: center;\n gap: 8px;\n }\n</style>\n\n<div class="flex-container">\n <span id="label-span" class="label"></span>\n <label class="switch">\n <input type="checkbox" aria-labelledby="label" />\n <div class="slider"></div>\n </label>\n</div>\n';
6788
+
6789
+ // src/web-components/wavelength-switch.ts
6790
+ var WavelengthSwitch = class extends HTMLElement {
6791
+ static get observedAttributes() {
6792
+ return ["checked", "label", "label-placement", "size", "disabled", "color", "label-font", "value"];
6793
+ }
6794
+ constructor() {
6795
+ super();
6796
+ this.shadow = this.attachShadow({ mode: "open" });
6797
+ this.shadow.innerHTML = wavelength_switch_template_default;
6798
+ }
6799
+ get checked() {
6800
+ return this.input.checked;
6801
+ }
6802
+ set checked(value) {
6803
+ this.input.checked = !!value;
6804
+ this.toggleAttribute("checked", this.input.checked);
6805
+ }
6806
+ connectedCallback() {
6807
+ this.input = this.shadow.querySelector("input");
6808
+ this.labelElement = this.shadow.querySelector(".label");
6809
+ this.flexContainer = this.shadow.querySelector(".flex-container");
6810
+ this._updateLabel();
6811
+ this._updateChecked();
6812
+ this._updateDisabled();
6813
+ this._updateColor();
6814
+ this._updateLabelFont();
6815
+ this.input.addEventListener("change", (e) => {
6816
+ this.dispatchEvent(
6817
+ new CustomEvent("wavelength-switch-change", {
6818
+ detail: {
6819
+ checked: e.target.checked,
6820
+ value: this.getAttribute("value")
6821
+ },
6822
+ bubbles: true,
6823
+ composed: true
6824
+ })
6825
+ );
6826
+ });
6827
+ }
6828
+ attributeChangedCallback(name, oldValue, newValue) {
6829
+ if (oldValue === newValue) return;
6830
+ if (!this.input) return;
6831
+ switch (name) {
6832
+ case "checked":
6833
+ this._updateChecked();
6834
+ break;
6835
+ case "label":
6836
+ this._updateLabel();
6837
+ break;
6838
+ case "disabled":
6839
+ this._updateDisabled();
6840
+ break;
6841
+ case "label-placement":
6842
+ this._updateLabel();
6843
+ break;
6844
+ case "color":
6845
+ this._updateColor();
6846
+ break;
6847
+ case "label-font":
6848
+ this._updateLabelFont();
6849
+ break;
6850
+ case "value":
6851
+ this._updateValue();
6852
+ break;
6853
+ }
6854
+ }
6855
+ disconnectedCallback() {
6856
+ this.input.removeEventListener("change", this._updateChecked);
6857
+ }
6858
+ _updateChecked() {
6859
+ this.input.checked = this.hasAttribute("checked") && this.getAttribute("checked") !== "false";
6860
+ }
6861
+ _updateLabel() {
6862
+ if (this.labelElement) {
6863
+ this.labelElement.textContent = this.getAttribute("label") || "";
6864
+ this.labelElement.style.display = this.hasAttribute("label") ? "block" : "none";
6865
+ }
6866
+ this._updateLabelPlacement();
6867
+ }
6868
+ _updateDisabled() {
6869
+ if (this.input) {
6870
+ this.input.disabled = this.hasAttribute("disabled") && this.getAttribute("disabled") !== "false";
6871
+ }
6872
+ }
6873
+ _updateColor() {
6874
+ if (this.hasAttribute("color")) {
6875
+ this.style.setProperty("--switch-color", this.getAttribute("color") || "");
6876
+ } else {
6877
+ this.style.removeProperty("--switch-color");
6878
+ }
6879
+ }
6880
+ _updateLabelFont() {
6881
+ if (this.hasAttribute("label-font")) {
6882
+ this.style.setProperty("--label-font", this.getAttribute("label-font") || "");
6883
+ } else {
6884
+ this.style.removeProperty("--label-font");
6885
+ }
6886
+ }
6887
+ _updateValue() {
6888
+ if (this.hasAttribute("value")) {
6889
+ this.input.value = this.getAttribute("value") || "";
6890
+ }
6891
+ }
6892
+ _updateLabelPlacement() {
6893
+ const placement = _nullishCoalesce(this.getAttribute("label-placement"), () => ( "left"));
6894
+ const directions = {
6895
+ left: "row",
6896
+ right: "row-reverse",
6897
+ top: "column",
6898
+ bottom: "column-reverse"
6899
+ };
6900
+ this.flexContainer.style.flexDirection = _nullishCoalesce(directions[placement], () => ( "row"));
6901
+ }
6902
+ };
6903
+ if (!customElements.get("wavelength-switch")) {
6904
+ customElements.define("wavelength-switch", WavelengthSwitch);
6905
+ }
6906
+
6907
+
6908
+
6509
6909
 
6510
6910
 
6511
6911
 
@@ -6529,7 +6929,7 @@ if (!customElements.get("wavelength-pagination")) {
6529
6929
 
6530
6930
 
6531
6931
 
6532
- exports.BaseWavelengthInput = BaseWavelengthInput; exports.BaseWavelengthMultiSelectAutocomplete = BaseWavelengthMultiSelectAutocomplete; exports.ChildDataTable = ChildDataTable; exports.SampleComponent = SampleComponent; exports.WavelengthBanner = WavelengthBanner; exports.WavelengthButton = WavelengthButton; exports.WavelengthCheckbox = WavelengthCheckbox; exports.WavelengthDatePicker = WavelengthDatePicker; exports.WavelengthDropdown = WavelengthDropdown; exports.WavelengthFileDropZone = WavelengthFileDropZone; exports.WavelengthForm = WavelengthForm; exports.WavelengthInput = WavelengthInput; exports.WavelengthManyPlanes = WavelengthManyPlanes; exports.WavelengthMenu = WavelengthMenu; exports.WavelengthMultiSelectAutocomplete = WavelengthMultiSelectAutocomplete; exports.WavelengthNavBar = WavelengthNavBar; exports.WavelengthNotificationPanel = WavelengthNotificationPanel; exports.WavelengthPagination = WavelengthPagination; exports.WavelengthPlaneTrail = WavelengthPlaneTrail; exports.WavelengthProgressBar = WavelengthProgressBar; exports.WavelengthSnackbar = WavelengthSnackbar; exports.WavelengthTitleBar = WavelengthTitleBar; exports.WavelengthToolTip = WavelengthToolTip;
6932
+ exports.BaseWavelengthInput = BaseWavelengthInput; exports.BaseWavelengthMultiSelectAutocomplete = BaseWavelengthMultiSelectAutocomplete; exports.ChildDataTable = ChildDataTable; exports.SampleComponent = SampleComponent; exports.WavelengthBanner = WavelengthBanner; exports.WavelengthButton = WavelengthButton; exports.WavelengthCheckbox = WavelengthCheckbox; exports.WavelengthDatePicker = WavelengthDatePicker; exports.WavelengthDropdown = WavelengthDropdown; exports.WavelengthFileDropZone = WavelengthFileDropZone; exports.WavelengthForm = WavelengthForm; exports.WavelengthInput = WavelengthInput; exports.WavelengthManyPlanes = WavelengthManyPlanes; exports.WavelengthMenu = WavelengthMenu; exports.WavelengthMultiSelectAutocomplete = WavelengthMultiSelectAutocomplete; exports.WavelengthNavBar = WavelengthNavBar; exports.WavelengthNotificationPanel = WavelengthNotificationPanel; exports.WavelengthPagination = WavelengthPagination; exports.WavelengthPlaneTrail = WavelengthPlaneTrail; exports.WavelengthProgressBar = WavelengthProgressBar; exports.WavelengthSearch = WavelengthSearch; exports.WavelengthSnackbar = WavelengthSnackbar; exports.WavelengthSwitch = WavelengthSwitch; exports.WavelengthTitleBar = WavelengthTitleBar; exports.WavelengthToolTip = WavelengthToolTip;
6533
6933
  /*! Bundled license information:
6534
6934
 
6535
6935
  react/cjs/react.production.min.js:
@@ -2308,4 +2308,57 @@ declare class WavelengthPagination extends HTMLElement {
2308
2308
  private _syncStyles;
2309
2309
  }
2310
2310
 
2311
- export { BaseWavelengthInput, BaseWavelengthMultiSelectAutocomplete, type CheckboxElements, ChildDataTable, SampleComponent, WavelengthBanner, WavelengthButton, WavelengthCheckbox, WavelengthDatePicker, WavelengthDropdown, WavelengthFileDropZone, WavelengthForm, WavelengthInput, WavelengthManyPlanes, WavelengthMenu, WavelengthMultiSelectAutocomplete, WavelengthNavBar, WavelengthNotificationPanel, WavelengthPagination, WavelengthPlaneTrail, WavelengthProgressBar, WavelengthSnackbar, WavelengthTitleBar, WavelengthToolTip };
2311
+ declare class WavelengthSearch extends HTMLElement {
2312
+ static get observedAttributes(): string[];
2313
+ private shadow;
2314
+ private input;
2315
+ private dropdown;
2316
+ private inputContainer;
2317
+ private animatedPlaceholder;
2318
+ private options;
2319
+ private highlightedIndex;
2320
+ private styleAttributes;
2321
+ constructor();
2322
+ connectedCallback(): void;
2323
+ disconnectedCallback(): void;
2324
+ attributeChangedCallback(name: string, oldValue: string | null, newValue: string | null): void;
2325
+ private handleSearch;
2326
+ private renderDropdown;
2327
+ private selectOption;
2328
+ get value(): string;
2329
+ set value(val: string);
2330
+ get optionsList(): string[] | undefined;
2331
+ set optionsList(val: string[] | undefined);
2332
+ private _syncStyles;
2333
+ private handleFocusIn;
2334
+ private handleFocusOut;
2335
+ private searchTimeout;
2336
+ private handleInputChange;
2337
+ private handleKeydown;
2338
+ private updateHighlight;
2339
+ private handleSearchIconClick;
2340
+ private handleDocumentClick;
2341
+ }
2342
+
2343
+ declare class WavelengthSwitch extends HTMLElement {
2344
+ static get observedAttributes(): string[];
2345
+ private shadow;
2346
+ private input;
2347
+ private labelElement;
2348
+ private flexContainer;
2349
+ constructor();
2350
+ get checked(): boolean;
2351
+ set checked(value: boolean);
2352
+ connectedCallback(): void;
2353
+ attributeChangedCallback(name: string, oldValue: string | null, newValue: string | null): void;
2354
+ disconnectedCallback(): void;
2355
+ private _updateChecked;
2356
+ private _updateLabel;
2357
+ private _updateDisabled;
2358
+ private _updateColor;
2359
+ private _updateLabelFont;
2360
+ private _updateValue;
2361
+ private _updateLabelPlacement;
2362
+ }
2363
+
2364
+ export { BaseWavelengthInput, BaseWavelengthMultiSelectAutocomplete, type CheckboxElements, ChildDataTable, SampleComponent, WavelengthBanner, WavelengthButton, WavelengthCheckbox, WavelengthDatePicker, WavelengthDropdown, WavelengthFileDropZone, WavelengthForm, WavelengthInput, WavelengthManyPlanes, WavelengthMenu, WavelengthMultiSelectAutocomplete, WavelengthNavBar, WavelengthNotificationPanel, WavelengthPagination, WavelengthPlaneTrail, WavelengthProgressBar, WavelengthSearch, WavelengthSnackbar, WavelengthSwitch, WavelengthTitleBar, WavelengthToolTip };
@@ -2308,4 +2308,57 @@ declare class WavelengthPagination extends HTMLElement {
2308
2308
  private _syncStyles;
2309
2309
  }
2310
2310
 
2311
- export { BaseWavelengthInput, BaseWavelengthMultiSelectAutocomplete, type CheckboxElements, ChildDataTable, SampleComponent, WavelengthBanner, WavelengthButton, WavelengthCheckbox, WavelengthDatePicker, WavelengthDropdown, WavelengthFileDropZone, WavelengthForm, WavelengthInput, WavelengthManyPlanes, WavelengthMenu, WavelengthMultiSelectAutocomplete, WavelengthNavBar, WavelengthNotificationPanel, WavelengthPagination, WavelengthPlaneTrail, WavelengthProgressBar, WavelengthSnackbar, WavelengthTitleBar, WavelengthToolTip };
2311
+ declare class WavelengthSearch extends HTMLElement {
2312
+ static get observedAttributes(): string[];
2313
+ private shadow;
2314
+ private input;
2315
+ private dropdown;
2316
+ private inputContainer;
2317
+ private animatedPlaceholder;
2318
+ private options;
2319
+ private highlightedIndex;
2320
+ private styleAttributes;
2321
+ constructor();
2322
+ connectedCallback(): void;
2323
+ disconnectedCallback(): void;
2324
+ attributeChangedCallback(name: string, oldValue: string | null, newValue: string | null): void;
2325
+ private handleSearch;
2326
+ private renderDropdown;
2327
+ private selectOption;
2328
+ get value(): string;
2329
+ set value(val: string);
2330
+ get optionsList(): string[] | undefined;
2331
+ set optionsList(val: string[] | undefined);
2332
+ private _syncStyles;
2333
+ private handleFocusIn;
2334
+ private handleFocusOut;
2335
+ private searchTimeout;
2336
+ private handleInputChange;
2337
+ private handleKeydown;
2338
+ private updateHighlight;
2339
+ private handleSearchIconClick;
2340
+ private handleDocumentClick;
2341
+ }
2342
+
2343
+ declare class WavelengthSwitch extends HTMLElement {
2344
+ static get observedAttributes(): string[];
2345
+ private shadow;
2346
+ private input;
2347
+ private labelElement;
2348
+ private flexContainer;
2349
+ constructor();
2350
+ get checked(): boolean;
2351
+ set checked(value: boolean);
2352
+ connectedCallback(): void;
2353
+ attributeChangedCallback(name: string, oldValue: string | null, newValue: string | null): void;
2354
+ disconnectedCallback(): void;
2355
+ private _updateChecked;
2356
+ private _updateLabel;
2357
+ private _updateDisabled;
2358
+ private _updateColor;
2359
+ private _updateLabelFont;
2360
+ private _updateValue;
2361
+ private _updateLabelPlacement;
2362
+ }
2363
+
2364
+ export { BaseWavelengthInput, BaseWavelengthMultiSelectAutocomplete, type CheckboxElements, ChildDataTable, SampleComponent, WavelengthBanner, WavelengthButton, WavelengthCheckbox, WavelengthDatePicker, WavelengthDropdown, WavelengthFileDropZone, WavelengthForm, WavelengthInput, WavelengthManyPlanes, WavelengthMenu, WavelengthMultiSelectAutocomplete, WavelengthNavBar, WavelengthNotificationPanel, WavelengthPagination, WavelengthPlaneTrail, WavelengthProgressBar, WavelengthSearch, WavelengthSnackbar, WavelengthSwitch, WavelengthTitleBar, WavelengthToolTip };
package/dist/esm/index.js CHANGED
@@ -3183,7 +3183,7 @@ if (!customElements.get("wavelength-progress-bar")) {
3183
3183
  }
3184
3184
 
3185
3185
  // src/web-components/wavelength-input.template.html
3186
- var wavelength_input_template_default = '<style>\n :host {\n display: block;\n width: 100%;\n font-family: sans-serif;\n --wavelength-container-background: #f8f8f8;\n --wavelength-label-background: #ffffff;\n }\n\n .field-wrapper {\n position: relative;\n }\n\n .floating-label {\n position: absolute;\n top: -0.325rem;\n left: 12px;\n font-size: 0.75rem;\n line-height: 1;\n color: var(--wavelength-label-color, #666666);\n padding: 0 4px;\n z-index: 1;\n pointer-events: none;\n user-select: none;\n }\n\n .floating-label::before,\n .floating-label::after {\n content: "";\n position: absolute;\n left: 0;\n width: 100%;\n z-index: -1;\n }\n\n .floating-label::before {\n top: 0;\n height: 50%;\n background: var(--wavelength-container-background, white);\n }\n\n .floating-label::after {\n bottom: 0;\n height: 50%;\n background: var(--wavelength-label-background, #ffffff);\n }\n\n :host([disabled]) .floating-label::before {\n opacity: 0;\n }\n\n input {\n font-size: 16px;\n padding: 16.5px 14px;\n border: 1px solid var(--wavelength-border-color, #cccccc);\n border-radius: 8px;\n width: 100%;\n box-sizing: border-box;\n background-color: var(--wavelength-background, #ffffff);\n transition: border-color 0.2s ease;\n overflow: auto;\n font-family: inherit;\n }\n\n input:focus {\n outline: none;\n }\n\n input:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n }\n\n :host([disabled]) .floating-label::after {\n opacity: 0;\n cursor: not-allowed;\n }\n\n input::placeholder {\n color: #999999;\n }\n\n .helper-message {\n margin-top: 4px;\n font-size: 0.75rem;\n max-width: 100%;\n word-wrap: break-word;\n white-space: normal;\n overflow-wrap: break-word;\n color: #000000;\n padding-left: 14px;\n margin-left: 2px;\n user-select: none;\n }\n\n .required-marker {\n color: red;\n font-weight: lighter;\n font-size: 0.75rem;\n }\n\n .clear-button {\n position: absolute;\n right: 12px;\n top: 50%;\n transform: translateY(-50%);\n font-size: 1.25 rem;\n color: #666666;\n cursor: pointer;\n opacity: 0.5;\n user-select: none;\n transition: opacity 0.2s ease;\n z-index: 2;\n display: none;\n line-height: 1;\n padding: 0 4px;\n }\n\n .clear-button:hover {\n opacity: 1;\n }\n\n :host([disabled]) .clear-button {\n display: none;\n }\n</style>\n<div class="field-wrapper">\n <label class="floating-label" id="floating-label"></label>\n <div class="input-wrapper"></div>\n <div class="clear-button" id="clear-button" title="Clear input">\u2715</div>\n</div>\n<div class="helper-message" id="helper"></div>\n';
3186
+ var wavelength_input_template_default = '<style>\n :host {\n display: block;\n width: 100%;\n font-family: sans-serif;\n --wavelength-container-background: #f8f8f8;\n --wavelength-label-background: #ffffff;\n }\n\n .field-wrapper {\n position: relative;\n width: 100%;\n height: 100%;\n }\n\n .input-wrapper {\n width: 100%;\n height: 100%;\n }\n\n .floating-label {\n position: absolute;\n top: -0.325rem;\n left: 12px;\n font-size: 0.75rem;\n line-height: 1;\n color: var(--wavelength-label-color, #666666);\n padding: 0 4px;\n z-index: 1;\n pointer-events: none;\n user-select: none;\n }\n\n .floating-label::before,\n .floating-label::after {\n content: "";\n position: absolute;\n left: 0;\n width: 100%;\n z-index: -1;\n }\n\n .floating-label::before {\n top: 0;\n height: 50%;\n background: var(--wavelength-container-background, white);\n }\n\n .floating-label::after {\n bottom: 0;\n height: 50%;\n background: var(--wavelength-label-background, #ffffff);\n }\n\n :host([disabled]) .floating-label::before {\n opacity: 0;\n }\n\n input {\n font-size: 16px;\n padding: 16.5px 14px;\n border: 1px solid var(--wavelength-border-color, #cccccc);\n border-radius: 8px;\n width: 100%;\n box-sizing: border-box;\n background-color: var(--wavelength-background, #ffffff);\n transition: border-color 0.2s ease;\n overflow: auto;\n font-family: inherit;\n }\n\n input:focus {\n outline: none;\n }\n\n input:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n }\n\n :host([disabled]) .floating-label::after {\n opacity: 0;\n cursor: not-allowed;\n }\n\n input::placeholder {\n color: #999999;\n }\n\n .helper-message {\n margin-top: 4px;\n font-size: 0.75rem;\n max-width: 100%;\n word-wrap: break-word;\n white-space: normal;\n overflow-wrap: break-word;\n color: #000000;\n padding-left: 14px;\n margin-left: 2px;\n user-select: none;\n }\n\n .required-marker {\n color: red;\n font-weight: lighter;\n font-size: 0.75rem;\n }\n\n .clear-button {\n position: absolute;\n right: 12px;\n top: 50%;\n transform: translateY(-50%);\n font-size: 1.25 rem;\n color: #666666;\n cursor: pointer;\n opacity: 0.5;\n user-select: none;\n transition: opacity 0.2s ease;\n z-index: 2;\n display: none;\n line-height: 1;\n padding: 0 4px;\n }\n\n .clear-button:hover {\n opacity: 1;\n }\n\n :host([disabled]) .clear-button {\n display: none;\n }\n</style>\n<div class="field-wrapper">\n <label class="floating-label" id="floating-label"></label>\n <div class="input-wrapper"></div>\n <div class="clear-button" id="clear-button" title="Clear input">\u2715</div>\n</div>\n<div class="helper-message" id="helper"></div>\n';
3187
3187
 
3188
3188
  // src/web-components/wavelength-input.ts
3189
3189
  function getAncestor(el) {
@@ -3302,7 +3302,9 @@ var BaseWavelengthInput = class extends HTMLElement {
3302
3302
  "max-length",
3303
3303
  "required",
3304
3304
  "force-error",
3305
- "label"
3305
+ "label",
3306
+ "font-size",
3307
+ "font-family"
3306
3308
  ];
3307
3309
  }
3308
3310
  connectedCallback() {
@@ -3430,6 +3432,7 @@ var BaseWavelengthInput = class extends HTMLElement {
3430
3432
  }
3431
3433
  this.helperEl.innerHTML = htmlMessage;
3432
3434
  this.helperEl.classList.add("error");
3435
+ this.helperEl.style.display = "block";
3433
3436
  this.inputEl.style.borderColor = "red";
3434
3437
  this.helperEl.style.color = "red";
3435
3438
  this.inputEl.setAttribute("aria-invalid", "true");
@@ -3442,6 +3445,7 @@ var BaseWavelengthInput = class extends HTMLElement {
3442
3445
  this.helperEl.textContent = helperText;
3443
3446
  this.helperEl.classList.remove("error");
3444
3447
  this.helperEl.style.color = helperColor;
3448
+ this.helperEl.style.display = helperText ? "block" : "none";
3445
3449
  this.inputEl.style.borderColor = borderColor;
3446
3450
  this.inputEl.setAttribute("aria-invalid", "false");
3447
3451
  this.removeAttribute("data-error");
@@ -3519,6 +3523,12 @@ var BaseWavelengthInput = class extends HTMLElement {
3519
3523
  this.inputEl.style.padding = rawPadding;
3520
3524
  this.inputEl.style.height = this.getAttribute("height") || "";
3521
3525
  this.inputEl.style.borderRadius = this.getAttribute("border-radius") || "8px";
3526
+ if (this.hasAttribute("font-size")) {
3527
+ this.inputEl.style.fontSize = this.getAttribute("font-size");
3528
+ }
3529
+ if (this.hasAttribute("font-family")) {
3530
+ this.inputEl.style.fontFamily = this.getAttribute("font-family");
3531
+ }
3522
3532
  this.helperEl.style.width = helperWidth;
3523
3533
  this.helperEl.style.paddingLeft = `${leftPaddingPx}px`;
3524
3534
  }
@@ -3564,6 +3574,7 @@ var BaseWavelengthInput = class extends HTMLElement {
3564
3574
  if (!hasError) {
3565
3575
  this.helperEl.textContent = helper;
3566
3576
  this.helperEl.style.color = helperColor;
3577
+ this.helperEl.style.display = helper ? "block" : "none";
3567
3578
  }
3568
3579
  }
3569
3580
  _applyAccessibility() {
@@ -3588,7 +3599,10 @@ var BaseWavelengthInput = class extends HTMLElement {
3588
3599
  this.inputEl.name = newValue || "";
3589
3600
  break;
3590
3601
  case "label":
3602
+ case "font-size":
3603
+ case "font-family":
3591
3604
  this._applyContent();
3605
+ this._applyLayout();
3592
3606
  break;
3593
3607
  case "helper-message":
3594
3608
  this._applyValidationHint();
@@ -6505,6 +6519,390 @@ var WavelengthPagination = class extends HTMLElement {
6505
6519
  if (!customElements.get("wavelength-pagination")) {
6506
6520
  customElements.define("wavelength-pagination", WavelengthPagination);
6507
6521
  }
6522
+
6523
+ // src/web-components/wavelength-search.template.html
6524
+ var wavelength_search_template_default = '<style>\n :host {\n display: block;\n --width: 200px;\n --height: 32px;\n --border-width: 1px;\n --mode: automatic;\n --font-size: 14px;\n --border-radius: 50px;\n --border-color: #000;\n --background-color: #fff;\n --hover-color: #007bff;\n --placeholder-color: #999;\n --placeholder-font: "Montserrat", system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;\n --input-color: #000;\n --input-font: "Montserrat", system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;\n }\n\n :host([height="small"]) {\n --height: 32px;\n }\n\n :host([height="medium"]) {\n --height: 48px;\n }\n\n :host([height="large"]) {\n --height: 64px;\n }\n\n .flex-container {\n display: block;\n flex-direction: column;\n width: fit-content;\n height: fit-content;\n position: relative;\n }\n\n .searchbar-wrapper {\n display: flex;\n flex-direction: row;\n align-items: center;\n border-radius: var(--border-radius);\n border: var(--border-width) solid var(--border-color);\n background-color: var(--background-color);\n width: var(--width);\n height: var(--height);\n margin: 1px;\n }\n\n .searchbar-wrapper:hover {\n border-color: var(--hover-color);\n }\n\n .searchbar-wrapper:focus-within {\n border-width: calc(var(--border-width) + 1px);\n border-color: var(--hover-color);\n margin: 0px;\n }\n\n :host([icon-pos="end"]) .searchbar-wrapper {\n flex-direction: row-reverse;\n }\n\n .search-button {\n width: 40px;\n height: 40px;\n border-radius: 50%;\n border: none;\n background-color: transparent;\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n margin: 0 10px;\n padding: 0;\n transition: background-color 0.2s;\n }\n\n .search-button:hover {\n background-color: rgba(0, 0, 0, 0.05);\n }\n\n .search-icon {\n width: var(--font-size);\n height: var(--font-size);\n fill: currentColor;\n }\n\n .input-container {\n position: relative;\n flex-grow: 1;\n display: flex;\n align-items: center;\n height: 100%;\n }\n\n .animated-placeholder {\n position: absolute;\n left: 14px;\n top: 50%;\n transform: translateY(-50%);\n color: var(--placeholder-color);\n font-family: var(--placeholder-font);\n font-size: var(--font-size);\n pointer-events: none;\n transition: all 0.2s ease;\n background-color: transparent;\n padding: 0 4px;\n border-radius: 4px;\n z-index: 5;\n }\n\n .input-container.focused .animated-placeholder,\n .input-container.has-value .animated-placeholder {\n top: -12px;\n font-size: calc(var(--font-size) * 0.75);\n color: var(--placeholder-color);\n background-color: transparent;\n }\n\n .dropdown {\n position: absolute;\n font-size: var(--font-size);\n font-family: var(--input-font);\n top: calc(100% + 4px);\n left: 0;\n max-height: 200px;\n width: 100%;\n background: white;\n border: 1px solid transparent;\n border-radius: 4px;\n display: none;\n z-index: 10;\n overflow-y: auto;\n overflow-x: hidden;\n box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);\n }\n\n .dropdown-item {\n padding: 8px 14px;\n cursor: pointer;\n border-left: 3px solid transparent;\n transition:\n background-color 0.1s,\n border-color 0.1s;\n }\n .dropdown-item:hover {\n background-color: rgba(0, 0, 0, 0.05);\n }\n .dropdown-item.highlighted {\n background-color: rgba(0, 0, 0, 0.08);\n border-left-color: var(--hover-color);\n }\n\n wavelength-input {\n flex-grow: 1;\n width: 100%;\n height: 100%;\n }\n</style>\n\n<div class="flex-container">\n <div class="searchbar-wrapper">\n <button class="search-button search-icon">\n <svg\n version="1.1"\n id="_x32_"\n xmlns="http://www.w3.org/2000/svg"\n xmlns:xlink="http://www.w3.org/1999/xlink"\n viewBox="0 0 512 512"\n xml:space="preserve"\n fill="#000000"\n style="width: 100%; height: 100%"\n >\n <g id="SVGRepo_bgCarrier" stroke-width="0"></g>\n <g id="SVGRepo_tracerCarrier" stroke-linecap="round" stroke-linejoin="round"></g>\n <g id="SVGRepo_iconCarrier">\n <style type="text/css">\n .st0 {\n fill: #000000;\n }\n </style>\n <g>\n <path\n class="st0"\n d="M312.069,53.445c-71.26-71.26-187.194-71.26-258.454,0c-71.261,71.26-71.261,187.206,0,258.466 c71.26,71.26,187.194,71.26,258.454,0S383.329,124.705,312.069,53.445z M286.694,286.536 c-57.351,57.34-150.353,57.34-207.704-0.011s-57.351-150.353,0-207.693c57.351-57.351,150.342-57.351,207.693,0 S344.045,229.174,286.694,286.536z"\n ></path>\n <path\n class="st0"\n d="M101.911,112.531c-29.357,37.725-31.801,89.631-7.321,129.702c1.877,3.087,5.902,4.048,8.978,2.182 c3.065-1.888,4.037-5.903,2.16-8.978c-21.666-35.456-19.506-81.538,6.469-114.876c2.226-2.837,1.713-6.938-1.135-9.154 C108.227,109.193,104.125,109.695,101.911,112.531z"\n ></path>\n <path\n class="st0"\n d="M498.544,447.722l-132.637-129.2c-7.255-7.07-18.84-6.982-26.008,0.174l-21.033,21.033 c-7.156,7.156-7.234,18.742-0.153,25.986l129.19,132.636c14.346,17.324,35.542,18.35,51.917,1.964 C516.216,483.951,515.857,462.068,498.544,447.722z"\n ></path>\n </g>\n </g>\n </svg>\n </button>\n <div class="input-container" id="inputContainer">\n <label class="animated-placeholder" id="animatedPlaceholder">Search...</label>\n <wavelength-input\n focus-color="transparent"\n background-color="transparent"\n border-color="transparent"\n label=""\n id="searchInput"\n placeholder=""\n validation-type="onBlur"\n min-length="0"\n clearable\n height="100%"\n padding="0 10px"\n ></wavelength-input>\n <div id="dropdown" class="dropdown"></div>\n </div>\n </div>\n</div>\n';
6525
+
6526
+ // src/web-components/wavelength-search.ts
6527
+ var WavelengthSearch = class extends HTMLElement {
6528
+ constructor() {
6529
+ super();
6530
+ this.options = [];
6531
+ this.highlightedIndex = -1;
6532
+ this.styleAttributes = [
6533
+ "width",
6534
+ "height",
6535
+ "font-size",
6536
+ "border-width",
6537
+ "border-radius",
6538
+ "border-color",
6539
+ "background-color",
6540
+ "hover-color",
6541
+ "placeholder-color",
6542
+ "placeholder-font",
6543
+ "input-color",
6544
+ "input-font"
6545
+ ];
6546
+ this.handleFocusIn = () => {
6547
+ this.inputContainer.classList.add("focused");
6548
+ };
6549
+ this.handleFocusOut = () => {
6550
+ this.inputContainer.classList.remove("focused");
6551
+ };
6552
+ this.handleInputChange = (e) => {
6553
+ const mode = this.getAttribute("mode") || "automatic";
6554
+ const value = e.detail.value;
6555
+ if (value) {
6556
+ this.inputContainer.classList.add("has-value");
6557
+ } else {
6558
+ this.inputContainer.classList.remove("has-value");
6559
+ }
6560
+ if (mode === "automatic") {
6561
+ if (this.searchTimeout) {
6562
+ clearTimeout(this.searchTimeout);
6563
+ }
6564
+ this.searchTimeout = setTimeout(() => {
6565
+ this.handleSearch(value);
6566
+ }, 300);
6567
+ }
6568
+ };
6569
+ this.handleKeydown = (e) => {
6570
+ const isDropdownVisible = this.dropdown.style.display === "block";
6571
+ const items = this.dropdown.querySelectorAll(".dropdown-item");
6572
+ if (e.key === "ArrowDown") {
6573
+ e.preventDefault();
6574
+ if (!isDropdownVisible) {
6575
+ this.handleSearch(this.input.value);
6576
+ } else if (items.length > 0) {
6577
+ this.highlightedIndex = (this.highlightedIndex + 1) % items.length;
6578
+ this.updateHighlight(items);
6579
+ }
6580
+ } else if (e.key === "ArrowUp") {
6581
+ e.preventDefault();
6582
+ if (isDropdownVisible && items.length > 0) {
6583
+ this.highlightedIndex = this.highlightedIndex <= 0 ? items.length - 1 : this.highlightedIndex - 1;
6584
+ this.updateHighlight(items);
6585
+ }
6586
+ } else if (e.key === "Escape" || e.key === "Tab") {
6587
+ this.dropdown.style.display = "none";
6588
+ this.highlightedIndex = -1;
6589
+ if (e.key === "Escape") {
6590
+ this.input.focus();
6591
+ }
6592
+ } else if (e.key === "Enter") {
6593
+ if (isDropdownVisible && this.highlightedIndex >= 0 && this.highlightedIndex < items.length) {
6594
+ e.preventDefault();
6595
+ this.selectOption(items[this.highlightedIndex].textContent || "");
6596
+ } else {
6597
+ const value = this.input.value;
6598
+ this.dispatchEvent(new CustomEvent("wavelength-search-submit", { detail: { value }, bubbles: true, composed: true }));
6599
+ this.handleSearch(value);
6600
+ }
6601
+ }
6602
+ };
6603
+ this.handleSearchIconClick = () => {
6604
+ const value = this.input.value;
6605
+ this.dispatchEvent(new CustomEvent("wavelength-search-submit", { detail: { value }, bubbles: true, composed: true }));
6606
+ this.handleSearch(value);
6607
+ };
6608
+ this.handleDocumentClick = (e) => {
6609
+ if (!this.contains(e.target)) {
6610
+ this.dropdown.style.display = "none";
6611
+ this.highlightedIndex = -1;
6612
+ }
6613
+ };
6614
+ this.shadow = this.attachShadow({ mode: "open" });
6615
+ this.shadow.innerHTML = wavelength_search_template_default;
6616
+ }
6617
+ static get observedAttributes() {
6618
+ return [
6619
+ "width",
6620
+ "height",
6621
+ "mode",
6622
+ "font-size",
6623
+ "border-width",
6624
+ "border-radius",
6625
+ "border-color",
6626
+ "background-color",
6627
+ "hover-color",
6628
+ "options",
6629
+ "placeholder",
6630
+ "icon-pos",
6631
+ "placeholder-color",
6632
+ "placeholder-font",
6633
+ "input-color",
6634
+ "input-font"
6635
+ ];
6636
+ }
6637
+ connectedCallback() {
6638
+ this._syncStyles();
6639
+ this.input = this.shadow.getElementById("searchInput");
6640
+ this.dropdown = this.shadow.getElementById("dropdown");
6641
+ this.inputContainer = this.shadow.getElementById("inputContainer");
6642
+ this.animatedPlaceholder = this.shadow.getElementById("animatedPlaceholder");
6643
+ if (!this.hasAttribute("icon-pos")) {
6644
+ this.setAttribute("icon-pos", "end");
6645
+ }
6646
+ if (!this.hasAttribute("height")) {
6647
+ this.setAttribute("height", "small");
6648
+ }
6649
+ const placeholder = this.getAttribute("placeholder") || "Search...";
6650
+ this.animatedPlaceholder.textContent = placeholder;
6651
+ const searchIcon = this.shadow.querySelector(".search-icon");
6652
+ this.input.addEventListener("focusin", this.handleFocusIn);
6653
+ this.input.addEventListener("focusout", this.handleFocusOut);
6654
+ this.input.addEventListener("inputChange", this.handleInputChange);
6655
+ this.input.addEventListener("keydown", this.handleKeydown);
6656
+ if (searchIcon) {
6657
+ searchIcon.addEventListener("click", this.handleSearchIconClick);
6658
+ }
6659
+ document.addEventListener("click", this.handleDocumentClick);
6660
+ }
6661
+ disconnectedCallback() {
6662
+ this.input.removeEventListener("focusin", this.handleFocusIn);
6663
+ this.input.removeEventListener("focusout", this.handleFocusOut);
6664
+ this.input.removeEventListener("inputChange", this.handleInputChange);
6665
+ this.input.removeEventListener("keydown", this.handleKeydown);
6666
+ const searchIcon = this.shadow.querySelector(".search-icon");
6667
+ if (searchIcon) {
6668
+ searchIcon.removeEventListener("click", this.handleSearchIconClick);
6669
+ }
6670
+ document.removeEventListener("click", this.handleDocumentClick);
6671
+ }
6672
+ attributeChangedCallback(name, oldValue, newValue) {
6673
+ if (oldValue === newValue) return;
6674
+ if (this.styleAttributes.includes(name)) {
6675
+ if (name === "height") {
6676
+ if (["small", "medium", "large"].includes(newValue || "")) {
6677
+ this.style.removeProperty("--height");
6678
+ } else if (newValue !== null) {
6679
+ this.style.setProperty("--height", newValue);
6680
+ } else {
6681
+ this.style.removeProperty("--height");
6682
+ }
6683
+ } else {
6684
+ if (newValue !== null) {
6685
+ this.style.setProperty(`--${name}`, newValue);
6686
+ } else {
6687
+ this.style.removeProperty(`--${name}`);
6688
+ }
6689
+ }
6690
+ }
6691
+ if (name === "options" && newValue) {
6692
+ try {
6693
+ this.options = JSON.parse(newValue);
6694
+ } catch (e) {
6695
+ this.options = newValue.split(",").map((s) => s.trim());
6696
+ }
6697
+ } else if (name === "placeholder" && this.animatedPlaceholder) {
6698
+ this.animatedPlaceholder.textContent = newValue || "Search...";
6699
+ } else if (name === "font-size" && this.input) {
6700
+ this.input.setAttribute("font-size", newValue || "");
6701
+ } else if (name === "input-color" && this.input) {
6702
+ this.input.setAttribute("text-color", newValue || "");
6703
+ } else if (name === "input-font" && this.input) {
6704
+ this.input.setAttribute("font-family", newValue || "");
6705
+ }
6706
+ }
6707
+ handleSearch(query) {
6708
+ if (this.searchTimeout) {
6709
+ clearTimeout(this.searchTimeout);
6710
+ this.searchTimeout = null;
6711
+ }
6712
+ if (!query) {
6713
+ this.dropdown.style.display = "none";
6714
+ return;
6715
+ }
6716
+ const results = this.options.filter((option) => option.toLowerCase().includes(query.toLowerCase()));
6717
+ this.highlightedIndex = -1;
6718
+ this.renderDropdown(results);
6719
+ }
6720
+ renderDropdown(results) {
6721
+ if (results.length === 0) {
6722
+ this.dropdown.style.display = "none";
6723
+ return;
6724
+ }
6725
+ this.dropdown.innerHTML = results.map((r) => `<div class="dropdown-item">${r}</div>`).join("");
6726
+ this.dropdown.style.display = "block";
6727
+ const items = this.dropdown.querySelectorAll(".dropdown-item");
6728
+ items.forEach((item, index) => {
6729
+ item.addEventListener("click", () => {
6730
+ this.selectOption(item.textContent || "");
6731
+ });
6732
+ item.addEventListener("mouseenter", () => {
6733
+ this.highlightedIndex = index;
6734
+ this.updateHighlight(items);
6735
+ });
6736
+ });
6737
+ this.updateHighlight(items);
6738
+ }
6739
+ selectOption(value) {
6740
+ this.input.value = value;
6741
+ this.dropdown.style.display = "none";
6742
+ this.highlightedIndex = -1;
6743
+ this.dispatchEvent(new CustomEvent("wavelength-search-select", { detail: { value }, bubbles: true, composed: true }));
6744
+ }
6745
+ // ---- Getters and Setters API ---- //
6746
+ get value() {
6747
+ return this.input.value;
6748
+ }
6749
+ set value(val) {
6750
+ this.input.value = val;
6751
+ }
6752
+ get optionsList() {
6753
+ return this.options;
6754
+ }
6755
+ set optionsList(val) {
6756
+ if (val) {
6757
+ this.options = val;
6758
+ this.setAttribute("options", JSON.stringify(val));
6759
+ }
6760
+ }
6761
+ _syncStyles() {
6762
+ this.styleAttributes.forEach((attr) => {
6763
+ const value = this.getAttribute(attr);
6764
+ if (value) {
6765
+ if (attr === "height" && ["small", "medium", "large"].includes(value)) {
6766
+ } else {
6767
+ this.style.setProperty(`--${attr}`, value);
6768
+ }
6769
+ }
6770
+ });
6771
+ }
6772
+ updateHighlight(items) {
6773
+ items.forEach((item, index) => {
6774
+ const isHighlighted = index === this.highlightedIndex;
6775
+ item.classList.toggle("highlighted", isHighlighted);
6776
+ if (isHighlighted) {
6777
+ item.scrollIntoView({ block: "nearest" });
6778
+ }
6779
+ });
6780
+ }
6781
+ };
6782
+ if (!customElements.get("wavelength-search")) {
6783
+ customElements.define("wavelength-search", WavelengthSearch);
6784
+ }
6785
+
6786
+ // src/web-components/wavelength-switch.template.html
6787
+ var wavelength_switch_template_default = '<style>\n :host {\n display: block;\n --font-color: #333;\n --font-size: 20px;\n --font-family: "Montserrat", system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;\n --switch-color: #2196f3;\n --label-font: "Montserrat", system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;\n\n /* Variable-based sizing */\n --container-width: 60px;\n --container-height: 34px;\n --track-height: 22px;\n --knob-size: 28px;\n\n /* Internal Calculations */\n --track-top: calc((var(--container-height) - var(--track-height)) / 2);\n --knob-top: calc((var(--container-height) - var(--knob-size)) / 2);\n --knob-translate: calc(var(--container-width) - var(--knob-size));\n }\n\n :host([size="small"]) {\n --container-width: 40px;\n --container-height: 24px;\n --track-height: 14px;\n --knob-size: 20px;\n --font-size: 16px;\n }\n\n :host([size="large"]) {\n --container-width: 80px;\n --container-height: 48px;\n --track-height: 30px;\n --knob-size: 40px;\n --font-size: 24px;\n }\n\n /* Switch Base Styles */\n .switch {\n position: relative;\n display: inline-block;\n width: var(--container-width);\n height: var(--container-height);\n }\n\n .switch input {\n opacity: 0;\n width: 0;\n height: 0;\n }\n\n /* Slider (The Track) */\n .slider {\n position: absolute;\n cursor: pointer;\n top: var(--track-top);\n left: 0;\n right: 0;\n bottom: var(--track-top);\n background-color: #ccc;\n -webkit-transition: 0.4s;\n transition: 0.4s;\n border-radius: var(--track-height);\n }\n\n .slider:hover {\n cursor: pointer;\n }\n\n /* Handle (The Slider Portion) */\n .slider:before {\n position: absolute;\n content: "";\n height: var(--knob-size);\n width: var(--knob-size);\n left: 0;\n top: calc((var(--track-height) - var(--knob-size)) / 2);\n background-color: white;\n -webkit-transition: 0.4s;\n transition: 0.4s;\n border-radius: var(--knob-size);\n box-shadow: 0 2px 4px rgba(0, 0, 0, 0.3);\n z-index: 2;\n }\n\n .slider:hover:before {\n box-shadow:\n 0 2px 4px rgba(0, 0, 0, 0.3),\n 0 0 0 8px rgba(0, 0, 0, 0.1);\n }\n\n /* Input Checked State Styles */\n input:checked + .slider {\n background-color: var(--switch-color);\n }\n\n input:focus + .slider {\n box-shadow: 0 0 1px #2196f3;\n }\n\n input:checked + .slider:before {\n -webkit-transform: translateX(var(--knob-translate));\n -ms-transform: translateX(var(--knob-translate));\n transform: translateX(var(--knob-translate));\n }\n\n input:checked + .slider:hover:before {\n box-shadow:\n 0 2px 4px rgba(0, 0, 0, 0.3),\n 0 0 0 8px color-mix(in srgb, var(--switch-color), transparent 80%);\n }\n\n /* Disabled State Styles */\n input:disabled + .slider {\n background-color: #e0e0e0;\n cursor: not-allowed;\n }\n\n input:disabled + .slider:before {\n background-color: #f5f5f5;\n box-shadow: 0 1px 2px rgba(0, 0, 0, 0.15);\n }\n\n input:disabled + .slider:hover:before {\n box-shadow: 0 1px 2px rgba(0, 0, 0, 0.15);\n }\n\n input:disabled:checked + .slider {\n background-color: color-mix(in srgb, var(--switch-color), white 50%);\n opacity: 0.8;\n }\n\n /* Label Styles */\n .label {\n font-size: var(--font-size);\n font-weight: 500;\n color: var(--font-color);\n font-family: var(--label-font);\n }\n\n :host([disabled]) .label {\n color: #9e9e9e;\n }\n\n .flex-container {\n display: flex;\n flex-direction: row;\n align-items: center;\n gap: 8px;\n }\n</style>\n\n<div class="flex-container">\n <span id="label-span" class="label"></span>\n <label class="switch">\n <input type="checkbox" aria-labelledby="label" />\n <div class="slider"></div>\n </label>\n</div>\n';
6788
+
6789
+ // src/web-components/wavelength-switch.ts
6790
+ var WavelengthSwitch = class extends HTMLElement {
6791
+ static get observedAttributes() {
6792
+ return ["checked", "label", "label-placement", "size", "disabled", "color", "label-font", "value"];
6793
+ }
6794
+ constructor() {
6795
+ super();
6796
+ this.shadow = this.attachShadow({ mode: "open" });
6797
+ this.shadow.innerHTML = wavelength_switch_template_default;
6798
+ }
6799
+ get checked() {
6800
+ return this.input.checked;
6801
+ }
6802
+ set checked(value) {
6803
+ this.input.checked = !!value;
6804
+ this.toggleAttribute("checked", this.input.checked);
6805
+ }
6806
+ connectedCallback() {
6807
+ this.input = this.shadow.querySelector("input");
6808
+ this.labelElement = this.shadow.querySelector(".label");
6809
+ this.flexContainer = this.shadow.querySelector(".flex-container");
6810
+ this._updateLabel();
6811
+ this._updateChecked();
6812
+ this._updateDisabled();
6813
+ this._updateColor();
6814
+ this._updateLabelFont();
6815
+ this.input.addEventListener("change", (e) => {
6816
+ this.dispatchEvent(
6817
+ new CustomEvent("wavelength-switch-change", {
6818
+ detail: {
6819
+ checked: e.target.checked,
6820
+ value: this.getAttribute("value")
6821
+ },
6822
+ bubbles: true,
6823
+ composed: true
6824
+ })
6825
+ );
6826
+ });
6827
+ }
6828
+ attributeChangedCallback(name, oldValue, newValue) {
6829
+ if (oldValue === newValue) return;
6830
+ if (!this.input) return;
6831
+ switch (name) {
6832
+ case "checked":
6833
+ this._updateChecked();
6834
+ break;
6835
+ case "label":
6836
+ this._updateLabel();
6837
+ break;
6838
+ case "disabled":
6839
+ this._updateDisabled();
6840
+ break;
6841
+ case "label-placement":
6842
+ this._updateLabel();
6843
+ break;
6844
+ case "color":
6845
+ this._updateColor();
6846
+ break;
6847
+ case "label-font":
6848
+ this._updateLabelFont();
6849
+ break;
6850
+ case "value":
6851
+ this._updateValue();
6852
+ break;
6853
+ }
6854
+ }
6855
+ disconnectedCallback() {
6856
+ this.input.removeEventListener("change", this._updateChecked);
6857
+ }
6858
+ _updateChecked() {
6859
+ this.input.checked = this.hasAttribute("checked") && this.getAttribute("checked") !== "false";
6860
+ }
6861
+ _updateLabel() {
6862
+ if (this.labelElement) {
6863
+ this.labelElement.textContent = this.getAttribute("label") || "";
6864
+ this.labelElement.style.display = this.hasAttribute("label") ? "block" : "none";
6865
+ }
6866
+ this._updateLabelPlacement();
6867
+ }
6868
+ _updateDisabled() {
6869
+ if (this.input) {
6870
+ this.input.disabled = this.hasAttribute("disabled") && this.getAttribute("disabled") !== "false";
6871
+ }
6872
+ }
6873
+ _updateColor() {
6874
+ if (this.hasAttribute("color")) {
6875
+ this.style.setProperty("--switch-color", this.getAttribute("color") || "");
6876
+ } else {
6877
+ this.style.removeProperty("--switch-color");
6878
+ }
6879
+ }
6880
+ _updateLabelFont() {
6881
+ if (this.hasAttribute("label-font")) {
6882
+ this.style.setProperty("--label-font", this.getAttribute("label-font") || "");
6883
+ } else {
6884
+ this.style.removeProperty("--label-font");
6885
+ }
6886
+ }
6887
+ _updateValue() {
6888
+ if (this.hasAttribute("value")) {
6889
+ this.input.value = this.getAttribute("value") || "";
6890
+ }
6891
+ }
6892
+ _updateLabelPlacement() {
6893
+ const placement = this.getAttribute("label-placement") ?? "left";
6894
+ const directions = {
6895
+ left: "row",
6896
+ right: "row-reverse",
6897
+ top: "column",
6898
+ bottom: "column-reverse"
6899
+ };
6900
+ this.flexContainer.style.flexDirection = directions[placement] ?? "row";
6901
+ }
6902
+ };
6903
+ if (!customElements.get("wavelength-switch")) {
6904
+ customElements.define("wavelength-switch", WavelengthSwitch);
6905
+ }
6508
6906
  export {
6509
6907
  BaseWavelengthInput,
6510
6908
  BaseWavelengthMultiSelectAutocomplete,
@@ -6526,7 +6924,9 @@ export {
6526
6924
  WavelengthPagination,
6527
6925
  WavelengthPlaneTrail,
6528
6926
  WavelengthProgressBar,
6927
+ WavelengthSearch,
6529
6928
  WavelengthSnackbar,
6929
+ WavelengthSwitch,
6530
6930
  WavelengthTitleBar,
6531
6931
  WavelengthToolTip
6532
6932
  };
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "@wavelengthusaf/web-components",
3
3
  "author": "563 EWS - Wavelength",
4
4
  "license": "MIT",
5
- "version": "1.11.0",
5
+ "version": "1.14.0",
6
6
  "description": "Common component library used by Wavelength developers (NATIVE WEB COMPONENTS)",
7
7
  "main": "/dist/cjs/index.cjs",
8
8
  "module": "/dist/esm/index.js",