@penn-libraries/web 1.1.0-dev.6 → 1.1.0-dev.7

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.
@@ -17,7 +17,7 @@ var patchBrowser = () => {
17
17
 
18
18
  patchBrowser().then(async (options) => {
19
19
  await globalScripts();
20
- return bootstrapLazy([["p-909144f6",[[1,"pennlibs-autocomplete",{"for":[1],"showSuggestions":[32],"currentIndex":[32],"originalValue":[32],"options":[32]},[[0,"slotchange","handleSlotChange"],[16,"input","handleInputEvent"],[16,"focus","handleFocusEvent"],[16,"blur","handleBlurEvent"],[0,"focusout","handleFocusOut"],[4,"keydown","handleKeyDown"]]],[1,"pennlibs-footer",{"navigationByChildren":[32]}],[1,"pennlibs-header",{"serviceName":[1,"service-name"],"serviceLede":[1,"service-lede"],"serviceHref":[1,"service-href"],"theme":[1],"isMenuOpen":[32],"navigation":[32]}]]],["p-20c0bd7a",[[1,"pennlibs-banner"]]],["p-cbae5952",[[1,"pennlibs-chat",{"href":[32]}]]],["p-5e385536",[[1,"pennlibs-fallback-img"]]],["p-370e32b1",[[1,"pennlibs-feedback",{"error":[32],"answer":[32]}]]],["p-07ad051f",[[1,"pennlibs-hero",{"heroPictureElement":[32],"heroHeadingElement":[32],"heroParagraphElement":[32],"heroSrc":[32]}]]]], options);
20
+ return bootstrapLazy([["p-e1215158",[[1,"pennlibs-autocomplete",{"for":[1],"showSuggestions":[32],"currentIndex":[32],"originalValue":[32],"options":[32]},[[0,"slotchange","handleSlotChange"],[16,"input","handleInputEvent"],[16,"focus","handleFocusEvent"],[16,"blur","handleBlurEvent"],[0,"focusout","handleFocusOut"],[4,"keydown","handleKeyDown"]]],[1,"pennlibs-footer",{"navigationByChildren":[32]}],[1,"pennlibs-header",{"serviceName":[1,"service-name"],"serviceLede":[1,"service-lede"],"serviceHref":[1,"service-href"],"theme":[1],"isMenuOpen":[32],"navigation":[32]}]]],["p-20c0bd7a",[[1,"pennlibs-banner"]]],["p-cbae5952",[[1,"pennlibs-chat",{"href":[32]}]]],["p-5e385536",[[1,"pennlibs-fallback-img"]]],["p-370e32b1",[[1,"pennlibs-feedback",{"error":[32],"answer":[32]}]]],["p-07ad051f",[[1,"pennlibs-hero",{"heroPictureElement":[32],"heroHeadingElement":[32],"heroParagraphElement":[32],"heroSrc":[32]}]]]], options);
21
21
  });
22
22
  //# sourceMappingURL=web.esm.js.map
23
23
 
package/hydrate/index.js CHANGED
@@ -3175,6 +3175,12 @@ class Autocomplete {
3175
3175
  this.currentIndex = -1;
3176
3176
  this.originalValue = '';
3177
3177
  this.options = [];
3178
+ this.keyHandlerMap = {
3179
+ 'Escape': () => this.handleEscape(),
3180
+ 'ArrowDown': () => this.handleArrowDown(),
3181
+ 'ArrowUp': () => this.handleArrowUp(),
3182
+ 'Enter': () => this.handleEnter()
3183
+ };
3178
3184
  this.handleOptionClick = (index) => {
3179
3185
  this.currentIndex = index;
3180
3186
  this.selectCurrent();
@@ -3226,7 +3232,12 @@ class Autocomplete {
3226
3232
  if (!this.for)
3227
3233
  return null;
3228
3234
  const slot = (_a = this.el.shadowRoot) === null || _a === void 0 ? void 0 : _a.querySelector('slot[name="start"]');
3229
- const input = slot.assignedElements()[0].querySelector(`input#${this.for}`);
3235
+ if (!slot)
3236
+ return null;
3237
+ const assignedElements = slot.assignedElements();
3238
+ if (assignedElements.length === 0)
3239
+ return null;
3240
+ const input = assignedElements[0].querySelector(`input#${this.for}`);
3230
3241
  return input || null;
3231
3242
  }
3232
3243
  isInputFocused() {
@@ -3285,35 +3296,33 @@ class Autocomplete {
3285
3296
  return;
3286
3297
  if (event.metaKey || event.ctrlKey)
3287
3298
  return; // Ignore keyboard shortcuts
3288
- const handler = this.keyHandlers()[event.key];
3299
+ const handler = this.keyHandlerMap[event.key];
3289
3300
  if (handler) {
3290
- event.preventDefault();
3301
+ // Don't prevent default for Enter - allow form submission
3302
+ if (event.key !== 'Enter') {
3303
+ event.preventDefault();
3304
+ }
3291
3305
  handler();
3292
3306
  }
3293
3307
  }
3294
- keyHandlers() {
3295
- return {
3296
- 'Escape': () => this.handleEscape(),
3297
- 'ArrowDown': () => this.handleArrowDown(),
3298
- 'ArrowUp': () => this.handleArrowUp(),
3299
- 'Enter': () => this.handleEnter()
3300
- };
3301
- }
3302
3308
  handleEscape() {
3303
3309
  this.reset();
3304
3310
  this.syncInputState();
3311
+ this.syncInputValueToSelection();
3305
3312
  }
3306
3313
  handleArrowDown() {
3307
3314
  if (!this.showSuggestions)
3308
3315
  return;
3309
3316
  this.moveNext();
3310
3317
  this.syncInputState();
3318
+ this.syncInputValueToSelection();
3311
3319
  }
3312
3320
  handleArrowUp() {
3313
3321
  if (!this.showSuggestions)
3314
3322
  return;
3315
3323
  this.movePrevious();
3316
3324
  this.syncInputState();
3325
+ this.syncInputValueToSelection();
3317
3326
  }
3318
3327
  handleEnter() {
3319
3328
  if (this.canSelect())
@@ -3353,7 +3362,6 @@ class Autocomplete {
3353
3362
  if (input)
3354
3363
  this.originalValue = input.value;
3355
3364
  this.showSuggestionsPanel();
3356
- this.syncInputState();
3357
3365
  }
3358
3366
  showSuggestionsPanel() {
3359
3367
  this.showSuggestions = true;
@@ -3362,8 +3370,11 @@ class Autocomplete {
3362
3370
  closeSuggestions() {
3363
3371
  this.reset();
3364
3372
  this.syncInputState();
3373
+ this.syncInputValueToSelection();
3365
3374
  }
3366
3375
  deferCloseSuggestions() {
3376
+ if (this.blurTimeout)
3377
+ clearTimeout(this.blurTimeout);
3367
3378
  this.blurTimeout = setTimeout(() => {
3368
3379
  if (this.isFocusOutsideComponent())
3369
3380
  this.closeSuggestions();
@@ -3390,30 +3401,34 @@ class Autocomplete {
3390
3401
  return;
3391
3402
  this.updateAriaExpanded(input);
3392
3403
  this.updateAriaActiveDescendant(input);
3393
- this.updateInputValue(input);
3404
+ }
3405
+ syncInputValueToSelection() {
3406
+ const input = this.getInput();
3407
+ if (!input)
3408
+ return;
3409
+ input.value = this.currentIndex >= 0 && this.currentIndex < this.options.length
3410
+ ? this.options[this.currentIndex].value
3411
+ : this.originalValue;
3394
3412
  }
3395
3413
  updateAriaExpanded(input) {
3396
3414
  input.setAttribute('aria-expanded', this.showSuggestions.toString());
3397
3415
  }
3398
3416
  updateAriaActiveDescendant(input) {
3399
- const hasSelection = this.showSuggestions && this.currentIndex >= 0;
3400
- if (hasSelection && this.options[this.currentIndex]) {
3417
+ const hasSelection = this.showSuggestions &&
3418
+ this.currentIndex >= 0 &&
3419
+ this.currentIndex < this.options.length;
3420
+ if (hasSelection) {
3401
3421
  input.setAttribute('aria-activedescendant', this.options[this.currentIndex].id);
3402
3422
  }
3403
3423
  else {
3404
3424
  input.removeAttribute('aria-activedescendant');
3405
3425
  }
3406
3426
  }
3407
- updateInputValue(input) {
3408
- input.value = this.currentIndex >= 0
3409
- ? this.options[this.currentIndex].value
3410
- : this.originalValue;
3411
- }
3412
3427
  shouldShowListbox() {
3413
3428
  return this.showSuggestions && this.options.length > 0 && this.isInputFocused();
3414
3429
  }
3415
3430
  render() {
3416
- return (hAsync("div", { key: '71422b55533372a9d8697e648e49f87fe223f4e0' }, hAsync("slot", { key: '951511fd2090b9816c2e6c1a5a40169ea08e72fd', name: "start" }), this.shouldShowListbox() && (hAsync("ol", { key: 'e3f6f14686bc99b6e25d34d8e053f01174f23438', role: "listbox", id: "listbox" }, this.options.map((option, index) => (hAsync("li", { role: "option", id: option.id, "aria-selected": this.currentIndex === index ? 'true' : 'false', tabindex: "-1", onClick: () => this.handleOptionClick(index), innerHTML: option.html })))))));
3431
+ return (hAsync("div", { key: 'd7c11d48e354937eedc76f608ef3b3b8762ddb4b' }, hAsync("slot", { key: 'a3c65cf477aa9f575c3310e364c1dd2a5dca9e57', name: "start" }), this.shouldShowListbox() && (hAsync("ol", { key: 'dc035d276f14da3ad0246924c345bc86ff5c68f9', role: "listbox", id: "listbox" }, this.options.map((option, index) => (hAsync("li", { role: "option", id: option.id, "aria-selected": this.currentIndex === index ? 'true' : 'false', tabindex: "-1", onClick: () => this.handleOptionClick(index), innerHTML: option.html })))))));
3417
3432
  }
3418
3433
  get el() { return getElement(this); }
3419
3434
  static get style() { return pennlibsAutocompleteCss; }
package/hydrate/index.mjs CHANGED
@@ -3173,6 +3173,12 @@ class Autocomplete {
3173
3173
  this.currentIndex = -1;
3174
3174
  this.originalValue = '';
3175
3175
  this.options = [];
3176
+ this.keyHandlerMap = {
3177
+ 'Escape': () => this.handleEscape(),
3178
+ 'ArrowDown': () => this.handleArrowDown(),
3179
+ 'ArrowUp': () => this.handleArrowUp(),
3180
+ 'Enter': () => this.handleEnter()
3181
+ };
3176
3182
  this.handleOptionClick = (index) => {
3177
3183
  this.currentIndex = index;
3178
3184
  this.selectCurrent();
@@ -3224,7 +3230,12 @@ class Autocomplete {
3224
3230
  if (!this.for)
3225
3231
  return null;
3226
3232
  const slot = (_a = this.el.shadowRoot) === null || _a === void 0 ? void 0 : _a.querySelector('slot[name="start"]');
3227
- const input = slot.assignedElements()[0].querySelector(`input#${this.for}`);
3233
+ if (!slot)
3234
+ return null;
3235
+ const assignedElements = slot.assignedElements();
3236
+ if (assignedElements.length === 0)
3237
+ return null;
3238
+ const input = assignedElements[0].querySelector(`input#${this.for}`);
3228
3239
  return input || null;
3229
3240
  }
3230
3241
  isInputFocused() {
@@ -3283,35 +3294,33 @@ class Autocomplete {
3283
3294
  return;
3284
3295
  if (event.metaKey || event.ctrlKey)
3285
3296
  return; // Ignore keyboard shortcuts
3286
- const handler = this.keyHandlers()[event.key];
3297
+ const handler = this.keyHandlerMap[event.key];
3287
3298
  if (handler) {
3288
- event.preventDefault();
3299
+ // Don't prevent default for Enter - allow form submission
3300
+ if (event.key !== 'Enter') {
3301
+ event.preventDefault();
3302
+ }
3289
3303
  handler();
3290
3304
  }
3291
3305
  }
3292
- keyHandlers() {
3293
- return {
3294
- 'Escape': () => this.handleEscape(),
3295
- 'ArrowDown': () => this.handleArrowDown(),
3296
- 'ArrowUp': () => this.handleArrowUp(),
3297
- 'Enter': () => this.handleEnter()
3298
- };
3299
- }
3300
3306
  handleEscape() {
3301
3307
  this.reset();
3302
3308
  this.syncInputState();
3309
+ this.syncInputValueToSelection();
3303
3310
  }
3304
3311
  handleArrowDown() {
3305
3312
  if (!this.showSuggestions)
3306
3313
  return;
3307
3314
  this.moveNext();
3308
3315
  this.syncInputState();
3316
+ this.syncInputValueToSelection();
3309
3317
  }
3310
3318
  handleArrowUp() {
3311
3319
  if (!this.showSuggestions)
3312
3320
  return;
3313
3321
  this.movePrevious();
3314
3322
  this.syncInputState();
3323
+ this.syncInputValueToSelection();
3315
3324
  }
3316
3325
  handleEnter() {
3317
3326
  if (this.canSelect())
@@ -3351,7 +3360,6 @@ class Autocomplete {
3351
3360
  if (input)
3352
3361
  this.originalValue = input.value;
3353
3362
  this.showSuggestionsPanel();
3354
- this.syncInputState();
3355
3363
  }
3356
3364
  showSuggestionsPanel() {
3357
3365
  this.showSuggestions = true;
@@ -3360,8 +3368,11 @@ class Autocomplete {
3360
3368
  closeSuggestions() {
3361
3369
  this.reset();
3362
3370
  this.syncInputState();
3371
+ this.syncInputValueToSelection();
3363
3372
  }
3364
3373
  deferCloseSuggestions() {
3374
+ if (this.blurTimeout)
3375
+ clearTimeout(this.blurTimeout);
3365
3376
  this.blurTimeout = setTimeout(() => {
3366
3377
  if (this.isFocusOutsideComponent())
3367
3378
  this.closeSuggestions();
@@ -3388,30 +3399,34 @@ class Autocomplete {
3388
3399
  return;
3389
3400
  this.updateAriaExpanded(input);
3390
3401
  this.updateAriaActiveDescendant(input);
3391
- this.updateInputValue(input);
3402
+ }
3403
+ syncInputValueToSelection() {
3404
+ const input = this.getInput();
3405
+ if (!input)
3406
+ return;
3407
+ input.value = this.currentIndex >= 0 && this.currentIndex < this.options.length
3408
+ ? this.options[this.currentIndex].value
3409
+ : this.originalValue;
3392
3410
  }
3393
3411
  updateAriaExpanded(input) {
3394
3412
  input.setAttribute('aria-expanded', this.showSuggestions.toString());
3395
3413
  }
3396
3414
  updateAriaActiveDescendant(input) {
3397
- const hasSelection = this.showSuggestions && this.currentIndex >= 0;
3398
- if (hasSelection && this.options[this.currentIndex]) {
3415
+ const hasSelection = this.showSuggestions &&
3416
+ this.currentIndex >= 0 &&
3417
+ this.currentIndex < this.options.length;
3418
+ if (hasSelection) {
3399
3419
  input.setAttribute('aria-activedescendant', this.options[this.currentIndex].id);
3400
3420
  }
3401
3421
  else {
3402
3422
  input.removeAttribute('aria-activedescendant');
3403
3423
  }
3404
3424
  }
3405
- updateInputValue(input) {
3406
- input.value = this.currentIndex >= 0
3407
- ? this.options[this.currentIndex].value
3408
- : this.originalValue;
3409
- }
3410
3425
  shouldShowListbox() {
3411
3426
  return this.showSuggestions && this.options.length > 0 && this.isInputFocused();
3412
3427
  }
3413
3428
  render() {
3414
- return (hAsync("div", { key: '71422b55533372a9d8697e648e49f87fe223f4e0' }, hAsync("slot", { key: '951511fd2090b9816c2e6c1a5a40169ea08e72fd', name: "start" }), this.shouldShowListbox() && (hAsync("ol", { key: 'e3f6f14686bc99b6e25d34d8e053f01174f23438', role: "listbox", id: "listbox" }, this.options.map((option, index) => (hAsync("li", { role: "option", id: option.id, "aria-selected": this.currentIndex === index ? 'true' : 'false', tabindex: "-1", onClick: () => this.handleOptionClick(index), innerHTML: option.html })))))));
3429
+ return (hAsync("div", { key: 'd7c11d48e354937eedc76f608ef3b3b8762ddb4b' }, hAsync("slot", { key: 'a3c65cf477aa9f575c3310e364c1dd2a5dca9e57', name: "start" }), this.shouldShowListbox() && (hAsync("ol", { key: 'dc035d276f14da3ad0246924c345bc86ff5c68f9', role: "listbox", id: "listbox" }, this.options.map((option, index) => (hAsync("li", { role: "option", id: option.id, "aria-selected": this.currentIndex === index ? 'true' : 'false', tabindex: "-1", onClick: () => this.handleOptionClick(index), innerHTML: option.html })))))));
3415
3430
  }
3416
3431
  get el() { return getElement(this); }
3417
3432
  static get style() { return pennlibsAutocompleteCss; }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@penn-libraries/web",
3
- "version": "1.1.0-dev.6",
3
+ "version": "1.1.0-dev.7",
4
4
  "description": "Reusable web designs for University of Pennsylvania Libraries websites. This package contains our code for shared Web Components and Cascading Style Sheets (CSS).",
5
5
  "main": "dist/index.cjs.js",
6
6
  "module": "dist/index.js",