From ce813faeb5120b6f0cfa622387091241cfebee4f Mon Sep 17 00:00:00 2001 From: sunhao Date: Tue, 5 Dec 2023 12:31:30 +0800 Subject: [PATCH] * search-box: support to binding hotkeys to searchbox. --- lib/search-box/src/components/search-box.tsx | 59 +++++++++++++++---- .../src/types/search-box-options.ts | 8 ++- 2 files changed, 53 insertions(+), 14 deletions(-) diff --git a/lib/search-box/src/components/search-box.tsx b/lib/search-box/src/components/search-box.tsx index a6b849c7fb..8d760165df 100644 --- a/lib/search-box/src/components/search-box.tsx +++ b/lib/search-box/src/components/search-box.tsx @@ -1,5 +1,5 @@ import {Component, createRef} from 'preact'; -import {classes, Icon, nextGid} from '@zui/core'; +import {$, classes, getHotkeysMap, Icon, nextGid} from '@zui/core'; import '../style'; import type {ComponentChildren, RenderableProps} from 'preact'; @@ -10,6 +10,7 @@ export class SearchBox extends Component { clearIcon: true, searchIcon: true, delay: 500, + hotkeys: true, }; protected _gid: string; @@ -18,12 +19,48 @@ export class SearchBox extends Component { protected _timer = 0; + protected _hotkeysScope?: string; + constructor(props: SearchBoxOptions) { super(props); this.state = {focus: false, value: props.defaultValue || ''}; this._gid = props.id || `search-box-${nextGid()}`; } + componentDidMount(): void { + const {hotkeys} = this.props; + if (hotkeys) { + const hotkeysMap = getHotkeysMap(hotkeys, { + clear: { + keys: ['Escape'], + handler: (event) => { + this.clear(event); + }, + }, + enter: { + keys: ['Enter'], + handler: (event) => { + this.props.onEnter?.(this.state.value, event); + }, + }, + }); + if (hotkeysMap) { + this._hotkeysScope = `SearchBox_${this._gid}`; + console.log('hotkeysMap', hotkeysMap); + $(this.input).hotkeys(hotkeysMap, { + scope: this._hotkeysScope, + event: 'keydown', + }); + } + } + } + + componentWillUnmount(): void { + if (this._hotkeysScope) { + $(this.input).unbindHotkeys(this._hotkeysScope); + } + } + get id() { return this._gid; } @@ -32,9 +69,12 @@ export class SearchBox extends Component { return this._input.current; } - _handleClearBtnClick = (event: MouseEvent) => { + focus() { + this.input?.focus(); + } + + clear(event?: Event) { const oldValue = this.state.value; - event.stopPropagation(); this.setState({value: ''}, () => { const {onChange, onClear} = this.props; onClear?.(event); @@ -43,6 +83,11 @@ export class SearchBox extends Component { onChange?.('', event); } }); + } + + _handleClearBtnClick = (event: MouseEvent) => { + event.stopPropagation(); + this.clear(event); }; _handleChange = (event: Event) => { @@ -80,14 +125,6 @@ export class SearchBox extends Component { this._timer = 0; } - focus() { - this.input?.focus(); - } - - componentWillUnmount(): void { - this._clearTimer(); - } - render(props: RenderableProps, state: Readonly) { const {style, className, rootClass, rootStyle, readonly, disabled, circle, placeholder, mergeIcon, searchIcon, clearIcon, value: controlledValue, compact, prefixClass, suffixClass} = props; const {focus, value} = state; diff --git a/lib/search-box/src/types/search-box-options.ts b/lib/search-box/src/types/search-box-options.ts index 785558beab..9ee0d88c95 100644 --- a/lib/search-box/src/types/search-box-options.ts +++ b/lib/search-box/src/types/search-box-options.ts @@ -1,4 +1,4 @@ -import type {ClassNameLike, IconType, JSX} from '@zui/core'; +import type {ClassNameLike, HotkeysSettings, IconType, JSX} from '@zui/core'; export type SearchBoxOptions = { id?: string; @@ -20,8 +20,10 @@ export type SearchBoxOptions = { mergeIcon?: boolean | IconType; prefixClass?: ClassNameLike; suffixClass?: ClassNameLike; - onChange?: (value: string, event: Event) => void; - onClear?: (event: MouseEvent) => void; + hotkeys?: HotkeysSettings; + onChange?: (value: string, event: Event | undefined) => void; + onEnter?: (value: string, event: Event | undefined) => void; + onClear?: (event: Event | undefined) => void; onFocus?: (event: FocusEvent) => void; onBlur?: (event: FocusEvent) => void; };