@penn-libraries/web 1.1.0-dev.4 → 1.1.0-dev.5

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.
@@ -15,10 +15,23 @@ export class Autocomplete {
15
15
  }
16
16
  componentDidLoad() {
17
17
  this.setupInput();
18
+ this.setupMutationObserver();
18
19
  }
19
20
  disconnectedCallback() {
20
21
  if (this.blurTimeout)
21
22
  clearTimeout(this.blurTimeout);
23
+ if (this.mutationObserver)
24
+ this.mutationObserver.disconnect();
25
+ }
26
+ setupMutationObserver() {
27
+ this.mutationObserver = new MutationObserver(() => {
28
+ this.options = this.parseOptionsFromDOM();
29
+ });
30
+ this.mutationObserver.observe(this.el, {
31
+ childList: true,
32
+ subtree: true,
33
+ characterData: true
34
+ });
22
35
  }
23
36
  parseOptionsFromDOM() {
24
37
  const listbox = this.findListbox();
@@ -79,7 +92,6 @@ export class Autocomplete {
79
92
  handleInputEvent(event) {
80
93
  const input = event.target;
81
94
  if (this.isTrackedInput(input)) {
82
- // Reset active option when user manually changes input
83
95
  this.currentIndex = -1;
84
96
  this.openSuggestions();
85
97
  }
@@ -202,7 +214,6 @@ export class Autocomplete {
202
214
  const active = document.activeElement;
203
215
  return !((_a = this.el.shadowRoot) === null || _a === void 0 ? void 0 : _a.contains(active)) && active !== this.getInput();
204
216
  }
205
- // Input State Sync
206
217
  syncInputState() {
207
218
  const input = this.getInput();
208
219
  if (!input)
@@ -232,7 +243,7 @@ export class Autocomplete {
232
243
  return this.showSuggestions && this.options.length > 0 && this.isInputFocused();
233
244
  }
234
245
  render() {
235
- return (h("div", { key: 'c9d88ed9a19ef99b53d0849d03c0a64d4e08a39c' }, h("slot", { key: 'bc5c0c3e42f40269818cd7a8f78ec4bb5f5f0d49', name: "start" }), this.shouldShowListbox() && (h("ol", { key: '4ad4f80d38a7de2537f343ec02e1bad3e5c2b100', role: "listbox", id: "listbox" }, this.options.map((option, index) => (h("li", { role: "option", id: option.id, "aria-selected": this.currentIndex === index ? 'true' : 'false', tabindex: "-1", onClick: () => this.handleOptionClick(index), innerHTML: option.html })))))));
246
+ return (h("div", { key: '71422b55533372a9d8697e648e49f87fe223f4e0' }, h("slot", { key: '951511fd2090b9816c2e6c1a5a40169ea08e72fd', name: "start" }), this.shouldShowListbox() && (h("ol", { key: 'e3f6f14686bc99b6e25d34d8e053f01174f23438', role: "listbox", id: "listbox" }, this.options.map((option, index) => (h("li", { role: "option", id: option.id, "aria-selected": this.currentIndex === index ? 'true' : 'false', tabindex: "-1", onClick: () => this.handleOptionClick(index), innerHTML: option.html })))))));
236
247
  }
237
248
  static get is() { return "pennlibs-autocomplete"; }
238
249
  static get encapsulation() { return "shadow"; }
@@ -261,7 +272,7 @@ export class Autocomplete {
261
272
  "optional": true,
262
273
  "docs": {
263
274
  "tags": [],
264
- "text": "The id of the input element to attach autocomplete functionality to"
275
+ "text": ""
265
276
  },
266
277
  "getter": false,
267
278
  "setter": false,
@@ -286,7 +297,7 @@ export class Autocomplete {
286
297
  "composed": true,
287
298
  "docs": {
288
299
  "tags": [],
289
- "text": "Emitted when a user activates (selects) an autocomplete option"
300
+ "text": ""
290
301
  },
291
302
  "complexType": {
292
303
  "original": "ActivatedEvent",
@@ -1 +1 @@
1
- {"version":3,"file":"pennlibs-autocomplete.js","sourceRoot":"","sources":["../../../src/components/pennlibs-autocomplete/pennlibs-autocomplete.tsx"],"names":[],"mappings":"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","sourcesContent":["import { Component, h, Element, State, Listen, Event, EventEmitter, Prop } from '@stencil/core';\n\ninterface ListboxOption {\n id: string;\n html: string;\n value: string;\n}\n\nexport interface ActivatedEvent {\n value: string;\n index: number;\n}\n\n@Component({\n tag: 'pennlibs-autocomplete',\n styleUrl: 'pennlibs-autocomplete.css',\n shadow: true\n})\nexport class Autocomplete {\n @Element() el!: HTMLElement;\n\n /**\n * The id of the input element to attach autocomplete functionality to\n */\n @Prop() for?: string;\n\n @State() showSuggestions: boolean = false;\n @State() currentIndex: number = -1;\n @State() originalValue: string = '';\n @State() options: ListboxOption[] = [];\n\n /**\n * Emitted when a user activates (selects) an autocomplete option\n */\n @Event({ eventName: 'pl:activated' }) activated: EventEmitter<ActivatedEvent>;\n\n private blurTimeout: number;\n\n componentWillLoad() {\n this.options = this.parseOptionsFromDOM();\n }\n\n componentDidLoad() {\n this.setupInput();\n }\n\n disconnectedCallback() {\n if (this.blurTimeout) clearTimeout(this.blurTimeout);\n }\n\n private parseOptionsFromDOM(): ListboxOption[] {\n const listbox = this.findListbox();\n if (!listbox) return [];\n\n const elements = Array.from(listbox.querySelectorAll('[role=\"option\"]')) as HTMLElement[];\n return elements.map((el, i) => this.createOption(el, i));\n }\n\n private findListbox(): HTMLOListElement | null {\n return Array.from(this.el.children).find(child =>\n child.matches('ol[role=\"listbox\"]')\n ) as HTMLOListElement;\n }\n\n private createOption(element: HTMLElement, index: number): ListboxOption {\n return {\n id: element.id || `option-${index}`,\n html: element.innerHTML,\n value: element.getAttribute('data-pl-value') || element.textContent?.trim() || ''\n };\n }\n\n private getInput(): HTMLInputElement | null {\n if (!this.for) return null;\n\n const slot = this.el.shadowRoot?.querySelector('slot[name=\"start\"]') as HTMLSlotElement;\n const input = slot.assignedElements()[0].querySelector(`input#${this.for}`) as HTMLInputElement;\n\n return input || null\n }\n\n private isInputFocused(): boolean {\n return this.getInput() === document.activeElement;\n }\n\n private isTrackedInput(input: HTMLInputElement): boolean {\n return input?.getAttribute('data-pl-autocomplete-connected') === 'true' &&\n this.el.contains(input);\n }\n\n private setupInput(): void {\n if (!this.for) {\n console.warn('<pennlibs-autocomplete> Missing \"for\" attribute. Please add for=\"input-id\" to specify which input to attach to.');\n return;\n }\n\n const input = this.getInput();\n if (!input) {\n console.warn(`<pennlibs-autocomplete> No input element found with id=\"${this.for}\". Ensure an input with this id exists.`);\n return;\n }\n\n this.setComboboxAttributes(input);\n input.setAttribute('data-pl-autocomplete-connected', 'true');\n }\n\n private setComboboxAttributes(input: HTMLInputElement): void {\n input.setAttribute('role', 'combobox');\n input.setAttribute('aria-autocomplete', 'list');\n input.setAttribute('aria-expanded', 'false');\n input.setAttribute('aria-controls', 'listbox');\n }\n\n @Listen('slotchange')\n handleSlotChange() {\n this.options = this.parseOptionsFromDOM();\n this.setupInput();\n }\n\n @Listen('input', { target: 'body' })\n handleInputEvent(event: Event) {\n const input = event.target as HTMLInputElement;\n if (this.isTrackedInput(input)) {\n // Reset active option when user manually changes input\n this.currentIndex = -1;\n this.openSuggestions();\n }\n }\n\n @Listen('focus', { target: 'body' })\n handleFocusEvent(event: Event) {\n const input = event.target as HTMLInputElement;\n if (this.isTrackedInput(input)) this.showSuggestionsPanel();\n }\n\n @Listen('blur', { target: 'body' })\n handleBlurEvent(event: Event) {\n const input = event.target as HTMLInputElement;\n if (this.isTrackedInput(input)) this.deferCloseSuggestions();\n }\n\n @Listen('focusout')\n handleFocusOut(event: FocusEvent) {\n if (this.isFocusLeavingComponent(event)) this.closeSuggestions();\n }\n\n @Listen('keydown', { target: 'document' })\n handleKeyDown(event: KeyboardEvent) {\n if (!this.isInputFocused()) return;\n if (event.metaKey || event.ctrlKey) return; // Ignore keyboard shortcuts\n\n const handler = this.keyHandlers()[event.key];\n if (handler) {\n event.preventDefault();\n handler();\n }\n }\n\n private keyHandlers() {\n return {\n 'Escape': () => this.handleEscape(),\n 'ArrowDown': () => this.handleArrowDown(),\n 'ArrowUp': () => this.handleArrowUp(),\n 'Enter': () => this.handleEnter()\n };\n }\n\n private handleEscape() {\n this.reset();\n this.syncInputState();\n }\n\n private handleArrowDown() {\n if (!this.showSuggestions) return;\n this.moveNext();\n this.syncInputState();\n }\n\n private handleArrowUp() {\n if (!this.showSuggestions) return;\n this.movePrevious();\n this.syncInputState();\n }\n\n private handleEnter() {\n if (this.canSelect()) this.selectCurrent();\n }\n\n // Navigation\n private moveNext(): void {\n const lastIndex = this.options.length - 1;\n this.currentIndex = this.currentIndex < lastIndex ? this.currentIndex + 1 : -1;\n }\n\n private movePrevious(): void {\n const lastIndex = this.options.length - 1;\n this.currentIndex = this.currentIndex > -1 ? this.currentIndex - 1 : lastIndex;\n }\n\n private canSelect(): boolean {\n return this.showSuggestions && this.currentIndex >= 0;\n }\n\n private selectCurrent(): void {\n if (this.currentIndex < 0) return;\n\n const selectedOption = this.options[this.currentIndex];\n const input = this.getInput();\n\n if (input) {\n input.value = selectedOption.value;\n this.originalValue = selectedOption.value;\n }\n\n this.activated.emit({\n index: this.currentIndex,\n value: selectedOption.value\n });\n\n this.closeSuggestions();\n }\n\n private handleOptionClick = (index: number): void => {\n this.currentIndex = index;\n this.selectCurrent();\n }\n\n private openSuggestions(): void {\n if (!this.isInputFocused()) return;\n\n const input = this.getInput();\n if (input) this.originalValue = input.value;\n\n this.showSuggestionsPanel();\n this.syncInputState();\n }\n\n private showSuggestionsPanel(): void {\n this.showSuggestions = true;\n this.syncInputState();\n }\n\n private closeSuggestions(): void {\n this.reset();\n this.syncInputState();\n }\n\n private deferCloseSuggestions(): void {\n this.blurTimeout = setTimeout(() => {\n if (this.isFocusOutsideComponent()) this.closeSuggestions();\n }, 150) as unknown as number;\n }\n\n private reset(): void {\n this.showSuggestions = false;\n this.currentIndex = -1;\n }\n\n private isFocusLeavingComponent(event: FocusEvent): boolean {\n const target = event.relatedTarget as HTMLElement;\n return !target ||\n (!this.el.contains(target) && !this.el.shadowRoot?.contains(target));\n }\n\n private isFocusOutsideComponent(): boolean {\n const active = document.activeElement;\n return !this.el.shadowRoot?.contains(active) && active !== this.getInput();\n }\n\n // Input State Sync\n private syncInputState(): void {\n const input = this.getInput();\n if (!input) return;\n\n this.updateAriaExpanded(input);\n this.updateAriaActiveDescendant(input);\n this.updateInputValue(input);\n }\n\n private updateAriaExpanded(input: HTMLInputElement): void {\n input.setAttribute('aria-expanded', this.showSuggestions.toString());\n }\n\n private updateAriaActiveDescendant(input: HTMLInputElement): void {\n const hasSelection = this.showSuggestions && this.currentIndex >= 0;\n if (hasSelection && this.options[this.currentIndex]) {\n input.setAttribute('aria-activedescendant', this.options[this.currentIndex].id);\n } else {\n input.removeAttribute('aria-activedescendant');\n }\n }\n\n private updateInputValue(input: HTMLInputElement): void {\n input.value = this.currentIndex >= 0\n ? this.options[this.currentIndex].value\n : this.originalValue;\n }\n\n private shouldShowListbox(): boolean {\n return this.showSuggestions && this.options.length > 0 && this.isInputFocused();\n }\n\n render() {\n return (\n <div>\n <slot name=\"start\" />\n {this.shouldShowListbox() && (\n <ol role=\"listbox\" id=\"listbox\">\n {this.options.map((option, index) => (\n <li\n role=\"option\"\n id={option.id}\n aria-selected={this.currentIndex === index ? 'true' : 'false'}\n tabindex=\"-1\"\n onClick={() => this.handleOptionClick(index)}\n innerHTML={option.html}\n />\n ))}\n </ol>\n )}\n </div>\n )\n }\n}\n"]}
1
+ {"version":3,"file":"pennlibs-autocomplete.js","sourceRoot":"","sources":["../../../src/components/pennlibs-autocomplete/pennlibs-autocomplete.tsx"],"names":[],"mappings":"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","sourcesContent":["import { Component, h, Element, State, Listen, Event, EventEmitter, Prop } from '@stencil/core';\n\ninterface ListboxOption {\n id: string;\n html: string;\n value: string;\n}\n\nexport interface ActivatedEvent {\n value: string;\n index: number;\n}\n\n@Component({\n tag: 'pennlibs-autocomplete',\n styleUrl: 'pennlibs-autocomplete.css',\n shadow: true\n})\nexport class Autocomplete {\n @Element() el!: HTMLElement;\n\n @Prop() for?: string;\n\n @State() showSuggestions: boolean = false;\n @State() currentIndex: number = -1;\n @State() originalValue: string = '';\n @State() options: ListboxOption[] = [];\n\n @Event({ eventName: 'pl:activated' }) activated: EventEmitter<ActivatedEvent>;\n\n private blurTimeout: number;\n private mutationObserver: MutationObserver;\n\n componentWillLoad() {\n this.options = this.parseOptionsFromDOM();\n }\n\n componentDidLoad() {\n this.setupInput();\n this.setupMutationObserver();\n }\n\n disconnectedCallback() {\n if (this.blurTimeout) clearTimeout(this.blurTimeout);\n if (this.mutationObserver) this.mutationObserver.disconnect();\n }\n\n private setupMutationObserver(): void {\n this.mutationObserver = new MutationObserver(() => {\n this.options = this.parseOptionsFromDOM();\n });\n\n this.mutationObserver.observe(this.el, {\n childList: true,\n subtree: true,\n characterData: true\n });\n }\n\n private parseOptionsFromDOM(): ListboxOption[] {\n const listbox = this.findListbox();\n if (!listbox) return [];\n\n const elements = Array.from(listbox.querySelectorAll('[role=\"option\"]')) as HTMLElement[];\n return elements.map((el, i) => this.createOption(el, i));\n }\n\n private findListbox(): HTMLOListElement | null {\n return Array.from(this.el.children).find(child =>\n child.matches('ol[role=\"listbox\"]')\n ) as HTMLOListElement;\n }\n\n private createOption(element: HTMLElement, index: number): ListboxOption {\n return {\n id: element.id || `option-${index}`,\n html: element.innerHTML,\n value: element.getAttribute('data-pl-value') || element.textContent?.trim() || ''\n };\n }\n\n private getInput(): HTMLInputElement | null {\n if (!this.for) return null;\n\n const slot = this.el.shadowRoot?.querySelector('slot[name=\"start\"]') as HTMLSlotElement;\n const input = slot.assignedElements()[0].querySelector(`input#${this.for}`) as HTMLInputElement;\n\n return input || null\n }\n\n private isInputFocused(): boolean {\n return this.getInput() === document.activeElement;\n }\n\n private isTrackedInput(input: HTMLInputElement): boolean {\n return input?.getAttribute('data-pl-autocomplete-connected') === 'true' &&\n this.el.contains(input);\n }\n\n private setupInput(): void {\n if (!this.for) {\n console.warn('<pennlibs-autocomplete> Missing \"for\" attribute. Please add for=\"input-id\" to specify which input to attach to.');\n return;\n }\n\n const input = this.getInput();\n if (!input) {\n console.warn(`<pennlibs-autocomplete> No input element found with id=\"${this.for}\". Ensure an input with this id exists.`);\n return;\n }\n\n this.setComboboxAttributes(input);\n input.setAttribute('data-pl-autocomplete-connected', 'true');\n }\n\n private setComboboxAttributes(input: HTMLInputElement): void {\n input.setAttribute('role', 'combobox');\n input.setAttribute('aria-autocomplete', 'list');\n input.setAttribute('aria-expanded', 'false');\n input.setAttribute('aria-controls', 'listbox');\n }\n\n @Listen('slotchange')\n handleSlotChange() {\n this.options = this.parseOptionsFromDOM();\n this.setupInput();\n }\n\n @Listen('input', { target: 'body' })\n handleInputEvent(event: Event) {\n const input = event.target as HTMLInputElement;\n if (this.isTrackedInput(input)) {\n this.currentIndex = -1;\n this.openSuggestions();\n }\n }\n\n @Listen('focus', { target: 'body' })\n handleFocusEvent(event: Event) {\n const input = event.target as HTMLInputElement;\n if (this.isTrackedInput(input)) this.showSuggestionsPanel();\n }\n\n @Listen('blur', { target: 'body' })\n handleBlurEvent(event: Event) {\n const input = event.target as HTMLInputElement;\n if (this.isTrackedInput(input)) this.deferCloseSuggestions();\n }\n\n @Listen('focusout')\n handleFocusOut(event: FocusEvent) {\n if (this.isFocusLeavingComponent(event)) this.closeSuggestions();\n }\n\n @Listen('keydown', { target: 'document' })\n handleKeyDown(event: KeyboardEvent) {\n if (!this.isInputFocused()) return;\n if (event.metaKey || event.ctrlKey) return; // Ignore keyboard shortcuts\n\n const handler = this.keyHandlers()[event.key];\n if (handler) {\n event.preventDefault();\n handler();\n }\n }\n\n private keyHandlers() {\n return {\n 'Escape': () => this.handleEscape(),\n 'ArrowDown': () => this.handleArrowDown(),\n 'ArrowUp': () => this.handleArrowUp(),\n 'Enter': () => this.handleEnter()\n };\n }\n\n private handleEscape() {\n this.reset();\n this.syncInputState();\n }\n\n private handleArrowDown() {\n if (!this.showSuggestions) return;\n this.moveNext();\n this.syncInputState();\n }\n\n private handleArrowUp() {\n if (!this.showSuggestions) return;\n this.movePrevious();\n this.syncInputState();\n }\n\n private handleEnter() {\n if (this.canSelect()) this.selectCurrent();\n }\n\n // Navigation\n private moveNext(): void {\n const lastIndex = this.options.length - 1;\n this.currentIndex = this.currentIndex < lastIndex ? this.currentIndex + 1 : -1;\n }\n\n private movePrevious(): void {\n const lastIndex = this.options.length - 1;\n this.currentIndex = this.currentIndex > -1 ? this.currentIndex - 1 : lastIndex;\n }\n\n private canSelect(): boolean {\n return this.showSuggestions && this.currentIndex >= 0;\n }\n\n private selectCurrent(): void {\n if (this.currentIndex < 0) return;\n\n const selectedOption = this.options[this.currentIndex];\n const input = this.getInput();\n\n if (input) {\n input.value = selectedOption.value;\n this.originalValue = selectedOption.value;\n }\n\n this.activated.emit({\n index: this.currentIndex,\n value: selectedOption.value\n });\n\n this.closeSuggestions();\n }\n\n private handleOptionClick = (index: number): void => {\n this.currentIndex = index;\n this.selectCurrent();\n }\n\n private openSuggestions(): void {\n if (!this.isInputFocused()) return;\n\n const input = this.getInput();\n if (input) this.originalValue = input.value;\n\n this.showSuggestionsPanel();\n this.syncInputState();\n }\n\n private showSuggestionsPanel(): void {\n this.showSuggestions = true;\n this.syncInputState();\n }\n\n private closeSuggestions(): void {\n this.reset();\n this.syncInputState();\n }\n\n private deferCloseSuggestions(): void {\n this.blurTimeout = setTimeout(() => {\n if (this.isFocusOutsideComponent()) this.closeSuggestions();\n }, 150) as unknown as number;\n }\n\n private reset(): void {\n this.showSuggestions = false;\n this.currentIndex = -1;\n }\n\n private isFocusLeavingComponent(event: FocusEvent): boolean {\n const target = event.relatedTarget as HTMLElement;\n return !target ||\n (!this.el.contains(target) && !this.el.shadowRoot?.contains(target));\n }\n\n private isFocusOutsideComponent(): boolean {\n const active = document.activeElement;\n return !this.el.shadowRoot?.contains(active) && active !== this.getInput();\n }\n\n private syncInputState(): void {\n const input = this.getInput();\n if (!input) return;\n\n this.updateAriaExpanded(input);\n this.updateAriaActiveDescendant(input);\n this.updateInputValue(input);\n }\n\n private updateAriaExpanded(input: HTMLInputElement): void {\n input.setAttribute('aria-expanded', this.showSuggestions.toString());\n }\n\n private updateAriaActiveDescendant(input: HTMLInputElement): void {\n const hasSelection = this.showSuggestions && this.currentIndex >= 0;\n if (hasSelection && this.options[this.currentIndex]) {\n input.setAttribute('aria-activedescendant', this.options[this.currentIndex].id);\n } else {\n input.removeAttribute('aria-activedescendant');\n }\n }\n\n private updateInputValue(input: HTMLInputElement): void {\n input.value = this.currentIndex >= 0\n ? this.options[this.currentIndex].value\n : this.originalValue;\n }\n\n private shouldShowListbox(): boolean {\n return this.showSuggestions && this.options.length > 0 && this.isInputFocused();\n }\n\n render() {\n return (\n <div>\n <slot name=\"start\" />\n {this.shouldShowListbox() && (\n <ol role=\"listbox\" id=\"listbox\">\n {this.options.map((option, index) => (\n <li\n role=\"option\"\n id={option.id}\n aria-selected={this.currentIndex === index ? 'true' : 'false'}\n tabindex=\"-1\"\n onClick={() => this.handleOptionClick(index)}\n innerHTML={option.html}\n />\n ))}\n </ol>\n )}\n </div>\n )\n }\n}\n"]}
@@ -22,10 +22,23 @@ const Autocomplete = /*@__PURE__*/ proxyCustomElement(class Autocomplete extends
22
22
  }
23
23
  componentDidLoad() {
24
24
  this.setupInput();
25
+ this.setupMutationObserver();
25
26
  }
26
27
  disconnectedCallback() {
27
28
  if (this.blurTimeout)
28
29
  clearTimeout(this.blurTimeout);
30
+ if (this.mutationObserver)
31
+ this.mutationObserver.disconnect();
32
+ }
33
+ setupMutationObserver() {
34
+ this.mutationObserver = new MutationObserver(() => {
35
+ this.options = this.parseOptionsFromDOM();
36
+ });
37
+ this.mutationObserver.observe(this.el, {
38
+ childList: true,
39
+ subtree: true,
40
+ characterData: true
41
+ });
29
42
  }
30
43
  parseOptionsFromDOM() {
31
44
  const listbox = this.findListbox();
@@ -86,7 +99,6 @@ const Autocomplete = /*@__PURE__*/ proxyCustomElement(class Autocomplete extends
86
99
  handleInputEvent(event) {
87
100
  const input = event.target;
88
101
  if (this.isTrackedInput(input)) {
89
- // Reset active option when user manually changes input
90
102
  this.currentIndex = -1;
91
103
  this.openSuggestions();
92
104
  }
@@ -209,7 +221,6 @@ const Autocomplete = /*@__PURE__*/ proxyCustomElement(class Autocomplete extends
209
221
  const active = document.activeElement;
210
222
  return !((_a = this.el.shadowRoot) === null || _a === void 0 ? void 0 : _a.contains(active)) && active !== this.getInput();
211
223
  }
212
- // Input State Sync
213
224
  syncInputState() {
214
225
  const input = this.getInput();
215
226
  if (!input)
@@ -239,7 +250,7 @@ const Autocomplete = /*@__PURE__*/ proxyCustomElement(class Autocomplete extends
239
250
  return this.showSuggestions && this.options.length > 0 && this.isInputFocused();
240
251
  }
241
252
  render() {
242
- return (h("div", { key: 'c9d88ed9a19ef99b53d0849d03c0a64d4e08a39c' }, h("slot", { key: 'bc5c0c3e42f40269818cd7a8f78ec4bb5f5f0d49', name: "start" }), this.shouldShowListbox() && (h("ol", { key: '4ad4f80d38a7de2537f343ec02e1bad3e5c2b100', role: "listbox", id: "listbox" }, this.options.map((option, index) => (h("li", { role: "option", id: option.id, "aria-selected": this.currentIndex === index ? 'true' : 'false', tabindex: "-1", onClick: () => this.handleOptionClick(index), innerHTML: option.html })))))));
253
+ return (h("div", { key: '71422b55533372a9d8697e648e49f87fe223f4e0' }, h("slot", { key: '951511fd2090b9816c2e6c1a5a40169ea08e72fd', name: "start" }), this.shouldShowListbox() && (h("ol", { key: 'e3f6f14686bc99b6e25d34d8e053f01174f23438', role: "listbox", id: "listbox" }, this.options.map((option, index) => (h("li", { role: "option", id: option.id, "aria-selected": this.currentIndex === index ? 'true' : 'false', tabindex: "-1", onClick: () => this.handleOptionClick(index), innerHTML: option.html })))))));
243
254
  }
244
255
  get el() { return this; }
245
256
  static get style() { return pennlibsAutocompleteCss; }
@@ -1 +1 @@
1
- {"file":"pennlibs-autocomplete.js","mappings":"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","names":["__stencil_proxyCustomElement"],"sources":["src/components/pennlibs-autocomplete/pennlibs-autocomplete.css?tag=pennlibs-autocomplete&encapsulation=shadow","src/components/pennlibs-autocomplete/pennlibs-autocomplete.tsx"],"sourcesContent":[":host {\n display: block;\n width: 100%;\n border-radius: 1.25rem;\n padding: 0;\n border-top: 0;\n position: relative;\n}\n\n[role=listbox] {\n position: absolute;\n margin-top: var(--pl-space-xs);\n background: var(--pl-color-bg-default);\n border-radius: 1.25rem;\n box-shadow: rgba(140, 149, 159, 0.3) 0px 8px 24px 0px;\n width: 100%;\n overflow: hidden;\n z-index: 1;\n\n display: flex;\n flex-direction: column;\n}\n\np {\n margin: 0;\n font-size: var(--pl-font-size-s);\n color: var(--pl-color-fg-subtle);\n padding: var(--pl-space-xs) calc(var(--pl-space-m) + var(--pl-space-2xs));\n font-size: var(--pl-font-size-s);\n order: 2;\n font-weight: 500;\n background: var(--pl-color-bg-subtle);\n border-radius: 0 0 1.25rem 1.25rem;\n\n display: flex;\n gap: var(--pl-space-s) var(--pl-space-l);\n flex-wrap: wrap;\n}\n\nol {\n list-style: none;\n margin: 0;\n padding: var(--pl-space-xs) 0;\n order: 1;\n}\n\n[role=option] {\n color: var(--pl-color-fg-default);\n padding: var(--pl-space-s) calc(var(--pl-space-m) + var(--pl-space-2xs));\n text-decoration: none;\n font-weight: 700; \n\n &:hover {\n cursor: pointer;\n }\n\n &:hover,\n &:focus {\n text-decoration-thickness: 2px;\n text-underline-offset: 2px;\n text-decoration: underline;\n }\n}\n\n[aria-selected=true] {\n text-decoration-thickness: 2px;\n text-underline-offset: 2px;\n text-decoration: underline;\n}\n\nmark {\n background: none;\n font-weight: 400;\n}\n\n.suggestion--border {\n border-bottom: solid 1px rgb(from var(--pl-color-fg-default) r g b / 0.2);\n padding-bottom: calc(var(--pl-space-2xs) + var(--pl-space-s));\n margin-bottom: var(--pl-space-2xs);\n}","import { Component, h, Element, State, Listen, Event, EventEmitter, Prop } from '@stencil/core';\n\ninterface ListboxOption {\n id: string;\n html: string;\n value: string;\n}\n\nexport interface ActivatedEvent {\n value: string;\n index: number;\n}\n\n@Component({\n tag: 'pennlibs-autocomplete',\n styleUrl: 'pennlibs-autocomplete.css',\n shadow: true\n})\nexport class Autocomplete {\n @Element() el!: HTMLElement;\n\n /**\n * The id of the input element to attach autocomplete functionality to\n */\n @Prop() for?: string;\n\n @State() showSuggestions: boolean = false;\n @State() currentIndex: number = -1;\n @State() originalValue: string = '';\n @State() options: ListboxOption[] = [];\n\n /**\n * Emitted when a user activates (selects) an autocomplete option\n */\n @Event({ eventName: 'pl:activated' }) activated: EventEmitter<ActivatedEvent>;\n\n private blurTimeout: number;\n\n componentWillLoad() {\n this.options = this.parseOptionsFromDOM();\n }\n\n componentDidLoad() {\n this.setupInput();\n }\n\n disconnectedCallback() {\n if (this.blurTimeout) clearTimeout(this.blurTimeout);\n }\n\n private parseOptionsFromDOM(): ListboxOption[] {\n const listbox = this.findListbox();\n if (!listbox) return [];\n\n const elements = Array.from(listbox.querySelectorAll('[role=\"option\"]')) as HTMLElement[];\n return elements.map((el, i) => this.createOption(el, i));\n }\n\n private findListbox(): HTMLOListElement | null {\n return Array.from(this.el.children).find(child =>\n child.matches('ol[role=\"listbox\"]')\n ) as HTMLOListElement;\n }\n\n private createOption(element: HTMLElement, index: number): ListboxOption {\n return {\n id: element.id || `option-${index}`,\n html: element.innerHTML,\n value: element.getAttribute('data-pl-value') || element.textContent?.trim() || ''\n };\n }\n\n private getInput(): HTMLInputElement | null {\n if (!this.for) return null;\n\n const slot = this.el.shadowRoot?.querySelector('slot[name=\"start\"]') as HTMLSlotElement;\n const input = slot.assignedElements()[0].querySelector(`input#${this.for}`) as HTMLInputElement;\n\n return input || null\n }\n\n private isInputFocused(): boolean {\n return this.getInput() === document.activeElement;\n }\n\n private isTrackedInput(input: HTMLInputElement): boolean {\n return input?.getAttribute('data-pl-autocomplete-connected') === 'true' &&\n this.el.contains(input);\n }\n\n private setupInput(): void {\n if (!this.for) {\n console.warn('<pennlibs-autocomplete> Missing \"for\" attribute. Please add for=\"input-id\" to specify which input to attach to.');\n return;\n }\n\n const input = this.getInput();\n if (!input) {\n console.warn(`<pennlibs-autocomplete> No input element found with id=\"${this.for}\". Ensure an input with this id exists.`);\n return;\n }\n\n this.setComboboxAttributes(input);\n input.setAttribute('data-pl-autocomplete-connected', 'true');\n }\n\n private setComboboxAttributes(input: HTMLInputElement): void {\n input.setAttribute('role', 'combobox');\n input.setAttribute('aria-autocomplete', 'list');\n input.setAttribute('aria-expanded', 'false');\n input.setAttribute('aria-controls', 'listbox');\n }\n\n @Listen('slotchange')\n handleSlotChange() {\n this.options = this.parseOptionsFromDOM();\n this.setupInput();\n }\n\n @Listen('input', { target: 'body' })\n handleInputEvent(event: Event) {\n const input = event.target as HTMLInputElement;\n if (this.isTrackedInput(input)) {\n // Reset active option when user manually changes input\n this.currentIndex = -1;\n this.openSuggestions();\n }\n }\n\n @Listen('focus', { target: 'body' })\n handleFocusEvent(event: Event) {\n const input = event.target as HTMLInputElement;\n if (this.isTrackedInput(input)) this.showSuggestionsPanel();\n }\n\n @Listen('blur', { target: 'body' })\n handleBlurEvent(event: Event) {\n const input = event.target as HTMLInputElement;\n if (this.isTrackedInput(input)) this.deferCloseSuggestions();\n }\n\n @Listen('focusout')\n handleFocusOut(event: FocusEvent) {\n if (this.isFocusLeavingComponent(event)) this.closeSuggestions();\n }\n\n @Listen('keydown', { target: 'document' })\n handleKeyDown(event: KeyboardEvent) {\n if (!this.isInputFocused()) return;\n if (event.metaKey || event.ctrlKey) return; // Ignore keyboard shortcuts\n\n const handler = this.keyHandlers()[event.key];\n if (handler) {\n event.preventDefault();\n handler();\n }\n }\n\n private keyHandlers() {\n return {\n 'Escape': () => this.handleEscape(),\n 'ArrowDown': () => this.handleArrowDown(),\n 'ArrowUp': () => this.handleArrowUp(),\n 'Enter': () => this.handleEnter()\n };\n }\n\n private handleEscape() {\n this.reset();\n this.syncInputState();\n }\n\n private handleArrowDown() {\n if (!this.showSuggestions) return;\n this.moveNext();\n this.syncInputState();\n }\n\n private handleArrowUp() {\n if (!this.showSuggestions) return;\n this.movePrevious();\n this.syncInputState();\n }\n\n private handleEnter() {\n if (this.canSelect()) this.selectCurrent();\n }\n\n // Navigation\n private moveNext(): void {\n const lastIndex = this.options.length - 1;\n this.currentIndex = this.currentIndex < lastIndex ? this.currentIndex + 1 : -1;\n }\n\n private movePrevious(): void {\n const lastIndex = this.options.length - 1;\n this.currentIndex = this.currentIndex > -1 ? this.currentIndex - 1 : lastIndex;\n }\n\n private canSelect(): boolean {\n return this.showSuggestions && this.currentIndex >= 0;\n }\n\n private selectCurrent(): void {\n if (this.currentIndex < 0) return;\n\n const selectedOption = this.options[this.currentIndex];\n const input = this.getInput();\n\n if (input) {\n input.value = selectedOption.value;\n this.originalValue = selectedOption.value;\n }\n\n this.activated.emit({\n index: this.currentIndex,\n value: selectedOption.value\n });\n\n this.closeSuggestions();\n }\n\n private handleOptionClick = (index: number): void => {\n this.currentIndex = index;\n this.selectCurrent();\n }\n\n private openSuggestions(): void {\n if (!this.isInputFocused()) return;\n\n const input = this.getInput();\n if (input) this.originalValue = input.value;\n\n this.showSuggestionsPanel();\n this.syncInputState();\n }\n\n private showSuggestionsPanel(): void {\n this.showSuggestions = true;\n this.syncInputState();\n }\n\n private closeSuggestions(): void {\n this.reset();\n this.syncInputState();\n }\n\n private deferCloseSuggestions(): void {\n this.blurTimeout = setTimeout(() => {\n if (this.isFocusOutsideComponent()) this.closeSuggestions();\n }, 150) as unknown as number;\n }\n\n private reset(): void {\n this.showSuggestions = false;\n this.currentIndex = -1;\n }\n\n private isFocusLeavingComponent(event: FocusEvent): boolean {\n const target = event.relatedTarget as HTMLElement;\n return !target ||\n (!this.el.contains(target) && !this.el.shadowRoot?.contains(target));\n }\n\n private isFocusOutsideComponent(): boolean {\n const active = document.activeElement;\n return !this.el.shadowRoot?.contains(active) && active !== this.getInput();\n }\n\n // Input State Sync\n private syncInputState(): void {\n const input = this.getInput();\n if (!input) return;\n\n this.updateAriaExpanded(input);\n this.updateAriaActiveDescendant(input);\n this.updateInputValue(input);\n }\n\n private updateAriaExpanded(input: HTMLInputElement): void {\n input.setAttribute('aria-expanded', this.showSuggestions.toString());\n }\n\n private updateAriaActiveDescendant(input: HTMLInputElement): void {\n const hasSelection = this.showSuggestions && this.currentIndex >= 0;\n if (hasSelection && this.options[this.currentIndex]) {\n input.setAttribute('aria-activedescendant', this.options[this.currentIndex].id);\n } else {\n input.removeAttribute('aria-activedescendant');\n }\n }\n\n private updateInputValue(input: HTMLInputElement): void {\n input.value = this.currentIndex >= 0\n ? this.options[this.currentIndex].value\n : this.originalValue;\n }\n\n private shouldShowListbox(): boolean {\n return this.showSuggestions && this.options.length > 0 && this.isInputFocused();\n }\n\n render() {\n return (\n <div>\n <slot name=\"start\" />\n {this.shouldShowListbox() && (\n <ol role=\"listbox\" id=\"listbox\">\n {this.options.map((option, index) => (\n <li\n role=\"option\"\n id={option.id}\n aria-selected={this.currentIndex === index ? 'true' : 'false'}\n tabindex=\"-1\"\n onClick={() => this.handleOptionClick(index)}\n innerHTML={option.html}\n />\n ))}\n </ol>\n )}\n </div>\n )\n }\n}\n"],"version":3}
1
+ {"file":"pennlibs-autocomplete.js","mappings":"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","names":["__stencil_proxyCustomElement"],"sources":["src/components/pennlibs-autocomplete/pennlibs-autocomplete.css?tag=pennlibs-autocomplete&encapsulation=shadow","src/components/pennlibs-autocomplete/pennlibs-autocomplete.tsx"],"sourcesContent":[":host {\n display: block;\n width: 100%;\n border-radius: 1.25rem;\n padding: 0;\n border-top: 0;\n position: relative;\n}\n\n[role=listbox] {\n position: absolute;\n margin-top: var(--pl-space-xs);\n background: var(--pl-color-bg-default);\n border-radius: 1.25rem;\n box-shadow: rgba(140, 149, 159, 0.3) 0px 8px 24px 0px;\n width: 100%;\n overflow: hidden;\n z-index: 1;\n\n display: flex;\n flex-direction: column;\n}\n\np {\n margin: 0;\n font-size: var(--pl-font-size-s);\n color: var(--pl-color-fg-subtle);\n padding: var(--pl-space-xs) calc(var(--pl-space-m) + var(--pl-space-2xs));\n font-size: var(--pl-font-size-s);\n order: 2;\n font-weight: 500;\n background: var(--pl-color-bg-subtle);\n border-radius: 0 0 1.25rem 1.25rem;\n\n display: flex;\n gap: var(--pl-space-s) var(--pl-space-l);\n flex-wrap: wrap;\n}\n\nol {\n list-style: none;\n margin: 0;\n padding: var(--pl-space-xs) 0;\n order: 1;\n}\n\n[role=option] {\n color: var(--pl-color-fg-default);\n padding: var(--pl-space-s) calc(var(--pl-space-m) + var(--pl-space-2xs));\n text-decoration: none;\n font-weight: 700; \n\n &:hover {\n cursor: pointer;\n }\n\n &:hover,\n &:focus {\n text-decoration-thickness: 2px;\n text-underline-offset: 2px;\n text-decoration: underline;\n }\n}\n\n[aria-selected=true] {\n text-decoration-thickness: 2px;\n text-underline-offset: 2px;\n text-decoration: underline;\n}\n\nmark {\n background: none;\n font-weight: 400;\n}\n\n.suggestion--border {\n border-bottom: solid 1px rgb(from var(--pl-color-fg-default) r g b / 0.2);\n padding-bottom: calc(var(--pl-space-2xs) + var(--pl-space-s));\n margin-bottom: var(--pl-space-2xs);\n}","import { Component, h, Element, State, Listen, Event, EventEmitter, Prop } from '@stencil/core';\n\ninterface ListboxOption {\n id: string;\n html: string;\n value: string;\n}\n\nexport interface ActivatedEvent {\n value: string;\n index: number;\n}\n\n@Component({\n tag: 'pennlibs-autocomplete',\n styleUrl: 'pennlibs-autocomplete.css',\n shadow: true\n})\nexport class Autocomplete {\n @Element() el!: HTMLElement;\n\n @Prop() for?: string;\n\n @State() showSuggestions: boolean = false;\n @State() currentIndex: number = -1;\n @State() originalValue: string = '';\n @State() options: ListboxOption[] = [];\n\n @Event({ eventName: 'pl:activated' }) activated: EventEmitter<ActivatedEvent>;\n\n private blurTimeout: number;\n private mutationObserver: MutationObserver;\n\n componentWillLoad() {\n this.options = this.parseOptionsFromDOM();\n }\n\n componentDidLoad() {\n this.setupInput();\n this.setupMutationObserver();\n }\n\n disconnectedCallback() {\n if (this.blurTimeout) clearTimeout(this.blurTimeout);\n if (this.mutationObserver) this.mutationObserver.disconnect();\n }\n\n private setupMutationObserver(): void {\n this.mutationObserver = new MutationObserver(() => {\n this.options = this.parseOptionsFromDOM();\n });\n\n this.mutationObserver.observe(this.el, {\n childList: true,\n subtree: true,\n characterData: true\n });\n }\n\n private parseOptionsFromDOM(): ListboxOption[] {\n const listbox = this.findListbox();\n if (!listbox) return [];\n\n const elements = Array.from(listbox.querySelectorAll('[role=\"option\"]')) as HTMLElement[];\n return elements.map((el, i) => this.createOption(el, i));\n }\n\n private findListbox(): HTMLOListElement | null {\n return Array.from(this.el.children).find(child =>\n child.matches('ol[role=\"listbox\"]')\n ) as HTMLOListElement;\n }\n\n private createOption(element: HTMLElement, index: number): ListboxOption {\n return {\n id: element.id || `option-${index}`,\n html: element.innerHTML,\n value: element.getAttribute('data-pl-value') || element.textContent?.trim() || ''\n };\n }\n\n private getInput(): HTMLInputElement | null {\n if (!this.for) return null;\n\n const slot = this.el.shadowRoot?.querySelector('slot[name=\"start\"]') as HTMLSlotElement;\n const input = slot.assignedElements()[0].querySelector(`input#${this.for}`) as HTMLInputElement;\n\n return input || null\n }\n\n private isInputFocused(): boolean {\n return this.getInput() === document.activeElement;\n }\n\n private isTrackedInput(input: HTMLInputElement): boolean {\n return input?.getAttribute('data-pl-autocomplete-connected') === 'true' &&\n this.el.contains(input);\n }\n\n private setupInput(): void {\n if (!this.for) {\n console.warn('<pennlibs-autocomplete> Missing \"for\" attribute. Please add for=\"input-id\" to specify which input to attach to.');\n return;\n }\n\n const input = this.getInput();\n if (!input) {\n console.warn(`<pennlibs-autocomplete> No input element found with id=\"${this.for}\". Ensure an input with this id exists.`);\n return;\n }\n\n this.setComboboxAttributes(input);\n input.setAttribute('data-pl-autocomplete-connected', 'true');\n }\n\n private setComboboxAttributes(input: HTMLInputElement): void {\n input.setAttribute('role', 'combobox');\n input.setAttribute('aria-autocomplete', 'list');\n input.setAttribute('aria-expanded', 'false');\n input.setAttribute('aria-controls', 'listbox');\n }\n\n @Listen('slotchange')\n handleSlotChange() {\n this.options = this.parseOptionsFromDOM();\n this.setupInput();\n }\n\n @Listen('input', { target: 'body' })\n handleInputEvent(event: Event) {\n const input = event.target as HTMLInputElement;\n if (this.isTrackedInput(input)) {\n this.currentIndex = -1;\n this.openSuggestions();\n }\n }\n\n @Listen('focus', { target: 'body' })\n handleFocusEvent(event: Event) {\n const input = event.target as HTMLInputElement;\n if (this.isTrackedInput(input)) this.showSuggestionsPanel();\n }\n\n @Listen('blur', { target: 'body' })\n handleBlurEvent(event: Event) {\n const input = event.target as HTMLInputElement;\n if (this.isTrackedInput(input)) this.deferCloseSuggestions();\n }\n\n @Listen('focusout')\n handleFocusOut(event: FocusEvent) {\n if (this.isFocusLeavingComponent(event)) this.closeSuggestions();\n }\n\n @Listen('keydown', { target: 'document' })\n handleKeyDown(event: KeyboardEvent) {\n if (!this.isInputFocused()) return;\n if (event.metaKey || event.ctrlKey) return; // Ignore keyboard shortcuts\n\n const handler = this.keyHandlers()[event.key];\n if (handler) {\n event.preventDefault();\n handler();\n }\n }\n\n private keyHandlers() {\n return {\n 'Escape': () => this.handleEscape(),\n 'ArrowDown': () => this.handleArrowDown(),\n 'ArrowUp': () => this.handleArrowUp(),\n 'Enter': () => this.handleEnter()\n };\n }\n\n private handleEscape() {\n this.reset();\n this.syncInputState();\n }\n\n private handleArrowDown() {\n if (!this.showSuggestions) return;\n this.moveNext();\n this.syncInputState();\n }\n\n private handleArrowUp() {\n if (!this.showSuggestions) return;\n this.movePrevious();\n this.syncInputState();\n }\n\n private handleEnter() {\n if (this.canSelect()) this.selectCurrent();\n }\n\n // Navigation\n private moveNext(): void {\n const lastIndex = this.options.length - 1;\n this.currentIndex = this.currentIndex < lastIndex ? this.currentIndex + 1 : -1;\n }\n\n private movePrevious(): void {\n const lastIndex = this.options.length - 1;\n this.currentIndex = this.currentIndex > -1 ? this.currentIndex - 1 : lastIndex;\n }\n\n private canSelect(): boolean {\n return this.showSuggestions && this.currentIndex >= 0;\n }\n\n private selectCurrent(): void {\n if (this.currentIndex < 0) return;\n\n const selectedOption = this.options[this.currentIndex];\n const input = this.getInput();\n\n if (input) {\n input.value = selectedOption.value;\n this.originalValue = selectedOption.value;\n }\n\n this.activated.emit({\n index: this.currentIndex,\n value: selectedOption.value\n });\n\n this.closeSuggestions();\n }\n\n private handleOptionClick = (index: number): void => {\n this.currentIndex = index;\n this.selectCurrent();\n }\n\n private openSuggestions(): void {\n if (!this.isInputFocused()) return;\n\n const input = this.getInput();\n if (input) this.originalValue = input.value;\n\n this.showSuggestionsPanel();\n this.syncInputState();\n }\n\n private showSuggestionsPanel(): void {\n this.showSuggestions = true;\n this.syncInputState();\n }\n\n private closeSuggestions(): void {\n this.reset();\n this.syncInputState();\n }\n\n private deferCloseSuggestions(): void {\n this.blurTimeout = setTimeout(() => {\n if (this.isFocusOutsideComponent()) this.closeSuggestions();\n }, 150) as unknown as number;\n }\n\n private reset(): void {\n this.showSuggestions = false;\n this.currentIndex = -1;\n }\n\n private isFocusLeavingComponent(event: FocusEvent): boolean {\n const target = event.relatedTarget as HTMLElement;\n return !target ||\n (!this.el.contains(target) && !this.el.shadowRoot?.contains(target));\n }\n\n private isFocusOutsideComponent(): boolean {\n const active = document.activeElement;\n return !this.el.shadowRoot?.contains(active) && active !== this.getInput();\n }\n\n private syncInputState(): void {\n const input = this.getInput();\n if (!input) return;\n\n this.updateAriaExpanded(input);\n this.updateAriaActiveDescendant(input);\n this.updateInputValue(input);\n }\n\n private updateAriaExpanded(input: HTMLInputElement): void {\n input.setAttribute('aria-expanded', this.showSuggestions.toString());\n }\n\n private updateAriaActiveDescendant(input: HTMLInputElement): void {\n const hasSelection = this.showSuggestions && this.currentIndex >= 0;\n if (hasSelection && this.options[this.currentIndex]) {\n input.setAttribute('aria-activedescendant', this.options[this.currentIndex].id);\n } else {\n input.removeAttribute('aria-activedescendant');\n }\n }\n\n private updateInputValue(input: HTMLInputElement): void {\n input.value = this.currentIndex >= 0\n ? this.options[this.currentIndex].value\n : this.originalValue;\n }\n\n private shouldShowListbox(): boolean {\n return this.showSuggestions && this.options.length > 0 && this.isInputFocused();\n }\n\n render() {\n return (\n <div>\n <slot name=\"start\" />\n {this.shouldShowListbox() && (\n <ol role=\"listbox\" id=\"listbox\">\n {this.options.map((option, index) => (\n <li\n role=\"option\"\n id={option.id}\n aria-selected={this.currentIndex === index ? 'true' : 'false'}\n tabindex=\"-1\"\n onClick={() => this.handleOptionClick(index)}\n innerHTML={option.html}\n />\n ))}\n </ol>\n )}\n </div>\n )\n }\n}\n"],"version":3}
package/dist/docs.json CHANGED
@@ -1,5 +1,5 @@
1
1
  {
2
- "timestamp": "2025-10-29T16:27:39",
2
+ "timestamp": "2025-10-29T19:40:29",
3
3
  "compiler": {
4
4
  "name": "@stencil/core",
5
5
  "version": "4.29.3",
@@ -26,7 +26,7 @@
26
26
  "mutable": false,
27
27
  "attr": "for",
28
28
  "reflectToAttr": false,
29
- "docs": "The id of the input element to attach autocomplete functionality to",
29
+ "docs": "",
30
30
  "docsTags": [],
31
31
  "values": [
32
32
  {
@@ -58,7 +58,7 @@
58
58
  },
59
59
  "cancelable": true,
60
60
  "composed": true,
61
- "docs": "Emitted when a user activates (selects) an autocomplete option",
61
+ "docs": "",
62
62
  "docsTags": []
63
63
  }
64
64
  ],