@kodaris/krubble-components 1.0.40 → 1.0.41

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.
@@ -150,6 +150,14 @@
150
150
  "name": "KRSelectOption",
151
151
  "module": "./form/index.js"
152
152
  }
153
+ },
154
+ {
155
+ "kind": "js",
156
+ "name": "KRAutoSuggest",
157
+ "declaration": {
158
+ "name": "KRAutoSuggest",
159
+ "module": "./form/index.js"
160
+ }
153
161
  }
154
162
  ]
155
163
  },
@@ -325,6 +333,11 @@
325
333
  "name": "KRTextareaField",
326
334
  "default": "class KRTextareaField extends i$2 { constructor() { super(); /** * The textarea label text */ this.label = ''; /** * The textarea name for form submission */ this.name = ''; /** * The current value */ this.value = ''; /** * Placeholder text */ this.placeholder = ''; /** * Whether the field is required */ this.required = false; /** * Whether the field is disabled */ this.disabled = false; /** * Whether the field is readonly */ this.readonly = false; /** * Number of visible text lines */ this.rows = 3; /** * Autocomplete attribute value */ this.autocomplete = ''; /** * Helper text shown below the textarea */ this.hint = ''; this._touched = false; this._dirty = false; this._handleInvalid = (e) => { e.preventDefault(); this._touched = true; }; this._internals = this.attachInternals(); } // Form-associated custom element callbacks get form() { return this._internals.form; } get validity() { return this._internals.validity; } get validationMessage() { return this._internals.validationMessage; } get willValidate() { return this._internals.willValidate; } checkValidity() { return this._internals.checkValidity(); } reportValidity() { return this._internals.reportValidity(); } formResetCallback() { this.value = ''; this._touched = false; this._dirty = false; this._internals.setFormValue(''); this._internals.setValidity({}); } formStateRestoreCallback(state) { this.value = state; } connectedCallback() { super.connectedCallback(); this.addEventListener('invalid', this._handleInvalid); } disconnectedCallback() { super.disconnectedCallback(); this.removeEventListener('invalid', this._handleInvalid); } firstUpdated() { this._updateValidity(); } updated(changedProperties) { if (changedProperties.has('required') || changedProperties.has('value')) { this._updateValidity(); } } _updateValidity() { if (this._textarea) { this._internals.setValidity(this._textarea.validity, this._textarea.validationMessage); } } _handleInput(e) { this.value = e.target.value; this._dirty = true; this._internals.setFormValue(this.value); this._internals.setValidity(this._textarea.validity, this._textarea.validationMessage); } _handleChange(e) { this.value = e.target.value; this._internals.setFormValue(this.value); } _handleBlur() { this._touched = true; this._internals.setValidity(this._textarea.validity, this._textarea.validationMessage); } render() { let validationMessage = ''; if (this._touched && this._textarea && !this._textarea.validity.valid) { validationMessage = this._textarea.validationMessage; } return b ` <div class=\"wrapper\"> ${this.label ? b ` <label for=\"textarea\"> ${this.label} ${this.required ? b `<span class=\"required\" aria-hidden=\"true\">*</span>` : A} </label> ` : A} <textarea id=\"textarea\" class=${e$1({ 'textarea--invalid': this._touched && this._textarea && !this._textarea.validity.valid })} name=${this.name} .value=${l(this.value)} placeholder=${this.placeholder} ?required=${this.required} ?disabled=${this.disabled} ?readonly=${this.readonly} rows=${this.rows} cols=${o(this.cols)} minlength=${o(this.minlength)} maxlength=${o(this.maxlength)} autocomplete=${o(this.autocomplete || undefined)} @input=${this._handleInput} @change=${this._handleChange} @blur=${this._handleBlur} ></textarea> ${validationMessage ? b `<div class=\"validation-message\">${validationMessage}</div>` : this.hint ? b `<div class=\"hint\">${this.hint}</div>` : A} </div> `; } // Public methods for programmatic control focus() { this._textarea?.focus(); } blur() { this._textarea?.blur(); } select() { this._textarea?.select(); } }",
327
335
  "description": "A textarea component that works with native browser forms.\n\nUses ElementInternals for form association, allowing the component\nto participate in form submission, validation, and reset.\n\nNative input and change events bubble up from the inner textarea element."
