From be45a793eb98e8164af2e898ab00002a6943f98a Mon Sep 17 00:00:00 2001 From: mimshins Date: Sat, 8 Mar 2025 14:34:40 +0330 Subject: [PATCH] attach keydown listener on pinwheel root --- .../src/pinwheel/item/Controller.ts | 95 +------------------ .../web-components/src/pinwheel/item/item.ts | 1 - .../web-components/src/pinwheel/pinwheel.ts | 95 +++++++++++++++++++ 3 files changed, 99 insertions(+), 92 deletions(-) diff --git a/packages/web-components/src/pinwheel/item/Controller.ts b/packages/web-components/src/pinwheel/item/Controller.ts index 9043338a..f4ca13e5 100644 --- a/packages/web-components/src/pinwheel/item/Controller.ts +++ b/packages/web-components/src/pinwheel/item/Controller.ts @@ -1,7 +1,4 @@ -import { requestFormSubmit } from "../../base-input/utils.ts"; -import { KeyboardKeys } from "../../internals/index.ts"; import { - clamp, SelectionController, type SelectionElement, } from "../../utils/index.ts"; @@ -28,14 +25,7 @@ class ItemSelectionController extends SelectionController { }); } - private _emitValueChange(newValue: string) { - const parent = this._parentTarget as Pinwheel | null; - - if (!parent) return; - if (parent.disabled) return; - - parent.value = newValue; - + private _emitValueChange() { this._host.dispatchEvent(new Event("change", { bubbles: true })); } @@ -55,93 +45,16 @@ class ItemSelectionController extends SelectionController { } public override async handleClick(event: MouseEvent) { - if (!(await super.handleClick(event))) return false; - - this._emitValueChange(this._host.value); - - return true; - } - - public override async handleKeyDown(event: KeyboardEvent) { - if (!(await super.handleKeyDown(event))) return false; - const parent = this._parentTarget as Pinwheel | null; if (!parent) return false; if (parent.disabled) return false; - const items = this._elements; - - switch (event.key) { - case KeyboardKeys.ENTER: { - event.preventDefault(); - - requestFormSubmit(parent); - - return true; - } - - case KeyboardKeys.UP: { - event.preventDefault(); - - if (items.length === 0) return false; - - const idx = items.findIndex(item => item.selected); - const nextIdx = idx === -1 ? 0 : clamp(idx - 1, 0, items.length - 1); - const newValue = items[nextIdx]?.value; - - if (!newValue) return false; - - this._emitValueChange(newValue); - - return true; - } - - case KeyboardKeys.DOWN: { - event.preventDefault(); - - if (items.length === 0) return false; - - const idx = items.findIndex(item => item.selected); - const nextIdx = clamp(idx + 1, 0, items.length - 1); - const newValue = items[nextIdx]?.value; - - if (!newValue) return false; - - this._emitValueChange(newValue); - - return true; - } - - case KeyboardKeys.HOME: { - event.preventDefault(); - - const nextIdx = 0; - const newValue = items[nextIdx]?.value; - - if (!newValue) return false; - - this._emitValueChange(newValue); - - return true; - } - - case KeyboardKeys.END: { - event.preventDefault(); - - const nextIdx = items.length - 1; - const newValue = items[nextIdx]?.value; - - if (!newValue) return false; - - this._emitValueChange(newValue); + if (!(await super.handleClick(event))) return false; - return true; - } + this._emitValueChange(); - default: - return false; - } + return true; } } diff --git a/packages/web-components/src/pinwheel/item/item.ts b/packages/web-components/src/pinwheel/item/item.ts index 8452bf62..6a6616c0 100644 --- a/packages/web-components/src/pinwheel/item/item.ts +++ b/packages/web-components/src/pinwheel/item/item.ts @@ -56,7 +56,6 @@ export class PinwheelItem extends LitElement { part="root" data-value=${this.value} @click=${this._selectionController.handleClick} - @keydown=${this._selectionController.handleKeyDown} > diff --git a/packages/web-components/src/pinwheel/pinwheel.ts b/packages/web-components/src/pinwheel/pinwheel.ts index 042bd076..d813e2f8 100644 --- a/packages/web-components/src/pinwheel/pinwheel.ts +++ b/packages/web-components/src/pinwheel/pinwheel.ts @@ -1,7 +1,10 @@ import { html, LitElement, nothing, type PropertyValues } from "lit"; import { property, query, state } from "lit/decorators.js"; import { classMap } from "lit/directives/class-map.js"; +import { requestFormSubmit } from "../base-input/utils.ts"; +import { KeyboardKeys } from "../internals/keyboard.ts"; import { + clamp, debounce, dispatchActivationClick, getBoundingClientRect, @@ -267,6 +270,97 @@ export class Pinwheel extends BaseClass { this.dispatchEvent(new Event("change", { bubbles: true })); } + private _handleKeyDown = async (event: KeyboardEvent) => { + if (this.disabled) return; + if (!this._root) return; + + // allow event to propagate to user code after a microtask. + await waitAMicrotask(); + + if (event.defaultPrevented) return; + + const items = this._items; + + switch (event.key) { + case KeyboardKeys.ENTER: { + event.preventDefault(); + + requestFormSubmit(this); + + return true; + } + + case KeyboardKeys.UP: { + event.preventDefault(); + + if (items.length === 0) return false; + + const idx = items.findIndex(item => item.selected); + const nextIdx = idx === -1 ? 0 : clamp(idx - 1, 0, items.length - 1); + const nextItem = items[nextIdx]; + + if (!nextItem) return false; + + nextItem.selected = true; + + this._emitValueChange(nextItem.value); + + return true; + } + + case KeyboardKeys.DOWN: { + event.preventDefault(); + + if (items.length === 0) return false; + + const idx = items.findIndex(item => item.selected); + const nextIdx = clamp(idx + 1, 0, items.length - 1); + const nextItem = items[nextIdx]; + + if (!nextItem) return false; + + nextItem.selected = true; + + this._emitValueChange(nextItem.value); + + return true; + } + + case KeyboardKeys.HOME: { + event.preventDefault(); + + const nextIdx = 0; + const nextItem = items[nextIdx]; + + if (!nextItem) return false; + + nextItem.selected = true; + + this._emitValueChange(nextItem.value); + + return true; + } + + case KeyboardKeys.END: { + event.preventDefault(); + + const nextIdx = items.length - 1; + const nextItem = items[nextIdx]; + + if (!nextItem) return false; + + nextItem.selected = true; + + this._emitValueChange(nextItem.value); + + return true; + } + + default: + return false; + } + }; + private _handleScroll = debounce(() => { if (!this._root) return; @@ -358,6 +452,7 @@ export class Pinwheel extends BaseClass { aria-valuenow=${this._spinArias.valueNow || nothing} aria-valuetext=${this._spinArias.valueText || nothing} @scroll=${this._handleScroll} + @keydown=${this._handleKeyDown} >