diff --git a/.changeset/calm-rabbits-do.md b/.changeset/calm-rabbits-do.md new file mode 100644 index 00000000..32ee2df3 --- /dev/null +++ b/.changeset/calm-rabbits-do.md @@ -0,0 +1,5 @@ +--- +'@soramitsu-ui/ui': minor +--- + +**feat**(`SSelect`,`SDropdown`): add sync search in dropdown (`dropdownSearch` bool prop) diff --git a/packages/ui/.eslintrc-auto-import.json b/packages/ui/.eslintrc-auto-import.json index f57bda2a..96e86b87 100644 --- a/packages/ui/.eslintrc-auto-import.json +++ b/packages/ui/.eslintrc-auto-import.json @@ -1,15 +1,19 @@ { "globals": { + "EffectScope": true, "asyncComputed": true, "autoResetRef": true, - "biSyncRef": true, "computed": true, + "computedAsync": true, + "computedEager": true, "computedInject": true, + "computedWithControl": true, "controlledComputed": true, "controlledRef": true, "createApp": true, "createEventHook": true, "createGlobalState": true, + "createInjectionState": true, "createReactiveFn": true, "createSharedComposable": true, "createUnrefFn": true, @@ -20,7 +24,6 @@ "defineComponent": true, "eagerComputed": true, "effectScope": true, - "EffectScope": true, "extendRef": true, "getCurrentInstance": true, "getCurrentScope": true, @@ -28,6 +31,8 @@ "ignorableWatch": true, "inject": true, "isDefined": true, + "isProxy": true, + "isReactive": true, "isReadonly": true, "isRef": true, "makeDestructurable": true, @@ -60,12 +65,20 @@ "reactivePick": true, "readonly": true, "ref": true, + "refAutoReset": true, + "refDebounced": true, "refDefault": true, + "refThrottled": true, + "refWithControl": true, "resolveComponent": true, + "resolveDirective": true, + "resolveRef": true, + "resolveUnref": true, "shallowReactive": true, "shallowReadonly": true, "shallowRef": true, "syncRef": true, + "syncRefs": true, "templateRef": true, "throttledRef": true, "throttledWatch": true, @@ -74,6 +87,7 @@ "toRef": true, "toRefs": true, "triggerRef": true, + "tryOnBeforeMount": true, "tryOnBeforeUnmount": true, "tryOnMounted": true, "tryOnScopeDispose": true, @@ -82,28 +96,39 @@ "unrefElement": true, "until": true, "useActiveElement": true, + "useArrayEvery": true, + "useArrayFilter": true, + "useArrayFind": true, + "useArrayFindIndex": true, + "useArrayJoin": true, + "useArrayMap": true, + "useArrayReduce": true, + "useArraySome": true, "useAsyncQueue": true, "useAsyncState": true, "useAttrs": true, "useBase64": true, "useBattery": true, + "useBluetooth": true, "useBreakpoints": true, "useBroadcastChannel": true, "useBrowserLocation": true, "useCached": true, - "useClamp": true, "useClipboard": true, + "useCloned": true, "useColorMode": true, "useConfirmDialog": true, "useCounter": true, "useCssModule": true, "useCssVar": true, "useCssVars": true, + "useCurrentElement": true, "useCycleList": true, "useDark": true, + "useDateFormat": true, "useDebounce": true, - "useDebouncedRefHistory": true, "useDebounceFn": true, + "useDebouncedRefHistory": true, "useDeviceMotion": true, "useDeviceOrientation": true, "useDevicePixelRatio": true, @@ -111,6 +136,7 @@ "useDisplayMedia": true, "useDocumentVisibility": true, "useDraggable": true, + "useDropZone": true, "useElementBounding": true, "useElementByPoint": true, "useElementHover": true, @@ -122,12 +148,16 @@ "useEyeDropper": true, "useFavicon": true, "useFetch": true, + "useFileDialog": true, + "useFileSystemAccess": true, "useFocus": true, "useFocusWithin": true, "useFps": true, "useFullscreen": true, + "useGamepad": true, "useGeolocation": true, "useIdle": true, + "useImage": true, "useInfiniteScroll": true, "useIntersectionObserver": true, "useInterval": true, @@ -149,6 +179,7 @@ "useNavigatorLanguage": true, "useNetwork": true, "useNow": true, + "useObjectUrl": true, "useOffsetPagination": true, "useOnline": true, "usePageLeave": true, @@ -157,11 +188,14 @@ "usePointer": true, "usePointerSwipe": true, "usePreferredColorScheme": true, + "usePreferredContrast": true, "usePreferredDark": true, "usePreferredLanguages": true, + "usePreferredReducedMotion": true, "useRafFn": true, "useRefHistory": true, "useResizeObserver": true, + "useScreenOrientation": true, "useScreenSafeArea": true, "useScriptTag": true, "useScroll": true, @@ -171,28 +205,35 @@ "useSlots": true, "useSpeechRecognition": true, "useSpeechSynthesis": true, + "useStepper": true, "useStorage": true, "useStorageAsync": true, "useStyleTag": true, + "useSupported": true, "useSwipe": true, "useTemplateRefsList": true, + "useTextDirection": true, "useTextSelection": true, + "useTextareaAutosize": true, "useThrottle": true, - "useThrottledRefHistory": true, "useThrottleFn": true, + "useThrottledRefHistory": true, "useTimeAgo": true, "useTimeout": true, "useTimeoutFn": true, + "useTimeoutPoll": true, "useTimestamp": true, "useTitle": true, + "useToNumber": true, + "useToString": true, "useToggle": true, "useTransition": true, "useUrlSearchParams": true, "useUserMedia": true, - "useVibrate": true, - "useVirtualList": true, "useVModel": true, "useVModels": true, + "useVibrate": true, + "useVirtualList": true, "useWakeLock": true, "useWebNotification": true, "useWebSocket": true, @@ -202,9 +243,17 @@ "useWindowScroll": true, "useWindowSize": true, "watch": true, + "watchArray": true, "watchAtMost": true, + "watchDebounced": true, "watchEffect": true, + "watchIgnorable": true, "watchOnce": true, + "watchPausable": true, + "watchPostEffect": true, + "watchSyncEffect": true, + "watchThrottled": true, + "watchTriggerable": true, "watchWithFilter": true, "whenever": true } diff --git a/packages/ui/auto-imports.d.ts b/packages/ui/auto-imports.d.ts index d7d68940..c8e0f6d4 100644 --- a/packages/ui/auto-imports.d.ts +++ b/packages/ui/auto-imports.d.ts @@ -1,16 +1,20 @@ // Generated by 'unplugin-auto-import' -// We suggest you to commit this file into source control +export {} declare global { + const EffectScope: typeof import('vue')['EffectScope'] const asyncComputed: typeof import('@vueuse/core')['asyncComputed'] const autoResetRef: typeof import('@vueuse/core')['autoResetRef'] - const biSyncRef: typeof import('@vueuse/core')['biSyncRef'] const computed: typeof import('vue')['computed'] + const computedAsync: typeof import('@vueuse/core')['computedAsync'] + const computedEager: typeof import('@vueuse/core')['computedEager'] const computedInject: typeof import('@vueuse/core')['computedInject'] + const computedWithControl: typeof import('@vueuse/core')['computedWithControl'] const controlledComputed: typeof import('@vueuse/core')['controlledComputed'] const controlledRef: typeof import('@vueuse/core')['controlledRef'] const createApp: typeof import('vue')['createApp'] const createEventHook: typeof import('@vueuse/core')['createEventHook'] const createGlobalState: typeof import('@vueuse/core')['createGlobalState'] + const createInjectionState: typeof import('@vueuse/core')['createInjectionState'] const createReactiveFn: typeof import('@vueuse/core')['createReactiveFn'] const createSharedComposable: typeof import('@vueuse/core')['createSharedComposable'] const createUnrefFn: typeof import('@vueuse/core')['createUnrefFn'] @@ -21,7 +25,6 @@ declare global { const defineComponent: typeof import('vue')['defineComponent'] const eagerComputed: typeof import('@vueuse/core')['eagerComputed'] const effectScope: typeof import('vue')['effectScope'] - const EffectScope: typeof import('vue')['EffectScope'] const extendRef: typeof import('@vueuse/core')['extendRef'] const getCurrentInstance: typeof import('vue')['getCurrentInstance'] const getCurrentScope: typeof import('vue')['getCurrentScope'] @@ -29,6 +32,8 @@ declare global { const ignorableWatch: typeof import('@vueuse/core')['ignorableWatch'] const inject: typeof import('vue')['inject'] const isDefined: typeof import('@vueuse/core')['isDefined'] + const isProxy: typeof import('vue')['isProxy'] + const isReactive: typeof import('vue')['isReactive'] const isReadonly: typeof import('vue')['isReadonly'] const isRef: typeof import('vue')['isRef'] const makeDestructurable: typeof import('@vueuse/core')['makeDestructurable'] @@ -61,12 +66,20 @@ declare global { const reactivePick: typeof import('@vueuse/core')['reactivePick'] const readonly: typeof import('vue')['readonly'] const ref: typeof import('vue')['ref'] + const refAutoReset: typeof import('@vueuse/core')['refAutoReset'] + const refDebounced: typeof import('@vueuse/core')['refDebounced'] const refDefault: typeof import('@vueuse/core')['refDefault'] + const refThrottled: typeof import('@vueuse/core')['refThrottled'] + const refWithControl: typeof import('@vueuse/core')['refWithControl'] const resolveComponent: typeof import('vue')['resolveComponent'] + const resolveDirective: typeof import('vue')['resolveDirective'] + const resolveRef: typeof import('@vueuse/core')['resolveRef'] + const resolveUnref: typeof import('@vueuse/core')['resolveUnref'] const shallowReactive: typeof import('vue')['shallowReactive'] const shallowReadonly: typeof import('vue')['shallowReadonly'] const shallowRef: typeof import('vue')['shallowRef'] const syncRef: typeof import('@vueuse/core')['syncRef'] + const syncRefs: typeof import('@vueuse/core')['syncRefs'] const templateRef: typeof import('@vueuse/core')['templateRef'] const throttledRef: typeof import('@vueuse/core')['throttledRef'] const throttledWatch: typeof import('@vueuse/core')['throttledWatch'] @@ -75,6 +88,7 @@ declare global { const toRef: typeof import('vue')['toRef'] const toRefs: typeof import('vue')['toRefs'] const triggerRef: typeof import('vue')['triggerRef'] + const tryOnBeforeMount: typeof import('@vueuse/core')['tryOnBeforeMount'] const tryOnBeforeUnmount: typeof import('@vueuse/core')['tryOnBeforeUnmount'] const tryOnMounted: typeof import('@vueuse/core')['tryOnMounted'] const tryOnScopeDispose: typeof import('@vueuse/core')['tryOnScopeDispose'] @@ -83,28 +97,39 @@ declare global { const unrefElement: typeof import('@vueuse/core')['unrefElement'] const until: typeof import('@vueuse/core')['until'] const useActiveElement: typeof import('@vueuse/core')['useActiveElement'] + const useArrayEvery: typeof import('@vueuse/core')['useArrayEvery'] + const useArrayFilter: typeof import('@vueuse/core')['useArrayFilter'] + const useArrayFind: typeof import('@vueuse/core')['useArrayFind'] + const useArrayFindIndex: typeof import('@vueuse/core')['useArrayFindIndex'] + const useArrayJoin: typeof import('@vueuse/core')['useArrayJoin'] + const useArrayMap: typeof import('@vueuse/core')['useArrayMap'] + const useArrayReduce: typeof import('@vueuse/core')['useArrayReduce'] + const useArraySome: typeof import('@vueuse/core')['useArraySome'] const useAsyncQueue: typeof import('@vueuse/core')['useAsyncQueue'] const useAsyncState: typeof import('@vueuse/core')['useAsyncState'] const useAttrs: typeof import('vue')['useAttrs'] const useBase64: typeof import('@vueuse/core')['useBase64'] const useBattery: typeof import('@vueuse/core')['useBattery'] + const useBluetooth: typeof import('@vueuse/core')['useBluetooth'] const useBreakpoints: typeof import('@vueuse/core')['useBreakpoints'] const useBroadcastChannel: typeof import('@vueuse/core')['useBroadcastChannel'] const useBrowserLocation: typeof import('@vueuse/core')['useBrowserLocation'] const useCached: typeof import('@vueuse/core')['useCached'] - const useClamp: typeof import('@vueuse/core')['useClamp'] const useClipboard: typeof import('@vueuse/core')['useClipboard'] + const useCloned: typeof import('@vueuse/core')['useCloned'] const useColorMode: typeof import('@vueuse/core')['useColorMode'] const useConfirmDialog: typeof import('@vueuse/core')['useConfirmDialog'] const useCounter: typeof import('@vueuse/core')['useCounter'] const useCssModule: typeof import('vue')['useCssModule'] const useCssVar: typeof import('@vueuse/core')['useCssVar'] const useCssVars: typeof import('vue')['useCssVars'] + const useCurrentElement: typeof import('@vueuse/core')['useCurrentElement'] const useCycleList: typeof import('@vueuse/core')['useCycleList'] const useDark: typeof import('@vueuse/core')['useDark'] + const useDateFormat: typeof import('@vueuse/core')['useDateFormat'] const useDebounce: typeof import('@vueuse/core')['useDebounce'] - const useDebouncedRefHistory: typeof import('@vueuse/core')['useDebouncedRefHistory'] const useDebounceFn: typeof import('@vueuse/core')['useDebounceFn'] + const useDebouncedRefHistory: typeof import('@vueuse/core')['useDebouncedRefHistory'] const useDeviceMotion: typeof import('@vueuse/core')['useDeviceMotion'] const useDeviceOrientation: typeof import('@vueuse/core')['useDeviceOrientation'] const useDevicePixelRatio: typeof import('@vueuse/core')['useDevicePixelRatio'] @@ -112,6 +137,7 @@ declare global { const useDisplayMedia: typeof import('@vueuse/core')['useDisplayMedia'] const useDocumentVisibility: typeof import('@vueuse/core')['useDocumentVisibility'] const useDraggable: typeof import('@vueuse/core')['useDraggable'] + const useDropZone: typeof import('@vueuse/core')['useDropZone'] const useElementBounding: typeof import('@vueuse/core')['useElementBounding'] const useElementByPoint: typeof import('@vueuse/core')['useElementByPoint'] const useElementHover: typeof import('@vueuse/core')['useElementHover'] @@ -123,12 +149,16 @@ declare global { const useEyeDropper: typeof import('@vueuse/core')['useEyeDropper'] const useFavicon: typeof import('@vueuse/core')['useFavicon'] const useFetch: typeof import('@vueuse/core')['useFetch'] + const useFileDialog: typeof import('@vueuse/core')['useFileDialog'] + const useFileSystemAccess: typeof import('@vueuse/core')['useFileSystemAccess'] const useFocus: typeof import('@vueuse/core')['useFocus'] const useFocusWithin: typeof import('@vueuse/core')['useFocusWithin'] const useFps: typeof import('@vueuse/core')['useFps'] const useFullscreen: typeof import('@vueuse/core')['useFullscreen'] + const useGamepad: typeof import('@vueuse/core')['useGamepad'] const useGeolocation: typeof import('@vueuse/core')['useGeolocation'] const useIdle: typeof import('@vueuse/core')['useIdle'] + const useImage: typeof import('@vueuse/core')['useImage'] const useInfiniteScroll: typeof import('@vueuse/core')['useInfiniteScroll'] const useIntersectionObserver: typeof import('@vueuse/core')['useIntersectionObserver'] const useInterval: typeof import('@vueuse/core')['useInterval'] @@ -150,6 +180,7 @@ declare global { const useNavigatorLanguage: typeof import('@vueuse/core')['useNavigatorLanguage'] const useNetwork: typeof import('@vueuse/core')['useNetwork'] const useNow: typeof import('@vueuse/core')['useNow'] + const useObjectUrl: typeof import('@vueuse/core')['useObjectUrl'] const useOffsetPagination: typeof import('@vueuse/core')['useOffsetPagination'] const useOnline: typeof import('@vueuse/core')['useOnline'] const usePageLeave: typeof import('@vueuse/core')['usePageLeave'] @@ -158,11 +189,14 @@ declare global { const usePointer: typeof import('@vueuse/core')['usePointer'] const usePointerSwipe: typeof import('@vueuse/core')['usePointerSwipe'] const usePreferredColorScheme: typeof import('@vueuse/core')['usePreferredColorScheme'] + const usePreferredContrast: typeof import('@vueuse/core')['usePreferredContrast'] const usePreferredDark: typeof import('@vueuse/core')['usePreferredDark'] const usePreferredLanguages: typeof import('@vueuse/core')['usePreferredLanguages'] + const usePreferredReducedMotion: typeof import('@vueuse/core')['usePreferredReducedMotion'] const useRafFn: typeof import('@vueuse/core')['useRafFn'] const useRefHistory: typeof import('@vueuse/core')['useRefHistory'] const useResizeObserver: typeof import('@vueuse/core')['useResizeObserver'] + const useScreenOrientation: typeof import('@vueuse/core')['useScreenOrientation'] const useScreenSafeArea: typeof import('@vueuse/core')['useScreenSafeArea'] const useScriptTag: typeof import('@vueuse/core')['useScriptTag'] const useScroll: typeof import('@vueuse/core')['useScroll'] @@ -172,28 +206,35 @@ declare global { const useSlots: typeof import('vue')['useSlots'] const useSpeechRecognition: typeof import('@vueuse/core')['useSpeechRecognition'] const useSpeechSynthesis: typeof import('@vueuse/core')['useSpeechSynthesis'] + const useStepper: typeof import('@vueuse/core')['useStepper'] const useStorage: typeof import('@vueuse/core')['useStorage'] const useStorageAsync: typeof import('@vueuse/core')['useStorageAsync'] const useStyleTag: typeof import('@vueuse/core')['useStyleTag'] + const useSupported: typeof import('@vueuse/core')['useSupported'] const useSwipe: typeof import('@vueuse/core')['useSwipe'] const useTemplateRefsList: typeof import('@vueuse/core')['useTemplateRefsList'] + const useTextDirection: typeof import('@vueuse/core')['useTextDirection'] const useTextSelection: typeof import('@vueuse/core')['useTextSelection'] + const useTextareaAutosize: typeof import('@vueuse/core')['useTextareaAutosize'] const useThrottle: typeof import('@vueuse/core')['useThrottle'] - const useThrottledRefHistory: typeof import('@vueuse/core')['useThrottledRefHistory'] const useThrottleFn: typeof import('@vueuse/core')['useThrottleFn'] + const useThrottledRefHistory: typeof import('@vueuse/core')['useThrottledRefHistory'] const useTimeAgo: typeof import('@vueuse/core')['useTimeAgo'] const useTimeout: typeof import('@vueuse/core')['useTimeout'] const useTimeoutFn: typeof import('@vueuse/core')['useTimeoutFn'] + const useTimeoutPoll: typeof import('@vueuse/core')['useTimeoutPoll'] const useTimestamp: typeof import('@vueuse/core')['useTimestamp'] const useTitle: typeof import('@vueuse/core')['useTitle'] + const useToNumber: typeof import('@vueuse/core')['useToNumber'] + const useToString: typeof import('@vueuse/core')['useToString'] const useToggle: typeof import('@vueuse/core')['useToggle'] const useTransition: typeof import('@vueuse/core')['useTransition'] const useUrlSearchParams: typeof import('@vueuse/core')['useUrlSearchParams'] const useUserMedia: typeof import('@vueuse/core')['useUserMedia'] - const useVibrate: typeof import('@vueuse/core')['useVibrate'] - const useVirtualList: typeof import('@vueuse/core')['useVirtualList'] const useVModel: typeof import('@vueuse/core')['useVModel'] const useVModels: typeof import('@vueuse/core')['useVModels'] + const useVibrate: typeof import('@vueuse/core')['useVibrate'] + const useVirtualList: typeof import('@vueuse/core')['useVirtualList'] const useWakeLock: typeof import('@vueuse/core')['useWakeLock'] const useWebNotification: typeof import('@vueuse/core')['useWebNotification'] const useWebSocket: typeof import('@vueuse/core')['useWebSocket'] @@ -203,10 +244,17 @@ declare global { const useWindowScroll: typeof import('@vueuse/core')['useWindowScroll'] const useWindowSize: typeof import('@vueuse/core')['useWindowSize'] const watch: typeof import('vue')['watch'] + const watchArray: typeof import('@vueuse/core')['watchArray'] const watchAtMost: typeof import('@vueuse/core')['watchAtMost'] + const watchDebounced: typeof import('@vueuse/core')['watchDebounced'] const watchEffect: typeof import('vue')['watchEffect'] + const watchIgnorable: typeof import('@vueuse/core')['watchIgnorable'] const watchOnce: typeof import('@vueuse/core')['watchOnce'] + const watchPausable: typeof import('@vueuse/core')['watchPausable'] + const watchPostEffect: typeof import('vue')['watchPostEffect'] + const watchSyncEffect: typeof import('vue')['watchSyncEffect'] + const watchThrottled: typeof import('@vueuse/core')['watchThrottled'] + const watchTriggerable: typeof import('@vueuse/core')['watchTriggerable'] const watchWithFilter: typeof import('@vueuse/core')['watchWithFilter'] const whenever: typeof import('@vueuse/core')['whenever'] } -export {} diff --git a/packages/ui/etc/api/ui.api.md b/packages/ui/etc/api/ui.api.md index 23bc0c0c..54e1f459 100644 --- a/packages/ui/etc/api/ui.api.md +++ b/packages/ui/etc/api/ui.api.md @@ -545,6 +545,7 @@ size?: SelectSize | undefined; inline?: boolean | undefined; noAutoClose?: boolean | undefined; loading?: boolean | undefined; +dropdownSearch?: boolean | undefined; }>, {}, unknown, {}, {}, ComponentOptionsMixin, ComponentOptionsMixin, Record, string, VNodeProps & AllowedComponentProps & ComponentCustomProps, Readonly[] | SelectOptionGroup[] | undefined; @@ -556,6 +557,7 @@ size?: SelectSize | undefined; inline?: boolean | undefined; noAutoClose?: boolean | undefined; loading?: boolean | undefined; +dropdownSearch?: boolean | undefined; }>>>, {}>; // @public (undocumented) @@ -581,7 +583,11 @@ export interface SelectApi extends UnwrapRef> { // (undocumented) readonly options: UnwrapRef[] | SelectOptionGroup[]>; // (undocumented) + readonly searchQuery: string; + // (undocumented) readonly size: SelectSize; + // (undocumented) + updateSearchQuery: (value: string) => void; } // @public (undocumented) @@ -1075,6 +1081,7 @@ label?: string | undefined; size?: SelectSize | undefined; noAutoClose?: boolean | undefined; loading?: boolean | undefined; +dropdownSearch?: boolean | undefined; }>, {}, unknown, {}, {}, ComponentOptionsMixin, ComponentOptionsMixin, Record, string, VNodeProps & AllowedComponentProps & ComponentCustomProps, Readonly[] | SelectOptionGroup[] | undefined; @@ -1085,6 +1092,7 @@ label?: string | undefined; size?: SelectSize | undefined; noAutoClose?: boolean | undefined; loading?: boolean | undefined; +dropdownSearch?: boolean | undefined; }>>>, {}>; // Warning: (ae-forgotten-export) The symbol "__VLS_WithDefaults" needs to be exported by the entry point lib.d.ts @@ -1103,6 +1111,7 @@ syncMenuAndInputWidths?: boolean | undefined; noAutoClose?: boolean | undefined; loading?: boolean | undefined; sameWidthPopper?: boolean | undefined; +dropdownSearch: boolean; }>, { size: "md"; options: () => never[]; @@ -1114,8 +1123,11 @@ noAutoClose: boolean; label: null; loading: boolean; sameWidthPopper: boolean; +dropdownSearch: boolean; }>, {}, unknown, {}, {}, ComponentOptionsMixin, ComponentOptionsMixin, { "update:modelValue": (value: any) => void; +} & { +search: (value: string) => void; }, string, VNodeProps & AllowedComponentProps & ComponentCustomProps, Readonly, { size: "md"; options: () => never[]; @@ -1139,8 +1152,10 @@ noAutoClose: boolean; label: null; loading: boolean; sameWidthPopper: boolean; +dropdownSearch: boolean; }>>> & { "onUpdate:modelValue"?: ((value: any) => any) | undefined; +onSearch?: ((value: string) => any) | undefined; }, { modelValue: any; multiple: boolean; @@ -1150,6 +1165,7 @@ loading: boolean; options: SelectOption[] | SelectOptionGroup[]; label: string | null; noAutoClose: boolean; +dropdownSearch: boolean; syncMenuAndInputWidths: boolean; sameWidthPopper: boolean; }>; diff --git a/packages/ui/package.json b/packages/ui/package.json index 1dc9a541..52d1b767 100644 --- a/packages/ui/package.json +++ b/packages/ui/package.json @@ -37,12 +37,14 @@ }, "dependencies": { "@popperjs/core": "^2.10.2", - "@vueuse/core": "7.7.1", + "@vueuse/core": "9.2.0", + "@vueuse/math": "9.2.0", "date-fns": "2.20.3", + "escape-string-regexp": "^5.0.0", "focus-trap": "^6.7.1", "jsoneditor": "^9.5.5", "lodash-es": "^4.17.21", - "vue": "^3.2.0" + "vue": "3.2.36" }, "devDependencies": { "@iconify/json": "^2.0.33", @@ -51,17 +53,17 @@ "@soramitsu-ui/icons": "0.1.0", "@soramitsu-ui/theme": "0.3.0", "@soramitsu-ui/vite-plugin-svg": "0.1.0", - "@storybook/addon-actions": "^6.3.9", - "@storybook/addon-essentials": "^6.3.9", - "@storybook/addon-links": "^6.3.9", - "@storybook/vue3": "^6.3.9", + "@storybook/addon-actions": "^6.5.16", + "@storybook/addon-essentials": "^6.5.16", + "@storybook/addon-links": "^6.5.16", + "@storybook/vue3": "^6.5.16", "@types/body-scroll-lock": "^3.1.0", "@types/jsoneditor": "^8.6.1", "@types/lodash-es": "^4.17.6", "@typescript-eslint/eslint-plugin": "^5.26.0", "@typescript-eslint/parser": "^5.26.0", - "@vitejs/plugin-vue": "^3.0.3", - "@vitejs/plugin-vue-jsx": "^2.0.0", + "@vitejs/plugin-vue": "^3.2.0", + "@vitejs/plugin-vue-jsx": "^2.1.1", "@vue/test-utils": "^2", "axe-core": "^4.4.1", "body-scroll-lock": "^4.0.0-beta.0", @@ -73,14 +75,14 @@ "npm-run-all": "^4.1.5", "postcss": "^8.4.16", "sass": "^1.41.1", - "storybook-builder-vite": "^0.1.15", + "storybook-builder-vite": "^0.1.23", "tabbable": "^6.0.0", "type-fest": "^2.18.1", "typescript": "4.7.4", - "unplugin-auto-import": "^0.5.11", + "unplugin-auto-import": "^0.13.0", "unplugin-icons": "^0.13.0", "vite": "^3.0.9", - "vite-plugin-windicss": "^1.8.4", + "vite-plugin-windicss": "^1.8.10", "vite-svg-loader": "^3.3.0", "vitest": "^0.22.1", "vue-tsc": "^0.30.0", diff --git a/packages/ui/src/components/DatePicker/SDatePicker.vue b/packages/ui/src/components/DatePicker/SDatePicker.vue index d492b6b8..1f95183a 100644 --- a/packages/ui/src/components/DatePicker/SDatePicker.vue +++ b/packages/ui/src/components/DatePicker/SDatePicker.vue @@ -6,7 +6,7 @@ import CustomPanel from './SDatePickerPanelCustom.vue' import { IconArrowsChevronBottom24 } from '@/components/icons' import { SPopover, SPopoverWrappedTransition } from '@/components/Popover' -import { and } from '@vueuse/core' +import { and } from '@vueuse/math' import { format } from 'date-fns' import { diff --git a/packages/ui/src/components/Modal/util.ts b/packages/ui/src/components/Modal/util.ts index 24468b3a..3fce0691 100644 --- a/packages/ui/src/components/Modal/util.ts +++ b/packages/ui/src/components/Modal/util.ts @@ -1,5 +1,5 @@ import { Ref } from 'vue' -import { not, or, and } from '@vueuse/core' +import { not, or, and } from '@vueuse/math' /** * Transforms *something* into something that could be binded to `Transition` component as `v-bind="something"` diff --git a/packages/ui/src/components/NavigationMenu/SNavigationSubmenu.vue b/packages/ui/src/components/NavigationMenu/SNavigationSubmenu.vue index e9ae9087..7c4363b8 100644 --- a/packages/ui/src/components/NavigationMenu/SNavigationSubmenu.vue +++ b/packages/ui/src/components/NavigationMenu/SNavigationSubmenu.vue @@ -4,7 +4,7 @@ import SNavigationMenuItemBody from '@/components/NavigationMenu/SNavigationMenu import { SCollapseTransition } from '@/components/Transitions' import { NAVIGATION_SUBMENU_API_KEY, useNavigationMenuApi } from '@/components/NavigationMenu/api' import { IconChevronBottom16 } from '@/components/icons' -import { and, not } from '@vueuse/core' +import { and, not } from '@vueuse/math' const includedItems = shallowReactive(new Set>([])) diff --git a/packages/ui/src/components/Pagination/SPagination.vue b/packages/ui/src/components/Pagination/SPagination.vue index d4ef6e97..7bb320c5 100644 --- a/packages/ui/src/components/Pagination/SPagination.vue +++ b/packages/ui/src/components/Pagination/SPagination.vue @@ -5,7 +5,7 @@ import { IconChevronsLeft16, IconChevronsRight16, } from '@/components/icons' -import { not } from '@vueuse/core' +import { not } from '@vueuse/math' import { SDropdown } from '@/components' const PAGINATION_MAX_PAGES_SELECTABLE = 7 diff --git a/packages/ui/src/components/Popover/SPopover.ts b/packages/ui/src/components/Popover/SPopover.ts index 652a397e..90839e89 100644 --- a/packages/ui/src/components/Popover/SPopover.ts +++ b/packages/ui/src/components/Popover/SPopover.ts @@ -1,6 +1,7 @@ import { Ref, cloneVNode, PropType } from 'vue' import { Placement, placements, Instance, State } from '@popperjs/core' -import { not, or } from '@vueuse/core' +import { MaybeElementRef } from '@vueuse/core' +import { not, or } from '@vueuse/math' import { usePopper } from '@/composables/popper' import { PopoverApi, POPOVER_API_KEY } from './api' import { Except } from 'type-fest' @@ -44,7 +45,7 @@ function useDelayedShow(show: Ref, delays: { show: Ref; hide: R } function createSanitizedTemplateRef(): { rawRef: Ref; sanitizedRef: Ref } { - const rawRef = ref(null) + const rawRef: MaybeElementRef = ref(null) const sanitizedRef = eagerComputed(() => { const el = unrefElement(rawRef) diff --git a/packages/ui/src/components/Radio/util.ts b/packages/ui/src/components/Radio/util.ts index e118f5c0..32c1641f 100644 --- a/packages/ui/src/components/Radio/util.ts +++ b/packages/ui/src/components/Radio/util.ts @@ -179,7 +179,7 @@ export function useRadiosRegistration({ valueRef, disabledRef: isDisabled, }: RegisterRadioParams): RadioGroupRegisteredItemApi { - const { focused: isFocused } = useFocus({ target: elRef }) + const { focused: isFocused } = useFocus(elRef) const index = eagerComputed(() => (elRef.value ? radioElements.value.indexOf(elRef.value) : -1)) diff --git a/packages/ui/src/components/Select/SDropdown.vue b/packages/ui/src/components/Select/SDropdown.vue index 6bd5caea..7b67dec2 100644 --- a/packages/ui/src/components/Select/SDropdown.vue +++ b/packages/ui/src/components/Select/SDropdown.vue @@ -15,6 +15,7 @@ const props = defineProps<{ inline?: boolean noAutoClose?: boolean loading?: boolean + dropdownSearch?: boolean }>() const buttonType = computed(() => (props.inline ? SelectButtonType.Inline : SelectButtonType.Default)) @@ -45,7 +46,10 @@ function isThereLabelSlot() { diff --git a/packages/ui/src/components/Select/SSelect.vue b/packages/ui/src/components/Select/SSelect.vue index c57f4936..6ae97cc2 100644 --- a/packages/ui/src/components/Select/SSelect.vue +++ b/packages/ui/src/components/Select/SSelect.vue @@ -14,6 +14,7 @@ const props = defineProps<{ size?: SelectSize noAutoClose?: boolean loading?: boolean + dropdownSearch?: boolean }>() const defaultOptionType = computed(() => (props.multiple ? SelectOptionType.Checkbox : SelectOptionType.Radio)) @@ -38,7 +39,10 @@ const defaultOptionType = computed(() => (props.multiple ? SelectOptionType.Chec diff --git a/packages/ui/src/components/Select/SSelectBase.vue b/packages/ui/src/components/Select/SSelectBase.vue index 367a539d..da8812d9 100644 --- a/packages/ui/src/components/Select/SSelectBase.vue +++ b/packages/ui/src/components/Select/SSelectBase.vue @@ -2,7 +2,7 @@ import { SelectSize, SelectOption, SelectOptionGroup } from './types' import { useSelectModel } from './use-model' import { SelectApi, SELECT_API_KEY } from './api' -import { and, not } from '@vueuse/core' +import { and, not } from '@vueuse/math' import { SPopover, SPopoverWrappedTransition } from '@/components/Popover' const props = withDefaults( @@ -51,6 +51,11 @@ const props = withDefaults( * Makes popper same width as trigger. */ sameWidthPopper?: boolean + + /** + * Adds search field to dropdown + */ + dropdownSearch: boolean }>(), { size: SelectSize.Md, @@ -63,10 +68,14 @@ const props = withDefaults( label: null, loading: false, sameWidthPopper: false, + dropdownSearch: false, }, ) -const emit = defineEmits<(event: 'update:modelValue', value: any) => void>() +const emit = defineEmits<{ + (event: 'update:modelValue', value: any): void + (event: 'search', value: string): void +}>() const model = useVModel(props, 'modelValue', emit) const { multiple, disabled, loading, options, size, label, noAutoClose } = toRefs(props) @@ -84,6 +93,17 @@ const [showPopper, togglePopper] = useToggle(false) // close popper if select is disabled whenever(and(disabled, showPopper), () => togglePopper(false), { immediate: true }) +const searchQuery = ref('') +whenever(not(showPopper), () => { + searchQuery.value = '' +}) + +function updateSearchQuery(query: string) { + searchQuery.value = query + + emit('search', searchQuery.value) +} + const api: SelectApi = reactive({ ...modeling, multiple, @@ -95,6 +115,8 @@ const api: SelectApi = reactive({ menuToggle: togglePopper, size, noAutoClose, + searchQuery, + updateSearchQuery, }) provide(SELECT_API_KEY, api) diff --git a/packages/ui/src/components/Select/SSelectDropdown.vue b/packages/ui/src/components/Select/SSelectDropdown.vue index 0bc281ac..ee48cd49 100644 --- a/packages/ui/src/components/Select/SSelectDropdown.vue +++ b/packages/ui/src/components/Select/SSelectDropdown.vue @@ -5,9 +5,12 @@ import SSelectOption from './SSelectOption.vue' import { ComputedRef } from 'vue' import { isSelectOptions } from '@/components/Select/utils' import SSpinner from '@/components/Spinner/SSpinner.vue' +import { IconBasicSearch24 } from '@/components/icons' +import escapeStringRegexp from 'escape-string-regexp' -defineProps<{ +const props = defineProps<{ itemType: SelectOptionType + search: boolean }>() const api = useSelectApi() @@ -24,10 +27,31 @@ const optionGroups: ComputedRef = computed(() => { return options }) +const isSearching = eagerComputed(() => props.search && api.searchQuery) + +const escapedQuery = computed(() => new RegExp(escapeStringRegexp(api.searchQuery), 'i')) +const shownOptionGroups: ComputedRef = computed(() => { + if (!api.searchQuery) { + return optionGroups.value + } + + return optionGroups.value.map((x) => ({ ...x, items: x.items.filter((x) => escapedQuery.value.test(x.label)) })) +}) + function isActionButtonShown(selectAllBtn: boolean) { return api.multiple && selectAllBtn } +function isHeaderShown(optionGroup: SelectOptionGroup) { + return !isSearching.value && (isActionButtonShown(!!optionGroup.selectAllBtn) || optionGroup.header) +} + +function handleSearchInput(event: Event) { + if (event.target instanceof HTMLInputElement) { + api.updateSearchQuery(event.target.value) + } +} + const HEADER_FONT = { [SelectSize.Xl]: 'sora-tpg-ch2', [SelectSize.Lg]: 'sora-tpg-ch3', @@ -35,12 +59,19 @@ const HEADER_FONT = { [SelectSize.Sm]: 'sora-tpg-ch3', } as const -const ACTION_FONT = { +const MAIN_FONT = { [SelectSize.Xl]: 'sora-tpg-p3', [SelectSize.Lg]: 'sora-tpg-p4', [SelectSize.Md]: 'sora-tpg-p4', [SelectSize.Sm]: 'sora-tpg-p4', } as const + +const SEARCH_ICON_SIZE = { + [SelectSize.Xl]: 24, + [SelectSize.Lg]: 16, + [SelectSize.Md]: 16, + [SelectSize.Sm]: 12, +} as const