336
+ },
337
+ {
338
+ "kind": "variable",
339
+ "name": "KRAutoSuggest",
340
+ "default": "class KRAutoSuggest extends i$2 { constructor() { super(); this.label = ''; this.name = ''; this.value = ''; this.placeholder = ''; this.disabled = false; this.readonly = false; this.required = false; this.hint = ''; this.options = []; this.statusType = 'finished'; this.loadingText = 'Loading...'; this.errorText = 'Error loading options'; this.emptyText = 'No matches found'; this.filteringType = 'auto'; this.highlightMatches = true; this._isOpen = false; this._highlightedIndex = -1; this._touched = false; this._dirty = false; this._handleDocumentClick = this._onDocumentClick.bind(this); this._internals = this.attachInternals(); } connectedCallback() { super.connectedCallback(); document.addEventListener('click', this._handleDocumentClick); } disconnectedCallback() { super.disconnectedCallback(); document.removeEventListener('click', this._handleDocumentClick); } firstUpdated() { this._updateFormValue(); } get form() { return this._internals.form; } get validity() { return this._internals.validity; } get validationMessage() { return this._internals.validationMessage; } checkValidity() { return this._internals.checkValidity(); } reportValidity() { return this._internals.reportValidity(); } formResetCallback() { this.value = ''; this._touched = false; this._dirty = false; this._isOpen = false; this._highlightedIndex = -1; this._updateFormValue(); } formStateRestoreCallback(state) { this.value = state; } get _filteredOptions() { if (this.filteringType === 'manual' || !this.value) { return this.options; } const searchValue = this.value.toLowerCase(); const filtered = []; for (const option of this.options) { if (isGroup(option)) { const filteredGroupOptions = option.options.filter((opt) => { const label = (opt.label || opt.value).toLowerCase(); const tags = opt.filteringTags?.join(' ').toLowerCase() || ''; return label.includes(searchValue) || tags.includes(searchValue); }); if (filteredGroupOptions.length > 0) { filtered.push({ ...option, options: filteredGroupOptions }); } } else { const label = (option.label || option.value).toLowerCase(); const tags = option.filteringTags?.join(' ').toLowerCase() || ''; if (label.includes(searchValue) || tags.includes(searchValue)) { filtered.push(option); } } } return filtered; } get _flatOptions() { const flat = []; for (const option of this._filteredOptions) { if (isGroup(option)) { flat.push(...option.options); } else { flat.push(option); } } return flat; } _updateFormValue() { this._internals.setFormValue(this.value); // Validation if (this.required && !this.value) { this._internals.setValidity({ valueMissing: true }, 'This field is required', this._input); } else { this._internals.setValidity({}); } } _onInput(e) { const target = e.target; this.value = target.value; this._dirty = true; this._isOpen = true; this._highlightedIndex = -1; this._updateFormValue(); this.dispatchEvent(new CustomEvent('change', { detail: { value: this.value }, bubbles: true, composed: true, })); if (this.filteringType === 'manual') { this.dispatchEvent(new CustomEvent('load-items', { detail: { filteringText: this.value }, bubbles: true, composed: true, })); } } _onFocus() { this._isOpen = true; if (this.filteringType === 'manual') { this.dispatchEvent(new CustomEvent('load-items', { detail: { filteringText: this.value }, bubbles: true, composed: true, })); } } _onBlur() { this._touched = true; // Delay to allow click on option setTimeout(() => { this._isOpen = false; this._highlightedIndex = -1; }, 200); this._updateFormValue(); } _onKeyDown(e) { const options = this._flatOptions; switch (e.key) { case 'ArrowDown': e.preventDefault(); this._isOpen = true; this._highlightedIndex = Math.min(this._highlightedIndex + 1, options.length - 1); this._scrollToHighlighted(); break; case 'ArrowUp': e.preventDefault(); this._highlightedIndex = Math.max(this._highlightedIndex - 1, -1); this._scrollToHighlighted(); break; case 'Enter': if (this._highlightedIndex >= 0 && options[this._highlightedIndex]) { e.preventDefault(); this._selectOption(options[this._highlightedIndex]); } break; case 'Escape': e.preventDefault(); this._isOpen = false; this._highlightedIndex = -1; break; case 'Tab': this._isOpen = false; this._highlightedIndex = -1; break; } } _scrollToHighlighted() { this.updateComplete.then(() => { const container = this.shadowRoot?.querySelector('.dropdown'); const highlighted = this.shadowRoot?.querySelector('.option.is-highlighted'); if (container && highlighted) { const containerRect = container.getBoundingClientRect(); const highlightedRect = highlighted.getBoundingClientRect(); if (highlightedRect.bottom > containerRect.bottom) { highlighted.scrollIntoView({ block: 'nearest' }); } else if (highlightedRect.top < containerRect.top) { highlighted.scrollIntoView({ block: 'nearest' }); } } }); } _selectOption(option) { if (option.disabled) return; this.value = option.label || option.value; this._isOpen = false; this._highlightedIndex = -1; this._dirty = true; this._updateFormValue(); this.dispatchEvent(new CustomEvent('select', { detail: { value: option.value, selectedOption: option }, bubbles: true, composed: true, })); this.dispatchEvent(new Event('change', { bubbles: true, composed: true })); } _handleClear() { this.value = ''; this._updateFormValue(); this.dispatchEvent(new CustomEvent('change', { detail: { value: '' }, bubbles: true, composed: true, })); this._input?.focus(); } _onDocumentClick(e) { const path = e.composedPath(); if (!path.includes(this)) { this._isOpen = false; } } _highlightMatch(text) { if (!this.value || this.filteringType === 'manual' || !this.highlightMatches) { return b `${text}`; } const searchValue = this.value.toLowerCase(); const index = text.toLowerCase().indexOf(searchValue); if (index === -1) { return b `${text}`; } const before = text.slice(0, index); const match = text.slice(index, index + this.value.length); const after = text.slice(index + this.value.length); return b `${before}<span class=\"highlight\">${match}</span>${after}`; } _renderOption(option, index) { const isHighlighted = index === this._highlightedIndex; return b ` <button class=${e$1({ option: true, 'is-highlighted': isHighlighted, })} type=\"button\" role=\"option\" aria-selected=${isHighlighted} ?disabled=${option.disabled} @click=${() => this._selectOption(option)} @mouseenter=${() => { this._highlightedIndex = index; }} > <div class=\"option-content\"> <div class=\"option-label\"> ${this._highlightMatch(option.label || option.value)} ${option.labelTag ? b `<span class=\"option-tag\">${option.labelTag}</span>` : A} </div> ${option.description ? b `<div class=\"option-description\">${option.description}</div>` : A} ${option.tags && option.tags.length > 0 ? b ` <div class=\"option-tags\"> ${option.tags.map((tag) => b `<span class=\"option-tag\">${tag}</span>`)} </div> ` : A} </div> </button> `; } _renderDropdownContent() { if (this.statusType === 'loading') { return b ` <div class=\"status\"> <div class=\"spinner\"></div> ${this.loadingText} </div> `; } if (this.statusType === 'error') { return b ` <div class=\"status is-error\"> <svg width=\"16\" height=\"16\" fill=\"currentColor\" viewBox=\"0 0 16 16\"> <path d=\"M8.982 1.566a1.13 1.13 0 0 0-1.96 0L.165 13.233c-.457.778.091 1.767.98 1.767h13.713c.889 0 1.438-.99.98-1.767L8.982 1.566zM8 5c.535 0 .954.462.9.995l-.35 3.507a.552.552 0 0 1-1.1 0L7.1 5.995A.905.905 0 0 1 8 5zm.002 6a1 1 0 1 1 0 2 1 1 0 0 1 0-2z\" /> </svg> ${this.errorText} </div> `; } const filtered = this._filteredOptions; if (filtered.length === 0) { return b `<div class=\"empty\">${this.emptyText}</div>`; } let optionIndex = 0; return b ` ${filtered.map((option) => { if (isGroup(option)) { const groupOptions = option.options.map((opt) => { const rendered = this._renderOption(opt, optionIndex); optionIndex++; return rendered; }); return b ` <div class=\"group-label\">${option.label}</div> ${groupOptions} `; } const rendered = this._renderOption(option, optionIndex); optionIndex++; return rendered; })} `; } render() { const hasError = this._touched && !this.validity.valid; return b ` <div class=\"field-wrapper\"> ${this.label ? b ` <label> ${this.label} ${this.required ? b `<span class=\"required\">*</span>` : A} </label> ` : A} <div class=\"input-container\"> <div class=\"input-wrapper\"> <input type=\"text\" .value=${l(this.value)} placeholder=${o(this.placeholder || undefined)} ?disabled=${this.disabled} ?readonly=${this.readonly} ?required=${this.required} name=${o(this.name || undefined)} autocomplete=\"off\" role=\"combobox\" aria-autocomplete=\"list\" aria-expanded=${this._isOpen} aria-controls=\"dropdown\" class=${e$1({ 'input--invalid': hasError, })} @input=${this._onInput} @blur=${this._onBlur} @focus=${this._onFocus} @keydown=${this._onKeyDown} /> <div class=\"icon-container\"> ${this.value && !this.disabled && !this.readonly ? b ` <button class=\"clear-button\" type=\"button\" aria-label=\"Clear\" @click=${this._handleClear} > <svg width=\"16\" height=\"16\" fill=\"currentColor\" viewBox=\"0 0 16 16\"> <path d=\"M4.646 4.646a.5.5 0 0 1 .708 0L8 7.293l2.646-2.647a.5.5 0 0 1 .708.708L8.707 8l2.647 2.646a.5.5 0 0 1-.708.708L8 8.707l-2.646 2.647a.5.5 0 0 1-.708-.708L7.293 8 4.646 5.354a.5.5 0 0 1 0-.708z\" /> </svg> </button> ` : ''} ${!this.value && !this.disabled && !this.readonly ? b ` <svg class=\"search-icon\" fill=\"currentColor\" viewBox=\"0 0 16 16\"> <path d=\"M11.742 10.344a6.5 6.5 0 1 0-1.397 1.398h-.001c.03.04.062.078.098.115l3.85 3.85a1 1 0 0 0 1.415-1.414l-3.85-3.85a1.007 1.007 0 0 0-.115-.1zM12 6.5a5.5 5.5 0 1 1-11 0 5.5 5.5 0 0 1 11 0z\" /> </svg> ` : ''} </div> </div> <div id=\"dropdown\" role=\"listbox\" class=${e$1({ dropdown: true, 'is-open': this._isOpen, })} > ${this._renderDropdownContent()} </div> </div> ${hasError ? b `<div class=\"validation-message\">${this.validationMessage}</div>` : this.hint ? b `<div class=\"hint\">${this.hint}</div>` : A} </div> `; } }"
328
341
  }
329
342
  ],
330
343
  "exports": [
@@ -360,6 +373,14 @@
360
373
  "module": "dist/krubble-components.bundled.js"
361
374
  }
362
375
  },
376
+ {
377
+ "kind": "js",
378
+ "name": "KRAutoSuggest",
379
+ "declaration": {
380
+ "name": "KRAutoSuggest",
381
+ "module": "dist/krubble-components.bundled.js"
382
+ }
383
+ },
363
384
  {
364
385
  "kind": "js",
365
386
  "name": "KRButton",
@@ -510,7 +531,7 @@
510
531
  },
511
532
  {
512
533
  "kind": "variable",
513
- "name": "ge",
534
+ "name": "fe",
514
535
  "default": "class extends re{constructor(){super(...arguments),this.header=\"\",this.expanded=!1}toggle(){this.expanded=!this.expanded}render(){return H` <div class=\"header\" @click=${this.toggle}> <span class=\"header__title\">${this.header}</span> <svg class=\"header__icon\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"> <path d=\"M6 9l6 6 6-6\"/> </svg> </div> <div class=\"content\"> <div class=\"content__inner\"> <div class=\"content__body\"> <slot></slot> </div> </div> </div> `}}"
515
536
  },
516
537
  {
@@ -525,12 +546,12 @@
525
546
  },
