├── .eslintrc.js ├── .github └── FUNDING.yml ├── .gitignore ├── CHANGELOG.md ├── LICENSE ├── README.md ├── __tests__ └── setupTest.ts ├── deploy.sh ├── docs ├── v2 │ ├── .vuepress │ │ ├── components │ │ │ ├── ExampleBlock.vue │ │ │ ├── UseAxios.vue │ │ │ ├── UseClipboard.vue │ │ │ ├── UseColor.vue │ │ │ ├── UseCssVars.vue │ │ │ ├── UseDebouncedRef.vue │ │ │ ├── UseElementSize.vue │ │ │ ├── UseEmitter.vue │ │ │ ├── UseEmitterEmit.vue │ │ │ ├── UseEmitterOn.vue │ │ │ ├── UseEventListener.vue │ │ │ ├── UseFullscreen.vue │ │ │ ├── UseInstance.vue │ │ │ ├── UseMouse.vue │ │ │ ├── UsePrecision.vue │ │ │ ├── UseResizeEvent.vue │ │ │ ├── UseResizeObserver.vue │ │ │ ├── UseShortcut.vue │ │ │ ├── UseStateshot.vue │ │ │ ├── UseVuex.vue │ │ │ └── UseWindowSize.vue │ │ ├── config.js │ │ ├── enhanceApp.js │ │ ├── store │ │ │ ├── actions.js │ │ │ ├── index.js │ │ │ ├── modules │ │ │ │ ├── counter.js │ │ │ │ └── index.js │ │ │ └── mutation-types.js │ │ └── styles │ │ │ ├── docs.styl │ │ │ └── index.styl │ ├── README.md │ ├── guide │ │ ├── README.md │ │ ├── axios │ │ │ └── useAxios.md │ │ ├── core │ │ │ ├── useClipboard.md │ │ │ ├── useColor.md │ │ │ ├── useCssVars.md │ │ │ ├── useDebouncedRef.md │ │ │ ├── useElementSize.md │ │ │ ├── useEmitter.md │ │ │ ├── useEventListener.md │ │ │ ├── useFullscreen.md │ │ │ ├── useInstance.md │ │ │ ├── useMouse.md │ │ │ ├── usePalette.md │ │ │ ├── usePrecision.md │ │ │ ├── useResizeEvent.md │ │ │ ├── useResizeObserver.md │ │ │ ├── useShortcut.md │ │ │ ├── useStateshot.md │ │ │ └── useWindowSize.md │ │ └── vuex │ │ │ ├── namespacing.md │ │ │ ├── useActions.md │ │ │ ├── useGetters.md │ │ │ ├── useMutations.md │ │ │ ├── useState.md │ │ │ ├── useStore.md │ │ │ └── useVuex.md │ ├── package.json │ ├── tailwind.config.js │ └── yarn.lock └── v3 │ ├── .vitepress │ ├── components │ │ ├── ExampleBlock.vue │ │ ├── UseAxiosDemo.vue │ │ ├── UseClipboardDemo.vue │ │ ├── UseColorDemo.vue │ │ ├── UseCssVarsDemo.vue │ │ ├── UseDebouncedRefDemo.vue │ │ ├── UseElementSizeDemo.vue │ │ ├── UseEmitterDemo.vue │ │ ├── UseEmitterEmitDemo.vue │ │ ├── UseEmitterOnDemo.vue │ │ ├── UseEventListenerDemo.vue │ │ ├── UseFullscreenDemo.vue │ │ ├── UseInstanceDemo.vue │ │ ├── UseMouseDemo.vue │ │ ├── UsePrecisionDemo.vue │ │ ├── UseResizeEventDemo.vue │ │ ├── UseResizeObserverDemo.vue │ │ ├── UseShortcutDemo.vue │ │ ├── UseStateshotDemo.vue │ │ ├── UseVuexDemo.vue │ │ └── UseWindowSizeDemo.vue │ ├── config.js │ ├── styles │ │ ├── docs.styl │ │ └── index.styl │ └── theme │ │ ├── index.js │ │ └── index.postcss │ ├── axios │ └── use-axios.md │ ├── core │ ├── use-clipboard.md │ ├── use-color.md │ ├── use-css-vars.md │ ├── use-debounced-ref.md │ ├── use-element-size.md │ ├── use-emitter.md │ ├── use-event-listener.md │ ├── use-fullscreen.md │ ├── use-instance.md │ ├── use-mouse.md │ ├── use-palette.md │ ├── use-precision.md │ ├── use-resize-event.md │ ├── use-resize-observer.md │ ├── use-shortcut.md │ ├── use-stateshot.md │ └── use-window-size.md │ ├── guide │ └── index.md │ ├── index.md │ ├── package.json │ ├── tailwind.config.js │ ├── vuex │ ├── namespacing.md │ ├── use-actions.md │ ├── use-getters.md │ ├── use-mutations.md │ ├── use-state.md │ ├── use-store.md │ └── use-vuex.md │ └── yarn.lock ├── examples ├── vue2-demo │ ├── .editorconfig │ ├── .gitignore │ ├── README.md │ ├── package.json │ ├── public │ │ ├── favicon.ico │ │ └── index.html │ ├── src │ │ ├── App.vue │ │ ├── assets │ │ │ └── logo.png │ │ ├── components │ │ │ ├── Counter.vue │ │ │ └── HelloWorld.vue │ │ ├── main.ts │ │ ├── shims-tsx.d.ts │ │ ├── shims-vue.d.ts │ │ └── store │ │ │ ├── actions.ts │ │ │ ├── index.ts │ │ │ ├── modules │ │ │ ├── counter.ts │ │ │ └── index.ts │ │ │ └── mutation-types.ts │ ├── tsconfig.json │ └── yarn.lock └── vue3-demo │ ├── .editorconfig │ ├── .gitignore │ ├── README.md │ ├── package.json │ ├── public │ ├── favicon.ico │ └── index.html │ ├── src │ ├── App.vue │ ├── assets │ │ └── logo.png │ ├── components │ │ ├── Counter.vue │ │ └── HelloWorld.vue │ ├── main.ts │ ├── shims-vue.d.ts │ └── store │ │ ├── actions.ts │ │ ├── index.ts │ │ ├── modules │ │ ├── counter.ts │ │ └── index.ts │ │ └── mutation-types.ts │ ├── tsconfig.json │ └── yarn.lock ├── jest.config.js ├── lerna.json ├── package.json ├── packages ├── axios │ ├── README.md │ ├── index.ts │ ├── package.json │ ├── useAxios.ts │ └── yarn.lock ├── core │ ├── README.md │ ├── __test__ │ │ ├── useDebouncedRef.spec.ts │ │ └── usePrecision.spec.ts │ ├── index.ts │ ├── package.json │ ├── types │ │ ├── color.ts │ │ ├── common.ts │ │ ├── dom.ts │ │ ├── index.ts │ │ ├── ref.ts │ │ ├── resize-observer.ts │ │ └── stateshot.ts │ ├── useClipboard │ │ └── index.ts │ ├── useColor │ │ └── index.ts │ ├── useCssVars │ │ └── index.ts │ ├── useDebouncedRef │ │ └── index.ts │ ├── useElementSize │ │ └── index.ts │ ├── useEmitter │ │ └── index.ts │ ├── useEventListener │ │ └── index.ts │ ├── useFullscreen │ │ └── index.ts │ ├── useInstance │ │ └── index.ts │ ├── useLifecycle │ │ └── index.ts │ ├── useMouse │ │ └── index.ts │ ├── usePrecision │ │ └── index.ts │ ├── useReactiveState │ │ └── index.ts │ ├── useResizeEvent │ │ └── index.ts │ ├── useResizeObserver │ │ └── index.ts │ ├── useShortcut │ │ └── index.ts │ ├── useStateshot │ │ └── index.ts │ ├── useWindowSize │ │ └── index.ts │ ├── utils │ │ ├── common.ts │ │ ├── index.ts │ │ ├── is.ts │ │ └── ref.ts │ └── yarn.lock ├── global.d.ts └── vuex │ ├── README.md │ ├── index.ts │ ├── package.json │ ├── useVuex.ts │ ├── utils │ └── index.ts │ └── yarn.lock ├── rollup.config.js ├── scripts ├── packages.ts └── rollup.config.ts ├── tsconfig.json └── yarn.lock /.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | root: true, 3 | globals: { 4 | __DEV__: true 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | 3 | github: [xiaoluoboding] 4 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules 3 | packages/**/lib 4 | packages/**/node_modules 5 | coverage 6 | docs/v2/.vuepress/dist 7 | docs/v3/.vitepress/dist 8 | 9 | # local env files 10 | .env.local 11 | .env.*.local 12 | 13 | # Log files 14 | npm-debug.log* 15 | yarn-debug.log* 16 | yarn-error.log* 17 | 18 | # Editor directories and files 19 | .idea 20 | .vscode 21 | *.suo 22 | *.ntvs* 23 | *.njsproj 24 | *.sln 25 | *.sw? 26 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 Yunwei Xiao 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /__tests__/setupTest.ts: -------------------------------------------------------------------------------- 1 | import { createLocalVue, mount } from '@vue/test-utils' 2 | import VueCompositionApi from '@vue/composition-api' 3 | import { defineComponent, UnwrapRef } from 'vue-demi' 4 | 5 | const localVue = createLocalVue() 6 | localVue.use(VueCompositionApi) 7 | 8 | export function renderHook( 9 | setup: () => V, 10 | ) { 11 | const App = defineComponent({ 12 | setup, 13 | template: '
', 14 | }) 15 | 16 | return mount>(App as any, { localVue }) 17 | } -------------------------------------------------------------------------------- /deploy.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | # 确保脚本抛出遇到的错误 4 | set -e 5 | 6 | # 生成静态文件 7 | npm run docs:build:v2 8 | 9 | # 进入生成的文件夹 10 | cd docs/v2/.vuepress/dist 11 | 12 | # 如果是发布到自定义域名 13 | # echo 'www.example.com' > CNAME 14 | 15 | git init 16 | git add -A 17 | git commit -m 'chore: deploy gh-pages' 18 | 19 | # 如果发布到 https://.github.io 20 | # git push -f git@github.com:/.github.io.git master 21 | 22 | # 如果发布到 https://.github.io/ 23 | git push -f https://github.com/vueblocks/vue-use-utilities.git master:gh-pages 24 | 25 | cd - 26 | -------------------------------------------------------------------------------- /docs/v2/.vuepress/components/ExampleBlock.vue: -------------------------------------------------------------------------------- 1 | 17 | 18 | -------------------------------------------------------------------------------- /docs/v2/.vuepress/components/UseAxios.vue: -------------------------------------------------------------------------------- 1 | 15 | 16 | 47 | -------------------------------------------------------------------------------- /docs/v2/.vuepress/components/UseClipboard.vue: -------------------------------------------------------------------------------- 1 | 20 | 21 | 43 | -------------------------------------------------------------------------------- /docs/v2/.vuepress/components/UseCssVars.vue: -------------------------------------------------------------------------------- 1 | 36 | 37 | 65 | 66 | 76 | -------------------------------------------------------------------------------- /docs/v2/.vuepress/components/UseDebouncedRef.vue: -------------------------------------------------------------------------------- 1 | 15 | 16 | -------------------------------------------------------------------------------- /docs/v2/.vuepress/components/UseElementSize.vue: -------------------------------------------------------------------------------- 1 | 19 | 20 | -------------------------------------------------------------------------------- /docs/v2/.vuepress/components/UseEmitter.vue: -------------------------------------------------------------------------------- 1 | 17 | 18 | 42 | -------------------------------------------------------------------------------- /docs/v2/.vuepress/components/UseEmitterEmit.vue: -------------------------------------------------------------------------------- 1 | 10 | 11 | 34 | -------------------------------------------------------------------------------- /docs/v2/.vuepress/components/UseEmitterOn.vue: -------------------------------------------------------------------------------- 1 | 10 | 11 | 39 | -------------------------------------------------------------------------------- /docs/v2/.vuepress/components/UseEventListener.vue: -------------------------------------------------------------------------------- 1 | 11 | 12 | 71 | -------------------------------------------------------------------------------- /docs/v2/.vuepress/components/UseFullscreen.vue: -------------------------------------------------------------------------------- 1 | 20 | 21 | 45 | -------------------------------------------------------------------------------- /docs/v2/.vuepress/components/UseInstance.vue: -------------------------------------------------------------------------------- 1 | 4 | 5 | 17 | -------------------------------------------------------------------------------- /docs/v2/.vuepress/components/UseMouse.vue: -------------------------------------------------------------------------------- 1 | 11 | 12 | 32 | -------------------------------------------------------------------------------- /docs/v2/.vuepress/components/UseResizeEvent.vue: -------------------------------------------------------------------------------- 1 | 23 | 24 | 84 | -------------------------------------------------------------------------------- /docs/v2/.vuepress/components/UseResizeObserver.vue: -------------------------------------------------------------------------------- 1 | 19 | 20 | -------------------------------------------------------------------------------- /docs/v2/.vuepress/components/UseShortcut.vue: -------------------------------------------------------------------------------- 1 | 14 | 15 | 49 | -------------------------------------------------------------------------------- /docs/v2/.vuepress/components/UseStateshot.vue: -------------------------------------------------------------------------------- 1 | 29 | 30 | 75 | -------------------------------------------------------------------------------- /docs/v2/.vuepress/components/UseVuex.vue: -------------------------------------------------------------------------------- 1 | 19 | 20 | 51 | -------------------------------------------------------------------------------- /docs/v2/.vuepress/components/UseWindowSize.vue: -------------------------------------------------------------------------------- 1 | 23 | 24 | 88 | -------------------------------------------------------------------------------- /docs/v2/.vuepress/enhanceApp.js: -------------------------------------------------------------------------------- 1 | import VueCompositionAPI from '@vue/composition-api' 2 | import store from './store' 3 | 4 | export default ({ Vue }) => { 5 | Vue.use(VueCompositionAPI) 6 | 7 | Vue.mixin({ store }) 8 | } 9 | -------------------------------------------------------------------------------- /docs/v2/.vuepress/store/actions.js: -------------------------------------------------------------------------------- 1 | const makeAction = type => { 2 | return ({ commit }, ...args) => commit(type, ...args) 3 | } 4 | 5 | export const makeActions = (types = {}) => { 6 | const actions = {} 7 | 8 | for (const type of Object.keys(types)) { 9 | const action = { 10 | [type]: makeAction(types[type]) 11 | } 12 | Object.assign(actions, action) 13 | } 14 | 15 | return actions 16 | } 17 | 18 | export const setState = makeAction('SET_STATE') 19 | -------------------------------------------------------------------------------- /docs/v2/.vuepress/store/index.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | import Vuex from 'vuex' 3 | 4 | import * as actions from './actions' 5 | import * as types from './mutation-types' 6 | import modules from './modules/index' 7 | 8 | Vue.use(Vuex) 9 | 10 | const state = { 11 | theme: 'light' 12 | } 13 | 14 | const getters = { 15 | isDarkmode: state => state.theme === 'dark' 16 | } 17 | 18 | const mutations = { 19 | [types.SET_STATE] (state, payload) { 20 | Object.assign(state, payload) 21 | }, 22 | [types.SET_THEME] (state, payload) { 23 | state.theme = payload 24 | } 25 | } 26 | 27 | // A Vuex instance is created by combining the state, mutations, actions, 28 | // and getters. 29 | export default new Vuex.Store({ 30 | state, 31 | getters, 32 | actions, 33 | mutations, 34 | modules 35 | }) 36 | -------------------------------------------------------------------------------- /docs/v2/.vuepress/store/modules/counter.js: -------------------------------------------------------------------------------- 1 | import { makeActions } from '../actions' 2 | import { counter } from '../mutation-types' 3 | 4 | // namespaced counter state object. 5 | // each Vuex instance is just a single state tree. 6 | const state = { 7 | count: 0 8 | } 9 | 10 | // mutations are operations that actually mutate the state. 11 | // each mutation handler gets the entire state tree as the 12 | // first argument, followed by additional payload arguments. 13 | // mutations must be synchronous and can be recorded by plugins 14 | // for debugging purposes. 15 | const mutations = { 16 | [counter.INCREMENT] (state) { 17 | state.count++ 18 | }, 19 | [counter.DECREMENT] (state) { 20 | state.count-- 21 | } 22 | } 23 | 24 | // actions are functions that cause side effects and can involve 25 | // asynchronous operations. 26 | const actions = { 27 | ...makeActions({ 28 | increment: counter.INCREMENT, 29 | decrement: counter.DECREMENT 30 | }), 31 | incrementIfOdd ({ commit, state }) { 32 | if ((state.count + 1) % 2 === 0) { 33 | commit(counter.INCREMENT) 34 | } 35 | }, 36 | incrementAsync ({ commit }) { 37 | return new Promise((resolve, reject) => { 38 | setTimeout(() => { 39 | commit(counter.INCREMENT) 40 | resolve() 41 | }, 1000) 42 | }) 43 | } 44 | } 45 | 46 | // getters are functions. 47 | const getters = { 48 | evenOrOdd: state => state.count % 2 === 0 ? 'even' : 'odd' 49 | } 50 | 51 | // nested modules 52 | // const modules = { 53 | 54 | // } 55 | 56 | export default { 57 | namespaced: true, 58 | state, 59 | getters, 60 | actions, 61 | mutations 62 | // modules 63 | } 64 | -------------------------------------------------------------------------------- /docs/v2/.vuepress/store/modules/index.js: -------------------------------------------------------------------------------- 1 | const files = require.context('.', false, /\.js$/) 2 | const modules = {} 3 | 4 | files.keys().forEach((key) => { 5 | if (key === './index.js') return 6 | modules[key.replace(/(\.\/|\.js)/g, '')] = files(key).default 7 | }) 8 | 9 | export default modules 10 | -------------------------------------------------------------------------------- /docs/v2/.vuepress/store/mutation-types.js: -------------------------------------------------------------------------------- 1 | export const SET_STATE = 'SET_STATE' 2 | export const SET_THEME = 'SET_THEME' 3 | 4 | // counter moudle 5 | export const counter = { 6 | SET_COUNTER_STATE: 'SET_COUNTER_STATE', 7 | INCREMENT: 'INCREMENT', 8 | DECREMENT: 'DECREMENT' 9 | } 10 | -------------------------------------------------------------------------------- /docs/v2/.vuepress/styles/docs.styl: -------------------------------------------------------------------------------- 1 | // use tailwindcss default border rule 2 | *, 3 | ::before, 4 | ::after { 5 | box-sizing: border-box; /* 1 */ 6 | border-width: 0; /* 2 */ 7 | border-style: solid; /* 2 */ 8 | border-color: #e5e7eb; /* 2 */ 9 | } 10 | 11 | // docs styles 12 | .example-panel 13 | &__codeblock 14 | pre 15 | @apply m-0 rounded-none !important -------------------------------------------------------------------------------- /docs/v2/.vuepress/styles/index.styl: -------------------------------------------------------------------------------- 1 | // @tailwind base; 2 | 3 | @tailwind components; 4 | 5 | @tailwind utilities; 6 | 7 | @require './docs.styl' 8 | -------------------------------------------------------------------------------- /docs/v2/README.md: -------------------------------------------------------------------------------- 1 | --- 2 | home: true 3 | # heroImage: images/banner-x.png 4 | actionText: Get Started → 5 | actionLink: /guide/ 6 | features: 7 | - title: 🔮 Reactive 8 | details: Full usable of `reactive`, ready to use on your templates. 9 | - title: 🛠 Composable 10 | details: All utilities is composable built on top of `@vue/composition-api` 11 | - title: 🌳 TreeShakable 12 | details: Packages is built with rollup, Tree-Shakable and SideEffects free. 13 | - title: 🤟 Vue 2 and 3 Support 14 | details: Compatible with Vue2.x and Vue 3, built on top of `vue-demi` 15 | - title: 💪 Fully Typed APIs 16 | details: Flexible programmatic APIs with full TypeScript typing. 17 | - title: 🧩 Advanced Integration 18 | details: Support commonly used add-ons like `Vuex`、`Axios`. 19 | footer: MIT Licensed | Copyright © 2020-present @xiaoluoboding 20 | --- 21 | -------------------------------------------------------------------------------- /docs/v2/guide/README.md: -------------------------------------------------------------------------------- 1 | # Vue Use Utilities 2 | 3 | ## What 4 | 5 | `@vueblocks/vue-use-utilities` is a out of box generic `composition-api` utilities. It's both Support 6 | Vue 2 / 3 Project. Built on top of [vue-demi](https://github.com/antfu/vue-demi) & [@vue/composition-api](https://github.com/vuejs/composition-api) 7 | 8 | ## Inspiration 9 | 10 | This libary is inspired by [@vueuse/core](https://github.com/antfu/vueuse) also other similar projects. 11 | 12 | ## Installation 13 | 14 | ```bash 15 | # Vue 2 with @vue/composition-api 16 | yarn add @vue/composition-api @vueblocks/vue-use-core -S 17 | or 18 | npm i @vue/composition-api @vueblocks/vue-use-core -S 19 | 20 | # Vue 3 21 | yarn add @vueblocks/vue-use-core -S 22 | or 23 | npm i @vueblocks/vue-use-core -S 24 | ``` 25 | -------------------------------------------------------------------------------- /docs/v2/guide/axios/useAxios.md: -------------------------------------------------------------------------------- 1 | # useAxios 2 | 3 | > Use Axios With Composition API Easily. 4 | 5 | ## Install 6 | 7 | ```bash 8 | # Vue 2 with @vue/composition-api 9 | yarn add @vue/composition-api @vueblocks/vue-use-axios -S 10 | or 11 | npm i @vue/composition-api @vueblocks/vue-use-axios -S 12 | 13 | # Vue 3 14 | yarn add @vueblocks/vue-use-axios -S 15 | or 16 | npm i @vueblocks/vue-use-axios -S 17 | ``` 18 | 19 | ## Example 20 | 21 | > Fetch Bitcoin Price every 20 seconds 22 | 23 | 24 | 25 | 26 | 27 | ## Usage 28 | 29 | `useAxios` is a wrapper of Axios 30 | 31 | ```js 32 | import { useAxios } from '@vueblocks/vue-use-axios' 33 | 34 | export default { 35 | ... 36 | setup () { 37 | const url = 'https://api.coindesk.com/v1/bpi/currentprice.json' 38 | 39 | const { refetch, data } = useAxios(url) 40 | 41 | const bitcoin = ref(data) 42 | 43 | const fetchBitcoinRate = () => { 44 | setInterval(() => { 45 | refetch() 46 | }, 20000) 47 | } 48 | 49 | onMounted(() => { 50 | fetchBitcoinRate() 51 | }) 52 | 53 | return { 54 | bitcoin 55 | } 56 | } 57 | ... 58 | } 59 | ``` 60 | 61 | ## Typing 62 | 63 | ```ts 64 | interface IAxiosOptions { 65 | debounce?: number; 66 | throttle?: number; 67 | } 68 | declare const useAxios: (url: string, config?: AxiosRequestConfig | undefined, options?: IAxiosOptions | undefined) => { 69 | refetch: () => void; 70 | cancel: (message?: string | undefined) => void; 71 | response: Ref; 72 | data: Ref; 73 | finished: Ref; 74 | canceled: Ref; 75 | error: Ref; 76 | }; 77 | ``` 78 | -------------------------------------------------------------------------------- /docs/v2/guide/core/useClipboard.md: -------------------------------------------------------------------------------- 1 | # useClipboard 2 | 3 | ::: tip useClipboard 4 | Reactive `navigator.clipboard` API 5 | ::: 6 | 7 | ## Example 8 | 9 | > Copy some input message 10 | 11 | 12 | 13 | 14 | 15 | ## Usage 16 | 17 | ```html 18 | 23 | 24 | 25 | ``` 26 | 27 | ```js 28 | import { ref, defineComponent } from 'vue' 29 | import { useClipboard } from '@vueblocks/vue-use-core' 30 | 31 | export default defineComponent({ 32 | setup () { 33 | const source = ref('') 34 | const { copy, copied, text, clear } = useClipboard({ source }) 35 | 36 | return { 37 | source, 38 | text, 39 | copy, 40 | copied, 41 | clear 42 | } 43 | } 44 | }) 45 | ``` 46 | 47 | ## Typing 48 | ```ts 49 | interface ClipboardOption { 50 | source?: string; 51 | during?: number; 52 | } 53 | interface ClipboardResult { 54 | text: Ref; 55 | copy: typeof NOOP; 56 | clear: typeof NOOP; 57 | copied: Ref; 58 | isSupported: Ref; 59 | } 60 | /** 61 | * A Reactive Clipboard API 62 | * @param options 63 | * @returns 64 | */ 65 | declare const useClipboard: (options?: ClipboardOption) => ClipboardResult; 66 | ``` 67 | -------------------------------------------------------------------------------- /docs/v2/guide/core/useColor.md: -------------------------------------------------------------------------------- 1 | # useColor 2 | 3 | ::: tip useColor 4 | Reactive color parsing and manipulation built on top of [color2k](https://github.com/ricokahler/color2k). 5 | ::: 6 | 7 | ## Example 8 | 9 | > Change Color and Watch Reactive Color. 10 | 11 | 12 | 13 | 14 | 15 | ## Usage 16 | 17 | ```html 18 |
19 |
20 |

Ligthen Color

21 |
{{ lightenColor }}
22 |
23 |
24 | ``` 25 | 26 | ```js 27 | import { useColor } from '@vueblocks/vue-use-core' 28 | 29 | export default { 30 | setup () { 31 | const mainColor = ref('#3eaf7c') 32 | const mainAmount = ref(0.5) 33 | 34 | const { lightenColor } = useColor(mainColor, mainAmount) 35 | 36 | return { 37 | lightenColor 38 | } 39 | } 40 | } 41 | ``` 42 | 43 | ## Typing 44 | 45 | ```ts 46 | interface ReactiveColor { 47 | hexColor: ComputedRef; 48 | hslaColor: ComputedRef; 49 | rgbaColor: ComputedRef; 50 | readableColor: ComputedRef; 51 | invertColor: ComputedRef; 52 | luminance: ComputedRef; 53 | lightenColor: ComputedRef; 54 | darkenColor: ComputedRef; 55 | tintColor: ComputedRef; 56 | shadeColor: ComputedRef; 57 | desaturateColor: ComputedRef; 58 | saturateColor: ComputedRef; 59 | opacifyColor: ComputedRef; 60 | transparentizeColor: ComputedRef; 61 | } 62 | 63 | /** 64 | * Reactive color parsing and manipulation built on top of color2k. 65 | * @param color 66 | * @param amount 67 | */ 68 | declare const useColor: ( 69 | color: Ref, 70 | amount?: Ref | undefined 71 | ) => ReactiveColor; 72 | ``` 73 | -------------------------------------------------------------------------------- /docs/v2/guide/core/useCssVars.md: -------------------------------------------------------------------------------- 1 | # useCssVars 2 | 3 | ::: tip useCssVars 4 | Munipulate CSS Variables. 5 | ::: 6 | 7 | ## Example 8 | 9 | > 💡 Change Color and Watch CSS Variables Changed. 10 | 11 | 12 | 13 | 14 | 15 | ## Usage 16 | 17 | ```js 18 | import { ref } from 'vue-demi' 19 | import { useCssVars } from '@vueblocks/vue-use-core' 20 | 21 | export default { 22 | setup () { 23 | const textEl = ref(null) 24 | const onInputTextColor = e => textColor.value = e.target.value 25 | const onInputBgColor = e => bgColor.value = e.target.value 26 | 27 | const textColor = useCssVars(textEl, '--text-color', '#000') 28 | const bgColor = useCssVars(textEl, '--bg-color', '#3eaf7c') 29 | 30 | return { 31 | textEl, 32 | textColor, 33 | bgColor, 34 | onInputTextColor, 35 | onInputBgColor 36 | } 37 | } 38 | } 39 | ``` 40 | 41 | ## Typing 42 | 43 | ```ts 44 | declare const useCssVars: ( 45 | el: MaybeRef, 46 | variable: string, 47 | defaultValue: string 48 | ) => Ref; 49 | ``` 50 | -------------------------------------------------------------------------------- /docs/v2/guide/core/useDebouncedRef.md: -------------------------------------------------------------------------------- 1 | # useDebouncedRef 2 | 3 | ::: tip useDebouncedRef 4 | Inspired by Vue3 Offical Document [customRef](https://v3.cn.vuejs.org/api/refs-api.html#customref) demo. 5 | ::: 6 | 7 | ## Example 8 | 9 | 10 | 11 | 12 | 13 | ## Usage 14 | 15 | ```html 16 | 17 | ``` 18 | 19 | ```js 20 | import { useDebouncedRef } from '@vueblocks/vue-use-core' 21 | 22 | export default { 23 | setup() { 24 | return { 25 | text: useDebouncedRef('hello') 26 | } 27 | } 28 | } 29 | ``` 30 | 31 | ## Typing 32 | 33 | ```ts 34 | declare const useDebouncedRef: (value: any, delay?: number) => Ref; 35 | ``` 36 | -------------------------------------------------------------------------------- /docs/v2/guide/core/useElementSize.md: -------------------------------------------------------------------------------- 1 | # useElementSize 2 | 3 | ::: tip useElementSize 4 | Reactive [Element](https://developer.mozilla.org/en-US/docs/Web/API/Element) size. 5 | ::: 6 | 7 | ## Example 8 | 9 | > 💡 resize the textarea, and watch the element size changed. 10 | 11 | 12 | 13 | 14 | 15 | ## Usage 16 | 17 | ```html 18 |
19 | 20 | 21 | 30 |
31 | ``` 32 | 33 | ```js 34 | import { useElementSize } from '@vueblocks/vue-use-core' 35 | 36 | export default { 37 | setup () { 38 | const textareaRef = ref(null) 39 | 40 | const { width, height } = useElementSize(textareaRef) 41 | 42 | return { 43 | textareaRef, 44 | width, 45 | height 46 | } 47 | } 48 | } 49 | ``` 50 | 51 | ## Typing 52 | 53 | ```ts 54 | interface WindowSize { 55 | width: Ref; 56 | height: Ref; 57 | } 58 | interface ElementSize extends WindowSize { 59 | } 60 | 61 | declare const useElementSize: (target: Element, options: ResizeObserverOptions) => ElementSize; 62 | ``` 63 | -------------------------------------------------------------------------------- /docs/v2/guide/core/useEmitter.md: -------------------------------------------------------------------------------- 1 | # useEmitter 2 | 3 | ::: tip useEmitter 4 | 5 | ::: 6 | 7 | ## Example 8 | 9 | > 💡 Emit a custom event 10 | 11 | 12 | 13 | 14 | 15 | ## Usage 16 | 17 | ```html 18 |
19 | Mouse Position: [X: {{ x }}, Y: {{ y }}] 20 |
21 | ``` 22 | 23 | ```js 24 | import { useEmitter } from '@vueblocks/vue-use-core' 25 | 26 | export default { 27 | setup () { 28 | const { off, emit } = useEmitter() 29 | 30 | return { 31 | emit 32 | } 33 | } 34 | } 35 | ``` 36 | 37 | ## Typing 38 | 39 | ```ts 40 | declare const useEmitter: (event: E, handler: Handler | WildcardHandler) => { 41 | off: () => void; 42 | emit: { 43 | (type: EventType, event?: T | undefined): void; 44 | (type: "*", event?: any): void; 45 | }; 46 | }; 47 | ``` 48 | -------------------------------------------------------------------------------- /docs/v2/guide/core/useFullscreen.md: -------------------------------------------------------------------------------- 1 | # useFullscreen 2 | 3 | ::: tip useFullscreen 4 | Reactive Fullscreen API build on top of [screenfull.js](https://github.com/sindresorhus/screenfull.js/) 5 | ::: 6 | 7 | ## Example 8 | 9 | > Click the image to make it fullscreen 10 | 11 | 12 | 13 | 14 | 15 | ## Usage 16 | 17 | ```html 18 |
19 | 23 | 24 |
25 | 26 |
27 |
28 | ``` 29 | 30 | ```js 31 | import { useFullscreen } from '@vueblocks/vue-use-core' 32 | 33 | export default { 34 | setup () { 35 | const imgRef = ref(null) 36 | const { 37 | isFullscreen, 38 | toggleFullscreen 39 | } = useFullscreen(imgRef) 40 | 41 | return { 42 | imgRef, 43 | isFullscreen, 44 | toggleFullscreen 45 | } 46 | } 47 | } 48 | ``` 49 | 50 | ## Typing 51 | 52 | ```ts 53 | /** 54 | * Reactive Fullscreen API build on top of screenfull.js 55 | * @param {HTMLElement} target 56 | * @return {boolean} isFullscreen 57 | * @return {function} toggleFullscreen 58 | */ 59 | declare const useFullscreen: (target: HTMLElement) => { 60 | isFullscreen: Ref; 61 | toggleFullscreen: () => void; 62 | }; 63 | ``` 64 | -------------------------------------------------------------------------------- /docs/v2/guide/core/useInstance.md: -------------------------------------------------------------------------------- 1 | # useInstance 2 | 3 | ::: tip useInstance 4 | Get `vm` from `getCurrentInstance` API, Same as [getCurrentInstance.proxy](https://github.com/vuejs/composition-api/releases/tag/v1.0.0-beta.22) 5 | ::: 6 | 7 | ## Example 8 | 9 | > 💡 Open DevTools, Instance Info already Print out. 10 | 11 | 12 | 13 | 14 | 15 | ## Usage 16 | 17 | ```js 18 | import { useInstance } from '@vueblocks/vue-use-core' 19 | 20 | export default { 21 | setup () { 22 | const vm = useInstance() 23 | 24 | console.log(vm) 25 | } 26 | } 27 | ``` 28 | 29 | ## Typing 30 | 31 | ```ts 32 | declare const useInstance: () => any; 33 | ``` 34 | -------------------------------------------------------------------------------- /docs/v2/guide/core/useMouse.md: -------------------------------------------------------------------------------- 1 | # useMouse 2 | 3 | ::: tip useMouse 4 | ♻️ Register [MouseMove](https://developer.mozilla.org/en-US/docs/Web/API/Element/mousemove_event) event on mounted, and remove event automatically on unmounted. 5 | ::: 6 | 7 | ## Example 8 | 9 | > 💡 Move your mouse 10 | 11 | 12 | 13 | 14 | 15 | ## Usage 16 | 17 | ```html 18 |
19 | Mouse Position: [X: {{ x }}, Y: {{ y }}] 20 |
21 | ``` 22 | 23 | ```js 24 | import { useMouse } from '@vueblocks/vue-use-core' 25 | 26 | export default { 27 | setup () { 28 | const { x, y, remove } = useMouse() 29 | 30 | return { 31 | x, 32 | y 33 | } 34 | } 35 | } 36 | ``` 37 | 38 | ## Typing 39 | 40 | ```ts 41 | /** 42 | * Register `MouseMove` event on mounted, and remove event automatically on unmounted. 43 | */ 44 | declare const useMouse: () => { 45 | x: Ref; 46 | y: Ref; 47 | remove: () => void; 48 | } 49 | ``` 50 | -------------------------------------------------------------------------------- /docs/v2/guide/core/usePalette.md: -------------------------------------------------------------------------------- 1 | # usePalette 2 | 3 | ::: tip usePalette 4 | Turn `color2k` to `usePalette`, we enhanced color2k with new utilities like `tint` 、 `shade` 、 `invert`. 5 | ::: 6 | 7 | 14 | 15 | ## Usage 16 | 17 | ```js 18 | import { ref } from 'vue-demi' 19 | import { usePalette } from '@vueblocks/vue-use-core' 20 | 21 | const { tint } = usePalette 22 | 23 | export default { 24 | setup () { 25 | const mainColor = '#3eaf7c' 26 | const tintColor = ref(tint(mainColor, 0.5)) 27 | 28 | return { 29 | tintColor 30 | } 31 | } 32 | } 33 | ``` 34 | 35 | ## Typing 36 | 37 | ```ts 38 | /** 39 | * enhanced `color2k` with new utilities like `tint` 、 `shade` 、 `invert`. 40 | */ 41 | declare const usePalette: { 42 | adjustHue: typeof adjustHue; 43 | darken: typeof darken; 44 | desaturate: typeof desaturate; 45 | getContrast: typeof getContrast; 46 | getLuminance: typeof getLuminance; 47 | getScale: typeof getScale; 48 | guard: typeof guard; 49 | hasBadContrast: typeof hasBadContrast; 50 | hsla: typeof hsla; 51 | lighten: typeof lighten; 52 | mix: typeof mix; 53 | opacify: typeof opacify; 54 | parseToHsla: typeof parseToHsla; 55 | readableColor: typeof readableColor; 56 | readableColorIsBlack: typeof readableColorIsBlack; 57 | rgba: typeof rgba; 58 | saturate: typeof saturate; 59 | transparentize: typeof transparentize; 60 | parseToRgba: typeof parseToRgba; 61 | ColorError: typeof ColorError; 62 | toHex: typeof toHex; 63 | toRgba: typeof toRgba; 64 | toHsla: typeof toHsla; 65 | /** 66 | * Tints a color by mixing it with white. 67 | * @param color 68 | * @param amount given as a decimal between 0 and 1 69 | */ 70 | tint: (color: string, amount: number) => string; 71 | /** 72 | * Shades a color by mixing it with black. 73 | * @param color 74 | * @param amount given as a decimal between 0 and 1 75 | */ 76 | shade: (color: string, amount: number) => string; 77 | /** 78 | * Inverts the red, green and blue values of a color. 79 | * @param color 80 | */ 81 | invert: (color: string) => string; 82 | }; 83 | ``` 84 | -------------------------------------------------------------------------------- /docs/v2/guide/core/usePrecision.md: -------------------------------------------------------------------------------- 1 | # usePrecision 2 | 3 | ::: tip usePrecision 4 | `usePrecision` provide reactive methods to perform addition, subtraction, multiplication & division operations precisely 5 | ::: 6 | 7 | ## Example 8 | 9 | 10 | 11 | 12 | 13 | ## Usage 14 | 15 | ```js 16 | import { ref, reactive, toRefs } from 'vue-demi' 17 | import { usePrecision } from '@vueblocks/vue-use-core' 18 | 19 | export default { 20 | setup () { 21 | const { plus, times } = usePrecision() 22 | 23 | const [plusA, plusB] = [ref(0.1), ref(0.2)] 24 | const [timesA, timesB] = [ref(7), ref(0.2)] 25 | 26 | const localState = reactive({ 27 | plusResult: plus(plusA, plusB), 28 | timesResult: times(timesA, timesB) 29 | }) 30 | 31 | return toRefs(localState) 32 | } 33 | } 34 | ``` 35 | 36 | ## Typing 37 | 38 | ```ts 39 | /** 40 | * `usePrecision` provide reactive methods to perform addition, subtraction, multiplication & division operations precisely. 41 | */ 42 | declare const usePrecision: () => { 43 | strip: (num: RefTyped, precision?: RefTyped) => ComputedRef; 44 | plus: (num1: RefTyped, num2: RefTyped, ...others: RefTyped[]) => ComputedRef; 45 | minus: (num1: RefTyped, num2: RefTyped, ...others: RefTyped[]) => ComputedRef; 46 | times: (num1: RefTyped, num2: RefTyped, ...others: RefTyped[]) => ComputedRef; 47 | divide: (num1: RefTyped, num2: RefTyped, ...others: RefTyped[]) => ComputedRef; 48 | round: (num: RefTyped, ratio: RefTyped) => ComputedRef; 49 | digitLength: (num: RefTyped) => ComputedRef; 50 | float2Fixed: (num: RefTyped) => ComputedRef; 51 | }; 52 | ``` 53 | -------------------------------------------------------------------------------- /docs/v2/guide/core/useResizeEvent.md: -------------------------------------------------------------------------------- 1 | # useResizeEvent 2 | 3 | ::: tip useResizeEvent 4 | ♻️ Register [resize](https://developer.mozilla.org/en-US/docs/Web/API/Window/resize_event) event on mounted, and remove event automatically on unmounted. 5 | ::: 6 | 7 | ## Example 8 | 9 | > 💡 resize the browser and watch document size changed. 10 | 11 | 12 | 13 | 14 | 15 | ## Usage 16 | 17 | ```html 18 |
19 | document size: {{ domSize }} 20 |
21 | ``` 22 | 23 | ```js 24 | import { useResizeEvent } from '@vueblocks/vue-use-core' 25 | 26 | export default { 27 | setup () { 28 | let domSize = reactive({ 29 | width: 0, 30 | height: 0 31 | }) 32 | 33 | const onResize = () => { 34 | domSize.width = document.body.clientWidth 35 | domSize.height = document.body.clientHeight 36 | } 37 | 38 | const { dispatchResize } = useResizeEvent(onResize) 39 | 40 | // dispatch resize event once 41 | onMounted(dispatchResize) 42 | 43 | return { 44 | domSize 45 | } 46 | } 47 | } 48 | ``` 49 | 50 | ## Typing 51 | 52 | ```ts 53 | interface EventOptions { 54 | useCapture?: boolean; 55 | useThrottle?: boolean | null; 56 | delay?: number; 57 | } 58 | 59 | /** 60 | * Reactive Resize API, When window resize, do someting. 61 | * @param {function} fn 62 | * @param {object} options 63 | * @return {function} dispatchResize 64 | */ 65 | declare const useResizeEvent: (fn: Fn, options?: EventOptions) => { 66 | dispatchResize: () => void; 67 | }; 68 | ``` 69 | -------------------------------------------------------------------------------- /docs/v2/guide/core/useWindowSize.md: -------------------------------------------------------------------------------- 1 | # useWindowSize 2 | 3 | ::: tip useWindowSize 4 | Reactive window size 5 | ::: 6 | 7 | ## Example 8 | 9 | > 💡 resize the browser and watch window size changed. 10 | 11 | 12 | 13 | 14 | 15 | ## Usage 16 | 17 | ```html 18 |
19 | window size: {{ width }} x {{ height }} 20 |
21 | ``` 22 | 23 | ```js 24 | import { useWindowSize } from '@vueblocks/vue-use-core' 25 | 26 | export default { 27 | setup () { 28 | const { width, height } = useWindowSize() 29 | 30 | return { 31 | width, 32 | height 33 | } 34 | } 35 | } 36 | ``` 37 | 38 | ## Typing 39 | 40 | ```ts 41 | interface WindowSize { 42 | width: Ref; 43 | height: Ref; 44 | } 45 | 46 | /** 47 | * Reactive window size 48 | * @param {boolean} useCapture 49 | * @param {boolean} useThrottle: true: throttle | false: debounce 50 | * @return {Ref} WindowSize 51 | */ 52 | declare const useWindowSize: ( 53 | useCapture?: boolean, 54 | useThrottle?: boolean 55 | ) => WindowSize; 56 | ``` 57 | -------------------------------------------------------------------------------- /docs/v2/guide/vuex/namespacing.md: -------------------------------------------------------------------------------- 1 | # Namespacing 2 | 3 | ## Binding Helpers with Namespace 4 | 5 | When binding a namespaced module to components with the `useState`, `useGetters`, `useActions` and `useMutations` helpers, it can get a bit verbose: 6 | 7 | ```js 8 | setup () { 9 | return { 10 | ...useState({ 11 | a: state => state.some.nested.module.a, 12 | b: state => state.some.nested.module.b 13 | }), 14 | ...useGetters([ 15 | 'some/nested/module/someGetter', // -> this['some/nested/module/someGetter'] 16 | 'some/nested/module/someOtherGetter', // -> this['some/nested/module/someOtherGetter'] 17 | ]), 18 | ...useActions([ 19 | 'some/nested/module/foo', // -> this['some/nested/module/foo']() 20 | 'some/nested/module/bar' // -> this['some/nested/module/bar']() 21 | ]) 22 | } 23 | } 24 | ``` 25 | 26 | In such cases, you can pass the module namespace string as the first argument to the helpers so that all bindings are done using that module as the context. The above can be simplified to: 27 | 28 | ```js 29 | setup () { 30 | return { 31 | ...mapState('some/nested/module', { 32 | a: state => state.a, 33 | b: state => state.b 34 | }), 35 | ...mapGetters('some/nested/module', [ 36 | 'someGetter', // -> this.someGetter 37 | 'someOtherGetter', // -> this.someOtherGetter 38 | ]), 39 | ...mapActions('some/nested/module', [ 40 | 'foo', // -> this.foo() 41 | 'bar' // -> this.bar() 42 | ]) 43 | } 44 | } 45 | ``` 46 | 47 | Furthermore, you can create namespaced helpers by using `useVuex`. It returns an object having new component binding helpers that are bound with the given namespace value: 48 | 49 | ```js {6} 50 | // Get namespaced component binding helpers in useVuex 51 | import { useVuex } from '@vueblocks/vue-use-vuex' 52 | 53 | export default { 54 | setup () { 55 | const { mapState, mapActions } = useVuex('some/nested/module') 56 | 57 | return { 58 | // look up in `some/nested/module` 59 | ...mapState({ 60 | a: state => state.a, 61 | b: state => state.b 62 | }) 63 | // look up in `some/nested/module` 64 | ...mapActions([ 65 | 'foo', 66 | 'bar' 67 | ]) 68 | } 69 | } 70 | } 71 | ``` 72 | -------------------------------------------------------------------------------- /docs/v2/guide/vuex/useActions.md: -------------------------------------------------------------------------------- 1 | # useActions 2 | 3 | > `useActions: (namespace?: string, map: Array | Object) => Object` 4 | 5 | Create component methods options that dispatch an action. 6 | 7 | The first argument can optionally be a namespace string. [Details](./namespacing.md) 8 | 9 | The second object argument's members can be a function. `function(dispatch: function, ...args: any[])` 10 | 11 | ## Usage 12 | 13 | When accessing actions, you can simply use `useActions` inside the setup hook. This is the equivalent of creating methods properties using the Option API. 14 | 15 | ```js {7} 16 | import { useVuex } from '@vueblocks/vue-use-vuex' 17 | 18 | export default { 19 | // ... 20 | setup () { 21 | // Use the useActions as you would use mapActions 22 | const { useActions } = useVuex() 23 | 24 | return { 25 | ...useActions([ 26 | 'increment', // map `increment()` to `this.$store.dispatch('increment')` 27 | 28 | // `mapActions` also supports payloads: 29 | 'incrementBy' // map `incrementBy(amount)` to `this.$store.dispatch('incrementBy', amount)` 30 | ]), 31 | ...useActions({ 32 | add: 'increment' // map `add()` to `this.$store.dispatch('increment')` 33 | }) 34 | } 35 | } 36 | } 37 | ``` 38 | -------------------------------------------------------------------------------- /docs/v2/guide/vuex/useGetters.md: -------------------------------------------------------------------------------- 1 | # useGetters 2 | 3 | > `useGetters: (namespace?: string, map: Array | Object) => Object` 4 | 5 | Create component computed options that return the evaluated value of a getter. 6 | 7 | The first argument can optionally be a namespace string. [Details](./namespacing.md) 8 | 9 | ## Usage 10 | 11 | In order to access getters, you can simply use `useGetters` helper inside the setup hook. This is the equivalent of creating computed properties using the Option API. 12 | 13 | ```js {7} 14 | import { useVuex } from '@vueblocks/vue-use-vuex' 15 | 16 | export default { 17 | // ... 18 | setup () { 19 | // Use the useGetters as you would use mapGetters 20 | const { useGetters } = useVuex() 21 | 22 | return { 23 | // mix the getters into outer object with the object spread operator 24 | ...useGetters([ 25 | 'doneTodosCount', 26 | 'anotherGetter', 27 | // ... 28 | ]), 29 | // if you want to map a getter to a different name, use an object: 30 | ...mapGetters({ 31 | // map `doneCount` to `this.$store.getters.doneTodosCount` 32 | doneCount: 'doneTodosCount' 33 | }) 34 | } 35 | } 36 | } 37 | ``` 38 | -------------------------------------------------------------------------------- /docs/v2/guide/vuex/useMutations.md: -------------------------------------------------------------------------------- 1 | # useMutations 2 | 3 | > `useMutations: (namespace?: string, map: Array | Object) => Object` 4 | 5 | Create component methods options that commit a mutation. 6 | 7 | The first argument can optionally be a namespace string. [Details](./namespacing.md) 8 | 9 | The second object argument's members can be a function. `function(commit: function, ...args: any[])` 10 | 11 | ## Usage 12 | 13 | When accessing mutations, you can simply use `useMutations` inside the setup hook. This is the equivalent of creating methods properties using the Option API. 14 | 15 | ```js {7} 16 | import { useVuex } from '@vueblocks/vue-use-vuex' 17 | 18 | export default { 19 | // ... 20 | setup () { 21 | // Use the useMutations as you would use mapMutations 22 | const { useMutations } = useVuex() 23 | 24 | return { 25 | ...useMutations([ 26 | 'increment', // map `increment()` to `this.$store.commit('increment')` 27 | 28 | // `mapMutations` also supports payloads: 29 | 'incrementBy' // map `incrementBy(amount)` to `this.$store.commit('incrementBy', amount)` 30 | ]), 31 | ...useMutations({ 32 | add: 'increment' // map `add()` to `this.$store.commit('increment')` 33 | }) 34 | } 35 | } 36 | } 37 | ``` 38 | -------------------------------------------------------------------------------- /docs/v2/guide/vuex/useState.md: -------------------------------------------------------------------------------- 1 | # useState 2 | 3 | > `useState: (namespace?: string, map: Array | Object) => Object` 4 | 5 | Create component computed options that return the sub tree of the Vuex store. 6 | 7 | The first argument can optionally be a namespace string. [Details](./namespacing.md) 8 | 9 | The second object argument's members can be a function. `function(state: any)` 10 | 11 | ## Usage 12 | 13 | In order to access state, you can simply use `useState` helper inside the setup hook. This is the equivalent of creating computed properties using the Option API. 14 | 15 | ```js {7} 16 | import { useVuex } from '@vueblocks/vue-use-vuex' 17 | 18 | export default { 19 | // ... 20 | setup () { 21 | // Use the useState as you would use mapState 22 | const { useState } = useVuex() 23 | 24 | return { 25 | // mix this into the outer object with the object spread operator 26 | ...useState({ 27 | // arrow functions can make the code very succinct! 28 | count: state => state.count, 29 | 30 | // passing the string value 'count' is same as `state => state.count` 31 | countAlias: 'count', 32 | 33 | // to access local state with `this`, a normal function must be used 34 | countPlusLocalState (state) { 35 | return state.count + this.localCount 36 | } 37 | }), 38 | ...mapState([ 39 | // map count to store.state.count 40 | 'count' 41 | ]) 42 | } 43 | } 44 | } 45 | ``` 46 | -------------------------------------------------------------------------------- /docs/v2/guide/vuex/useStore.md: -------------------------------------------------------------------------------- 1 | # useStore 2 | 3 | ## Vuex 4 4 | 5 | > Vuex 4 introduces a new API to interact with the store in Composition API. You can use the `useStore` composition function to retrieve the store within the component `setup` hook. 6 | 7 | ```js {2} 8 | // Vuex version is 4.x 9 | import { useStore } from 'vuex' 10 | 11 | export default { 12 | setup () { 13 | const store = useStore() 14 | } 15 | } 16 | ``` 17 | 18 | ## What we provide 19 | 20 | We talk about how to retrieve the store in `Vue 2 & Vuex 3` Project. 21 | 22 | Maybe you already have the answer, it's very easy, just use `this.$store`. 23 | 24 | But, We know about Composition API, Inside [setup()](https://v3.vuejs.org/guide/composition-api-setup.html#usage-of-this), `this` **won't be a reference to the current active instance** Since `setup()` is called before other component options are resolved. 25 | 26 | So, we provide `useStore` in `@vueblocks/vue-use-vuex` libary. 27 | 28 | ```js {1} 29 | import { useStore } from '@vueblocks/vue-use-vuex' 30 | 31 | export default { 32 | setup () { 33 | // Use the useStore as you would use useStore in Vuex 4 34 | const store = useStore() 35 | } 36 | } 37 | ``` 38 | 39 | ## Typing 40 | 41 | ```ts 42 | /** 43 | * Get $store from current instance 44 | * @return {Store} vm.$store 45 | */ 46 | declare const useStore: () => Store 47 | ``` 48 | -------------------------------------------------------------------------------- /docs/v2/guide/vuex/useVuex.md: -------------------------------------------------------------------------------- 1 | # useVuex 2 | 3 | > Use Vuex With Composition API Easily. 4 | 5 | ## Install 6 | 7 | ```bash 8 | # Vue 2 with @vue/composition-api 9 | yarn add @vue/composition-api @vueblocks/vue-use-vuex -S 10 | or 11 | npm i @vue/composition-api @vueblocks/vue-use-vuex -S 12 | 13 | # Vue 3 14 | yarn add @vueblocks/vue-use-vuex -S 15 | or 16 | npm i @vueblocks/vue-use-vuex -S 17 | ``` 18 | 19 | ## Usage 20 | 21 | `useVuex` utilities just similar with [Vuex Component Binding Helpers](https://vuex.vuejs.org/api/#component-binding-helpers) 22 | 23 | It export these composable helpers: 24 | 25 | * [useState](./useState.md) - same as `mapState` helper in Vuex 26 | * [useGetters](./useGetters.md) - same as `mapGetters` helper in Vuex 27 | * [useMutations](./useMutations.md) - same as `mapMutations` helper in Vuex 28 | * [useActions](./useActions.md) - same as `mapActions` helper in Vuex 29 | 30 | Differently, `useVuex` do not export `createNamespacedHelpers` function, Instead `useVuex` allow you provide 31 | the namespace as first argument, then return will be the namespaced component binding helpers. 32 | 33 | Read more about namespacing [documention](./namespacing.md). 34 | 35 | It seems familiar right? 36 | 37 | ## Example 38 | 39 | ::: tip 💡 Tips 40 | `useVuex` also allow you provide the `namespace` as first argument, then return will be the namespaced component binding helpers. 41 | ::: 42 | 43 | 44 | 45 | 46 | 47 | > Open dev-tools you will find `store` printing. 48 | 49 | ```js 50 | import { useVuex, useStore } from '@vueblocks/vue-use-vuex' 51 | 52 | export default { 53 | setup () { 54 | const store = useStore() 55 | console.log(store) 56 | const { useState, useGetters, useActions } = useVuex('counter') 57 | 58 | return { 59 | ...useState(['count']), 60 | 61 | ...useGetters([ 62 | 'evenOrOdd' 63 | ]), 64 | 65 | ...useActions([ 66 | 'increment', 67 | 'decrement', 68 | 'incrementIfOdd', 69 | 'incrementAsync' 70 | ]) 71 | } 72 | } 73 | } 74 | ``` 75 | 76 | ## Typing 77 | 78 | ```ts 79 | /** 80 | * Use Vuex with composition api easily. Both support Vue2.x / Vue3.x 81 | * @param {String} namespace 82 | * @param {Store} store ### vm.$store 83 | */ 84 | declare function useVuex(namespace?: string, store?: Store): { 85 | useState: (namespace?: string, map: Array | Object) => Object; 86 | useGetters: (namespace?: string, map: Array | Object) => Object; 87 | useMutations: (namespace?: string, map: Array | Object) => Object; 88 | useActions: (namespace?: string, map: Array | Object) => Object; 89 | }; 90 | ``` 91 | -------------------------------------------------------------------------------- /docs/v2/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@vueblock/vue-use-docs-vue2", 3 | "version": "1.0.0", 4 | "license": "MIT", 5 | "scripts": { 6 | "dev": "vuepress dev", 7 | "build": "vuepress build" 8 | }, 9 | "dependencies": { 10 | "@vue/composition-api": "^1.2.4", 11 | "@vueblocks/vue-use-axios": "^0.2.6", 12 | "@vueblocks/vue-use-core": "^0.2.10", 13 | "@vueblocks/vue-use-vuex": "^0.2.10", 14 | "axios": "^0.24.0", 15 | "vue-demi": "0.10.0", 16 | "vuex": "^3.6.2" 17 | }, 18 | "postcss": { 19 | "plugins": { 20 | "tailwindcss": {}, 21 | "autoprefixer": {} 22 | } 23 | }, 24 | "devDependencies": { 25 | "@tailwindcss/postcss7-compat": "^2.0.3", 26 | "autoprefixer": "^9", 27 | "postcss": "^7", 28 | "tailwindcss": "npm:@tailwindcss/postcss7-compat", 29 | "vuepress": "^1.8.2" 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /docs/v2/tailwind.config.js: -------------------------------------------------------------------------------- 1 | // tailwind.config.js 2 | module.exports = { 3 | purge: [], 4 | darkMode: false, // or 'media' or 'class' 5 | theme: { 6 | extend: {} 7 | }, 8 | variants: {}, 9 | plugins: [] 10 | } 11 | -------------------------------------------------------------------------------- /docs/v3/.vitepress/components/ExampleBlock.vue: -------------------------------------------------------------------------------- 1 | 17 | 18 | -------------------------------------------------------------------------------- /docs/v3/.vitepress/components/UseAxiosDemo.vue: -------------------------------------------------------------------------------- 1 | 15 | 16 | 43 | -------------------------------------------------------------------------------- /docs/v3/.vitepress/components/UseClipboardDemo.vue: -------------------------------------------------------------------------------- 1 | 20 | 21 | 43 | -------------------------------------------------------------------------------- /docs/v3/.vitepress/components/UseCssVarsDemo.vue: -------------------------------------------------------------------------------- 1 | 36 | 37 | 63 | 64 | -------------------------------------------------------------------------------- /docs/v3/.vitepress/components/UseDebouncedRefDemo.vue: -------------------------------------------------------------------------------- 1 | 17 | 18 | -------------------------------------------------------------------------------- /docs/v3/.vitepress/components/UseElementSizeDemo.vue: -------------------------------------------------------------------------------- 1 | 21 | 22 | -------------------------------------------------------------------------------- /docs/v3/.vitepress/components/UseEmitterDemo.vue: -------------------------------------------------------------------------------- 1 | 17 | 18 | 40 | -------------------------------------------------------------------------------- /docs/v3/.vitepress/components/UseEmitterEmitDemo.vue: -------------------------------------------------------------------------------- 1 | 10 | 11 | 33 | -------------------------------------------------------------------------------- /docs/v3/.vitepress/components/UseEmitterOnDemo.vue: -------------------------------------------------------------------------------- 1 | 10 | 11 | 38 | -------------------------------------------------------------------------------- /docs/v3/.vitepress/components/UseEventListenerDemo.vue: -------------------------------------------------------------------------------- 1 | 13 | 14 | 71 | -------------------------------------------------------------------------------- /docs/v3/.vitepress/components/UseFullscreenDemo.vue: -------------------------------------------------------------------------------- 1 | 22 | 23 | 46 | -------------------------------------------------------------------------------- /docs/v3/.vitepress/components/UseInstanceDemo.vue: -------------------------------------------------------------------------------- 1 | 4 | 5 | 18 | -------------------------------------------------------------------------------- /docs/v3/.vitepress/components/UseMouseDemo.vue: -------------------------------------------------------------------------------- 1 | 13 | 14 | 32 | -------------------------------------------------------------------------------- /docs/v3/.vitepress/components/UseResizeEventDemo.vue: -------------------------------------------------------------------------------- 1 | 29 | 30 | 88 | -------------------------------------------------------------------------------- /docs/v3/.vitepress/components/UseResizeObserverDemo.vue: -------------------------------------------------------------------------------- 1 | 21 | 22 | -------------------------------------------------------------------------------- /docs/v3/.vitepress/components/UseShortcutDemo.vue: -------------------------------------------------------------------------------- 1 | 16 | 17 | 49 | 50 | -------------------------------------------------------------------------------- /docs/v3/.vitepress/components/UseStateshotDemo.vue: -------------------------------------------------------------------------------- 1 | 31 | 32 | 75 | -------------------------------------------------------------------------------- /docs/v3/.vitepress/components/UseVuexDemo.vue: -------------------------------------------------------------------------------- 1 | 17 | 18 | 48 | -------------------------------------------------------------------------------- /docs/v3/.vitepress/components/UseWindowSizeDemo.vue: -------------------------------------------------------------------------------- 1 | 29 | 30 | 92 | -------------------------------------------------------------------------------- /docs/v3/.vitepress/styles/docs.styl: -------------------------------------------------------------------------------- 1 | // use tailwindcss default border rule 2 | *, 3 | ::before, 4 | ::after { 5 | box-sizing: border-box; /* 1 */ 6 | border-width: 0; /* 2 */ 7 | border-style: solid; /* 2 */ 8 | border-color: #e5e7eb; /* 2 */ 9 | } 10 | 11 | // docs styles 12 | .example-panel 13 | &__codeblock 14 | pre 15 | @apply m-0 rounded-none !important -------------------------------------------------------------------------------- /docs/v3/.vitepress/styles/index.styl: -------------------------------------------------------------------------------- 1 | // @tailwind base; 2 | 3 | @tailwind components; 4 | 5 | @tailwind utilities; 6 | 7 | @require './docs.styl' 8 | -------------------------------------------------------------------------------- /docs/v3/.vitepress/theme/index.js: -------------------------------------------------------------------------------- 1 | // .vitepress/theme/index.js 2 | import './index.postcss' 3 | import DefaultTheme from 'vitepress/theme' 4 | 5 | import ExampleBlock from '../components/ExampleBlock.vue' 6 | import UseAxiosDemo from '../components/UseAxiosDemo.vue' 7 | import UseClipboardDemo from '../components/UseClipboardDemo.vue' 8 | import UseColorDemo from '../components/UseColorDemo.vue' 9 | import UseCssVarsDemo from '../components/UseCssVarsDemo.vue' 10 | import UseDebouncedRefDemo from '../components/UseDebouncedRefDemo.vue' 11 | import UseElementSizeDemo from '../components/UseElementSizeDemo.vue' 12 | import UseEventListenerDemo from '../components/UseEventListenerDemo.vue' 13 | import UseFullscreenDemo from '../components/UseFullscreenDemo.vue' 14 | import UseInstanceDemo from '../components/UseInstanceDemo.vue' 15 | import UseMouseDemo from '../components/UseMouseDemo.vue' 16 | import UsePrecisionDemo from '../components/UsePrecisionDemo.vue' 17 | import UseResizeEventDemo from '../components/UseResizeEventDemo.vue' 18 | import UseResizeObserverDemo from '../components/UseResizeObserverDemo.vue' 19 | import UseShortcutDemo from '../components/UseShortcutDemo.vue' 20 | import UseStateshotDemo from '../components/UseStateshotDemo.vue' 21 | import UseWindowSizeDemo from '../components/UseWindowSizeDemo.vue' 22 | import UseVuexDemo from '../components/UseVuexDemo.vue' 23 | 24 | export default { 25 | ...DefaultTheme, 26 | enhanceApp({ app, router, siteData }) { 27 | // app is the Vue 3 app instance from `createApp()`. router is VitePress' 28 | // custom router. `siteData`` is a `ref`` of current site-level metadata. 29 | console.log(siteData.value) 30 | app.component(ExampleBlock.name, ExampleBlock) 31 | app.component(UseAxiosDemo.name, UseAxiosDemo) 32 | app.component(UseClipboardDemo.name, UseClipboardDemo) 33 | app.component(UseColorDemo.name, UseColorDemo) 34 | app.component(UseCssVarsDemo.name, UseCssVarsDemo) 35 | app.component(UseDebouncedRefDemo.name, UseDebouncedRefDemo) 36 | app.component(UseElementSizeDemo.name, UseElementSizeDemo) 37 | app.component(UseEventListenerDemo.name, UseEventListenerDemo) 38 | app.component(UseFullscreenDemo.name, UseFullscreenDemo) 39 | app.component(UseInstanceDemo.name, UseInstanceDemo) 40 | app.component(UseMouseDemo.name, UseMouseDemo) 41 | app.component(UsePrecisionDemo.name, UsePrecisionDemo) 42 | app.component(UseResizeEventDemo.name, UseResizeEventDemo) 43 | app.component(UseResizeObserverDemo.name, UseResizeObserverDemo) 44 | app.component(UseShortcutDemo.name, UseShortcutDemo) 45 | app.component(UseStateshotDemo.name, UseStateshotDemo) 46 | app.component(UseWindowSizeDemo.name, UseWindowSizeDemo) 47 | app.component(UseVuexDemo.name, UseVuexDemo) 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /docs/v3/.vitepress/theme/index.postcss: -------------------------------------------------------------------------------- 1 | @tailwind base; 2 | 3 | @tailwind components; 4 | 5 | @tailwind utilities; 6 | -------------------------------------------------------------------------------- /docs/v3/axios/use-axios.md: -------------------------------------------------------------------------------- 1 | # useAxios 2 | 3 | > Use Axios With Composition API Easily. 4 | 5 | ## Install 6 | 7 | ```bash 8 | # Vue 2 with @vue/composition-api 9 | yarn add @vue/composition-api @vueblocks/vue-use-axios -S 10 | or 11 | npm i @vue/composition-api @vueblocks/vue-use-axios -S 12 | 13 | # Vue 3 14 | yarn add @vueblocks/vue-use-axios -S 15 | or 16 | npm i @vueblocks/vue-use-axios -S 17 | ``` 18 | 19 | ## Example 20 | 21 | > Fetch Bitcoin Price every 20 seconds 22 | 23 | 24 | 25 | 26 | 27 | ## Usage 28 | 29 | `useAxios` is a wrapper of Axios 30 | 31 | ```js 32 | import { useAxios } from '@vueblocks/vue-use-axios' 33 | 34 | export default { 35 | ... 36 | setup () { 37 | const url = 'https://api.coindesk.com/v1/bpi/currentprice.json' 38 | 39 | const { refetch, data } = useAxios(url) 40 | 41 | const bitcoin = ref(data) 42 | 43 | const fetchBitcoinRate = () => { 44 | setInterval(() => { 45 | refetch() 46 | }, 20000) 47 | } 48 | 49 | onMounted(() => { 50 | fetchBitcoinRate() 51 | }) 52 | 53 | return { 54 | bitcoin 55 | } 56 | } 57 | ... 58 | } 59 | ``` 60 | 61 | ## Typing 62 | 63 | ```ts 64 | interface IAxiosOptions { 65 | debounce?: number; 66 | throttle?: number; 67 | } 68 | declare const useAxios: (url: string, config?: AxiosRequestConfig | undefined, options?: IAxiosOptions | undefined) => { 69 | refetch: () => void; 70 | cancel: (message?: string | undefined) => void; 71 | response: Ref; 72 | data: Ref; 73 | finished: Ref; 74 | canceled: Ref; 75 | error: Ref; 76 | }; 77 | ``` 78 | -------------------------------------------------------------------------------- /docs/v3/core/use-clipboard.md: -------------------------------------------------------------------------------- 1 | # useClipboard 2 | 3 | ::: tip useClipboard 4 | Reactive `navigator.clipboard` API 5 | ::: 6 | 7 | ## Example 8 | 9 | > Copy some input message 10 | 11 | 12 | 13 | 14 | 15 | ## Usage 16 | 17 | ```html 18 | 23 | 24 | 25 | ``` 26 | 27 | ```js 28 | import { ref, defineComponent } from 'vue' 29 | import { useClipboard } from '@vueblocks/vue-use-core' 30 | 31 | export default defineComponent({ 32 | setup () { 33 | const source = ref('') 34 | const { copy, copied, text, clear } = useClipboard({ source }) 35 | 36 | return { 37 | source, 38 | text, 39 | copy, 40 | copied, 41 | clear 42 | } 43 | } 44 | }) 45 | ``` 46 | 47 | ## Typing 48 | ```ts 49 | interface ClipboardOption { 50 | source?: string; 51 | during?: number; 52 | } 53 | interface ClipboardResult { 54 | text: Ref; 55 | copy: typeof NOOP; 56 | clear: typeof NOOP; 57 | copied: Ref; 58 | isSupported: Ref; 59 | } 60 | /** 61 | * A Reactive Clipboard API 62 | * @param options 63 | * @returns 64 | */ 65 | declare const useClipboard: (options?: ClipboardOption) => ClipboardResult; 66 | ``` 67 | -------------------------------------------------------------------------------- /docs/v3/core/use-color.md: -------------------------------------------------------------------------------- 1 | # useColor 2 | 3 | ::: tip useColor 4 | Reactive color parsing and manipulation built on top of [color2k](https://github.com/ricokahler/color2k). 5 | ::: 6 | 7 | ## Example 8 | 9 | > Change Color and Watch Reactive Color. 10 | 11 | 12 | 13 | 14 | 15 | ## Usage 16 | 17 | ```html 18 |
19 |
20 |

Ligthen Color

21 |
{{ lightenColor }}
22 |
23 |
24 | ``` 25 | 26 | ```js 27 | import { useColor } from '@vueblocks/vue-use-core' 28 | 29 | export default { 30 | setup () { 31 | const mainColor = ref('#3eaf7c') 32 | const mainAmount = ref(0.5) 33 | 34 | const { lightenColor } = useColor(mainColor, mainAmount) 35 | 36 | return { 37 | lightenColor 38 | } 39 | } 40 | } 41 | ``` 42 | 43 | ## Typing 44 | 45 | ```ts 46 | interface ReactiveColor { 47 | hexColor: ComputedRef; 48 | hslaColor: ComputedRef; 49 | rgbaColor: ComputedRef; 50 | readableColor: ComputedRef; 51 | invertColor: ComputedRef; 52 | luminance: ComputedRef; 53 | lightenColor: ComputedRef; 54 | darkenColor: ComputedRef; 55 | tintColor: ComputedRef; 56 | shadeColor: ComputedRef; 57 | desaturateColor: ComputedRef; 58 | saturateColor: ComputedRef; 59 | opacifyColor: ComputedRef; 60 | transparentizeColor: ComputedRef; 61 | } 62 | 63 | /** 64 | * Reactive color parsing and manipulation built on top of color2k. 65 | * @param color 66 | * @param amount 67 | */ 68 | declare const useColor: ( 69 | color: Ref, 70 | amount?: Ref | undefined 71 | ) => ReactiveColor; 72 | ``` 73 | -------------------------------------------------------------------------------- /docs/v3/core/use-css-vars.md: -------------------------------------------------------------------------------- 1 | # useCssVars 2 | 3 | ::: tip useCssVars 4 | Munipulate CSS Variables. 5 | ::: 6 | 7 | ## Example 8 | 9 | > 💡 Change Color and Watch CSS Variables Changed. 10 | 11 | 12 | 13 | 14 | 15 | ## Usage 16 | 17 | ```js 18 | import { ref } from 'vue' 19 | import { useCssVars } from '@vueblocks/vue-use-core' 20 | 21 | export default { 22 | setup () { 23 | const textEl = ref(null) 24 | const onInputTextColor = e => textColor.value = e.target.value 25 | const onInputBgColor = e => bgColor.value = e.target.value 26 | 27 | const textColor = useCssVars(textEl, '--text-color', '#000') 28 | const bgColor = useCssVars(textEl, '--bg-color', '#3eaf7c') 29 | 30 | return { 31 | textEl, 32 | textColor, 33 | bgColor, 34 | onInputTextColor, 35 | onInputBgColor 36 | } 37 | } 38 | } 39 | ``` 40 | 41 | ## Typing 42 | 43 | ```ts 44 | declare const useCssVars: ( 45 | el: MaybeRef, 46 | variable: string, 47 | defaultValue: string 48 | ) => Ref; 49 | ``` 50 | -------------------------------------------------------------------------------- /docs/v3/core/use-debounced-ref.md: -------------------------------------------------------------------------------- 1 | # useDebouncedRef 2 | 3 | ::: tip useDebouncedRef 4 | Inspired by Vue3 Offical Document [customRef](https://v3.cn.vuejs.org/api/refs-api.html#customref) demo. 5 | ::: 6 | 7 | ## Example 8 | 9 | 10 | 11 | 12 | 13 | ## Usage 14 | 15 | ```html 16 | 17 | ``` 18 | 19 | ```js 20 | import { useDebouncedRef } from '@vueblocks/vue-use-core' 21 | 22 | export default { 23 | setup() { 24 | return { 25 | text: useDebouncedRef('hello') 26 | } 27 | } 28 | } 29 | ``` 30 | 31 | ## Typing 32 | 33 | ```ts 34 | declare const useDebouncedRef: (value: any, delay?: number) => Ref; 35 | ``` 36 | -------------------------------------------------------------------------------- /docs/v3/core/use-element-size.md: -------------------------------------------------------------------------------- 1 | # useElementSize 2 | 3 | ::: tip useElementSize 4 | Reactive [Element](https://developer.mozilla.org/en-US/docs/Web/API/Element) size. 5 | ::: 6 | 7 | ## Example 8 | 9 | > 💡 resize the textarea, and watch the element size changed. 10 | 11 | 12 | 13 | 14 | 15 | ## Usage 16 | 17 | ```html 18 |
19 | 20 | 21 | 30 |
31 | ``` 32 | 33 | ```ts 34 | import { defineComponent, ref, onMounted } from 'vue' 35 | import { useElementSize } from '@vueblocks/vue-use-core' 36 | 37 | export default defineComponent({ 38 | setup () { 39 | const position = ref({}) 40 | const textareaRef = ref() 41 | 42 | onMounted(() => { 43 | position.value = useElementSize(textareaRef, {}) 44 | }) 45 | 46 | return { 47 | textareaRef, 48 | position 49 | } 50 | } 51 | }) 52 | ``` 53 | 54 | ## Typing 55 | 56 | ```ts 57 | interface WindowSize { 58 | width: Ref; 59 | height: Ref; 60 | } 61 | interface ElementSize extends WindowSize { 62 | } 63 | /** 64 | * Options to be given to the resize observer, 65 | * when observing a new element. 66 | * 67 | * https://drafts.csswg.org/resize-observer-1/#dictdef-resizeobserveroptions 68 | */ 69 | interface ResizeObserverOptions { 70 | box?: 'content-box' | 'border-box' | 'device-pixel-content-box' | ResizeObserverBoxOptions; 71 | } 72 | 73 | declare const useElementSize: (target: RefElement, options?: ResizeObserverOptions) => ElementSize; 74 | ``` 75 | -------------------------------------------------------------------------------- /docs/v3/core/use-emitter.md: -------------------------------------------------------------------------------- 1 | # useEmitter 2 | 3 | ::: tip useEmitter 4 | 5 | ::: 6 | 7 | ## Example 8 | 9 | > 💡 Emit a custom event 10 | 11 | 14 | 15 | ## Usage 16 | 17 | ```html 18 |
19 | Mouse Position: [X: {{ x }}, Y: {{ y }}] 20 |
21 | ``` 22 | 23 | ```js 24 | import { useEmitter } from '@vueblocks/vue-use-core' 25 | 26 | export default { 27 | setup () { 28 | const { off, emit } = useEmitter() 29 | 30 | return { 31 | emit 32 | } 33 | } 34 | } 35 | ``` 36 | 37 | ## Typing 38 | 39 | ```ts 40 | declare const useEmitter: (event: E, handler: Handler | WildcardHandler) => { 41 | off: () => void; 42 | emit: { 43 | (type: EventType, event?: T | undefined): void; 44 | (type: "*", event?: any): void; 45 | }; 46 | }; 47 | ``` 48 | -------------------------------------------------------------------------------- /docs/v3/core/use-fullscreen.md: -------------------------------------------------------------------------------- 1 | # useFullscreen 2 | 3 | ::: tip useFullscreen 4 | Reactive Fullscreen API build on top of [screenfull.js](https://github.com/sindresorhus/screenfull.js/) 5 | ::: 6 | 7 | ## Example 8 | 9 | > Click the image to make it fullscreen 10 | 11 | 12 | 13 | 14 | 15 | ## Usage 16 | 17 | ```html 18 |
19 | 23 | 24 |
25 | 26 |
27 |
28 | ``` 29 | 30 | ```js 31 | import { useFullscreen } from '@vueblocks/vue-use-core' 32 | 33 | export default { 34 | setup () { 35 | const imgRef = ref(null) 36 | const { 37 | isFullscreen, 38 | toggleFullscreen 39 | } = useFullscreen(imgRef) 40 | 41 | return { 42 | imgRef, 43 | isFullscreen, 44 | toggleFullscreen 45 | } 46 | } 47 | } 48 | ``` 49 | 50 | ## Typing 51 | 52 | ```ts 53 | /** 54 | * Reactive Fullscreen API build on top of screenfull.js 55 | * @param {HTMLElement} target 56 | * @return {boolean} isFullscreen 57 | * @return {function} toggleFullscreen 58 | */ 59 | declare const useFullscreen: (target: HTMLElement) => { 60 | isFullscreen: Ref; 61 | toggleFullscreen: () => void; 62 | }; 63 | ``` 64 | -------------------------------------------------------------------------------- /docs/v3/core/use-instance.md: -------------------------------------------------------------------------------- 1 | # useInstance 2 | 3 | ::: tip useInstance 4 | Get `vm` from `getCurrentInstance` API, Same as [getCurrentInstance.proxy](https://github.com/vuejs/composition-api/releases/tag/v1.0.0-beta.22) 5 | ::: 6 | 7 | ## Example 8 | 9 | > 💡 Open DevTools, Instance Info already Print out. 10 | 11 | 12 | 13 | 14 | 15 | ## Usage 16 | 17 | ```js 18 | import { useInstance } from '@vueblocks/vue-use-core' 19 | 20 | export default { 21 | setup () { 22 | const vm = useInstance() 23 | 24 | console.log(vm) 25 | } 26 | } 27 | ``` 28 | 29 | ## Typing 30 | 31 | ```ts 32 | declare const useInstance: () => any; 33 | ``` 34 | -------------------------------------------------------------------------------- /docs/v3/core/use-mouse.md: -------------------------------------------------------------------------------- 1 | # useMouse 2 | 3 | ::: tip useMouse 4 | ♻️ Register [MouseMove](https://developer.mozilla.org/en-US/docs/Web/API/Element/mousemove_event) event on mounted, and remove event automatically on unmounted. 5 | ::: 6 | 7 | ## Example 8 | 9 | > 💡 Move your mouse 10 | 11 | 12 | 13 | 14 | 15 | ## Usage 16 | 17 | ```html 18 |
19 | Mouse Position: [X: {{ x }}, Y: {{ y }}] 20 |
21 | ``` 22 | 23 | ```js 24 | import { useMouse } from '@vueblocks/vue-use-core' 25 | 26 | export default { 27 | setup () { 28 | const { x, y, remove } = useMouse() 29 | 30 | return { 31 | x, 32 | y 33 | } 34 | } 35 | } 36 | ``` 37 | 38 | ## Typing 39 | 40 | ```ts 41 | /** 42 | * Register `MouseMove` event on mounted, and remove event automatically on unmounted. 43 | */ 44 | declare const useMouse: () => { 45 | x: Ref; 46 | y: Ref; 47 | remove: () => void; 48 | } 49 | ``` 50 | -------------------------------------------------------------------------------- /docs/v3/core/use-palette.md: -------------------------------------------------------------------------------- 1 | # usePalette 2 | 3 | ::: tip usePalette 4 | Turn `color2k` to `usePalette`, we enhanced color2k with new utilities like `tint` 、 `shade` 、 `invert`. 5 | ::: 6 | 7 | 14 | 15 | ## Usage 16 | 17 | ```js 18 | import { ref } from 'vue' 19 | import { usePalette } from '@vueblocks/vue-use-core' 20 | 21 | const { tint } = usePalette 22 | 23 | export default { 24 | setup () { 25 | const mainColor = '#3eaf7c' 26 | const tintColor = ref(tint(mainColor, 0.5)) 27 | 28 | return { 29 | tintColor 30 | } 31 | } 32 | } 33 | ``` 34 | 35 | ## Typing 36 | 37 | ```ts 38 | /** 39 | * enhanced `color2k` with new utilities like `tint` 、 `shade` 、 `invert`. 40 | */ 41 | declare const usePalette: { 42 | adjustHue: typeof adjustHue; 43 | darken: typeof darken; 44 | desaturate: typeof desaturate; 45 | getContrast: typeof getContrast; 46 | getLuminance: typeof getLuminance; 47 | getScale: typeof getScale; 48 | guard: typeof guard; 49 | hasBadContrast: typeof hasBadContrast; 50 | hsla: typeof hsla; 51 | lighten: typeof lighten; 52 | mix: typeof mix; 53 | opacify: typeof opacify; 54 | parseToHsla: typeof parseToHsla; 55 | readableColor: typeof readableColor; 56 | readableColorIsBlack: typeof readableColorIsBlack; 57 | rgba: typeof rgba; 58 | saturate: typeof saturate; 59 | transparentize: typeof transparentize; 60 | parseToRgba: typeof parseToRgba; 61 | ColorError: typeof ColorError; 62 | toHex: typeof toHex; 63 | toRgba: typeof toRgba; 64 | toHsla: typeof toHsla; 65 | /** 66 | * Tints a color by mixing it with white. 67 | * @param color 68 | * @param amount given as a decimal between 0 and 1 69 | */ 70 | tint: (color: string, amount: number) => string; 71 | /** 72 | * Shades a color by mixing it with black. 73 | * @param color 74 | * @param amount given as a decimal between 0 and 1 75 | */ 76 | shade: (color: string, amount: number) => string; 77 | /** 78 | * Inverts the red, green and blue values of a color. 79 | * @param color 80 | */ 81 | invert: (color: string) => string; 82 | }; 83 | ``` 84 | -------------------------------------------------------------------------------- /docs/v3/core/use-precision.md: -------------------------------------------------------------------------------- 1 | # usePrecision 2 | 3 | ::: tip usePrecision 4 | `usePrecision` provide reactive methods to perform addition, subtraction, multiplication & division operations precisely 5 | ::: 6 | 7 | ## Example 8 | 9 | 10 | 11 | 12 | 13 | ## Usage 14 | 15 | ```js 16 | import { ref, reactive, toRefs } from 'vue' 17 | import { usePrecision } from '@vueblocks/vue-use-core' 18 | 19 | export default { 20 | setup () { 21 | const { plus, times } = usePrecision() 22 | 23 | const [plusA, plusB] = [ref(0.1), ref(0.2)] 24 | const [timesA, timesB] = [ref(7), ref(0.2)] 25 | 26 | const localState = reactive({ 27 | plusResult: plus(plusA, plusB), 28 | timesResult: times(timesA, timesB) 29 | }) 30 | 31 | return toRefs(localState) 32 | } 33 | } 34 | ``` 35 | 36 | ## Typing 37 | 38 | ```ts 39 | /** 40 | * `usePrecision` provide reactive methods to perform addition, subtraction, multiplication & division operations precisely. 41 | */ 42 | declare const usePrecision: () => { 43 | strip: (num: RefTyped, precision?: RefTyped) => ComputedRef; 44 | plus: (num1: RefTyped, num2: RefTyped, ...others: RefTyped[]) => ComputedRef; 45 | minus: (num1: RefTyped, num2: RefTyped, ...others: RefTyped[]) => ComputedRef; 46 | times: (num1: RefTyped, num2: RefTyped, ...others: RefTyped[]) => ComputedRef; 47 | divide: (num1: RefTyped, num2: RefTyped, ...others: RefTyped[]) => ComputedRef; 48 | round: (num: RefTyped, ratio: RefTyped) => ComputedRef; 49 | digitLength: (num: RefTyped) => ComputedRef; 50 | float2Fixed: (num: RefTyped) => ComputedRef; 51 | }; 52 | ``` 53 | -------------------------------------------------------------------------------- /docs/v3/core/use-resize-event.md: -------------------------------------------------------------------------------- 1 | # useResizeEvent 2 | 3 | ::: tip useResizeEvent 4 | ♻️ Register [resize](https://developer.mozilla.org/en-US/docs/Web/API/Window/resize_event) event on mounted, and remove event automatically on unmounted. 5 | ::: 6 | 7 | ## Example 8 | 9 | > 💡 resize the browser and watch document size changed. 10 | 11 | 12 | 13 | 14 | 15 | ## Usage 16 | 17 | ```html 18 |
19 | document size: {{ domSize }} 20 |
21 | ``` 22 | 23 | ```js 24 | import { useResizeEvent } from '@vueblocks/vue-use-core' 25 | 26 | export default { 27 | setup () { 28 | let domSize = reactive({ 29 | width: 0, 30 | height: 0 31 | }) 32 | 33 | const onResize = () => { 34 | domSize.width = document.body.clientWidth 35 | domSize.height = document.body.clientHeight 36 | } 37 | 38 | const { dispatchResize } = useResizeEvent(onResize) 39 | 40 | // dispatch resize event once 41 | onMounted(dispatchResize) 42 | 43 | return { 44 | domSize 45 | } 46 | } 47 | } 48 | ``` 49 | 50 | ## Typing 51 | 52 | ```ts 53 | interface EventOptions { 54 | useCapture?: boolean; 55 | useThrottle?: boolean | null; 56 | delay?: number; 57 | } 58 | 59 | /** 60 | * Reactive Resize API, When window resize, do someting. 61 | * @param {function} fn 62 | * @param {object} options 63 | * @return {function} dispatchResize 64 | */ 65 | declare const useResizeEvent: (fn: Fn, options?: EventOptions) => { 66 | dispatchResize: () => void; 67 | }; 68 | ``` 69 | -------------------------------------------------------------------------------- /docs/v3/core/use-shortcut.md: -------------------------------------------------------------------------------- 1 | # useShortcut 2 | 3 | ::: tip useShortcut 4 | Bind Keyboard Shortcuts API build on top of [keymaster](https://github.com/madrobby/keymaster). 5 | 6 | ♻️ Bind shortcuts on mounted, and unbind shortcuts automatically on unmounted. 7 | ::: 8 | 9 | ## Example 10 | 11 | > Type one of the following Keys👇: 12 | 13 | 14 | 15 | 16 | 17 | ## Usage 18 | 19 | ```html 20 |
21 |
22 | Shift + D 23 |
24 |
25 | Command + D or Ctrl + D 26 |
27 |
28 | ``` 29 | 30 | ```js 31 | import { useShortcut } from '@vueblocks/vue-use-core' 32 | 33 | export default { 34 | setup () { 35 | const pressedKeyCodes = ref([]) 36 | 37 | useShortcut({ 38 | 'shift+d': (event, handler) => { 39 | pressedKeyCodes.value.push(handler.shortcut) 40 | alert("The 'Shift' and 'd' keys were pressed at the same time") 41 | }, 42 | '⌘+d, ctrl+d': (event, handler) => { 43 | pressedKeyCodes.value.push(handler.shortcut) 44 | alert("Either 'Control+d' or 'Meta+d' were pressed") 45 | } 46 | }) 47 | 48 | onUnmounted(() => pressedKeyCodes.value = []) 49 | 50 | return { 51 | pressedKeyCodes 52 | } 53 | } 54 | } 55 | ``` 56 | 57 | ## Typing 58 | 59 | ```ts 60 | /** 61 | * A map of keybinding strings to event handlers. 62 | */ 63 | interface KeyBindingMap { 64 | [keybinding: string]: (event: KeyboardEvent) => void; 65 | } 66 | interface KeymasterEvent { 67 | key: string; 68 | method: KeyHandler; 69 | mods: number[]; 70 | scope: string; 71 | shortcut: string; 72 | } 73 | interface KeyHandler { 74 | (keyboardEvent: KeyboardEvent, keymasterEvent: KeymasterEvent): void; 75 | } 76 | /** 77 | * Bind shortcut onMounted & unbind shortcut automatically onUnmounted in setup hooks 78 | * or 79 | * Unbind shortcut before bind shortcut without setup hooks 80 | * @param keymap 81 | * @param vm 82 | * @return shortcut 83 | */ 84 | declare const useShortcut: (keymap: KeyBindingMap, vm?: any) => { 85 | shift: boolean; 86 | alt: boolean; 87 | option: boolean; 88 | ctrl: boolean; 89 | control: boolean; 90 | command: boolean; 91 | setScope(scopeName: string): void; 92 | getScope(): string; 93 | deleteScope(scopeName: string): void; 94 | noConflict(): void; 95 | unbind(key: string): void; 96 | unbind(key: string, scopeName: string): void; 97 | isPressed(keyCode: number): boolean; 98 | getPressedKeyCodes(): number[]; 99 | filter(event: FilterEvent): void; 100 | bind: (seed: string, func: Function) => void; 101 | }; 102 | ``` 103 | -------------------------------------------------------------------------------- /docs/v3/core/use-window-size.md: -------------------------------------------------------------------------------- 1 | # useWindowSize 2 | 3 | ::: tip useWindowSize 4 | Reactive window size 5 | ::: 6 | 7 | ## Example 8 | 9 | > 💡 resize the browser and watch window size changed. 10 | 11 | 12 | 13 | 14 | 15 | ## Usage 16 | 17 | ```html 18 |
19 | window size: {{ width }} x {{ height }} 20 |
21 | ``` 22 | 23 | ```js 24 | import { useWindowSize } from '@vueblocks/vue-use-core' 25 | 26 | export default { 27 | setup () { 28 | const { width, height } = useWindowSize() 29 | 30 | return { 31 | width, 32 | height 33 | } 34 | } 35 | } 36 | ``` 37 | 38 | ## Typing 39 | 40 | ```ts 41 | interface WindowSize { 42 | width: Ref; 43 | height: Ref; 44 | } 45 | 46 | interface EventOptions { 47 | useCapture?: boolean; 48 | useThrottle?: boolean | null; 49 | delay?: number; 50 | } 51 | 52 | /** 53 | * Reactive window size 54 | * @param {object} options 55 | * @return {Ref} WindowSize 56 | */ 57 | declare const useWindowSize: (options?: EventOptions) => WindowSize; 58 | ``` 59 | -------------------------------------------------------------------------------- /docs/v3/guide/index.md: -------------------------------------------------------------------------------- 1 | # Introduction 2 | 3 | ## What is vue-use-utilities 4 | 5 | `@vueblocks/vue-use-utilities` is a out of box generic `composition-api` utilities. It's both Support 6 | Vue 2 / 3 Project. Built on top of [vue-demi](https://github.com/antfu/vue-demi) & [@vue/composition-api](https://github.com/vuejs/composition-api) 7 | 8 | ## Inspiration 9 | 10 | This libary is inspired by [@vueuse/core](https://github.com/antfu/vueuse) also other similar projects. 11 | 12 | ## Installation 13 | 14 | ```bash 15 | # Vue 2 with @vue/composition-api 16 | yarn add @vue/composition-api @vueblocks/vue-use-core -S 17 | or 18 | npm i @vue/composition-api @vueblocks/vue-use-core -S 19 | 20 | # Vue 3 21 | yarn add @vueblocks/vue-use-core -S 22 | or 23 | npm i @vueblocks/vue-use-core -S 24 | ``` 25 | -------------------------------------------------------------------------------- /docs/v3/index.md: -------------------------------------------------------------------------------- 1 | --- 2 | home: true 3 | # heroImage: images/banner-x.png 4 | actionText: Get Started → 5 | actionLink: /guide/ 6 | altActionText: Documnentation 7 | altActionLink: /guide/ 8 | features: 9 | - title: 🔮 Reactive 10 | details: Full usable of `reactive`, ready to use on your templates. 11 | - title: 🛠 Composable 12 | details: All utilities is composable built on top of `@vue/composition-api` 13 | - title: 🌳 TreeShakable 14 | details: Packages is built with rollup, Tree-Shakable and SideEffects free. 15 | - title: 🤟 Vue 2 and 3 Support 16 | details: Compatible with Vue2.x and Vue 3, built on top of `vue-demi` 17 | - title: 💪 Fully Typed APIs 18 | details: Flexible programmatic APIs with full TypeScript typing. 19 | - title: 🧩 Advanced Integration 20 | details: Support commonly used add-ons like `Vuex`、`Axios`. 21 | footer: MIT Licensed | Copyright © 2020-present @xiaoluoboding 22 | --- 23 | -------------------------------------------------------------------------------- /docs/v3/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@vueblock/vue-use-docs-vue3", 3 | "version": "1.0.0", 4 | "license": "MIT", 5 | "scripts": { 6 | "dev": "vitepress dev --port 4949", 7 | "build": "vitepress build" 8 | }, 9 | "dependencies": { 10 | "@vueblocks/vue-use-axios": "^0.2.6", 11 | "@vueblocks/vue-use-core": "^0.2.10", 12 | "@vueblocks/vue-use-vuex": "^0.2.10", 13 | "axios": "^0.24.0", 14 | "vuex": "^3.6.2" 15 | }, 16 | "postcss": { 17 | "plugins": { 18 | "tailwindcss": {}, 19 | "autoprefixer": {} 20 | } 21 | }, 22 | "devDependencies": { 23 | "@tailwindcss/postcss7-compat": "^2.0.3", 24 | "autoprefixer": "^9", 25 | "postcss": "^7", 26 | "tailwindcss": "npm:@tailwindcss/postcss7-compat", 27 | "vitepress": "^0.20.0" 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /docs/v3/tailwind.config.js: -------------------------------------------------------------------------------- 1 | // tailwind.config.js 2 | module.exports = { 3 | purge: [], 4 | darkMode: false, // or 'media' or 'class' 5 | theme: { 6 | extend: {} 7 | }, 8 | variants: {}, 9 | plugins: [] 10 | } 11 | -------------------------------------------------------------------------------- /docs/v3/vuex/namespacing.md: -------------------------------------------------------------------------------- 1 | # Namespacing 2 | 3 | ## Binding Helpers with Namespace 4 | 5 | When binding a namespaced module to components with the `useState`, `useGetters`, `useActions` and `useMutations` helpers, it can get a bit verbose: 6 | 7 | ```js 8 | setup () { 9 | return { 10 | ...useState({ 11 | a: state => state.some.nested.module.a, 12 | b: state => state.some.nested.module.b 13 | }), 14 | ...useGetters([ 15 | 'some/nested/module/someGetter', // -> this['some/nested/module/someGetter'] 16 | 'some/nested/module/someOtherGetter', // -> this['some/nested/module/someOtherGetter'] 17 | ]), 18 | ...useActions([ 19 | 'some/nested/module/foo', // -> this['some/nested/module/foo']() 20 | 'some/nested/module/bar' // -> this['some/nested/module/bar']() 21 | ]) 22 | } 23 | } 24 | ``` 25 | 26 | In such cases, you can pass the module namespace string as the first argument to the helpers so that all bindings are done using that module as the context. The above can be simplified to: 27 | 28 | ```js 29 | setup () { 30 | return { 31 | ...mapState('some/nested/module', { 32 | a: state => state.a, 33 | b: state => state.b 34 | }), 35 | ...mapGetters('some/nested/module', [ 36 | 'someGetter', // -> this.someGetter 37 | 'someOtherGetter', // -> this.someOtherGetter 38 | ]), 39 | ...mapActions('some/nested/module', [ 40 | 'foo', // -> this.foo() 41 | 'bar' // -> this.bar() 42 | ]) 43 | } 44 | } 45 | ``` 46 | 47 | Furthermore, you can create namespaced helpers by using `useVuex`. It returns an object having new component binding helpers that are bound with the given namespace value: 48 | 49 | ```js {6} 50 | // Get namespaced component binding helpers in useVuex 51 | import { useVuex } from '@vueblocks/vue-use-vuex' 52 | 53 | export default { 54 | setup () { 55 | const { mapState, mapActions } = useVuex('some/nested/module') 56 | 57 | return { 58 | // look up in `some/nested/module` 59 | ...mapState({ 60 | a: state => state.a, 61 | b: state => state.b 62 | }) 63 | // look up in `some/nested/module` 64 | ...mapActions([ 65 | 'foo', 66 | 'bar' 67 | ]) 68 | } 69 | } 70 | } 71 | ``` 72 | -------------------------------------------------------------------------------- /docs/v3/vuex/use-actions.md: -------------------------------------------------------------------------------- 1 | # useActions 2 | 3 | > `useActions: (namespace?: string, map: Array | Object) => Object` 4 | 5 | Create component methods options that dispatch an action. 6 | 7 | The first argument can optionally be a namespace string. [Details](./namespacing.md) 8 | 9 | The second object argument's members can be a function. `function(dispatch: function, ...args: any[])` 10 | 11 | ## Usage 12 | 13 | When accessing actions, you can simply use `useActions` inside the setup hook. This is the equivalent of creating methods properties using the Option API. 14 | 15 | ```js {7} 16 | import { useVuex } from '@vueblocks/vue-use-vuex' 17 | 18 | export default { 19 | // ... 20 | setup () { 21 | // Use the useActions as you would use mapActions 22 | const { useActions } = useVuex() 23 | 24 | return { 25 | ...useActions([ 26 | 'increment', // map `increment()` to `this.$store.dispatch('increment')` 27 | 28 | // `mapActions` also supports payloads: 29 | 'incrementBy' // map `incrementBy(amount)` to `this.$store.dispatch('incrementBy', amount)` 30 | ]), 31 | ...useActions({ 32 | add: 'increment' // map `add()` to `this.$store.dispatch('increment')` 33 | }) 34 | } 35 | } 36 | } 37 | ``` 38 | -------------------------------------------------------------------------------- /docs/v3/vuex/use-getters.md: -------------------------------------------------------------------------------- 1 | # useGetters 2 | 3 | > `useGetters: (namespace?: string, map: Array | Object) => Object` 4 | 5 | Create component computed options that return the evaluated value of a getter. 6 | 7 | The first argument can optionally be a namespace string. [Details](./namespacing.md) 8 | 9 | ## Usage 10 | 11 | In order to access getters, you can simply use `useGetters` helper inside the setup hook. This is the equivalent of creating computed properties using the Option API. 12 | 13 | ```js {7} 14 | import { useVuex } from '@vueblocks/vue-use-vuex' 15 | 16 | export default { 17 | // ... 18 | setup () { 19 | // Use the useGetters as you would use mapGetters 20 | const { useGetters } = useVuex() 21 | 22 | return { 23 | // mix the getters into outer object with the object spread operator 24 | ...useGetters([ 25 | 'doneTodosCount', 26 | 'anotherGetter', 27 | // ... 28 | ]), 29 | // if you want to map a getter to a different name, use an object: 30 | ...mapGetters({ 31 | // map `doneCount` to `this.$store.getters.doneTodosCount` 32 | doneCount: 'doneTodosCount' 33 | }) 34 | } 35 | } 36 | } 37 | ``` 38 | -------------------------------------------------------------------------------- /docs/v3/vuex/use-mutations.md: -------------------------------------------------------------------------------- 1 | # useMutations 2 | 3 | > `useMutations: (namespace?: string, map: Array | Object) => Object` 4 | 5 | Create component methods options that commit a mutation. 6 | 7 | The first argument can optionally be a namespace string. [Details](./namespacing.md) 8 | 9 | The second object argument's members can be a function. `function(commit: function, ...args: any[])` 10 | 11 | ## Usage 12 | 13 | When accessing mutations, you can simply use `useMutations` inside the setup hook. This is the equivalent of creating methods properties using the Option API. 14 | 15 | ```js {7} 16 | import { useVuex } from '@vueblocks/vue-use-vuex' 17 | 18 | export default { 19 | // ... 20 | setup () { 21 | // Use the useMutations as you would use mapMutations 22 | const { useMutations } = useVuex() 23 | 24 | return { 25 | ...useMutations([ 26 | 'increment', // map `increment()` to `this.$store.commit('increment')` 27 | 28 | // `mapMutations` also supports payloads: 29 | 'incrementBy' // map `incrementBy(amount)` to `this.$store.commit('incrementBy', amount)` 30 | ]), 31 | ...useMutations({ 32 | add: 'increment' // map `add()` to `this.$store.commit('increment')` 33 | }) 34 | } 35 | } 36 | } 37 | ``` 38 | -------------------------------------------------------------------------------- /docs/v3/vuex/use-state.md: -------------------------------------------------------------------------------- 1 | # useState 2 | 3 | > `useState: (namespace?: string, map: Array | Object) => Object` 4 | 5 | Create component computed options that return the sub tree of the Vuex store. 6 | 7 | The first argument can optionally be a namespace string. [Details](./namespacing.md) 8 | 9 | The second object argument's members can be a function. `function(state: any)` 10 | 11 | ## Usage 12 | 13 | In order to access state, you can simply use `useState` helper inside the setup hook. This is the equivalent of creating computed properties using the Option API. 14 | 15 | ```js {7} 16 | import { useVuex } from '@vueblocks/vue-use-vuex' 17 | 18 | export default { 19 | // ... 20 | setup () { 21 | // Use the useState as you would use mapState 22 | const { useState } = useVuex() 23 | 24 | return { 25 | // mix this into the outer object with the object spread operator 26 | ...useState({ 27 | // arrow functions can make the code very succinct! 28 | count: state => state.count, 29 | 30 | // passing the string value 'count' is same as `state => state.count` 31 | countAlias: 'count', 32 | 33 | // to access local state with `this`, a normal function must be used 34 | countPlusLocalState (state) { 35 | return state.count + this.localCount 36 | } 37 | }), 38 | ...mapState([ 39 | // map count to store.state.count 40 | 'count' 41 | ]) 42 | } 43 | } 44 | } 45 | ``` 46 | -------------------------------------------------------------------------------- /docs/v3/vuex/use-store.md: -------------------------------------------------------------------------------- 1 | # useStore 2 | 3 | ## Vuex 4 4 | 5 | > Vuex 4 introduces a new API to interact with the store in Composition API. You can use the `useStore` composition function to retrieve the store within the component `setup` hook. 6 | 7 | ```js {2} 8 | // Vuex version is 4.x 9 | import { useStore } from 'vuex' 10 | 11 | export default { 12 | setup () { 13 | const store = useStore() 14 | } 15 | } 16 | ``` 17 | 18 | ## What we provide 19 | 20 | We talk about how to retrieve the store in `Vue 2 & Vuex 3` Project. 21 | 22 | Maybe you already have the answer, it's very easy, just use `this.$store`. 23 | 24 | But, We know about Composition API, Inside [setup()](https://v3.vuejs.org/guide/composition-api-setup.html#usage-of-this), `this` **won't be a reference to the current active instance** Since `setup()` is called before other component options are resolved. 25 | 26 | So, we provide `useStore` in `@vueblocks/vue-use-vuex` libary. 27 | 28 | ```js {1} 29 | import { useStore } from '@vueblocks/vue-use-vuex' 30 | 31 | export default { 32 | setup () { 33 | // Use the useStore as you would use useStore in Vuex 4 34 | const store = useStore() 35 | } 36 | } 37 | ``` 38 | 39 | ## Typing 40 | 41 | ```ts 42 | /** 43 | * Get $store from current instance 44 | * @return {Store} vm.$store 45 | */ 46 | declare const useStore: () => Store 47 | ``` 48 | -------------------------------------------------------------------------------- /docs/v3/vuex/use-vuex.md: -------------------------------------------------------------------------------- 1 | # useVuex 2 | 3 | > Use Vuex With Composition API Easily. 4 | 5 | ## Install 6 | 7 | ```bash 8 | # Vue 2 with @vue/composition-api 9 | yarn add @vue/composition-api @vueblocks/vue-use-vuex -S 10 | or 11 | npm i @vue/composition-api @vueblocks/vue-use-vuex -S 12 | 13 | # Vue 3 14 | yarn add @vueblocks/vue-use-vuex -S 15 | or 16 | npm i @vueblocks/vue-use-vuex -S 17 | ``` 18 | 19 | ## Usage 20 | 21 | `useVuex` utilities just similar with [Vuex Component Binding Helpers](https://vuex.vuejs.org/api/#component-binding-helpers) 22 | 23 | It export these composable helpers: 24 | 25 | * [useState](./use-state.md) - same as `mapState` helper in Vuex 26 | * [useGetters](./use-getters.md) - same as `mapGetters` helper in Vuex 27 | * [useMutations](./use-mutations.md) - same as `mapMutations` helper in Vuex 28 | * [useActions](./use-actions.md) - same as `mapActions` helper in Vuex 29 | 30 | Differently, `useVuex` do not export `createNamespacedHelpers` function, Instead `useVuex` allow you provide 31 | the namespace as first argument, then return will be the namespaced component binding helpers. 32 | 33 | Read more about namespacing [documention](./namespacing.md). 34 | 35 | It seems familiar right? 36 | 37 | ## Example 38 | 39 | ::: tip 💡 Tips 40 | `useVuex` also allow you provide the `namespace` as first argument, then return will be the namespaced component binding helpers. 41 | ::: 42 | 43 | ```js 44 | import { useVuex, useStore } from '@vueblocks/vue-use-vuex' 45 | 46 | export default { 47 | setup () { 48 | const store = useStore() 49 | const { useState, useGetters, useActions } = useVuex('counter') 50 | 51 | return { 52 | ...useState(['count']), 53 | 54 | ...useGetters([ 55 | 'evenOrOdd' 56 | ]), 57 | 58 | ...useActions([ 59 | 'increment', 60 | 'decrement', 61 | 'incrementIfOdd', 62 | 'incrementAsync' 63 | ]) 64 | } 65 | } 66 | } 67 | ``` 68 | 69 | ## Typing 70 | 71 | ```ts 72 | /** 73 | * Use Vuex with composition api easily. Both support Vue2.x / Vue3.x 74 | * @param {String} namespace 75 | * @param {Store} store ### vm.$store 76 | */ 77 | declare function useVuex(namespace?: string, store?: Store): { 78 | useState: (namespace?: string, map: Array | Object) => Object; 79 | useGetters: (namespace?: string, map: Array | Object) => Object; 80 | useMutations: (namespace?: string, map: Array | Object) => Object; 81 | useActions: (namespace?: string, map: Array | Object) => Object; 82 | }; 83 | ``` 84 | -------------------------------------------------------------------------------- /examples/vue2-demo/.editorconfig: -------------------------------------------------------------------------------- 1 | [*.{js,jsx,ts,tsx,vue}] 2 | indent_style = space 3 | indent_size = 2 4 | trim_trailing_whitespace = true 5 | insert_final_newline = true 6 | -------------------------------------------------------------------------------- /examples/vue2-demo/.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules 3 | /dist 4 | 5 | 6 | # local env files 7 | .env.local 8 | .env.*.local 9 | 10 | # Log files 11 | npm-debug.log* 12 | yarn-debug.log* 13 | yarn-error.log* 14 | pnpm-debug.log* 15 | 16 | # Editor directories and files 17 | .idea 18 | .vscode 19 | *.suo 20 | *.ntvs* 21 | *.njsproj 22 | *.sln 23 | *.sw? 24 | -------------------------------------------------------------------------------- /examples/vue2-demo/README.md: -------------------------------------------------------------------------------- 1 | # vue2-ts 2 | 3 | ## Project setup 4 | ``` 5 | yarn install 6 | ``` 7 | 8 | ### Compiles and hot-reloads for development 9 | ``` 10 | yarn serve 11 | ``` 12 | 13 | ### Compiles and minifies for production 14 | ``` 15 | yarn build 16 | ``` 17 | 18 | ### Lints and fixes files 19 | ``` 20 | yarn lint 21 | ``` 22 | 23 | ### Customize configuration 24 | See [Configuration Reference](https://cli.vuejs.org/config/). 25 | -------------------------------------------------------------------------------- /examples/vue2-demo/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "vue2-demo", 3 | "version": "0.1.0", 4 | "private": true, 5 | "scripts": { 6 | "serve": "vue-cli-service serve", 7 | "build": "vue-cli-service build", 8 | "lint": "vue-cli-service lint" 9 | }, 10 | "dependencies": { 11 | "@vue/composition-api": "^1.2.4", 12 | "@vueblocks/vue-use-core": "^0.2.11", 13 | "@vueblocks/vue-use-vuex": "^0.2.11", 14 | "vue": "^2.6.11", 15 | "vue-demi": "0.10.0", 16 | "vuex": "^3.4.0" 17 | }, 18 | "devDependencies": { 19 | "@typescript-eslint/eslint-plugin": "^4.18.0", 20 | "@typescript-eslint/parser": "^4.18.0", 21 | "@vue/cli-plugin-eslint": "~4.5.0", 22 | "@vue/cli-plugin-typescript": "~4.5.0", 23 | "@vue/cli-plugin-vuex": "~4.5.0", 24 | "@vue/cli-service": "~4.5.0", 25 | "@vue/eslint-config-standard": "^5.1.2", 26 | "@vue/eslint-config-typescript": "^7.0.0", 27 | "eslint": "^6.7.2", 28 | "eslint-plugin-import": "^2.20.2", 29 | "eslint-plugin-node": "^11.1.0", 30 | "eslint-plugin-promise": "^4.2.1", 31 | "eslint-plugin-standard": "^4.0.0", 32 | "eslint-plugin-vue": "^6.2.2", 33 | "sass": "^1.26.5", 34 | "sass-loader": "^8.0.2", 35 | "tslib": "^2.3.1", 36 | "typescript": "^4.4.4", 37 | "vue-template-compiler": "^2.6.11" 38 | }, 39 | "eslintConfig": { 40 | "root": true, 41 | "env": { 42 | "node": true 43 | }, 44 | "extends": [ 45 | "plugin:vue/essential", 46 | "@vue/standard", 47 | "@vue/typescript/recommended" 48 | ], 49 | "parserOptions": { 50 | "ecmaVersion": 2020 51 | }, 52 | "rules": {} 53 | }, 54 | "browserslist": [ 55 | "> 1%", 56 | "last 2 versions", 57 | "not dead" 58 | ] 59 | } 60 | -------------------------------------------------------------------------------- /examples/vue2-demo/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vueblocks/vue-use-utilities/15cfbd077848c55c82e52cd094ea1fcf644b6cf1/examples/vue2-demo/public/favicon.ico -------------------------------------------------------------------------------- /examples/vue2-demo/public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | <%= htmlWebpackPlugin.options.title %> 9 | 10 | 11 | 14 |
15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /examples/vue2-demo/src/App.vue: -------------------------------------------------------------------------------- 1 | 7 | 8 | 21 | 22 | 32 | -------------------------------------------------------------------------------- /examples/vue2-demo/src/assets/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vueblocks/vue-use-utilities/15cfbd077848c55c82e52cd094ea1fcf644b6cf1/examples/vue2-demo/src/assets/logo.png -------------------------------------------------------------------------------- /examples/vue2-demo/src/components/Counter.vue: -------------------------------------------------------------------------------- 1 | 14 | 15 | 76 | -------------------------------------------------------------------------------- /examples/vue2-demo/src/components/HelloWorld.vue: -------------------------------------------------------------------------------- 1 | 11 | 12 | 32 | 33 | 34 | 50 | -------------------------------------------------------------------------------- /examples/vue2-demo/src/main.ts: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | import App from './App.vue' 3 | import store from './store' 4 | 5 | Vue.config.productionTip = false 6 | 7 | new Vue({ 8 | store, 9 | render: h => h(App) 10 | }).$mount('#app') 11 | -------------------------------------------------------------------------------- /examples/vue2-demo/src/shims-tsx.d.ts: -------------------------------------------------------------------------------- 1 | import Vue, { VNode } from 'vue' 2 | 3 | declare global { 4 | namespace JSX { 5 | // tslint:disable no-empty-interface 6 | interface Element extends VNode {} 7 | // tslint:disable no-empty-interface 8 | interface ElementClass extends Vue {} 9 | interface IntrinsicElements { 10 | [elem: string]: any 11 | } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /examples/vue2-demo/src/shims-vue.d.ts: -------------------------------------------------------------------------------- 1 | declare module '*.vue' { 2 | import Vue from 'vue' 3 | export default Vue 4 | } 5 | -------------------------------------------------------------------------------- /examples/vue2-demo/src/store/actions.ts: -------------------------------------------------------------------------------- 1 | const makeAction = (type: string) => { 2 | return (payload: any, ...args: any) => { 3 | const { commit } = payload 4 | return commit(type, ...args) 5 | } 6 | } 7 | 8 | export const makeActions = (types: any = {}) => { 9 | const actions = {} 10 | 11 | for (const type of Object.keys(types)) { 12 | const action = { 13 | [type]: makeAction(types[type]) 14 | } 15 | Object.assign(actions, action) 16 | } 17 | 18 | return actions 19 | } 20 | 21 | export const setState = makeAction('SET_STATE') 22 | -------------------------------------------------------------------------------- /examples/vue2-demo/src/store/index.ts: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | import Vuex from 'vuex' 3 | 4 | import * as actions from './actions' 5 | import * as types from './mutation-types' 6 | import modules from './modules/index' 7 | 8 | Vue.use(Vuex) 9 | 10 | const state = { 11 | theme: 'light' 12 | } 13 | 14 | type RootState = typeof state 15 | 16 | const getters = { 17 | isDarkmode: (state: RootState) => state.theme === 'dark' 18 | } 19 | 20 | const mutations = { 21 | [types.SET_STATE] (state: RootState, payload: any) { 22 | Object.assign(state, payload) 23 | }, 24 | [types.SET_THEME] (state: RootState, payload: any) { 25 | state.theme = payload 26 | } 27 | } 28 | 29 | // A Vuex instance is created by combining the state, mutations, actions, 30 | // and getters. 31 | export default new Vuex.Store({ 32 | state, 33 | getters, 34 | actions, 35 | mutations, 36 | modules 37 | }) 38 | -------------------------------------------------------------------------------- /examples/vue2-demo/src/store/modules/counter.ts: -------------------------------------------------------------------------------- 1 | import { makeActions } from '../actions' 2 | import { counter } from '../mutation-types' 3 | 4 | // namespaced counter state object. 5 | // each Vuex instance is just a single state tree. 6 | const state = { 7 | count: 0 8 | } 9 | 10 | type State = typeof state 11 | 12 | // mutations are operations that actually mutate the state. 13 | // each mutation handler gets the entire state tree as the 14 | // first argument, followed by additional payload arguments. 15 | // mutations must be synchronous and can be recorded by plugins 16 | // for debugging purposes. 17 | const mutations = { 18 | [counter.INCREMENT] (state: State): void { 19 | state.count++ 20 | }, 21 | [counter.DECREMENT] (state: State): void { 22 | state.count-- 23 | } 24 | } 25 | 26 | // actions are functions that cause side effects and can involve 27 | // asynchronous operations. 28 | const actions = { 29 | ...makeActions({ 30 | increment: counter.INCREMENT, 31 | decrement: counter.DECREMENT 32 | }), 33 | incrementIfOdd ({ commit, state }: any): void { 34 | if ((state.count + 1) % 2 === 0) { 35 | commit(counter.INCREMENT) 36 | } 37 | }, 38 | incrementAsync ({ commit, state }: any): Promise { 39 | return new Promise((resolve, reject) => { 40 | setTimeout(() => { 41 | commit(counter.INCREMENT) 42 | resolve(state.count) 43 | }, 1000) 44 | }) 45 | } 46 | } 47 | 48 | // getters are functions. 49 | const getters = { 50 | evenOrOdd: (state: State) => state.count % 2 === 0 ? 'even' : 'odd' 51 | } 52 | 53 | // nested modules 54 | // const modules = { 55 | 56 | // } 57 | 58 | export default { 59 | namespaced: true, 60 | state, 61 | getters, 62 | actions, 63 | mutations 64 | // modules 65 | } 66 | -------------------------------------------------------------------------------- /examples/vue2-demo/src/store/modules/index.ts: -------------------------------------------------------------------------------- 1 | const files = require.context('.', false, /\.ts$/) 2 | const modules = {} as any 3 | 4 | files.keys().forEach((key) => { 5 | if (key === './index.ts') return 6 | modules[key.replace(/(\.\/|\.ts)/g, '')] = files(key).default 7 | }) 8 | 9 | export default modules 10 | -------------------------------------------------------------------------------- /examples/vue2-demo/src/store/mutation-types.ts: -------------------------------------------------------------------------------- 1 | export const SET_STATE = 'SET_STATE' 2 | export const SET_THEME = 'SET_THEME' 3 | 4 | // counter moudle 5 | export const counter = { 6 | SET_COUNTER_STATE: 'SET_COUNTER_STATE', 7 | INCREMENT: 'INCREMENT', 8 | DECREMENT: 'DECREMENT' 9 | } 10 | -------------------------------------------------------------------------------- /examples/vue2-demo/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es5", 4 | "module": "esnext", 5 | "strict": true, 6 | "jsx": "preserve", 7 | "importHelpers": true, 8 | "moduleResolution": "node", 9 | "skipLibCheck": true, 10 | "esModuleInterop": true, 11 | "allowSyntheticDefaultImports": true, 12 | "sourceMap": true, 13 | "baseUrl": ".", 14 | "types": [ 15 | "webpack-env" 16 | ], 17 | "paths": { 18 | "@/*": [ 19 | "src/*" 20 | ] 21 | }, 22 | "lib": [ 23 | "esnext", 24 | "dom", 25 | "dom.iterable", 26 | "scripthost" 27 | ] 28 | }, 29 | "include": [ 30 | "src/**/*.ts", 31 | "src/**/*.tsx", 32 | "src/**/*.vue", 33 | "tests/**/*.ts", 34 | "tests/**/*.tsx" 35 | ], 36 | "exclude": [ 37 | "node_modules" 38 | ] 39 | } 40 | -------------------------------------------------------------------------------- /examples/vue3-demo/.editorconfig: -------------------------------------------------------------------------------- 1 | [*.{js,jsx,ts,tsx,vue}] 2 | indent_style = space 3 | indent_size = 2 4 | trim_trailing_whitespace = true 5 | insert_final_newline = true 6 | -------------------------------------------------------------------------------- /examples/vue3-demo/.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules 3 | /dist 4 | 5 | 6 | # local env files 7 | .env.local 8 | .env.*.local 9 | 10 | # Log files 11 | npm-debug.log* 12 | yarn-debug.log* 13 | yarn-error.log* 14 | pnpm-debug.log* 15 | 16 | # Editor directories and files 17 | .idea 18 | .vscode 19 | *.suo 20 | *.ntvs* 21 | *.njsproj 22 | *.sln 23 | *.sw? 24 | -------------------------------------------------------------------------------- /examples/vue3-demo/README.md: -------------------------------------------------------------------------------- 1 | # vue3-ts 2 | 3 | ## Project setup 4 | ``` 5 | yarn install 6 | ``` 7 | 8 | ### Compiles and hot-reloads for development 9 | ``` 10 | yarn serve 11 | ``` 12 | 13 | ### Compiles and minifies for production 14 | ``` 15 | yarn build 16 | ``` 17 | 18 | ### Lints and fixes files 19 | ``` 20 | yarn lint 21 | ``` 22 | 23 | ### Customize configuration 24 | See [Configuration Reference](https://cli.vuejs.org/config/). 25 | -------------------------------------------------------------------------------- /examples/vue3-demo/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "vue3-ts", 3 | "version": "0.1.0", 4 | "private": true, 5 | "scripts": { 6 | "serve": "vue-cli-service serve", 7 | "build": "vue-cli-service build", 8 | "lint": "vue-cli-service lint" 9 | }, 10 | "dependencies": { 11 | "@vueblocks/vue-use-core": "^0.2.11", 12 | "@vueblocks/vue-use-vuex": "^0.2.11", 13 | "vue": "^3.0.0", 14 | "vuex": "^4.0.2" 15 | }, 16 | "devDependencies": { 17 | "@typescript-eslint/eslint-plugin": "^4.18.0", 18 | "@typescript-eslint/parser": "^4.18.0", 19 | "@vue/cli-plugin-eslint": "~4.5.0", 20 | "@vue/cli-plugin-typescript": "~4.5.0", 21 | "@vue/cli-plugin-vuex": "~4.5.0", 22 | "@vue/cli-service": "~4.5.0", 23 | "@vue/compiler-sfc": "^3.0.0", 24 | "@vue/eslint-config-standard": "^5.1.2", 25 | "@vue/eslint-config-typescript": "^7.0.0", 26 | "eslint": "^6.7.2", 27 | "eslint-plugin-import": "^2.20.2", 28 | "eslint-plugin-node": "^11.1.0", 29 | "eslint-plugin-promise": "^4.2.1", 30 | "eslint-plugin-standard": "^4.0.0", 31 | "eslint-plugin-vue": "^7.0.0", 32 | "sass": "^1.26.5", 33 | "sass-loader": "^8.0.2", 34 | "typescript": "~4.1.5" 35 | }, 36 | "eslintConfig": { 37 | "root": true, 38 | "env": { 39 | "node": true 40 | }, 41 | "extends": [ 42 | "plugin:vue/vue3-essential", 43 | "@vue/standard", 44 | "@vue/typescript/recommended" 45 | ], 46 | "parserOptions": { 47 | "ecmaVersion": 2020 48 | }, 49 | "rules": {} 50 | }, 51 | "browserslist": [ 52 | "> 1%", 53 | "last 2 versions", 54 | "not dead" 55 | ] 56 | } 57 | -------------------------------------------------------------------------------- /examples/vue3-demo/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vueblocks/vue-use-utilities/15cfbd077848c55c82e52cd094ea1fcf644b6cf1/examples/vue3-demo/public/favicon.ico -------------------------------------------------------------------------------- /examples/vue3-demo/public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | <%= htmlWebpackPlugin.options.title %> 9 | 10 | 11 | 14 |
15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /examples/vue3-demo/src/App.vue: -------------------------------------------------------------------------------- 1 | 5 | 6 | 19 | 20 | 30 | -------------------------------------------------------------------------------- /examples/vue3-demo/src/assets/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vueblocks/vue-use-utilities/15cfbd077848c55c82e52cd094ea1fcf644b6cf1/examples/vue3-demo/src/assets/logo.png -------------------------------------------------------------------------------- /examples/vue3-demo/src/components/Counter.vue: -------------------------------------------------------------------------------- 1 | 14 | 15 | 77 | -------------------------------------------------------------------------------- /examples/vue3-demo/src/components/HelloWorld.vue: -------------------------------------------------------------------------------- 1 | 11 | 12 | 32 | 33 | 34 | 50 | -------------------------------------------------------------------------------- /examples/vue3-demo/src/main.ts: -------------------------------------------------------------------------------- 1 | import { createApp } from 'vue' 2 | import App from './App.vue' 3 | import store from './store' 4 | 5 | createApp(App).use(store).mount('#app') 6 | -------------------------------------------------------------------------------- /examples/vue3-demo/src/shims-vue.d.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable */ 2 | declare module '*.vue' { 3 | import type { DefineComponent } from 'vue' 4 | const component: DefineComponent<{}, {}, any> 5 | export default component 6 | } 7 | -------------------------------------------------------------------------------- /examples/vue3-demo/src/store/actions.ts: -------------------------------------------------------------------------------- 1 | const makeAction = (type: string) => { 2 | return (payload: any, ...args: any) => { 3 | const { commit } = payload 4 | return commit(type, ...args) 5 | } 6 | } 7 | 8 | export const makeActions = (types: any = {}) => { 9 | const actions = {} 10 | 11 | for (const type of Object.keys(types)) { 12 | const action = { 13 | [type]: makeAction(types[type]) 14 | } 15 | Object.assign(actions, action) 16 | } 17 | 18 | return actions 19 | } 20 | 21 | export const setState = makeAction('SET_STATE') 22 | -------------------------------------------------------------------------------- /examples/vue3-demo/src/store/index.ts: -------------------------------------------------------------------------------- 1 | import { createStore } from 'vuex' 2 | 3 | import * as actions from './actions' 4 | import * as types from './mutation-types' 5 | import modules from './modules/index' 6 | 7 | const state = { 8 | theme: 'light' 9 | } 10 | 11 | type RootState = typeof state 12 | 13 | const getters = { 14 | isDarkmode: (state: RootState) => state.theme === 'dark' 15 | } 16 | 17 | const mutations = { 18 | [types.SET_STATE] (state: RootState, payload: any) { 19 | Object.assign(state, payload) 20 | }, 21 | [types.SET_THEME] (state: RootState, payload: any) { 22 | state.theme = payload 23 | } 24 | } 25 | 26 | // A Vuex instance is created by combining the state, mutations, actions, 27 | // and getters. 28 | export default createStore({ 29 | state, 30 | getters, 31 | actions, 32 | mutations, 33 | modules 34 | }) 35 | -------------------------------------------------------------------------------- /examples/vue3-demo/src/store/modules/counter.ts: -------------------------------------------------------------------------------- 1 | import { makeActions } from '../actions' 2 | import { counter } from '../mutation-types' 3 | 4 | // namespaced counter state object. 5 | // each Vuex instance is just a single state tree. 6 | const state = { 7 | count: 0 8 | } 9 | 10 | type State = typeof state 11 | 12 | // mutations are operations that actually mutate the state. 13 | // each mutation handler gets the entire state tree as the 14 | // first argument, followed by additional payload arguments. 15 | // mutations must be synchronous and can be recorded by plugins 16 | // for debugging purposes. 17 | const mutations = { 18 | [counter.INCREMENT] (state: State): void { 19 | state.count++ 20 | }, 21 | [counter.DECREMENT] (state: State): void { 22 | state.count-- 23 | } 24 | } 25 | 26 | // actions are functions that cause side effects and can involve 27 | // asynchronous operations. 28 | const actions = { 29 | ...makeActions({ 30 | increment: counter.INCREMENT, 31 | decrement: counter.DECREMENT 32 | }), 33 | incrementIfOdd ({ commit, state }: any): void { 34 | if ((state.count + 1) % 2 === 0) { 35 | commit(counter.INCREMENT) 36 | } 37 | }, 38 | incrementAsync ({ commit, state }: any): Promise { 39 | return new Promise((resolve, reject) => { 40 | setTimeout(() => { 41 | commit(counter.INCREMENT) 42 | resolve(state.count) 43 | }, 1000) 44 | }) 45 | } 46 | } 47 | 48 | // getters are functions. 49 | const getters = { 50 | evenOrOdd: (state: State) => state.count % 2 === 0 ? 'even' : 'odd' 51 | } 52 | 53 | // nested modules 54 | // const modules = { 55 | 56 | // } 57 | 58 | export default { 59 | namespaced: true, 60 | state, 61 | getters, 62 | actions, 63 | mutations 64 | // modules 65 | } 66 | -------------------------------------------------------------------------------- /examples/vue3-demo/src/store/modules/index.ts: -------------------------------------------------------------------------------- 1 | const files = require.context('.', false, /\.ts$/) 2 | const modules = {} as any 3 | 4 | files.keys().forEach((key) => { 5 | if (key === './index.ts') return 6 | modules[key.replace(/(\.\/|\.ts)/g, '')] = files(key).default 7 | }) 8 | 9 | export default modules 10 | -------------------------------------------------------------------------------- /examples/vue3-demo/src/store/mutation-types.ts: -------------------------------------------------------------------------------- 1 | export const SET_STATE = 'SET_STATE' 2 | export const SET_THEME = 'SET_THEME' 3 | 4 | // counter moudle 5 | export const counter = { 6 | SET_COUNTER_STATE: 'SET_COUNTER_STATE', 7 | INCREMENT: 'INCREMENT', 8 | DECREMENT: 'DECREMENT' 9 | } 10 | -------------------------------------------------------------------------------- /examples/vue3-demo/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es5", 4 | "module": "esnext", 5 | "strict": true, 6 | "jsx": "preserve", 7 | "importHelpers": true, 8 | "moduleResolution": "node", 9 | "skipLibCheck": true, 10 | "esModuleInterop": true, 11 | "allowSyntheticDefaultImports": true, 12 | "sourceMap": true, 13 | "baseUrl": ".", 14 | "types": [ 15 | "webpack-env" 16 | ], 17 | "paths": { 18 | "@/*": [ 19 | "src/*" 20 | ] 21 | }, 22 | "lib": [ 23 | "esnext", 24 | "dom", 25 | "dom.iterable", 26 | "scripthost" 27 | ] 28 | }, 29 | "include": [ 30 | "src/**/*.ts", 31 | "src/**/*.tsx", 32 | "src/**/*.vue", 33 | "tests/**/*.ts", 34 | "tests/**/*.tsx" 35 | ], 36 | "exclude": [ 37 | "node_modules" 38 | ] 39 | } 40 | -------------------------------------------------------------------------------- /jest.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | roots: [ 3 | '/packages', 4 | ], 5 | setupFiles: [ 6 | "/__tests__/setupTest.ts" 7 | ], 8 | testMatch: [ 9 | '**/__tests__/**/*.+(ts|tsx|js)', 10 | '**/?(*.)+(spec|test).+(ts|tsx|js)', 11 | ], 12 | transform: { 13 | '^.+\\.(ts|tsx)$': 'ts-jest', 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /lerna.json: -------------------------------------------------------------------------------- 1 | { 2 | "lerna": "3.22.1", 3 | "packages": [ 4 | "packages/*" 5 | ], 6 | "command": { 7 | "publish": { 8 | "message": "chore(release): publish" 9 | } 10 | }, 11 | "version": "0.2.11" 12 | } 13 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@vueblocks/vue-use-utilities", 3 | "version": "0.2.10", 4 | "description": "A collection of Vue composition-api utilities", 5 | "scripts": { 6 | "docs:dev:v2": "npm run dev --prefix docs/v2", 7 | "docs:dev:v3": "npm run dev --prefix docs/v3", 8 | "docs:build:v2": "npm run build --prefix docs/v2", 9 | "docs:build:v3": "npm run build --prefix docs/v3", 10 | "docs:deploy": "sh deploy.sh", 11 | "build": "rollup -c rollup.config.js", 12 | "release": "lerna publish", 13 | "test": "jest --coverage", 14 | "changelog": "conventional-changelog -p angular -i CHANGELOG.md -s -r 1" 15 | }, 16 | "sideEffects": false, 17 | "devDependencies": { 18 | "@rollup/plugin-replace": "^3.0.0", 19 | "@types/jest": "^26.0.20", 20 | "@types/node": "^16.4.0", 21 | "@vue/test-utils": "^1.2.1", 22 | "esbuild": "^0.8.29", 23 | "esbuild-register": "^1.2.1", 24 | "eslint": "^7.17.0", 25 | "eslint-plugin-jest": "^24.1.3", 26 | "esm": "^3.2.25", 27 | "jest": "^26.6.3", 28 | "lerna": "^3.22.1", 29 | "rollup": "^2.40.0", 30 | "rollup-plugin-dts": "^2.0.1", 31 | "rollup-plugin-filesize": "^9.1.1", 32 | "rollup-plugin-terser": "^7.0.2", 33 | "rollup-plugin-typescript2": "^0.29.0", 34 | "ts-jest": "^26.5.3", 35 | "typescript": "^4.2.3" 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /packages/axios/README.md: -------------------------------------------------------------------------------- 1 | # @vueblocks/vue-use-axios 2 | 3 | > Use Axios With Composition API Easily. 4 | 5 | ## Install 6 | 7 | ```bash 8 | yarn add @vueblocks/vue-use-axios 9 | ``` 10 | 11 | ## Usage 12 | 13 | `useAxios` is a wrapper of Axios 14 | 15 | ```js 16 | import { useAxios } from '@vueblocks/vue-use-axios' 17 | 18 | export default { 19 | ... 20 | setup () { 21 | const url = 'https://api.coindesk.com/v1/bpi/currentprice.json' 22 | 23 | const { refetch, data } = useAxios(url) 24 | 25 | const fetchBitcoinPrice = () => { 26 | setInterval(() => { 27 | refetch() 28 | }, 20000) 29 | } 30 | 31 | return { 32 | data, 33 | fetchBitcoinPrice 34 | } 35 | } 36 | ... 37 | } 38 | ``` 39 | 40 | ## License 41 | 42 | MIT [@xiaoluoboding](https://github.com/xiaoluoboding) 43 | -------------------------------------------------------------------------------- /packages/axios/index.ts: -------------------------------------------------------------------------------- 1 | export * from './useAxios' 2 | -------------------------------------------------------------------------------- /packages/axios/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@vueblocks/vue-use-axios", 3 | "description": "Use Axios With Composition API Easily.", 4 | "version": "0.2.11", 5 | "main": "lib/index.cjs.js", 6 | "types": "lib/index.d.ts", 7 | "module": "lib/index.esm.js", 8 | "unpkg": "lib/index.umd.min.js", 9 | "jsdelivr": "lib/index.umd.min.js", 10 | "files": [ 11 | "lib" 12 | ], 13 | "publishConfig": { 14 | "access": "public" 15 | }, 16 | "repository": { 17 | "type": "git", 18 | "url": "git+https://github.com/vueblocks/vue-use-utilities.git" 19 | }, 20 | "homepage": "https://github.com/vueblocks/vue-use-utilities", 21 | "keywords": [ 22 | "vue", 23 | "vue-use", 24 | "axios", 25 | "composition-api", 26 | "utilities" 27 | ], 28 | "author": "xiaoluoboding", 29 | "license": "MIT", 30 | "sideEffects": false, 31 | "peerDependenciesMeta": { 32 | "@vue/composition-api": { 33 | "optional": true 34 | } 35 | }, 36 | "peerDependencies": { 37 | "@vue/composition-api": "^1.2.4", 38 | "axios": "^0.21.0", 39 | "vue": "^2.6.14 || ^3.2.0" 40 | }, 41 | "dependencies": { 42 | "@vue/composition-api": "^1.2.4", 43 | "axios": "^0.24.0", 44 | "lodash.debounce": "^4.0.8", 45 | "lodash.throttle": "^4.1.1", 46 | "vue-demi": "0.10.0" 47 | }, 48 | "devDependencies": { 49 | "@types/lodash.debounce": "^4.0.6", 50 | "@types/lodash.throttle": "^4.1.6", 51 | "@vue/compiler-sfc": "^3.2.20", 52 | "vue": "^3.2.20", 53 | "vue2": "npm:vue@2" 54 | }, 55 | "gitHead": "19fec27b41f71b70a73f0afd37180c39bb362827" 56 | } 57 | -------------------------------------------------------------------------------- /packages/axios/useAxios.ts: -------------------------------------------------------------------------------- 1 | import { reactive, toRefs } from 'vue-demi' 2 | import axios, { 3 | AxiosError, 4 | AxiosRequestConfig, 5 | AxiosResponse, 6 | CancelTokenSource 7 | } from 'axios' 8 | import debounce from 'lodash.debounce' 9 | import throttle from 'lodash.throttle' 10 | 11 | interface IAxiosState { 12 | response: any 13 | data: any 14 | finished: boolean 15 | canceled: boolean 16 | error: any 17 | } 18 | 19 | interface IAxiosOptions { 20 | debounce?: number 21 | throttle?: number 22 | } 23 | 24 | const state = reactive({ 25 | response: null, 26 | data: undefined, 27 | finished: false, 28 | canceled: false, 29 | error: null 30 | }) 31 | 32 | const request = (url: string, config?: AxiosRequestConfig, options?: IAxiosOptions) => { 33 | axios(url, config) 34 | .then((r: AxiosResponse) => { 35 | state.response = r 36 | state.data = r.data 37 | state.finished = true 38 | }) 39 | .catch((e: AxiosError) => { 40 | state.error = e 41 | state.finished = true 42 | }) 43 | } 44 | 45 | const useAxios = ( 46 | url: string, 47 | config?: AxiosRequestConfig, 48 | options?: IAxiosOptions 49 | ) => { 50 | // handle cancel request 51 | const cancelToken: CancelTokenSource = axios.CancelToken.source() 52 | const cancel = (message?: string) => { 53 | cancelToken.cancel(message) 54 | state.canceled = true 55 | } 56 | 57 | let axiosConfig: AxiosRequestConfig = { 58 | ...config, 59 | cancelToken: cancelToken.token 60 | } 61 | 62 | let refetch 63 | if (options && options.debounce && options.debounce > 0) { 64 | refetch = debounce(() => request(url, axiosConfig, options), options.debounce) 65 | } else if (options && options.throttle && options.throttle > 0) { 66 | refetch = throttle(() => request(url, axiosConfig, options), options.throttle) 67 | } else { 68 | refetch = () => request(url, axiosConfig, options) 69 | } 70 | 71 | refetch() 72 | 73 | return { 74 | ...toRefs(state), 75 | refetch, 76 | cancel 77 | } 78 | } 79 | 80 | export { useAxios } 81 | -------------------------------------------------------------------------------- /packages/core/README.md: -------------------------------------------------------------------------------- 1 | # @vueblocks/vue-use-core 2 | 3 | > A Collection of Vue Compositon API Utilities. 4 | 5 | ## Install 6 | 7 | ```bash 8 | # Vue 2 with @vue/composition-api 9 | yarn add @vue/composition-api @vueblocks/vue-use-core -S 10 | or 11 | npm i @vue/composition-api @vueblocks/vue-use-core -S 12 | 13 | # Vue 3 14 | yarn add @vueblocks/vue-use-core -S 15 | or 16 | npm i @vueblocks/vue-use-core -S 17 | ``` 18 | 19 | ## Usage 20 | 21 | ```js 22 | import { useMouse } from '@vueblocks/vue-use-core' 23 | 24 | export default { 25 | setup () { 26 | const { x, y, remove } = useMouse() 27 | 28 | return { 29 | x, 30 | y 31 | } 32 | } 33 | } 34 | ``` 35 | 36 | ## License 37 | 38 | MIT [@xiaoluoboding](https://github.com/xiaoluoboding) 39 | -------------------------------------------------------------------------------- /packages/core/__test__/useDebouncedRef.spec.ts: -------------------------------------------------------------------------------- 1 | import { renderHook } from '../../../__tests__/setupTest' 2 | import { useDebouncedRef } from '../useDebouncedRef' 3 | 4 | test('useDebouncedRef', () => { 5 | renderHook(() => {}) 6 | const debouncedValue = useDebouncedRef('before', 1000) 7 | expect(debouncedValue.value).toEqual('before') 8 | debouncedValue.value = 'after1' 9 | debouncedValue.value = 'after2' 10 | debouncedValue.value = 'after3' 11 | debouncedValue.value = 'after4' 12 | debouncedValue.value = 'after5' 13 | expect(debouncedValue.value).toEqual('before') 14 | setTimeout(() => { 15 | expect(debouncedValue.value).toEqual('after5') 16 | }, 1000) 17 | }) -------------------------------------------------------------------------------- /packages/core/__test__/usePrecision.spec.ts: -------------------------------------------------------------------------------- 1 | import { ref, reactive } from 'vue-demi' 2 | 3 | import { renderHook } from '../../../__tests__/setupTest' 4 | import { usePrecision } from '../usePrecision' 5 | 6 | test('usePrecision', () => { 7 | renderHook(() => {}) 8 | const { strip, plus, minus, times, divide, round } = usePrecision() 9 | 10 | const [plusA, plusB] = [ref(0.1), ref(0.2)] 11 | const [minusA, minusB] = [ref(1.0), ref(0.9)] 12 | const [timesA, timesB] = [ref(7), ref(0.2)] 13 | const [divideA, divideB] = [ref(1.21), ref(1.1)] 14 | const roundA = ref(0.105) 15 | 16 | const localState = reactive({ 17 | plusResult: plus(plusA, plusB), 18 | minusResult: minus(minusA, minusB), 19 | timesResult: times(timesA, timesB), 20 | divideResult: divide(divideA, divideB), 21 | roundResult: round(roundA, 2), 22 | stripResult: strip(0.1 + 0.2) 23 | }) 24 | 25 | expect(localState.plusResult).toEqual(0.3) 26 | expect(localState.minusResult).toEqual(0.1) 27 | expect(localState.timesResult).toEqual(1.4) 28 | expect(localState.divideResult).toEqual(1.1) 29 | expect(localState.roundResult).toEqual(0.11) 30 | expect(localState.stripResult).toEqual(0.3) 31 | 32 | plusA.value = 2.3 33 | plusB.value = 2.4 34 | expect(localState.plusResult).toEqual(4.7) 35 | timesA.value = 3 36 | timesB.value = 0.3 37 | expect(localState.timesResult).toEqual(0.9) 38 | }) -------------------------------------------------------------------------------- /packages/core/index.ts: -------------------------------------------------------------------------------- 1 | export * from './useClipboard' 2 | export * from './useCssVars' 3 | export * from './useColor' 4 | export * from './useDebouncedRef' 5 | export * from './useElementSize' 6 | // export * from './useEmitter' 7 | export * from './useEventListener' 8 | export * from './useFullscreen' 9 | export * from './useInstance' 10 | export * from './useLifecycle' 11 | export * from './useMouse' 12 | export * from './usePrecision' 13 | export * from './useReactiveState' 14 | export * from './useResizeEvent' 15 | export * from './useShortcut' 16 | export * from './useStateshot' 17 | export * from './useResizeObserver' 18 | export * from './useWindowSize' 19 | export { reactiveFn } from './utils' 20 | -------------------------------------------------------------------------------- /packages/core/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@vueblocks/vue-use-core", 3 | "description": "A Collection of Vue Compositon API Utilities.", 4 | "version": "0.2.11", 5 | "main": "lib/index.cjs.js", 6 | "types": "lib/index.d.ts", 7 | "module": "lib/index.esm.js", 8 | "unpkg": "lib/index.umd.min.js", 9 | "jsdelivr": "lib/index.umd.min.js", 10 | "files": [ 11 | "lib" 12 | ], 13 | "publishConfig": { 14 | "access": "public" 15 | }, 16 | "repository": { 17 | "type": "git", 18 | "url": "git+https://github.com/vueblocks/vue-use-utilities.git" 19 | }, 20 | "homepage": "https://github.com/vueblocks/vue-use-utilities", 21 | "keywords": [ 22 | "vue", 23 | "vue-use", 24 | "composition-api", 25 | "utilities" 26 | ], 27 | "author": "xiaoluoboding", 28 | "license": "MIT", 29 | "sideEffects": false, 30 | "peerDependenciesMeta": { 31 | "@vue/composition-api": { 32 | "optional": true 33 | } 34 | }, 35 | "peerDependencies": { 36 | "@vue/composition-api": "^1.2.4", 37 | "vue": "^2.6.14 || ^3.2.0" 38 | }, 39 | "dependencies": { 40 | "@juggle/resize-observer": "^3.2.0", 41 | "@vue/composition-api": "^1.2.4", 42 | "color2k": "^1.2.4", 43 | "keymaster": "^1.6.2", 44 | "lodash.clonedeep": "^4.5.0", 45 | "lodash.debounce": "^4.0.8", 46 | "lodash.throttle": "^4.1.1", 47 | "number-precision": "^1.5.0", 48 | "screenfull": "^5.1.0", 49 | "stateshot": "^1.3.3", 50 | "vue-demi": "0.10.0" 51 | }, 52 | "devDependencies": { 53 | "@types/keymaster": "^1.6.30", 54 | "@types/lodash.clonedeep": "^4.5.6", 55 | "@types/lodash.debounce": "^4.0.6", 56 | "@types/lodash.throttle": "^4.1.6", 57 | "@vue/compiler-sfc": "^3.2.20", 58 | "vue": "^3.2.20", 59 | "vue2": "npm:vue@2" 60 | }, 61 | "gitHead": "19fec27b41f71b70a73f0afd37180c39bb362827" 62 | } 63 | -------------------------------------------------------------------------------- /packages/core/types/color.ts: -------------------------------------------------------------------------------- 1 | import { ComputedRef } from 'vue-demi' 2 | 3 | export interface ReactiveColor { 4 | hexColor: ComputedRef; 5 | hslaColor: ComputedRef; 6 | rgbaColor: ComputedRef; 7 | readableColor: ComputedRef; 8 | invertColor: ComputedRef; 9 | luminance: ComputedRef; 10 | lightenColor: ComputedRef; 11 | darkenColor: ComputedRef; 12 | tintColor: ComputedRef; 13 | shadeColor: ComputedRef; 14 | desaturateColor: ComputedRef; 15 | saturateColor: ComputedRef; 16 | opacifyColor: ComputedRef; 17 | transparentizeColor: ComputedRef; 18 | } 19 | 20 | /** 21 | * @property {number} hue 22 | * @property {number} saturation 23 | * @property {number} lightness 24 | */ 25 | export type HslColor = { 26 | hue: number, 27 | saturation: number, 28 | lightness: number, 29 | } 30 | 31 | /** 32 | * @property {number} hue 33 | * @property {number} saturation 34 | * @property {number} lightness 35 | * @property {number} alpha 36 | */ 37 | export type HslaColor = { 38 | hue: number, 39 | saturation: number, 40 | lightness: number, 41 | alpha: number, 42 | } 43 | 44 | /** 45 | * @property {number} red 46 | * @property {number} green 47 | * @property {number} blue 48 | */ 49 | export type RgbColor = { 50 | red: number, 51 | green: number, 52 | blue: number, 53 | } 54 | 55 | /** 56 | * @property {number} red 57 | * @property {number} green 58 | * @property {number} blue 59 | * @property {number} alpha 60 | */ 61 | export type RgbaColor = { 62 | red: number, 63 | green: number, 64 | blue: number, 65 | alpha: number, 66 | } 67 | -------------------------------------------------------------------------------- /packages/core/types/common.ts: -------------------------------------------------------------------------------- 1 | import type { History } from 'stateshot' 2 | 3 | export type Fn = () => void 4 | 5 | export interface IHistory extends History { 6 | $chunks?: object; 7 | 8 | $records?: Array; 9 | 10 | $index?: number; 11 | 12 | $debounceTime?: any; 13 | 14 | $pending?: object; 15 | } 16 | -------------------------------------------------------------------------------- /packages/core/types/dom.ts: -------------------------------------------------------------------------------- 1 | import { Ref } from 'vue-demi' 2 | 3 | export interface Coordinates { 4 | x: Ref; 5 | y: Ref; 6 | } 7 | export interface WindowSize { 8 | width: Ref; 9 | height: Ref; 10 | } 11 | 12 | export interface ElementSize extends WindowSize {} 13 | 14 | export interface EventOptions { 15 | useCapture?: boolean; 16 | useThrottle?: boolean | null; 17 | delay?: number; 18 | } 19 | -------------------------------------------------------------------------------- /packages/core/types/index.ts: -------------------------------------------------------------------------------- 1 | export type { 2 | Fn 3 | } from './common' 4 | 5 | export * from './ref' 6 | 7 | export type { 8 | ResizeObserverSize, 9 | ResizeObserverEntry, 10 | ResizeObserverOptions, 11 | ResizeObserverCallback 12 | } from './resize-observer' 13 | 14 | export type { 15 | WindowSize, 16 | ElementSize, 17 | EventOptions 18 | } from './dom' 19 | 20 | export type { 21 | ReactiveColor, 22 | HslColor, 23 | HslaColor, 24 | RgbColor, 25 | RgbaColor 26 | } from './color' 27 | 28 | export * from './stateshot' 29 | -------------------------------------------------------------------------------- /packages/core/types/ref.ts: -------------------------------------------------------------------------------- 1 | import { defineComponent, Ref, ComputedRef } from 'vue-demi' 2 | 3 | export type RefTyped = T | Ref 4 | export type RefTypedElement = RefTyped 5 | export type RefElement = Element | Ref 6 | export type ToRefs = { [K in keyof T]: Ref } 7 | export type ReactiveFn = T extends (...args: infer A) => infer R 8 | ? (...args: { [K in keyof A]: RefTyped }) => ComputedRef 9 | : never 10 | 11 | export type VueInstance = InstanceType> 12 | -------------------------------------------------------------------------------- /packages/core/types/resize-observer.ts: -------------------------------------------------------------------------------- 1 | import { ResizeObserver } from '@juggle/resize-observer' 2 | 3 | /** 4 | * Size of a specific box. 5 | * 6 | * https://drafts.csswg.org/resize-observer-1/#resizeobserversize 7 | */ 8 | interface ResizeObserverSize { 9 | readonly inlineSize: number; 10 | readonly blockSize: number; 11 | } 12 | 13 | /** 14 | * Used to observe different box sizes. 15 | * 16 | * https://drafts.csswg.org/resize-observer-1/#enumdef-resizeobserverboxoptions 17 | */ 18 | enum ResizeObserverBoxOptions { 19 | BORDER_BOX = 'border-box', 20 | CONTENT_BOX = 'content-box', 21 | DEVICE_PIXEL_CONTENT_BOX = 'device-pixel-content-box' 22 | } 23 | 24 | /** 25 | * Options to be given to the resize observer, 26 | * when observing a new element. 27 | * 28 | * https://drafts.csswg.org/resize-observer-1/#dictdef-resizeobserveroptions 29 | */ 30 | interface ResizeObserverOptions { 31 | box?: 'content-box' | 'border-box' | 'device-pixel-content-box' | ResizeObserverBoxOptions; 32 | } 33 | 34 | /** 35 | * https://drafts.csswg.org/resize-observer-1/#resize-observer-entry-interface 36 | */ 37 | interface ResizeObserverEntry { 38 | readonly target: Element 39 | readonly contentRect: DOMRectReadOnly 40 | readonly borderBoxSize?: ReadonlyArray 41 | readonly contentBoxSize?: ReadonlyArray 42 | readonly devicePixelContentBoxSize?: ReadonlyArray 43 | } 44 | 45 | /** 46 | * https://drafts.csswg.org/resize-observer-1/#resize-observer-callback 47 | */ 48 | type ResizeObserverCallback = (entries: ReadonlyArray, observer: ResizeObserver) => void; 49 | 50 | export { 51 | ResizeObserverSize, 52 | ResizeObserverOptions, 53 | ResizeObserverEntry, 54 | ResizeObserverCallback 55 | } 56 | -------------------------------------------------------------------------------- /packages/core/types/stateshot.ts: -------------------------------------------------------------------------------- 1 | import type { History } from 'stateshot' 2 | import type { Ref } from 'vue-demi' 3 | 4 | export interface IHistory extends History { 5 | $chunks?: object; 6 | 7 | $records?: Array; 8 | 9 | $index?: number; 10 | 11 | $debounceTime?: any; 12 | 13 | $pending?: object; 14 | } 15 | 16 | export interface StateshotStore { 17 | historyState: Ref; 18 | historyLength: Ref; 19 | hasRedo: Ref; 20 | hasUndo: Ref; 21 | undoCount: Ref; 22 | redoCount: Ref; 23 | } 24 | -------------------------------------------------------------------------------- /packages/core/useClipboard/index.ts: -------------------------------------------------------------------------------- 1 | import { ref, unref, Ref } from 'vue-demi' 2 | import { NOOP } from '../utils' 3 | 4 | export interface ClipboardOption { 5 | source?: string 6 | during?: number 7 | } 8 | 9 | export interface ClipboardResult { 10 | text: Ref 11 | copy: typeof NOOP 12 | clear: typeof NOOP 13 | copied: Ref 14 | isSupported: Ref 15 | } 16 | 17 | /** 18 | * A Reactive Clipboard API 19 | * @param options 20 | * @returns 21 | */ 22 | const useClipboard = (options: ClipboardOption = {}): ClipboardResult => { 23 | const { 24 | source = '', 25 | during = 2000 26 | } = options 27 | 28 | const text = ref('') 29 | const copied = ref(false) 30 | const timer = ref() 31 | const isSupported = ref(false) 32 | 33 | isSupported.value = Boolean(typeof navigator !== 'undefined' && navigator.clipboard) 34 | 35 | const handleCopyText = (isCopied: boolean) => { 36 | clearTimeout(timer.value) 37 | timer.value = setTimeout(() => { 38 | copied.value = false 39 | }, during) 40 | copied.value = isCopied 41 | } 42 | 43 | const copy = () => { 44 | const valueToCopy = unref(source) 45 | if (isSupported) { 46 | navigator.clipboard 47 | .writeText(valueToCopy) 48 | .then(() => { 49 | text.value = valueToCopy 50 | handleCopyText(true) 51 | }) 52 | .catch((err) => { 53 | console.log('Something went wrong', err) 54 | }) 55 | } 56 | } 57 | 58 | const clear = () => { 59 | text.value = '' 60 | copied.value = false 61 | clearTimeout(timer.value) 62 | if (isSupported) { 63 | navigator.clipboard.writeText('') 64 | } 65 | } 66 | 67 | return { 68 | text, 69 | copy, 70 | clear, 71 | copied, 72 | isSupported 73 | } 74 | } 75 | 76 | export { useClipboard } 77 | -------------------------------------------------------------------------------- /packages/core/useCssVars/index.ts: -------------------------------------------------------------------------------- 1 | import { Ref, ref, watch } from 'vue-demi' 2 | import { RefTyped } from '../types' 3 | 4 | const cssVariableRegex = /--[\S]*/g 5 | 6 | const useCssVars = ( 7 | el: RefTyped, 8 | variable: string, 9 | defaultValue: string 10 | ): Ref => { 11 | if (!variable || !variable.match(cssVariableRegex)) { 12 | console.warn(`[useCssVars] css variable is not valid: ${variable}`) 13 | } 14 | 15 | const propertyValue = ref('') 16 | const target = ref(el || window.document.documentElement) 17 | 18 | watch( 19 | target, 20 | (el) => { 21 | if (window && el) { 22 | const propValue = window.getComputedStyle(el).getPropertyValue(variable) || defaultValue || '' 23 | propertyValue.value = propValue 24 | } 25 | }, 26 | { immediate: true } 27 | ) 28 | 29 | watch( 30 | propertyValue, 31 | (newVal) => { 32 | if (target.value && target.value.style) { 33 | target.value.style.setProperty(variable, newVal) 34 | } 35 | } 36 | ) 37 | 38 | return propertyValue 39 | } 40 | 41 | export { useCssVars } 42 | -------------------------------------------------------------------------------- /packages/core/useDebouncedRef/index.ts: -------------------------------------------------------------------------------- 1 | import { customRef, Ref } from 'vue-demi' 2 | import debounce from 'lodash.debounce' 3 | 4 | const useDebouncedRef = (value: any, delay = 200): Ref => { 5 | return customRef((track, trigger) => { 6 | return { 7 | get() { 8 | track() 9 | return value 10 | }, 11 | set: debounce((newValue) => { 12 | value = newValue 13 | trigger() 14 | }, delay) 15 | } 16 | }) 17 | } 18 | 19 | export { useDebouncedRef } 20 | -------------------------------------------------------------------------------- /packages/core/useElementSize/index.ts: -------------------------------------------------------------------------------- 1 | import { ref } from 'vue-demi' 2 | 3 | import { useResizeObserver } from '../useResizeObserver' 4 | import { ResizeObserverOptions, ElementSize, RefTypedElement } from '../types' 5 | import { isElement } from '../utils' 6 | 7 | const useElementSize = ( 8 | target: RefTypedElement, 9 | options: ResizeObserverOptions = {}, 10 | ): ElementSize => { 11 | const width = ref(isElement(target) ? target.clientWidth : 0) 12 | const height = ref(isElement(target) ? target.clientHeight : 0) 13 | 14 | useResizeObserver( 15 | target, 16 | ([entry]) => { 17 | width.value = entry.contentRect.width 18 | height.value = entry.contentRect.height 19 | }, 20 | options 21 | ) 22 | 23 | return { width, height } 24 | } 25 | 26 | export { useElementSize } 27 | -------------------------------------------------------------------------------- /packages/core/useEmitter/index.ts: -------------------------------------------------------------------------------- 1 | import mitt, { EventType, Emitter, Handler, WildcardHandler } from 'mitt' 2 | import { onUnmounted } from 'vue-demi' 3 | 4 | const useEmitter = ( 5 | event: E, 6 | handler: Handler | WildcardHandler 7 | ) => { 8 | const emitter: Emitter = mitt() 9 | emitter.on(event, handler) 10 | 11 | const off = () => emitter.off(event, handler) 12 | onUnmounted(off) 13 | 14 | return { 15 | off, 16 | emit: emitter.emit 17 | } 18 | } 19 | 20 | export { useEmitter } 21 | -------------------------------------------------------------------------------- /packages/core/useEventListener/index.ts: -------------------------------------------------------------------------------- 1 | import { watch, Ref, ref } from 'vue-demi' 2 | 3 | import { RefElement, RefTyped, Fn } from '../types' 4 | import { NOOP } from '../utils' 5 | 6 | export function useEventListener( 7 | target: Window, 8 | event: E, 9 | listener: (this: Window, ev: WindowEventMap[E]) => any, 10 | options?: boolean | AddEventListenerOptions 11 | ): Fn 12 | 13 | export function useEventListener( 14 | target: Document, 15 | event: E, 16 | listener: (this: Document, ev: DocumentEventMap[E]) => any, 17 | options?: boolean | AddEventListenerOptions 18 | ): Fn 19 | 20 | export function useEventListener( 21 | target: RefElement | Ref, 22 | event: E, 23 | listener: (this: Element, ev: DocumentEventMap[E]) => any, 24 | options?: boolean | AddEventListenerOptions, 25 | ): Fn 26 | 27 | export function useEventListener( 28 | target: RefTyped, 29 | event: string, 30 | listener: EventListener, 31 | options?: boolean | AddEventListenerOptions 32 | ): Fn 33 | 34 | export function useEventListener ( 35 | target: any, 36 | event: string, 37 | listener: EventListenerOrEventListenerObject, 38 | options?: boolean | AddEventListenerOptions 39 | ): Fn { 40 | let remove = NOOP 41 | 42 | if (target) { 43 | const element: Ref = ref(target as Element) 44 | 45 | const removeEventListener = (e: Element) => e.removeEventListener(event, listener) 46 | const addEventListener = (e: Element) => e.addEventListener(event, listener, options) 47 | 48 | const removeWatch = watch( 49 | element, 50 | (n, _, cleanUp) => { 51 | if (n) { 52 | addEventListener(n) 53 | cleanUp(() => removeEventListener(n)) 54 | } 55 | }, 56 | { immediate: true } 57 | ) 58 | 59 | remove = () => { 60 | removeEventListener(element.value) 61 | removeWatch() 62 | } 63 | } 64 | 65 | return remove 66 | } 67 | 68 | // export { useEventListener } -------------------------------------------------------------------------------- /packages/core/useFullscreen/index.ts: -------------------------------------------------------------------------------- 1 | import { ref, Ref } from 'vue-demi' 2 | import screenfull, { Screenfull } from 'screenfull' 3 | import { tryOnMounted } from '../useLifecycle' 4 | import { Fn, RefElement } from '../types' 5 | 6 | export interface IFullScreen { 7 | isFullscreen: Ref; 8 | toggleFullscreen: Fn; 9 | } 10 | 11 | /** 12 | * Reactive Fullscreen API build on top of screenfull.js 13 | * @param target 14 | * @param options 15 | */ 16 | const useFullscreen = ( 17 | target: RefElement, 18 | options: FullscreenOptions = {} 19 | ): IFullScreen => { 20 | const targetRef = ref(target || document.querySelector('html')) 21 | const isFullscreen = ref(false) 22 | 23 | const toggleFullscreen = () => { 24 | screenfull.isEnabled && screenfull.toggle(targetRef.value, options) 25 | } 26 | 27 | tryOnMounted(() => { 28 | if (screenfull.isEnabled) { 29 | screenfull.on('change', () => { 30 | isFullscreen.value = (screenfull).isFullscreen 31 | }) 32 | } 33 | }) 34 | 35 | return { 36 | isFullscreen, 37 | toggleFullscreen 38 | } 39 | } 40 | 41 | export { useFullscreen } 42 | -------------------------------------------------------------------------------- /packages/core/useInstance/index.ts: -------------------------------------------------------------------------------- 1 | import { getCurrentInstance, ComponentInternalInstance } from 'vue-demi' 2 | 3 | export type InstanceProxy = ComponentInternalInstance['proxy'] | null 4 | 5 | const useInstance = (): any => { 6 | const instance = getCurrentInstance() 7 | 8 | if (!instance) { 9 | console.error( 10 | '`getCurrentInstance` only works during setup or Lifecycle Hooks' 11 | ) 12 | return null 13 | } 14 | 15 | return instance.proxy 16 | } 17 | 18 | export { useInstance } 19 | -------------------------------------------------------------------------------- /packages/core/useLifecycle/index.ts: -------------------------------------------------------------------------------- 1 | import { getCurrentInstance, onMounted, onUnmounted, nextTick } from 'vue-demi' 2 | 3 | import { Fn } from '../types' 4 | 5 | /** 6 | * Call onMounted() if it's inside a component lifecycle, if not, run just call the function 7 | * @param fn 8 | * @param sync if set to false, it will run in the nextTick() of Vue 9 | */ 10 | export function tryOnMounted (fn: Fn, sync = true) { 11 | if (getCurrentInstance()) { 12 | onMounted(fn) 13 | } else if (sync) { 14 | fn() 15 | } else { 16 | nextTick(fn) 17 | } 18 | } 19 | 20 | /** 21 | * Call onUnmounted() if it's inside a component lifecycle, if not, do nothing 22 | * @param fn 23 | */ 24 | export function tryOnUnmounted (fn: Fn) { 25 | if (getCurrentInstance()) onUnmounted(fn) 26 | } 27 | -------------------------------------------------------------------------------- /packages/core/useMouse/index.ts: -------------------------------------------------------------------------------- 1 | import { ref, Ref } from 'vue-demi' 2 | 3 | import { useEventListener } from '../useEventListener' 4 | import { NOOP } from '../utils' 5 | 6 | /** 7 | * Register `MouseMove` event on mounted, and remove event automatically on unmounted. 8 | */ 9 | const useMouse = () => { 10 | let remove = NOOP 11 | const x: Ref = ref(0) 12 | const y: Ref = ref(0) 13 | 14 | // const touchHandler = (event: TouchEvent) => { 15 | // if (event.touches.length > 0) { 16 | // x.value = event.touches[0].clientX 17 | // y.value = event.touches[0].clientY 18 | // } 19 | // } 20 | 21 | if (window) { 22 | const mouseHandler = (event: MouseEvent) => { 23 | x.value = event.pageX 24 | y.value = event.pageY 25 | } 26 | remove = useEventListener(window, 'mousemove', mouseHandler, { passive: true }) 27 | } 28 | 29 | return { 30 | x, 31 | y, 32 | remove 33 | } 34 | } 35 | 36 | export { useMouse } 37 | -------------------------------------------------------------------------------- /packages/core/usePrecision/index.ts: -------------------------------------------------------------------------------- 1 | import { 2 | strip, 3 | plus, 4 | minus, 5 | times, 6 | divide, 7 | round, 8 | digitLength, 9 | float2Fixed 10 | } from 'number-precision' 11 | 12 | import { reactiveFn } from '../utils' 13 | 14 | /** 15 | * `usePrecision` provide reactive methods to perform addition, subtraction, multiplication & division operations precisely. 16 | */ 17 | const usePrecision = () => { 18 | return { 19 | strip: reactiveFn(strip), 20 | plus: reactiveFn(plus), 21 | minus: reactiveFn(minus), 22 | times: reactiveFn(times), 23 | divide: reactiveFn(divide), 24 | round: reactiveFn(round), 25 | digitLength: reactiveFn(digitLength), 26 | float2Fixed: reactiveFn(float2Fixed) 27 | } 28 | } 29 | 30 | export { usePrecision } 31 | -------------------------------------------------------------------------------- /packages/core/useReactiveState/index.ts: -------------------------------------------------------------------------------- 1 | import { reactive } from 'vue-demi' 2 | 3 | export function useReactiveState(getter: () => Required): [Required, VoidFunction] { 4 | const state = reactive(getter()) 5 | 6 | const update = (): void => { 7 | Object.assign(state, getter()) 8 | } 9 | 10 | return [state, update] 11 | } 12 | -------------------------------------------------------------------------------- /packages/core/useResizeEvent/index.ts: -------------------------------------------------------------------------------- 1 | import debounce from 'lodash.debounce' 2 | import throttle from 'lodash.throttle' 3 | import { tryOnMounted, tryOnUnmounted } from '../useLifecycle' 4 | import { Fn, EventOptions } from '../types' 5 | import { isBoolean } from '../utils' 6 | 7 | /** 8 | * Reactive Resize API, When window resize, do someting. 9 | * @param {function} fn 10 | * @param {object} options 11 | * @return {function} dispatchResize 12 | */ 13 | const useResizeEvent = ( 14 | fn: Fn, 15 | options: EventOptions = { useCapture: false, useThrottle: null, delay: 500 } 16 | ) => { 17 | const { useCapture = false, useThrottle = null, delay = 500 } = options 18 | 19 | const dispatchResize = () => { 20 | const e = document.createEvent('Event') 21 | e.initEvent('resize', true, true) 22 | window.dispatchEvent(e) 23 | } 24 | 25 | const waitFn = isBoolean(useThrottle) 26 | ? useThrottle 27 | ? throttle(fn, delay) 28 | : debounce(fn, delay) 29 | : fn 30 | 31 | tryOnMounted(() => { 32 | window.addEventListener('resize', waitFn, useCapture) 33 | }) 34 | tryOnUnmounted(() => { 35 | window.removeEventListener('resize', waitFn, useCapture) 36 | }) 37 | 38 | return { 39 | dispatchResize 40 | } 41 | } 42 | 43 | export { useResizeEvent } 44 | -------------------------------------------------------------------------------- /packages/core/useResizeObserver/index.ts: -------------------------------------------------------------------------------- 1 | import { watch } from 'vue-demi' 2 | import { ResizeObserver } from '@juggle/resize-observer' 3 | import { 4 | ResizeObserverOptions, 5 | ResizeObserverCallback, 6 | RefTypedElement 7 | } from '../types' 8 | import { unrefElement } from '../utils' 9 | import { tryOnUnmounted } from '../useLifecycle' 10 | 11 | /** 12 | * It immediately detects when an element resizes and provides accurate sizing information back to the handler. 13 | * @param target 14 | * @param callback 15 | * @param options 16 | */ 17 | const useResizeObserver = ( 18 | target: RefTypedElement, 19 | callback: ResizeObserverCallback, 20 | options: ResizeObserverOptions = {} 21 | ) => { 22 | let ro: ResizeObserver | undefined 23 | const isSupported = window && 'ResizeObserver' in window 24 | 25 | const stopWatch = watch( 26 | () => unrefElement(target), 27 | (el) => { 28 | if (isSupported && window && el) { 29 | ro = new ResizeObserver(callback) 30 | 31 | ro.observe(el, options) 32 | } 33 | }, 34 | { immediate: true } 35 | ) 36 | 37 | const stop = () => { 38 | ro && ro.disconnect() 39 | ro = undefined 40 | stopWatch() 41 | } 42 | 43 | tryOnUnmounted(stop) 44 | 45 | return { 46 | stop 47 | } 48 | } 49 | 50 | export { useResizeObserver } 51 | -------------------------------------------------------------------------------- /packages/core/useShortcut/index.ts: -------------------------------------------------------------------------------- 1 | import keymaster from 'keymaster' 2 | import { getCurrentInstance } from 'vue-demi' 3 | 4 | import { tryOnMounted, tryOnUnmounted } from '../useLifecycle' 5 | 6 | /** 7 | * A map of keybinding strings to event handlers. 8 | */ 9 | export interface KeyBindingMap { 10 | [keybinding: string]: (event: KeyboardEvent) => void 11 | } 12 | 13 | export interface KeymasterEvent { 14 | key: string; 15 | method: KeyHandler; 16 | mods: number[]; 17 | scope: string; 18 | shortcut: string; 19 | } 20 | 21 | export interface KeyHandler { 22 | (keyboardEvent: KeyboardEvent, keymasterEvent: KeymasterEvent): void; 23 | } 24 | 25 | const bindKeyHandler = (fn: Function) => { 26 | return (...args: any) => { 27 | fn(...args) 28 | return false 29 | } 30 | } 31 | 32 | /** 33 | * Given shortcut a new bind function 34 | */ 35 | const shortcut = { 36 | bind: (seed: string, func: Function) => keymaster(seed, bindKeyHandler(func)), 37 | ...keymaster 38 | } 39 | 40 | /** 41 | * Bind shortcut onMounted & unbind shortcut automatically onUnmounted in setup hooks 42 | * or 43 | * Unbind shortcut before bind shortcut without setup hooks 44 | * @param keymap 45 | * @param vm 46 | * @return shortcut 47 | */ 48 | const useShortcut = (keymap: KeyBindingMap, vm: any = undefined) => { 49 | let sync = true 50 | 51 | if (!vm) { 52 | vm = getCurrentInstance() 53 | } else { 54 | sync = false 55 | unbindKeys() 56 | } 57 | 58 | function bindKeys () { 59 | Object.keys(keymap).forEach(key => { 60 | shortcut.bind(key, keymap[key]) 61 | }) 62 | } 63 | 64 | function unbindKeys () { 65 | Object.keys(keymap).forEach(key => { 66 | shortcut.unbind(key) 67 | }) 68 | } 69 | 70 | tryOnMounted(bindKeys, sync) 71 | 72 | tryOnUnmounted(unbindKeys) 73 | 74 | return shortcut 75 | } 76 | 77 | export { useShortcut } 78 | -------------------------------------------------------------------------------- /packages/core/useWindowSize/index.ts: -------------------------------------------------------------------------------- 1 | import { onMounted, ref } from 'vue-demi' 2 | import { isClient } from '../utils' 3 | import { useResizeEvent } from '../useResizeEvent' 4 | import { WindowSize, EventOptions } from '../types' 5 | 6 | /** 7 | * Reactive window size 8 | * @param {object} options 9 | * @return {Ref} WindowSize 10 | */ 11 | const useWindowSize = (options: EventOptions = {}): WindowSize => { 12 | const width = ref(isClient ? window.innerWidth : 0) 13 | const height = ref(isClient ? window.innerHeight : 0) 14 | 15 | const onResize = () => { 16 | width.value = window.innerWidth 17 | height.value = window.innerHeight 18 | } 19 | 20 | const { dispatchResize } = useResizeEvent(onResize, options) 21 | 22 | onMounted(dispatchResize) 23 | 24 | return { width, height } 25 | } 26 | 27 | export { useWindowSize } 28 | -------------------------------------------------------------------------------- /packages/core/utils/common.ts: -------------------------------------------------------------------------------- 1 | export const NOOP = () => {} 2 | -------------------------------------------------------------------------------- /packages/core/utils/index.ts: -------------------------------------------------------------------------------- 1 | export { 2 | isArray, 3 | isClient, 4 | isElement, 5 | isBoolean, 6 | isUndefined 7 | } from './is' 8 | 9 | export * from './common' 10 | export * from './ref' 11 | -------------------------------------------------------------------------------- /packages/core/utils/is.ts: -------------------------------------------------------------------------------- 1 | type ConstructorType = new (...args: any[]) => T 2 | const isString = (str: string | T): str is string => { 3 | return typeof str === 'string' 4 | }; 5 | export const is = (type: ConstructorType | string, val: any) => 6 | ![, null].includes(val) && 7 | (isString(type) ? val.constructor.name === type : val.constructor === type) 8 | export const isArray = Array.isArray 9 | export const isBoolean = (val: any): val is boolean => typeof val === 'boolean' 10 | export const isClient = ![typeof window, typeof document].includes('undefined') 11 | export const isElement = (val: any): val is Element => 12 | typeof val === 'object' && !!val.tagName 13 | export const isUndefined = (val: any) => val === undefined 14 | -------------------------------------------------------------------------------- /packages/core/utils/ref.ts: -------------------------------------------------------------------------------- 1 | import { isRef, ref, Ref, computed, unref } from 'vue-demi' 2 | 3 | import { RefTyped, RefElement, ReactiveFn, RefTypedElement } from '../types' 4 | 5 | export function unwrap(o: RefTyped): T 6 | export function unwrap(o: RefTyped): T { 7 | return isRef(o) ? o.value : o 8 | } 9 | 10 | export function wrap(o: RefElement): Ref 11 | export function wrap(o: RefTyped): Ref 12 | export function wrap(o: any): any { 13 | return isRef(o) ? o : ref(o) 14 | } 15 | 16 | export function reactiveFn(fn: T): ReactiveFn { 17 | return function (this: any, ...args: any[]) { 18 | return computed(() => fn.apply(this, args.map(v => unref(v)))) 19 | } as ReactiveFn 20 | } 21 | 22 | export function unrefElement(refEl: RefTypedElement): any { 23 | return unref(refEl) 24 | } 25 | -------------------------------------------------------------------------------- /packages/global.d.ts: -------------------------------------------------------------------------------- 1 | // Global compile-time constants 2 | declare var __DEV__: boolean; 3 | -------------------------------------------------------------------------------- /packages/vuex/README.md: -------------------------------------------------------------------------------- 1 | # @vueblocks/vue-use-vuex 2 | 3 | > Use Vuex With Composition API Easily. 4 | 5 | ## Install 6 | 7 | ```bash 8 | # Vue 2 with @vue/composition-api 9 | yarn add @vue/composition-api @vueblocks/vue-use-vuex -S 10 | or 11 | npm i @vue/composition-api @vueblocks/vue-use-vuex -S 12 | 13 | # Vue 3 14 | yarn add @vueblocks/vue-use-vuex -S 15 | or 16 | npm i @vueblocks/vue-use-vuex -S 17 | ``` 18 | 19 | ## Usage 20 | 21 | ### useVuex 22 | 23 | `useVuex` utilities just similar with [Vuex Component Binding Helpers](https://vuex.vuejs.org/api/#component-binding-helpers) 24 | 25 | It export these composable helpers: 26 | 27 | * [useState](./useState.md) - same as `mapState` helper in Vuex 28 | * [useGetters](./useGetters.md) - same as `mapGetters` helper in Vuex 29 | * [useMutations](./useMutations.md) - same as `mapMutations` helper in Vuex 30 | * [useActions](./useActions.md) - same as `mapActions` helper in Vuex 31 | 32 | Differently, `useVuex` do not export `createNamespacedHelpers` function, Instead `useVuex` allow you provide 33 | the namespace as first argument, then return will be the namespaced component binding helpers. 34 | 35 | Read more about namespacing [documention](./namespacing.md). 36 | 37 | ### useStore 38 | 39 | `useStore` utilities just do the same thing with Vuex 4.x composition api [useStore](https://next.vuex.vuejs.org/guide/composition-api.html) 40 | 41 | It seems familiar right? 42 | 43 | ## Typing 44 | 45 | ```ts 46 | /** 47 | * Get $store from current instance 48 | * @return {Store} vm.$store 49 | */ 50 | declare const useStore: () => Store; 51 | /** 52 | * Use Vuex with composition api easily. Both support Vue2.x / Vue3.x 53 | * @param {String} namespace 54 | * @param {Store} store ### vm.$store 55 | */ 56 | declare function useVuex(namespace?: string, store?: Store): { 57 | useState: (namespace?: string, map: Array | Object) => Object 58 | useGetters: (namespace?: string, map: Array | Object) => Object 59 | useMutations: (namespace?: string, map: Array | Object) => Object 60 | useActions: (namespace?: string, map: Array | Object) => Object 61 | }; 62 | ``` 63 | -------------------------------------------------------------------------------- /packages/vuex/index.ts: -------------------------------------------------------------------------------- 1 | export * from './useVuex' -------------------------------------------------------------------------------- /packages/vuex/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@vueblocks/vue-use-vuex", 3 | "description": "Use Vuex With Composition API Easily.", 4 | "version": "0.2.11", 5 | "main": "lib/index.cjs.js", 6 | "types": "lib/index.d.ts", 7 | "module": "lib/index.esm.js", 8 | "unpkg": "lib/index.umd.min.js", 9 | "jsdelivr": "lib/index.umd.min.js", 10 | "files": [ 11 | "lib" 12 | ], 13 | "publishConfig": { 14 | "access": "public" 15 | }, 16 | "repository": { 17 | "type": "git", 18 | "url": "git+https://github.com/vueblocks/vue-use-utilities.git" 19 | }, 20 | "homepage": "https://github.com/vueblocks/vue-use-utilities", 21 | "keywords": [ 22 | "vue", 23 | "vue-use", 24 | "vuex", 25 | "composition-api", 26 | "utilities" 27 | ], 28 | "author": "xiaoluoboding", 29 | "license": "MIT", 30 | "sideEffects": false, 31 | "peerDependenciesMeta": { 32 | "@vue/composition-api": { 33 | "optional": true 34 | } 35 | }, 36 | "peerDependencies": { 37 | "@vue/composition-api": "^1.2.4", 38 | "vue": "^2.6.14 || ^3.2.0", 39 | "vuex": "^3.6.2" 40 | }, 41 | "dependencies": { 42 | "@vue/composition-api": "^1.2.4", 43 | "vue-demi": "0.10.0", 44 | "vuex": "^3.6.2" 45 | }, 46 | "devDependencies": { 47 | "@vue/compiler-sfc": "^3.2.20", 48 | "vue": "^3.2.20", 49 | "vue2": "npm:vue@2" 50 | }, 51 | "gitHead": "19fec27b41f71b70a73f0afd37180c39bb362827" 52 | } 53 | -------------------------------------------------------------------------------- /packages/vuex/utils/index.ts: -------------------------------------------------------------------------------- 1 | export const isObject = (val: any): val is object => toString.call(val) === '[object Object]' 2 | export const isString = (str: string | T): str is string => typeof str === 'string' 3 | export const partial = (fn: Function, ...partials: Array) => (...args: Array) => fn(...partials, ...args) 4 | -------------------------------------------------------------------------------- /rollup.config.js: -------------------------------------------------------------------------------- 1 | // Set options as a parameter, environment variable, or rc file. 2 | require = require('esm')(module /*, options*/ ) 3 | require('esbuild-register') 4 | module.exports = require('./scripts/rollup.config.ts') 5 | -------------------------------------------------------------------------------- /scripts/packages.ts: -------------------------------------------------------------------------------- 1 | export interface PackageManifest { 2 | name: string 3 | display: string 4 | addon?: boolean 5 | author?: string 6 | description?: string 7 | external?: string[] 8 | globals?: Record 9 | manualImport?: boolean 10 | deprecated?: boolean 11 | } 12 | 13 | export const packages: PackageManifest[] = [ 14 | { 15 | name: 'core', 16 | display: 'VueUseUtilities', 17 | description: 'Collection of essential Vue Composition API Utilities', 18 | external: [ 19 | 'lodash.debounce', 20 | 'lodash.throttle', 21 | 'lodash.clonedeep', 22 | 'screenfull', 23 | 'keymaster', 24 | '@juggle/resize-observer', 25 | 'color2k', 26 | 'mitt', 27 | 'stateshot', 28 | 'number-precision' 29 | ], 30 | globals: { 31 | 'lodash.debounce': 'lodash.debounce', 32 | 'lodash.throttle': 'lodash.throttle', 33 | 'lodash.clonedeep': 'lodash.clonedeep', 34 | 'screenfull': 'screenfull', 35 | '@juggle/resize-observer': 'ResizeObserver', 36 | 'keymaster': 'keymaster', 37 | 'color2k': 'color2k', 38 | 'mitt': 'mitt', 39 | 'stateshot': 'stateshot', 40 | 'number-precision': 'number-precision' 41 | } 42 | }, 43 | { 44 | name: 'vuex', 45 | display: 'Vuex', 46 | description: 'Utilities for Vuex', 47 | addon: true, 48 | external: [ 49 | 'vuex' 50 | ], 51 | globals: { 52 | 'vuex': 'Vuex' 53 | } 54 | }, 55 | { 56 | name: 'axios', 57 | display: 'Axios', 58 | description: 'Utilities for Axios', 59 | addon: true, 60 | external: [ 61 | 'axios', 62 | 'lodash.debounce', 63 | 'lodash.throttle' 64 | ], 65 | globals: { 66 | 'axios': 'Axios', 67 | 'lodash.debounce': 'lodash.debounce', 68 | 'lodash.throttle': 'lodash.throttle' 69 | } 70 | } 71 | ] 72 | 73 | export const activePackages = packages.filter(i => !i.deprecated) 74 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "esnext", 4 | "module": "esnext", 5 | "strict": true, 6 | "jsx": "preserve", 7 | "importHelpers": true, 8 | "moduleResolution": "node", 9 | "skipLibCheck": true, 10 | "esModuleInterop": true, 11 | "declaration": true, 12 | "declarationDir": "./types", 13 | "rootDir": ".", 14 | "baseUrl": ".", 15 | "types": [ 16 | "jest", 17 | "node" 18 | ], 19 | "lib": [ 20 | "esnext", 21 | "dom", 22 | "dom.iterable", 23 | "scripthost" 24 | ] 25 | }, 26 | "include": ["packages"], 27 | "exclude": [ 28 | "node_modules", 29 | "**/**/*.test.ts", 30 | "**/**/*.md" 31 | ] 32 | } 33 | --------------------------------------------------------------------------------