diff --git a/packages/devui-vue/devui/search/__tests__/search.spec.ts b/packages/devui-vue/devui/search/__tests__/search.spec.ts new file mode 100644 index 0000000000000000000000000000000000000000..dab7f787550967e8f36908a80373617c4ddd637f --- /dev/null +++ b/packages/devui-vue/devui/search/__tests__/search.spec.ts @@ -0,0 +1,95 @@ +import { mount } from '@vue/test-utils'; +import DSearch from '../src//search' +import { ref, nextTick } from 'vue' + +describe('search test', () => { + it('should render correctly', async () => { + const value = ref('test') + const size = ref('') + const disabled = ref(false) + const wrapper = mount({ + components: { DSearch }, + template: ` + + `, + setup() { + return { + value, + size, + disabled, + } + } + }) + expect(wrapper.classes()).toContain('devui-search') + const search = wrapper.find('.devui-search') + const input = search.find('input') + expect(input.element.value).toBe('test') + + // test size + expect(input.classes()).not.toContain('devui-input-sm') + expect(input.classes()).not.toContain('devui-input-lg') + + size.value = 'sm' + await nextTick() + expect(wrapper.classes()).toContain(`devui-search__sm`) + expect(wrapper.classes()).not.toContain('devui-search__lg') + size.value = 'lg' + await nextTick() + expect(wrapper.classes()).not.toContain('devui-search__sm') + expect(wrapper.classes()).toContain(`devui-search__lg`) + + // test v-model + await input.setValue('def') + expect(value.value).toBe('def') + + value.value = 'change value' + await nextTick() + expect(input.element.value).toBe('change value') + + // test clear + const clear = wrapper.find('.devui-search__clear') + await clear.trigger('click') + expect(input.element.value).toBe('') + expect(value.value).toBe('') + + // test disabled + expect(input.attributes('disabled')).toBe(undefined) + expect(wrapper.classes()).not.toContain('devui-search__disbaled') + + disabled.value = true + await nextTick() + expect(wrapper.classes()).toContain('devui-search__disbaled') + expect(input.attributes('disabled')).toBe('') + }) + + it('should event correctly', async () => { + const value = ref('test') + const onSearch = jest.fn() + const wrapper = mount({ + components: { DSearch }, + template: ` + + `, + setup() { + return { + value, + onSearch + } + } + }) + const search = wrapper.find('.devui-search') + const searchBtn = search.find('.devui-search__icon') + await searchBtn.trigger('click') + await onSearch((str) => { + expect(str).toBe('test') + }) + expect(onSearch).toBeCalledTimes(1); + }) +}) diff --git a/packages/devui-vue/devui/search/hooks/use-search-class.ts b/packages/devui-vue/devui/search/src/hooks/use-search-class.ts similarity index 91% rename from packages/devui-vue/devui/search/hooks/use-search-class.ts rename to packages/devui-vue/devui/search/src/hooks/use-search-class.ts index 36b4c79ffd7209353c5203efec6ce76548fffbba..dec0969b181186121dfef2add9dc8a4087f8d660 100644 --- a/packages/devui-vue/devui/search/hooks/use-search-class.ts +++ b/packages/devui-vue/devui/search/src/hooks/use-search-class.ts @@ -2,7 +2,7 @@ * 定义组件class */ import { computed, ComputedRef } from 'vue'; -import { SearchProps } from '../src/search-types' +import { SearchProps } from '../search-types' const SIZE_CLASS = { lg: 'lg', sm: 'sm', diff --git a/packages/devui-vue/devui/search/hooks/use-search-keydown.ts b/packages/devui-vue/devui/search/src/hooks/use-search-keydown.ts similarity index 86% rename from packages/devui-vue/devui/search/hooks/use-search-keydown.ts rename to packages/devui-vue/devui/search/src/hooks/use-search-keydown.ts index 7e69826d50ccdd417949fffb17d3924ef013c451..c3b73f92ed615c60237d6fced6d99ae6453d9c1a 100644 --- a/packages/devui-vue/devui/search/hooks/use-search-keydown.ts +++ b/packages/devui-vue/devui/search/src/hooks/use-search-keydown.ts @@ -2,13 +2,13 @@ * 清空按钮显示、隐藏 */ import { SetupContext, Ref, } from 'vue' -import { KeydownReturnTypes } from '../src/search-types' +import { KeydownReturnTypes } from '../search-types' import { debounce } from 'lodash-es' const KEYS_MAP = { enter: 'Enter' } as const -type EmitProps = 'update:modelValue' | 'searchFn' +type EmitProps = 'update:modelValue' | 'onSearch' export const keydownHandles = (ctx: SetupContext<(EmitProps)[]>, keywords: Ref, delay: number): KeydownReturnTypes => { // 删除按钮显示 @@ -31,7 +31,7 @@ export const keydownHandles = (ctx: SetupContext<(EmitProps)[]>, keywords: Ref { - ctx.emit('searchFn', value) + ctx.emit('onSearch', value) }, delay) return { onInputKeydown, diff --git a/packages/devui-vue/devui/search/hooks/use-search-keywords.ts b/packages/devui-vue/devui/search/src/hooks/use-search-keywords.ts similarity index 86% rename from packages/devui-vue/devui/search/hooks/use-search-keywords.ts rename to packages/devui-vue/devui/search/src/hooks/use-search-keywords.ts index d0feccc8b40a1d622217cec8d3c0ffb3480258c5..e03864603df6ce7b53829dd735476e7c89fd624f 100644 --- a/packages/devui-vue/devui/search/hooks/use-search-keywords.ts +++ b/packages/devui-vue/devui/search/src/hooks/use-search-keywords.ts @@ -2,8 +2,8 @@ * 输入框内容定义、删改操作 */ import { ref, watch, computed, SetupContext } from 'vue' -import { SearchProps, KeywordsReturnTypes } from '../src/search-types' -type EmitProps = 'update:modelValue' | 'searchFn' +import { SearchProps, KeywordsReturnTypes } from '../search-types' +type EmitProps = 'update:modelValue' | 'onSearch' export const keywordsHandles = (ctx: SetupContext<(EmitProps)[]>, props: SearchProps): KeywordsReturnTypes => { const keywords = ref('') // 输入框内容 diff --git a/packages/devui-vue/devui/search/src/search-types.ts b/packages/devui-vue/devui/search/src/search-types.ts index 05a97d6fe7197f5ee298997a5aaf49da084e6b3b..23c74e20a0ee7cadd449f95215f3680583cb86fc 100644 --- a/packages/devui-vue/devui/search/src/search-types.ts +++ b/packages/devui-vue/devui/search/src/search-types.ts @@ -48,7 +48,7 @@ export const searchProps = { type: String, default: '', }, - searchFn: { + onSearch: { type: Function as PropType<(v: string) => void>, default: undefined }, diff --git a/packages/devui-vue/devui/search/src/search.tsx b/packages/devui-vue/devui/search/src/search.tsx index 9a8ef570cb18d03cd5b4eb535c22d6a9a5e6a21a..004a106ac5b3c4f0e140079b3720bf0e5c75ce30 100644 --- a/packages/devui-vue/devui/search/src/search.tsx +++ b/packages/devui-vue/devui/search/src/search.tsx @@ -1,15 +1,15 @@ import { defineComponent } from 'vue' import { SearchProps, searchProps } from './search-types' -import { getRootClass } from '../hooks/use-search-class' -import { keywordsHandles } from '../hooks/use-search-keywords' -import { keydownHandles } from '../hooks/use-search-keydown' +import { getRootClass } from './hooks/use-search-class' +import { keywordsHandles } from './hooks/use-search-keywords' +import { keydownHandles } from './hooks/use-search-keydown' import DInput from '../../input/src/input'; import './search.scss' export default defineComponent({ name: 'DSearch', props: searchProps, - emits: ['update:modelValue', 'searchFn'], + emits: ['update:modelValue', 'onSearch'], setup(props: SearchProps, ctx) { const rootClasses = getRootClass(props) // 输入框内容定义、删改 @@ -32,7 +32,7 @@ export default defineComponent({
{props.iconPosition === 'left' &&
- +
} - +
} {props.iconPosition === 'right' &&
- +
} diff --git a/packages/devui-vue/docs/components/search/index.md b/packages/devui-vue/docs/components/search/index.md index 97d61245108d3272d3158b1ae026903170b0984a..56d2381fe70c25cfbc86eb7340d055b4433a6c56 100644 --- a/packages/devui-vue/docs/components/search/index.md +++ b/packages/devui-vue/docs/components/search/index.md @@ -13,16 +13,34 @@ ```vue + ``` ::: @@ -59,7 +77,7 @@ ```vue +``` +::: + +### Left Search Icon + +:::demo Use `left`, `right` to define `Search` icon position, default `right` + +```vue + +``` +::: + +### No Border + +:::demo Use `noBorder` to define `Search` without borders + +```vue + +``` +::: + +### VModel + +:::demo Use `v-model` two-way binding + +```vue + + + + +``` + +::: + +### API + +| Parameter | Type | Default | Description | Jump to Demo | Global Config | +| :---------: | :------: | :-------: | :----------------------- | --------------------------------- | --------- | +| size | `'sm'\|''\|'lg'` | '' | Optional. Specifies the size of the search box. The options are lg, '', and sm. | [Basic Usage](#BasicUsage) || +| placeholder | `string` | -- | Optional. This parameter specifies the placeholder in the input box. | [Left Search Icon](#LeftSearchIcon) || +| maxLength | `number` | -- | Optional. Max-length of the text box. | [VModel](#VModel) || +| delay | `number` | 300 | Optional. Delay of debounceTime. | [Basic Usage](#BasicUsage) || +| disabled | `boolean` | false | Optional. Indicating whether the text box is available. | [Basic Usage](#BasicUsage) || +| autoFocus | `boolean` | false | Optional. Whether to enable autofocus for the text box. | [Basic Usage](#BasicUsage) || +| isKeyupSearch | `boolean` | false | Optional. Indicates whether to support immediate searchFn after input. | [Basic Usage](#BasicUsage) || +| iconPosition | `string` | 'right' | Optional. The options are'left' and'right'. | [Left Search Icon](#LeftSearchIcon) || +| noBorder | `boolean` | false | Optional. Specifies whether to display the border. | [No Border](#NoBorder) || +| cssClass | `string` | '' | Optional. The class name can be transferred to the text box. | [VModel](#VModel) || + +### d-search event + +| Event | Type | Description | Jump to Demo | +| :---------: | :------: | :--------------------: | :---------: | +| onSearch | `string` | Callback function triggered by pressing Enter or clicking the search button to return the value entered in the text box. | [Basic Usage](#BasicUsage) | + +