526
547
  {
527
548
  "kind": "variable",
528
- "name": "Oe",
529
- "default": "class extends re{constructor(){super(...arguments),this.language=\"html\",this.code=\"\",this.activeTab=\"preview\",this.copied=!1,this.highlightedCode=\"\"}connectedCallback(){super.connectedCallback(),requestAnimationFrame((()=>{this.code||(this.code=this.innerHTML.trim().replace(/=\"\"(?=[\\s>])/g,\"\")),this.querySelectorAll(\"script\").forEach((e=>{const t=document.createElement(\"script\");t.textContent=e.textContent,e.replaceWith(t)})),this.code&&window.hljs&&window.hljs.getLanguage(this.language)?this.highlightedCode=window.hljs.highlight(this.code,{language:this.language}).value:this.highlightedCode=this.code.replace(/&/g,\"&amp;\").replace(/</g,\"&lt;\").replace(/>/g,\"&gt;\")}))}activateTab(e){this.activeTab=e}copyCode(){this.code&&navigator.clipboard.writeText(this.code).then((()=>{this.copied=!0,setTimeout((()=>{this.copied=!1}),2e3)}))}render(){return H` <div class=\"tabs\"> <button class=${ke({tab:!0,\"tab--active\":\"preview\"===this.activeTab})} @click=${()=>this.activateTab(\"preview\")} > Preview </button> <button class=${ke({tab:!0,\"tab--active\":\"code\"===this.activeTab})} @click=${()=>this.activateTab(\"code\")} > Code </button> <button class=${ke({copy:!0,\"copy--success\":this.copied})} @click=${this.copyCode} title=${this.copied?\"Copied!\":\"Copy code\"} > ${this.copied?H`<svg width=\"18\" height=\"18\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><polyline points=\"20 6 9 17 4 12\"></polyline></svg>`:H`<svg width=\"18\" height=\"18\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><rect x=\"9\" y=\"9\" width=\"13\" height=\"13\" rx=\"2\" ry=\"2\"></rect><path d=\"M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1\"></path></svg>`} </button> </div> <div class=${ke({panel:!0,\"panel--active\":\"preview\"===this.activeTab,\"panel--preview\":!0})}> <slot></slot> </div> <div class=${ke({panel:!0,\"panel--active\":\"code\"===this.activeTab,\"panel--code\":!0})}> <pre class=\"code\"><code>${Ae(this.highlightedCode)}</code></pre> </div> `}}"
549
+ "name": "ze",
550
+ "default": "class extends re{constructor(){super(...arguments),this.language=\"html\",this.code=\"\",this.activeTab=\"preview\",this.copied=!1,this.highlightedCode=\"\"}connectedCallback(){super.connectedCallback(),requestAnimationFrame((()=>{this.code||(this.code=this.innerHTML.trim().replace(/=\"\"(?=[\\s>])/g,\"\")),this.querySelectorAll(\"script\").forEach((e=>{const t=document.createElement(\"script\");t.textContent=e.textContent,e.replaceWith(t)})),this.code&&window.hljs&&window.hljs.getLanguage(this.language)?this.highlightedCode=window.hljs.highlight(this.code,{language:this.language}).value:this.highlightedCode=this.code.replace(/&/g,\"&amp;\").replace(/</g,\"&lt;\").replace(/>/g,\"&gt;\")}))}activateTab(e){this.activeTab=e}copyCode(){this.code&&navigator.clipboard.writeText(this.code).then((()=>{this.copied=!0,setTimeout((()=>{this.copied=!1}),2e3)}))}render(){return H` <div class=\"tabs\"> <button class=${ke({tab:!0,\"tab--active\":\"preview\"===this.activeTab})} @click=${()=>this.activateTab(\"preview\")} > Preview </button> <button class=${ke({tab:!0,\"tab--active\":\"code\"===this.activeTab})} @click=${()=>this.activateTab(\"code\")} > Code </button> <button class=${ke({copy:!0,\"copy--success\":this.copied})} @click=${this.copyCode} title=${this.copied?\"Copied!\":\"Copy code\"} > ${this.copied?H`<svg width=\"18\" height=\"18\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><polyline points=\"20 6 9 17 4 12\"></polyline></svg>`:H`<svg width=\"18\" height=\"18\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><rect x=\"9\" y=\"9\" width=\"13\" height=\"13\" rx=\"2\" ry=\"2\"></rect><path d=\"M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1\"></path></svg>`} </button> </div> <div class=${ke({panel:!0,\"panel--active\":\"preview\"===this.activeTab,\"panel--preview\":!0})}> <slot></slot> </div> <div class=${ke({panel:!0,\"panel--active\":\"code\"===this.activeTab,\"panel--code\":!0})}> <pre class=\"code\"><code>${Oe(this.highlightedCode)}</code></pre> </div> `}}"
530
551
  },
531
552
  {
532
553
  "kind": "variable",
533
- "name": "Te",
554
+ "name": "Pe",
534
555
  "default": "class extends re{constructor(){super(...arguments),this.items=[],this.resolvePromise=null,this.boundHandleOutsideClick=this.handleOutsideClick.bind(this),this.boundHandleKeyDown=this.handleKeyDown.bind(this)}static async open(e){const t=document.querySelector(\"kr-context-menu\");t&&t.remove();const i=document.createElement(\"kr-context-menu\");return document.body.appendChild(i),i.show(e)}async show(e){this.items=e.items,this.style.left=`${e.x}px`,this.style.top=`${e.y}px`,await this.updateComplete;const t=this.getBoundingClientRect();return t.right>window.innerWidth&&(this.style.left=e.x-t.width+\"px\"),t.bottom>window.innerHeight&&(this.style.top=e.y-t.height+\"px\"),requestAnimationFrame((()=>{document.addEventListener(\"click\",this.boundHandleOutsideClick),document.addEventListener(\"contextmenu\",this.boundHandleOutsideClick),document.addEventListener(\"keydown\",this.boundHandleKeyDown)})),new Promise((e=>{this.resolvePromise=e}))}handleOutsideClick(e){this.contains(e.target)||this.close(null)}handleKeyDown(e){\"Escape\"===e.key&&this.close(null)}handleItemClick(e){e.disabled||e.divider||this.close(e)}close(e){document.removeEventListener(\"click\",this.boundHandleOutsideClick),document.removeEventListener(\"contextmenu\",this.boundHandleOutsideClick),document.removeEventListener(\"keydown\",this.boundHandleKeyDown),this.resolvePromise&&(this.resolvePromise(e),this.resolvePromise=null),this.remove()}render(){return H` <div class=\"menu\"> ${this.items.map((e=>e.divider?H`<div class=\"menu__divider\"></div>`:H` <button class=\"menu__item\" ?disabled=${e.disabled} @click=${()=>this.handleItemClick(e)} > ${e.icon?H`<span class=\"menu__item-icon\">${e.icon}</span>`:null} ${e.label} </button> `))} </div> `}}"
535
556
  },
536
557
  {
@@ -634,8 +655,13 @@
634
655
  },
