diff --git a/packages/core/index.ts b/packages/core/index.ts index 5707de41c3b..9b72b72c4c2 100644 --- a/packages/core/index.ts +++ b/packages/core/index.ts @@ -29,6 +29,7 @@ export * from './useDeviceMotion' export * from './useDeviceOrientation' export * from './useDevicePixelRatio' export * from './useDevicesList' +export * from './useDir' export * from './useDisplayMedia' export * from './useDocumentVisibility' export * from './useDraggable' diff --git a/packages/core/useDir/demo.vue b/packages/core/useDir/demo.vue new file mode 100644 index 00000000000..6178dc9b216 --- /dev/null +++ b/packages/core/useDir/demo.vue @@ -0,0 +1,41 @@ + + + + + diff --git a/packages/core/useDir/index.md b/packages/core/useDir/index.md new file mode 100644 index 00000000000..ad674a4246f --- /dev/null +++ b/packages/core/useDir/index.md @@ -0,0 +1,35 @@ +--- +category: Browser +--- + +# useDir + +Reactive [dir](https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/dir) of the element's text. + +## Basic Usage + +```ts +import { useDir } from '@vueuse/core' + +const dir = useDir() // Ref<'ltr' | 'rtl' | 'auto'> + +``` +By default, which enables `rlt` direction when dir `rtl` is applied to the `html` tag, for example: + +```html + + ... + + + ... +``` + +## Config + +```ts +import { useDir } from '@vueuse/core' + +const mode = useDir({ + selector: 'body' +}) // Ref<'ltr' | 'rtl' | 'auto'> +``` diff --git a/packages/core/useDir/index.ts b/packages/core/useDir/index.ts new file mode 100644 index 00000000000..49715060d42 --- /dev/null +++ b/packages/core/useDir/index.ts @@ -0,0 +1,61 @@ +import { ref, watch } from 'vue-demi' + +import type { MaybeElement } from '../unrefElement' +import { useMutationObserver } from '../useMutationObserver' + +export interface UseDirOptions { + /** + * CSS Selector for the target element applying to + * + * @default 'html' + */ + selector?: string + /** + * Observe `document.querySelector(selector)` changes using MutationObserve + * + * @default false + */ + observe?: boolean +} + +/** + * Reactive dir of the element's text. + * + * @see https://vueuse.org/useDir + * @param options + */ +export const useDir = ( + options: UseDirOptions = {}, +) => { + const { + selector = 'html', + observe = false, + } = options + + const defaultDir = 'ltr' + const dir = ref(document.querySelector(selector)?.getAttribute('dir') ?? defaultDir) + + const isSupportedDir = (dir: string) => { + return ['ltr', 'rtl', 'auto'].includes(dir) + } + + watch(dir, () => { + if (isSupportedDir(dir.value)) + document.querySelector(selector)?.setAttribute('dir', dir.value) + else + document.querySelector(selector)?.removeAttribute('dir') + }, { immediate: true }) + + if (observe && document) { + useMutationObserver( + document.querySelector(selector) as MaybeElement, + () => { + const crtDir = document.querySelector(selector)?.getAttribute('dir') ?? defaultDir + dir.value = isSupportedDir(crtDir) ? crtDir : defaultDir + }, + { attributes: true }, + ) + } + + return dir +}