635
656
  {
636
657
  "kind": "variable",
637
- "name": "ft",
658
+ "name": "gt",
638
659
  "default": "class extends re{constructor(){super(),this.label=\"\",this.name=\"\",this.value=\"\",this.placeholder=\"\",this.required=!1,this.disabled=!1,this.readonly=!1,this.rows=3,this.autocomplete=\"\",this.hint=\"\",this._touched=!1,this._dirty=!1,this._handleInvalid=e=>{e.preventDefault(),this._touched=!0},this._internals=this.attachInternals()}get form(){return this._internals.form}get validity(){return this._internals.validity}get validationMessage(){return this._internals.validationMessage}get willValidate(){return this._internals.willValidate}checkValidity(){return this._internals.checkValidity()}reportValidity(){return this._internals.reportValidity()}formResetCallback(){this.value=\"\",this._touched=!1,this._dirty=!1,this._internals.setFormValue(\"\"),this._internals.setValidity({})}formStateRestoreCallback(e){this.value=e}connectedCallback(){super.connectedCallback(),this.addEventListener(\"invalid\",this._handleInvalid)}disconnectedCallback(){super.disconnectedCallback(),this.removeEventListener(\"invalid\",this._handleInvalid)}firstUpdated(){this._updateValidity()}updated(e){(e.has(\"required\")||e.has(\"value\"))&&this._updateValidity()}_updateValidity(){this._textarea&&this._internals.setValidity(this._textarea.validity,this._textarea.validationMessage)}_handleInput(e){this.value=e.target.value,this._dirty=!0,this._internals.setFormValue(this.value),this._internals.setValidity(this._textarea.validity,this._textarea.validationMessage)}_handleChange(e){this.value=e.target.value,this._internals.setFormValue(this.value)}_handleBlur(){this._touched=!0,this._internals.setValidity(this._textarea.validity,this._textarea.validationMessage)}render(){let e=\"\";return this._touched&&this._textarea&&!this._textarea.validity.valid&&(e=this._textarea.validationMessage),H` <div class=\"wrapper\"> ${this.label?H` <label for=\"textarea\"> ${this.label} ${this.required?H`<span class=\"required\" aria-hidden=\"true\">*</span>`:U} </label> `:U} <textarea id=\"textarea\" class=${ke({\"textarea--invalid\":this._touched&&this._textarea&&!this._textarea.validity.valid})} name=${this.name} .value=${nt(this.value)} placeholder=${this.placeholder} ?required=${this.required} ?disabled=${this.disabled} ?readonly=${this.readonly} rows=${this.rows} cols=${st(this.cols)} minlength=${st(this.minlength)} maxlength=${st(this.maxlength)} autocomplete=${st(this.autocomplete||void 0)} @input=${this._handleInput} @change=${this._handleChange} @blur=${this._handleBlur} ></textarea> ${e?H`<div class=\"validation-message\">${e}</div>`:this.hint?H`<div class=\"hint\">${this.hint}</div>`:U} </div> `}focus(){this._textarea?.focus()}blur(){this._textarea?.blur()}select(){this._textarea?.select()}}"
660
+ },
661
+ {
662
+ "kind": "variable",
663
+ "name": "mt",
664
+ "default": "class extends re{constructor(){super(),this.label=\"\",this.name=\"\",this.value=\"\",this.placeholder=\"\",this.disabled=!1,this.readonly=!1,this.required=!1,this.hint=\"\",this.options=[],this.statusType=\"finished\",this.loadingText=\"Loading...\",this.errorText=\"Error loading options\",this.emptyText=\"No matches found\",this.filteringType=\"auto\",this.highlightMatches=!0,this._isOpen=!1,this._highlightedIndex=-1,this._touched=!1,this._dirty=!1,this._handleDocumentClick=this._onDocumentClick.bind(this),this._internals=this.attachInternals()}connectedCallback(){super.connectedCallback(),document.addEventListener(\"click\",this._handleDocumentClick)}disconnectedCallback(){super.disconnectedCallback(),document.removeEventListener(\"click\",this._handleDocumentClick)}firstUpdated(){this._updateFormValue()}get form(){return this._internals.form}get validity(){return this._internals.validity}get validationMessage(){return this._internals.validationMessage}checkValidity(){return this._internals.checkValidity()}reportValidity(){return this._internals.reportValidity()}formResetCallback(){this.value=\"\",this._touched=!1,this._dirty=!1,this._isOpen=!1,this._highlightedIndex=-1,this._updateFormValue()}formStateRestoreCallback(e){this.value=e}get _filteredOptions(){if(\"manual\"===this.filteringType||!this.value)return this.options;const e=this.value.toLowerCase(),t=[];for(const i of this.options)if(yt(i)){const o=i.options.filter((t=>{const i=(t.label||t.value).toLowerCase(),o=t.filteringTags?.join(\" \").toLowerCase()||\"\";return i.includes(e)||o.includes(e)}));o.length>0&&t.push({...i,options:o})}else{const o=(i.label||i.value).toLowerCase(),s=i.filteringTags?.join(\" \").toLowerCase()||\"\";(o.includes(e)||s.includes(e))&&t.push(i)}return t}get _flatOptions(){const e=[];for(const t of this._filteredOptions)yt(t)?e.push(...t.options):e.push(t);return e}_updateFormValue(){this._internals.setFormValue(this.value),this.required&&!this.value?this._internals.setValidity({valueMissing:!0},\"This field is required\",this._input):this._internals.setValidity({})}_onInput(e){const t=e.target;this.value=t.value,this._dirty=!0,this._isOpen=!0,this._highlightedIndex=-1,this._updateFormValue(),this.dispatchEvent(new CustomEvent(\"change\",{detail:{value:this.value},bubbles:!0,composed:!0})),\"manual\"===this.filteringType&&this.dispatchEvent(new CustomEvent(\"load-items\",{detail:{filteringText:this.value},bubbles:!0,composed:!0}))}_onFocus(){this._isOpen=!0,\"manual\"===this.filteringType&&this.dispatchEvent(new CustomEvent(\"load-items\",{detail:{filteringText:this.value},bubbles:!0,composed:!0}))}_onBlur(){this._touched=!0,setTimeout((()=>{this._isOpen=!1,this._highlightedIndex=-1}),200),this._updateFormValue()}_onKeyDown(e){const t=this._flatOptions;switch(e.key){case\"ArrowDown\":e.preventDefault(),this._isOpen=!0,this._highlightedIndex=Math.min(this._highlightedIndex+1,t.length-1),this._scrollToHighlighted();break;case\"ArrowUp\":e.preventDefault(),this._highlightedIndex=Math.max(this._highlightedIndex-1,-1),this._scrollToHighlighted();break;case\"Enter\":this._highlightedIndex>=0&&t[this._highlightedIndex]&&(e.preventDefault(),this._selectOption(t[this._highlightedIndex]));break;case\"Escape\":e.preventDefault(),this._isOpen=!1,this._highlightedIndex=-1;break;case\"Tab\":this._isOpen=!1,this._highlightedIndex=-1}}_scrollToHighlighted(){this.updateComplete.then((()=>{const e=this.shadowRoot?.querySelector(\".dropdown\"),t=this.shadowRoot?.querySelector(\".option.is-highlighted\");if(e&&t){const i=e.getBoundingClientRect(),o=t.getBoundingClientRect();(o.bottom>i.bottom||o.top<i.top)&&t.scrollIntoView({block:\"nearest\"})}}))}_selectOption(e){e.disabled||(this.value=e.label||e.value,this._isOpen=!1,this._highlightedIndex=-1,this._dirty=!0,this._updateFormValue(),this.dispatchEvent(new CustomEvent(\"select\",{detail:{value:e.value,selectedOption:e},bubbles:!0,composed:!0})),this.dispatchEvent(new Event(\"change\",{bubbles:!0,composed:!0})))}_handleClear(){this.value=\"\",this._updateFormValue(),this.dispatchEvent(new CustomEvent(\"change\",{detail:{value:\"\"},bubbles:!0,composed:!0})),this._input?.focus()}_onDocumentClick(e){e.composedPath().includes(this)||(this._isOpen=!1)}_highlightMatch(e){if(!this.value||\"manual\"===this.filteringType||!this.highlightMatches)return H`${e}`;const t=this.value.toLowerCase(),i=e.toLowerCase().indexOf(t);if(-1===i)return H`${e}`;const o=e.slice(0,i),s=e.slice(i,i+this.value.length),r=e.slice(i+this.value.length);return H`${o}<span class=\"highlight\">${s}</span>${r}`}_renderOption(e,t){const i=t===this._highlightedIndex;return H` <button class=${ke({option:!0,\"is-highlighted\":i})} type=\"button\" role=\"option\" aria-selected=${i} ?disabled=${e.disabled} @click=${()=>this._selectOption(e)} @mouseenter=${()=>{this._highlightedIndex=t}} > <div class=\"option-content\"> <div class=\"option-label\"> ${this._highlightMatch(e.label||e.value)} ${e.labelTag?H`<span class=\"option-tag\">${e.labelTag}</span>`:U} </div> ${e.description?H`<div class=\"option-description\">${e.description}</div>`:U} ${e.tags&&e.tags.length>0?H` <div class=\"option-tags\"> ${e.tags.map((e=>H`<span class=\"option-tag\">${e}</span>`))} </div> `:U} </div> </button> `}_renderDropdownContent(){if(\"loading\"===this.statusType)return H` <div class=\"status\"> <div class=\"spinner\"></div> ${this.loadingText} </div> `;if(\"error\"===this.statusType)return H` <div class=\"status is-error\"> <svg width=\"16\" height=\"16\" fill=\"currentColor\" viewBox=\"0 0 16 16\"> <path d=\"M8.982 1.566a1.13 1.13 0 0 0-1.96 0L.165 13.233c-.457.778.091 1.767.98 1.767h13.713c.889 0 1.438-.99.98-1.767L8.982 1.566zM8 5c.535 0 .954.462.9.995l-.35 3.507a.552.552 0 0 1-1.1 0L7.1 5.995A.905.905 0 0 1 8 5zm.002 6a1 1 0 1 1 0 2 1 1 0 0 1 0-2z\" /> </svg> ${this.errorText} </div> `;const e=this._filteredOptions;if(0===e.length)return H`<div class=\"empty\">${this.emptyText}</div>`;let t=0;return H` ${e.map((e=>{if(yt(e)){const i=e.options.map((e=>{const i=this._renderOption(e,t);return t++,i}));return H` <div class=\"group-label\">${e.label}</div> ${i} `}const i=this._renderOption(e,t);return t++,i}))} `}render(){const e=this._touched&&!this.validity.valid;return H` <div class=\"field-wrapper\"> ${this.label?H` <label> ${this.label} ${this.required?H`<span class=\"required\">*</span>`:U} </label> `:U} <div class=\"input-container\"> <div class=\"input-wrapper\"> <input type=\"text\" .value=${nt(this.value)} placeholder=${st(this.placeholder||void 0)} ?disabled=${this.disabled} ?readonly=${this.readonly} ?required=${this.required} name=${st(this.name||void 0)} autocomplete=\"off\" role=\"combobox\" aria-autocomplete=\"list\" aria-expanded=${this._isOpen} aria-controls=\"dropdown\" class=${ke({\"input--invalid\":e})} @input=${this._onInput} @blur=${this._onBlur} @focus=${this._onFocus} @keydown=${this._onKeyDown} /> <div class=\"icon-container\"> ${!this.value||this.disabled||this.readonly?\"\":H` <button class=\"clear-button\" type=\"button\" aria-label=\"Clear\" @click=${this._handleClear} > <svg width=\"16\" height=\"16\" fill=\"currentColor\" viewBox=\"0 0 16 16\"> <path d=\"M4.646 4.646a.5.5 0 0 1 .708 0L8 7.293l2.646-2.647a.5.5 0 0 1 .708.708L8.707 8l2.647 2.646a.5.5 0 0 1-.708.708L8 8.707l-2.646 2.647a.5.5 0 0 1-.708-.708L7.293 8 4.646 5.354a.5.5 0 0 1 0-.708z\" /> </svg> </button> `} ${this.value||this.disabled||this.readonly?\"\":H` <svg class=\"search-icon\" fill=\"currentColor\" viewBox=\"0 0 16 16\"> <path d=\"M11.742 10.344a6.5 6.5 0 1 0-1.397 1.398h-.001c.03.04.062.078.098.115l3.85 3.85a1 1 0 0 0 1.415-1.414l-3.85-3.85a1.007 1.007 0 0 0-.115-.1zM12 6.5a5.5 5.5 0 1 1-11 0 5.5 5.5 0 0 1 11 0z\" /> </svg> `} </div> </div> <div id=\"dropdown\" role=\"listbox\" class=${ke({dropdown:!0,\"is-open\":this._isOpen})} > ${this._renderDropdownContent()} </div> </div> ${e?H`<div class=\"validation-message\">${this.validationMessage}</div>`:this.hint?H`<div class=\"hint\">${this.hint}</div>`:U} </div> `}}"
639
665
  }
640
666
  ],
641
667
  "exports": [
@@ -659,7 +685,7 @@
659
685
  "kind": "js",
660
686
  "name": "KRAccordion",
661
687
  "declaration": {
662
- "name": "ge",
688
+ "name": "fe",
663
689
  "module": "dist/krubble-components.bundled.min.js"
664
690
  }
665
691
  },
@@ -671,6 +697,14 @@
671
697
  "module": "dist/krubble-components.bundled.min.js"
672
698
  }
673
699
  },
700
+ {
701
+ "kind": "js",
702
+ "name": "KRAutoSuggest",
703
+ "declaration": {
704
+ "name": "mt",
705
+ "module": "dist/krubble-components.bundled.min.js"
706
+ }
707
+ },
674
708
  {
675
709
  "kind": "js",
676
710
  "name": "KRButton",
@@ -683,7 +717,7 @@
683
717
  "kind": "js",
684
718
  "name": "KRCodeDemo",
685
719
  "declaration": {
686
- "name": "Oe",
720
+ "name": "ze",
687
721
  "module": "dist/krubble-components.bundled.min.js"
688
722
  }
689
723
  },
@@ -691,7 +725,7 @@
691
725
  "kind": "js",
692
726
  "name": "KRContextMenu",
693
727
  "declaration": {
694
- "name": "Te",
728
+ "name": "Pe",
695
729
  "module": "dist/krubble-components.bundled.min.js"
696
730
  }
697
731
  },
@@ -787,7 +821,7 @@
787
821
  "kind": "js",
788
822
  "name": "KRTextareaField",
789
823
  "declaration": {
790
- "name": "ft",
824
+ "name": "gt",
791
825
  "module": "dist/krubble-components.bundled.min.js"
792
826
  }
793
827
  },
@@ -1067,6 +1101,14 @@
1067
1101
  "module": "./form/index.js"
1068
1102
  }
1069
1103
  },
1104
+ {
1105
+ "kind": "js",
1106
+ "name": "KRAutoSuggest",
1107
+ "declaration": {
1108
+ "name": "KRAutoSuggest",
1109
+ "module": "./form/index.js"
1110
+ }
1111
+ },
1070
1112
  {
1071
1113
  "kind": "js",
1072
1114
  "name": "ContextMenuItem",
@@ -1098,6 +1140,46 @@
1098
1140
  "name": "KRSnackbarOptions",
1099
1141
  "module": "./snackbar/snackbar.js"
1100
1142
  }
1143
+ },
1144
+ {
1145
+ "kind": "js",
1146
+ "name": "SuggestionOption",
1147
+ "declaration": {
1148
+ "name": "SuggestionOption",
1149
+ "module": "./form/auto-suggest/auto-suggest.js"
1150
+ }
1151
+ },
1152
+ {
1153
+ "kind": "js",
1154
+ "name": "SuggestionOptionGroup",
1155
+ "declaration": {
1156
+ "name": "SuggestionOptionGroup",
1157
+ "module": "./form/auto-suggest/auto-suggest.js"
1158
+ }
1159
+ },
1160
+ {
1161
+ "kind": "js",
1162
+ "name": "SuggestionOptions",
1163
+ "declaration": {
1164
+ "name": "SuggestionOptions",
1165
+ "module": "./form/auto-suggest/auto-suggest.js"
1166
+ }
1167
+ },
1168
+ {
1169
+ "kind": "js",
1170
+ "name": "AutoSuggestStatusType",
1171
+ "declaration": {
1172
+ "name": "AutoSuggestStatusType",
1173
+ "module": "./form/auto-suggest/auto-suggest.js"
1174
+ }
1175
+ },
1176
+ {
1177
+ "kind": "js",
1178
+ "name": "AutoSuggestFilteringType",
1179
+ "declaration": {
1180
+ "name": "AutoSuggestFilteringType",
1181
+ "module": "./form/auto-suggest/auto-suggest.js"
1182
+ }
1101
1183
  }
1102
1184
  ]
1103
1185
  },
@@ -1373,6 +1455,14 @@
1373
1455
  "name": "KRDetailField",
1374
1456
  "module": "./detail-field/detail-field.js"
1375
1457
  }
1458
+ },
1459
+ {
1460
+ "kind": "js",
1461
+ "name": "KRAutoSuggest",
1462
+ "declaration": {
1463
+ "name": "KRAutoSuggest",
1464
+ "module": "./auto-suggest/auto-suggest.js"
1465
+ }
1376
1466
  }
1377
1467
  ]
1378
1468
  },
@@ -2757,6 +2847,14 @@
2757
2847
  "name": "KRDetailField",
2758
2848
  "module": "./detail-field/detail-field.js"
2759
2849
  }
2850
+ },
2851
+ {
2852
+ "kind": "js",
2853
+ "name": "KRAutoSuggest",
2854
+ "declaration": {
2855
+ "name": "KRAutoSuggest",
2856
+ "module": "./auto-suggest/auto-suggest.js"
2857
+ }
2760
2858
  }
2761
2859
  ]
2762
2860
  },
@@ -4143,6 +4241,27 @@
4143
4241
  }
4144
4242
  ]
4145
4243
  },
4244
+ {
4245
+ "kind": "javascript-module",
4246
+ "path": "dist/form/auto-suggest/auto-suggest.js",
4247
+ "declarations": [
4248
+ {
4249
+ "kind": "variable",
4250
+ "name": "KRAutoSuggest",
4251
+ "default": "class KRAutoSuggest extends LitElement { constructor() { super(); this.label = ''; this.name = ''; this.value = ''; this.placeholder = ''; this.disabled = false; this.readonly = false; this.required = false; this.hint = ''; this.options = []; this.statusType = 'finished'; this.loadingText = 'Loading...'; this.errorText = 'Error loading options'; this.emptyText = 'No matches found'; this.filteringType = 'auto'; this.highlightMatches = true; this._isOpen = false; this._highlightedIndex = -1; this._touched = false; this._dirty = false; this._handleDocumentClick = this._onDocumentClick.bind(this); this._internals = this.attachInternals(); } connectedCallback() { super.connectedCallback(); document.addEventListener('click', this._handleDocumentClick); } disconnectedCallback() { super.disconnectedCallback(); document.removeEventListener('click', this._handleDocumentClick); } firstUpdated() { this._updateFormValue(); } get form() { return this._internals.form; } get validity() { return this._internals.validity; } get validationMessage() { return this._internals.validationMessage; } checkValidity() { return this._internals.checkValidity(); } reportValidity() { return this._internals.reportValidity(); } formResetCallback() { this.value = ''; this._touched = false; this._dirty = false; this._isOpen = false; this._highlightedIndex = -1; this._updateFormValue(); } formStateRestoreCallback(state) { this.value = state; } get _filteredOptions() { if (this.filteringType === 'manual' || !this.value) { return this.options; } const searchValue = this.value.toLowerCase(); const filtered = []; for (const option of this.options) { if (isGroup(option)) { const filteredGroupOptions = option.options.filter((opt) => { const label = (opt.label || opt.value).toLowerCase(); const tags = opt.filteringTags?.join(' ').toLowerCase() || ''; return label.includes(searchValue) || tags.includes(searchValue); }); if (filteredGroupOptions.length > 0) { filtered.push({ ...option, options: filteredGroupOptions }); } } else { const label = (option.label || option.value).toLowerCase(); const tags = option.filteringTags?.join(' ').toLowerCase() || ''; if (label.includes(searchValue) || tags.includes(searchValue)) { filtered.push(option); } } } return filtered; } get _flatOptions() { const flat = []; for (const option of this._filteredOptions) { if (isGroup(option)) { flat.push(...option.options); } else { flat.push(option); } } return flat; } _updateFormValue() { this._internals.setFormValue(this.value); // Validation if (this.required && !this.value) { this._internals.setValidity({ valueMissing: true }, 'This field is required', this._input); } else { this._internals.setValidity({}); } } _onInput(e) { const target = e.target; this.value = target.value; this._dirty = true; this._isOpen = true; this._highlightedIndex = -1; this._updateFormValue(); this.dispatchEvent(new CustomEvent('change', { detail: { value: this.value }, bubbles: true, composed: true, })); if (this.filteringType === 'manual') { this.dispatchEvent(new CustomEvent('load-items', { detail: { filteringText: this.value }, bubbles: true, composed: true, })); } } _onFocus() { this._isOpen = true; if (this.filteringType === 'manual') { this.dispatchEvent(new CustomEvent('load-items', { detail: { filteringText: this.value }, bubbles: true, composed: true, })); } } _onBlur() { this._touched = true; // Delay to allow click on option setTimeout(() => { this._isOpen = false; this._highlightedIndex = -1; }, 200); this._updateFormValue(); } _onKeyDown(e) { const options = this._flatOptions; switch (e.key) { case 'ArrowDown': e.preventDefault(); this._isOpen = true; this._highlightedIndex = Math.min(this._highlightedIndex + 1, options.length - 1); this._scrollToHighlighted(); break; case 'ArrowUp': e.preventDefault(); this._highlightedIndex = Math.max(this._highlightedIndex - 1, -1); this._scrollToHighlighted(); break; case 'Enter': if (this._highlightedIndex >= 0 && options[this._highlightedIndex]) { e.preventDefault(); this._selectOption(options[this._highlightedIndex]); } break; case 'Escape': e.preventDefault(); this._isOpen = false; this._highlightedIndex = -1; break; case 'Tab': this._isOpen = false; this._highlightedIndex = -1; break; } } _scrollToHighlighted() { this.updateComplete.then(() => { const container = this.shadowRoot?.querySelector('.dropdown'); const highlighted = this.shadowRoot?.querySelector('.option.is-highlighted'); if (container && highlighted) { const containerRect = container.getBoundingClientRect(); const highlightedRect = highlighted.getBoundingClientRect(); if (highlightedRect.bottom > containerRect.bottom) { highlighted.scrollIntoView({ block: 'nearest' }); } else if (highlightedRect.top < containerRect.top) { highlighted.scrollIntoView({ block: 'nearest' }); } } }); } _selectOption(option) { if (option.disabled) return; this.value = option.label || option.value; this._isOpen = false; this._highlightedIndex = -1; this._dirty = true; this._updateFormValue(); this.dispatchEvent(new CustomEvent('select', { detail: { value: option.value, selectedOption: option }, bubbles: true, composed: true, })); this.dispatchEvent(new Event('change', { bubbles: true, composed: true })); } _handleClear() { this.value = ''; this._updateFormValue(); this.dispatchEvent(new CustomEvent('change', { detail: { value: '' }, bubbles: true, composed: true, })); this._input?.focus(); } _onDocumentClick(e) { const path = e.composedPath(); if (!path.includes(this)) { this._isOpen = false; } } _highlightMatch(text) { if (!this.value || this.filteringType === 'manual' || !this.highlightMatches) { return html `${text}`; } const searchValue = this.value.toLowerCase(); const index = text.toLowerCase().indexOf(searchValue); if (index === -1) { return html `${text}`; } const before = text.slice(0, index); const match = text.slice(index, index + this.value.length); const after = text.slice(index + this.value.length); return html `${before}<span class=\"highlight\">${match}</span>${after}`; } _renderOption(option, index) { const isHighlighted = index === this._highlightedIndex; return html ` <button class=${classMap({ option: true, 'is-highlighted': isHighlighted, })} type=\"button\" role=\"option\" aria-selected=${isHighlighted} ?disabled=${option.disabled} @click=${() => this._selectOption(option)} @mouseenter=${() => { this._highlightedIndex = index; }} > <div class=\"option-content\"> <div class=\"option-label\"> ${this._highlightMatch(option.label || option.value)} ${option.labelTag ? html `<span class=\"option-tag\">${option.labelTag}</span>` : nothing} </div> ${option.description ? html `<div class=\"option-description\">${option.description}</div>` : nothing} ${option.tags && option.tags.length > 0 ? html ` <div class=\"option-tags\"> ${option.tags.map((tag) => html `<span class=\"option-tag\">${tag}</span>`)} </div> ` : nothing} </div> </button> `; } _renderDropdownContent() { if (this.statusType === 'loading') { return html ` <div class=\"status\"> <div class=\"spinner\"></div> ${this.loadingText} </div> `; } if (this.statusType === 'error') { return html ` <div class=\"status is-error\"> <svg width=\"16\" height=\"16\" fill=\"currentColor\" viewBox=\"0 0 16 16\"> <path d=\"M8.982 1.566a1.13 1.13 0 0 0-1.96 0L.165 13.233c-.457.778.091 1.767.98 1.767h13.713c.889 0 1.438-.99.98-1.767L8.982 1.566zM8 5c.535 0 .954.462.9.995l-.35 3.507a.552.552 0 0 1-1.1 0L7.1 5.995A.905.905 0 0 1 8 5zm.002 6a1 1 0 1 1 0 2 1 1 0 0 1 0-2z\" /> </svg> ${this.errorText} </div> `; } const filtered = this._filteredOptions; if (filtered.length === 0) { return html `<div class=\"empty\">${this.emptyText}</div>`; } let optionIndex = 0; return html ` ${filtered.map((option) => { if (isGroup(option)) { const groupOptions = option.options.map((opt) => { const rendered = this._renderOption(opt, optionIndex); optionIndex++; return rendered; }); return html ` <div class=\"group-label\">${option.label}</div> ${groupOptions} `; } const rendered = this._renderOption(option, optionIndex); optionIndex++; return rendered; })} `; } render() { const hasError = this._touched && !this.validity.valid; return html ` <div class=\"field-wrapper\"> ${this.label ? html ` <label> ${this.label} ${this.required ? html `<span class=\"required\">*</span>` : nothing} </label> ` : nothing} <div class=\"input-container\"> <div class=\"input-wrapper\"> <input type=\"text\" .value=${live(this.value)} placeholder=${ifDefined(this.placeholder || undefined)} ?disabled=${this.disabled} ?readonly=${this.readonly} ?required=${this.required} name=${ifDefined(this.name || undefined)} autocomplete=\"off\" role=\"combobox\" aria-autocomplete=\"list\" aria-expanded=${this._isOpen} aria-controls=\"dropdown\" class=${classMap({ 'input--invalid': hasError, })} @input=${this._onInput} @blur=${this._onBlur} @focus=${this._onFocus} @keydown=${this._onKeyDown} /> <div class=\"icon-container\"> ${this.value && !this.disabled && !this.readonly ? html ` <button class=\"clear-button\" type=\"button\" aria-label=\"Clear\" @click=${this._handleClear} > <svg width=\"16\" height=\"16\" fill=\"currentColor\" viewBox=\"0 0 16 16\"> <path d=\"M4.646 4.646a.5.5 0 0 1 .708 0L8 7.293l2.646-2.647a.5.5 0 0 1 .708.708L8.707 8l2.647 2.646a.5.5 0 0 1-.708.708L8 8.707l-2.646 2.647a.5.5 0 0 1-.708-.708L7.293 8 4.646 5.354a.5.5 0 0 1 0-.708z\" /> </svg> </button> ` : ''} ${!this.value && !this.disabled && !this.readonly ? html ` <svg class=\"search-icon\" fill=\"currentColor\" viewBox=\"0 0 16 16\"> <path d=\"M11.742 10.344a6.5 6.5 0 1 0-1.397 1.398h-.001c.03.04.062.078.098.115l3.85 3.85a1 1 0 0 0 1.415-1.414l-3.85-3.85a1.007 1.007 0 0 0-.115-.1zM12 6.5a5.5 5.5 0 1 1-11 0 5.5 5.5 0 0 1 11 0z\" /> </svg> ` : ''} </div> </div> <div id=\"dropdown\" role=\"listbox\" class=${classMap({ dropdown: true, 'is-open': this._isOpen, })} > ${this._renderDropdownContent()} </div> </div> ${hasError ? html `<div class=\"validation-message\">${this.validationMessage}</div>` : this.hint ? html `<div class=\"hint\">${this.hint}</div>` : nothing} </div> `; } }"
4252
+ }
4253
+ ],
4254
+ "exports": [
4255
+ {
4256
+ "kind": "js",
4257
+ "name": "KRAutoSuggest",
4258
+ "declaration": {
4259
+ "name": "KRAutoSuggest",
4260
+ "module": "dist/form/auto-suggest/auto-suggest.js"
4261
+ }
4262
+ }
4263
+ ]
4264
+ },
4146
4265
  {
4147
4266
  "kind": "javascript-module",
4148
4267
  "path": "dist/form/detail-field/detail-field.js",
@@ -4253,6 +4372,641 @@
4253
4372
  }
4254
4373
  ]
4255
4374
  },
4375
+ {
4376
+ "kind": "javascript-module",
4377
+ "path": "src/form/auto-suggest/auto-suggest.ts",
4378
+ "declarations": [
4379
+ {
4380
+ "kind": "class",
4381
+ "description": "",
4382
+ "name": "KRAutoSuggest",
4383
+ "slots": [
4384
+ {
4385
+ "description": "Not used",
4386
+ "name": ""
4387
+ }
4388
+ ],
4389
+ "members": [
4390
+ {
4391
+ "kind": "field",
4392
+ "name": "formAssociated",
4393
+ "type": {
4394
+ "text": "boolean"
4395
+ },
4396
+ "static": true,
4397
+ "default": "true"
4398
+ },
4399
+ {
4400
+ "kind": "field",
4401
+ "name": "label",
4402
+ "type": {
4403
+ "text": "string"
4404
+ },
4405
+ "default": "''",
4406
+ "description": "Label text for the input",
4407
+ "attribute": "label"
4408
+ },
4409
+ {
4410
+ "kind": "field",
4411
+ "name": "name",
4412
+ "type": {
4413
+ "text": "string"
4414
+ },
4415
+ "default": "''",
4416
+ "description": "Name for form submission",
4417
+ "attribute": "name"
4418
+ },
4419
+ {
4420
+ "kind": "field",
4421
+ "name": "value",
4422
+ "type": {
4423
+ "text": "string"
4424
+ },
4425
+ "default": "''",
4426
+ "description": "Current input value",
4427
+ "attribute": "value"
4428
+ },
4429
+ {
4430
+ "kind": "field",
4431
+ "name": "placeholder",
4432
+ "type": {
4433
+ "text": "string"
4434
+ },
4435
+ "default": "''",
4436
+ "description": "Placeholder text",
4437
+ "attribute": "placeholder"
4438
+ },
4439
+ {
4440
+ "kind": "field",
4441
+ "name": "disabled",
4442
+ "type": {
4443
+ "text": "boolean"
4444
+ },
4445
+ "default": "false",
4446
+ "description": "Whether the input is disabled",
4447
+ "attribute": "disabled"
4448
+ },
4449
+ {
4450
+ "kind": "field",
4451
+ "name": "readonly",
4452
+ "type": {
4453
+ "text": "boolean"
4454
+ },
4455
+ "default": "false",
4456
+ "description": "Whether the input is readonly",
4457
+ "attribute": "readonly"
4458
+ },
4459
+ {
4460
+ "kind": "field",
4461
+ "name": "required",
4462
+ "type": {
4463
+ "text": "boolean"
4464
+ },
4465
+ "default": "false",
4466
+ "description": "Whether the input is required",
4467
+ "attribute": "required"
4468
+ },
4469
+ {
4470
+ "kind": "field",
4471
+ "name": "hint",
4472
+ "type": {
4473
+ "text": "string"
4474
+ },
4475
+ "default": "''",
4476
+ "description": "Helper text displayed below the input",
4477
+ "attribute": "hint"
4478
+ },
4479
+ {
4480
+ "kind": "field",
4481
+ "name": "options",
4482
+ "type": {
4483
+ "text": "SuggestionOptions"
4484
+ },
4485
+ "default": "[]",
4486
+ "description": "Array of suggestion options or groups",
4487
+ "attribute": "options"
4488
+ },
4489
+ {
4490
+ "kind": "field",
4491
+ "name": "statusType",
4492
+ "type": {
4493
+ "text": "AutoSuggestStatusType"
4494
+ },
4495
+ "default": "'finished'",
4496
+ "description": "Loading state: 'pending' | 'loading' | 'finished' | 'error'",
4497
+ "attribute": "status-type"
4498
+ },
4499
+ {
4500
+ "kind": "field",
4501
+ "name": "loadingText",
4502
+ "type": {
4503
+ "text": "string"
4504
+ },
4505
+ "default": "'Loading...'",
4506
+ "description": "Text to show during loading",
4507
+ "attribute": "loading-text"
4508
+ },
4509
+ {
4510
+ "kind": "field",
4511
+ "name": "errorText",
4512
+ "type": {
4513
+ "text": "string"
4514
+ },
4515
+ "default": "'Error loading options'",
4516
+ "description": "Text to show on error",
4517
+ "attribute": "error-text"
4518
+ },
4519
+ {
4520
+ "kind": "field",
4521
+ "name": "emptyText",
4522
+ "type": {
4523
+ "text": "string"
4524
+ },
4525
+ "default": "'No matches found'",
4526
+ "description": "Text to show when no matches",
4527
+ "attribute": "empty-text"
4528
+ },
4529
+ {
4530
+ "kind": "field",
4531
+ "name": "filteringType",
4532
+ "type": {
4533
+ "text": "AutoSuggestFilteringType"
4534
+ },
4535
+ "default": "'auto'",
4536
+ "description": "'auto' (client-side) or 'manual' (server-side)",
4537
+ "attribute": "filtering-type"
4538
+ },
4539
+ {
4540
+ "kind": "field",
4541
+ "name": "highlightMatches",
4542
+ "type": {
4543
+ "text": "boolean"
4544
+ },
4545
+ "default": "true",
4546
+ "description": "Whether to highlight matching text",
4547
+ "attribute": "highlight-matches"
4548
+ },
4549
+ {
4550
+ "kind": "field",
4551
+ "name": "_isOpen",
4552
+ "type": {
4553
+ "text": "boolean"
4554
+ },
4555
+ "privacy": "private",
4556
+ "default": "false"
4557
+ },
4558
+ {
4559
+ "kind": "field",
4560
+ "name": "_highlightedIndex",
4561
+ "type": {
4562
+ "text": "number"
4563
+ },
4564
+ "privacy": "private",
4565
+ "default": "-1"
4566
+ },
4567
+ {
4568
+ "kind": "field",
4569
+ "name": "_touched",
4570
+ "type": {
4571
+ "text": "boolean"
4572
+ },
4573
+ "privacy": "private",
4574
+ "default": "false"
4575
+ },
4576
+ {
4577
+ "kind": "field",
4578
+ "name": "_dirty",
4579
+ "type": {
4580
+ "text": "boolean"
4581
+ },
4582
+ "privacy": "private",
4583
+ "default": "false"
4584
+ },
4585
+ {
4586
+ "kind": "field",
4587
+ "name": "_input",
4588
+ "type": {
4589
+ "text": "HTMLInputElement"
4590
+ },
4591
+ "privacy": "private"
4592
+ },
4593
+ {
4594
+ "kind": "field",
4595
+ "name": "_internals",
4596
+ "type": {
4597
+ "text": "ElementInternals"
4598
+ },
4599
+ "privacy": "private"
4600
+ },
4601
+ {
4602
+ "kind": "field",
4603
+ "name": "_handleDocumentClick",
4604
+ "privacy": "private"
4605
+ },
4606
+ {
4607
+ "kind": "field",
4608
+ "name": "form",
4609
+ "readonly": true
4610
+ },
4611
+ {
4612
+ "kind": "field",
4613
+ "name": "validity",
4614
+ "readonly": true
4615
+ },
4616
+ {
4617
+ "kind": "field",
4618
+ "name": "validationMessage",
4619
+ "readonly": true
4620
+ },
4621
+ {
4622
+ "kind": "method",
4623
+ "name": "checkValidity"
4624
+ },
4625
+ {
4626
+ "kind": "method",
4627
+ "name": "reportValidity"
4628
+ },
4629
+ {
4630
+ "kind": "method",
4631
+ "name": "formResetCallback"
4632
+ },
4633
+ {
4634
+ "kind": "method",
4635
+ "name": "formStateRestoreCallback",
4636
+ "parameters": [
4637
+ {
4638
+ "name": "state",
4639
+ "type": {
4640
+ "text": "string"
4641
+ }
4642
+ }
4643
+ ]
4644
+ },
4645
+ {
4646
+ "kind": "field",
4647
+ "name": "_filteredOptions",
4648
+ "type": {
4649
+ "text": "SuggestionOptions"
4650
+ },
4651
+ "privacy": "private",
4652
+ "readonly": true
4653
+ },
4654
+ {
4655
+ "kind": "field",
4656
+ "name": "_flatOptions",
4657
+ "type": {
4658
+ "text": "SuggestionOption[]"
4659
+ },
4660
+ "privacy": "private",
4661
+ "readonly": true
4662
+ },
4663
+ {
4664
+ "kind": "method",
4665
+ "name": "_updateFormValue",
4666
+ "privacy": "private",
4667
+ "return": {
4668
+ "type": {
4669
+ "text": "void"
4670
+ }
4671
+ }
4672
+ },
4673
+ {
4674
+ "kind": "method",
4675
+ "name": "_onInput",
4676
+ "privacy": "private",
4677
+ "return": {
4678
+ "type": {
4679
+ "text": "void"
4680
+ }
4681
+ },
4682
+ "parameters": [
4683
+ {
4684
+ "name": "e",
4685
+ "type": {
4686
+ "text": "Event"
4687
+ }
4688
+ }
4689
+ ]
4690
+ },
4691
+ {
4692
+ "kind": "method",
4693
+ "name": "_onFocus",
4694
+ "privacy": "private",
4695
+ "return": {
4696
+ "type": {
4697
+ "text": "void"
4698
+ }
4699
+ }
4700
+ },
4701
+ {
4702
+ "kind": "method",
4703
+ "name": "_onBlur",
4704
+ "privacy": "private",
4705
+ "return": {
4706
+ "type": {
4707
+ "text": "void"
4708
+ }
4709
+ }
4710
+ },
4711
+ {
4712
+ "kind": "method",
4713
+ "name": "_onKeyDown",
4714
+ "privacy": "private",
4715
+ "return": {
4716
+ "type": {
4717
+ "text": "void"
4718
+ }
4719
+ },
4720
+ "parameters": [
4721
+ {
4722
+ "name": "e",
4723
+ "type": {
4724
+ "text": "KeyboardEvent"
4725
+ }
4726
+ }
4727
+ ]
4728
+ },
4729
+ {
4730
+ "kind": "method",
4731
+ "name": "_scrollToHighlighted",
4732
+ "privacy": "private",
4733
+ "return": {
4734
+ "type": {
4735
+ "text": "void"
4736
+ }
4737
+ }
4738
+ },
4739
+ {
4740
+ "kind": "method",
4741
+ "name": "_selectOption",
4742
+ "privacy": "private",
4743
+ "return": {
4744
+ "type": {
4745
+ "text": "void"
4746
+ }
4747
+ },
4748
+ "parameters": [
4749
+ {
4750
+ "name": "option",
4751
+ "type": {
4752
+ "text": "SuggestionOption"
4753
+ }
4754
+ }
4755
+ ]
4756
+ },
4757
+ {
4758
+ "kind": "method",
4759
+ "name": "_handleClear",
4760
+ "privacy": "private",
4761
+ "return": {
4762
+ "type": {
4763
+ "text": "void"
4764
+ }
4765
+ }
4766
+ },
4767
+ {
4768
+ "kind": "method",
4769
+ "name": "_onDocumentClick",
4770
+ "privacy": "private",
4771
+ "return": {
4772
+ "type": {
4773
+ "text": "void"
4774
+ }
4775
+ },
4776
+ "parameters": [
4777
+ {
4778
+ "name": "e",
4779
+ "type": {
4780
+ "text": "Event"
4781
+ }
4782
+ }
4783
+ ]
4784
+ },
4785
+ {
4786
+ "kind": "method",
4787
+ "name": "_highlightMatch",
4788
+ "privacy": "private",
4789
+ "parameters": [
4790
+ {
4791
+ "name": "text",
4792
+ "type": {
4793
+ "text": "string"
4794
+ }
4795
+ }
4796
+ ]
4797
+ },
4798
+ {
4799
+ "kind": "method",
4800
+ "name": "_renderOption",
4801
+ "privacy": "private",
4802
+ "parameters": [
4803
+ {
4804
+ "name": "option",
4805
+ "type": {
4806
+ "text": "SuggestionOption"
4807
+ }
4808
+ },
4809
+ {
4810
+ "name": "index",
4811
+ "type": {
4812
+ "text": "number"
4813
+ }
4814
+ }
4815
+ ]
4816
+ },
4817
+ {
4818
+ "kind": "method",
4819
+ "name": "_renderDropdownContent",
4820
+ "privacy": "private"
4821
+ }
4822
+ ],
4823
+ "events": [
4824
+ {
4825
+ "name": "change",
4826
+ "type": {
4827
+ "text": "CustomEvent"
4828
+ },
4829
+ "description": "Fired when the input value changes"
4830
+ },
4831
+ {
4832
+ "name": "load-items",
4833
+ "type": {
4834
+ "text": "CustomEvent"
4835
+ },
4836
+ "description": "Fired when items should be loaded (manual filtering)"
4837
+ },
4838
+ {
4839
+ "name": "select",
4840
+ "type": {
4841
+ "text": "CustomEvent"
4842
+ },
4843
+ "description": "Fired when a suggestion is selected"
4844
+ }
4845
+ ],
4846
+ "attributes": [
4847
+ {
4848
+ "name": "label",
4849
+ "type": {
4850
+ "text": "string"
4851
+ },
4852
+ "default": "''",
4853
+ "description": "Label text for the input",
4854
+ "fieldName": "label"
4855
+ },
4856
+ {
4857
+ "name": "name",
4858
+ "type": {
4859
+ "text": "string"
4860
+ },
4861
+ "default": "''",
4862
+ "description": "Name for form submission",
4863
+ "fieldName": "name"
4864
+ },
4865
+ {
4866
+ "name": "value",
4867
+ "type": {
4868
+ "text": "string"
4869
+ },
4870
+ "default": "''",
4871
+ "description": "Current input value",
4872
+ "fieldName": "value"
4873
+ },
4874
+ {
4875
+ "name": "placeholder",
4876
+ "type": {
4877
+ "text": "string"
4878
+ },
4879
+ "default": "''",
4880
+ "description": "Placeholder text",
4881
+ "fieldName": "placeholder"
4882
+ },
4883
+ {
4884
+ "name": "disabled",
4885
+ "type": {
4886
+ "text": "boolean"
4887
+ },
4888
+ "default": "false",
4889
+ "description": "Whether the input is disabled",
4890
+ "fieldName": "disabled"
4891
+ },
4892
+ {
4893
+ "name": "readonly",
4894
+ "type": {
4895
+ "text": "boolean"
4896
+ },
4897
+ "default": "false",
4898
+ "description": "Whether the input is readonly",
4899
+ "fieldName": "readonly"
4900
+ },
4901
+ {
4902
+ "name": "required",
4903
+ "type": {
4904
+ "text": "boolean"
4905
+ },
4906
+ "default": "false",
4907
+ "description": "Whether the input is required",
4908
+ "fieldName": "required"
4909
+ },
4910
+ {
4911
+ "name": "hint",
4912
+ "type": {
4913
+ "text": "string"
4914
+ },
4915
+ "default": "''",
4916
+ "description": "Helper text displayed below the input",
4917
+ "fieldName": "hint"
4918
+ },
4919
+ {
4920
+ "name": "options",
4921
+ "type": {
4922
+ "text": "SuggestionOptions"
4923
+ },
4924
+ "default": "[]",
4925
+ "description": "Array of suggestion options or groups",
4926
+ "fieldName": "options"
4927
+ },
4928
+ {
4929
+ "name": "status-type",
4930
+ "type": {
4931
+ "text": "AutoSuggestStatusType"
4932
+ },
4933
+ "default": "'finished'",
4934
+ "description": "Loading state: 'pending' | 'loading' | 'finished' | 'error'",
4935
+ "fieldName": "statusType"
4936
+ },
4937
+ {
4938
+ "name": "loading-text",
4939
+ "type": {
4940
+ "text": "string"
4941
+ },
4942
+ "default": "'Loading...'",
4943
+ "description": "Text to show during loading",
4944
+ "fieldName": "loadingText"
4945
+ },
4946
+ {
4947
+ "name": "error-text",
4948
+ "type": {
4949
+ "text": "string"
4950
+ },
4951
+ "default": "'Error loading options'",
4952
+ "description": "Text to show on error",
4953
+ "fieldName": "errorText"
4954
+ },
4955
+ {
4956
+ "name": "empty-text",
4957
+ "type": {
4958
+ "text": "string"
4959
+ },
4960
+ "default": "'No matches found'",
4961
+ "description": "Text to show when no matches",
4962
+ "fieldName": "emptyText"
4963
+ },
4964
+ {
4965
+ "name": "filtering-type",
4966
+ "type": {
4967
+ "text": "AutoSuggestFilteringType"
4968
+ },
4969
+ "default": "'auto'",
4970
+ "description": "'auto' (client-side) or 'manual' (server-side)",
4971
+ "fieldName": "filteringType"
4972
+ },
4973
+ {
4974
+ "name": "highlight-matches",
4975
+ "type": {
4976
+ "text": "boolean"
4977
+ },
4978
+ "default": "true",
4979
+ "description": "Whether to highlight matching text",
4980
+ "fieldName": "highlightMatches"
4981
+ }
4982
+ ],
4983
+ "superclass": {
4984
+ "name": "LitElement",
4985
+ "package": "lit"
4986
+ },
4987
+ "tagName": "kr-auto-suggest",
4988
+ "customElement": true
4989
+ }
4990
+ ],
4991
+ "exports": [
4992
+ {
4993
+ "kind": "js",
4994
+ "name": "KRAutoSuggest",
4995
+ "declaration": {
4996
+ "name": "KRAutoSuggest",
4997
+ "module": "src/form/auto-suggest/auto-suggest.ts"
4998
+ }
4999
+ },
5000
+ {
5001
+ "kind": "custom-element-definition",
5002
+ "name": "kr-auto-suggest",
5003
+ "declaration": {
5004
+ "name": "KRAutoSuggest",
5005
+ "module": "src/form/auto-suggest/auto-suggest.ts"
5006
+ }
5007
+ }
5008
+ ]
5009
+ },
4256
5010
  {
4257
5011
  "kind": "javascript-module",
4258
5012
  "path": "src/form/detail-field/detail-field.ts",