Use element size (#169)

* Install resize observer

* Add use-element-size composition

* Rename function to match filename

* Remove false statement from readme
This commit is contained in:
Rijk van Zanten
2020-03-12 13:58:41 -04:00
committed by GitHub
parent 68c625ec79
commit 101abb9634
6 changed files with 163 additions and 0 deletions

View File

@@ -26,6 +26,7 @@
"lodash": "^4.17.15",
"nanoid": "^2.1.11",
"pinia": "0.0.5",
"resize-observer": "^1.0.0",
"stylelint-config-prettier": "^8.0.1",
"vue": "^2.6.11",
"vue-i18n": "^8.15.5",

View File

@@ -0,0 +1,4 @@
import useElementSize from './use-element-size';
export { useElementSize };
export default useElementSize;

View File

@@ -0,0 +1,29 @@
# `useElementSize`
```ts
function useElementSize(element: Element): { width: Ref<number>, height: Ref<number> }
```
Allows you to reactively watch an elements width and height.
## Usage
```vue
<template>
<div ref="el">
My size is: {{ width }} x {{ height }}
</div>
</template>
<script lang="ts">
import { defineComponent } from '@vue/composition-api';
import { useElementSize } from '@/compositions/use-element-size';
export default defineComponent({
setup(props) {
const el = ref<Element>(null);
const { width, height } = useElementSize(el);
return { el, width, height };
}
});
</script>
```

View File

@@ -0,0 +1,97 @@
import mountComposition from '../../../.jest/mount-composition';
import useElementSize from './use-element-size';
import { ResizeObserver } from 'resize-observer';
import { ref } from '@vue/composition-api';
jest.mock('resize-observer');
const mockResizeObserver = {
observe: jest.fn(),
disconnect: jest.fn()
};
describe('Compositions / useElementSize', () => {
beforeEach(() => {
(ResizeObserver as jest.Mock).mockImplementation(() => {
return mockResizeObserver;
});
});
it('Creates a resize observer', () => {
const el = document.createElement('div');
mountComposition(() => {
useElementSize(el);
});
expect(ResizeObserver).toHaveBeenCalled();
});
it('Calls observe with the passed element on mount', () => {
const el = document.createElement('div');
mountComposition(() => {
useElementSize(el);
});
expect(mockResizeObserver.observe).toHaveBeenCalledWith(el);
});
it('Calls observer with element if ref is passed', () => {
const el = document.createElement('div');
mountComposition(() => {
const refEl = ref<Element>(el);
useElementSize(refEl);
});
expect(mockResizeObserver.observe).toHaveBeenCalledWith(el);
});
it('Does not call observe when passed element is null or undefined', () => {
mountComposition(() => {
useElementSize(ref(null));
});
expect(mockResizeObserver.observe).not.toHaveBeenCalled();
});
it('Calls disconnect on unmount', () => {
const el = document.createElement('div');
mountComposition(() => {
useElementSize(el);
}).destroy();
expect(mockResizeObserver.disconnect).toHaveBeenCalled();
});
it('Sets the returned width and height refs on ResizeObserver handler', () => {
let handler: (_: any) => void;
(ResizeObserver as jest.Mock).mockImplementation(constructorParam => {
handler = constructorParam;
return mockResizeObserver;
});
const el = document.createElement('div');
mountComposition(() => {
const { width, height } = useElementSize(el);
expect(width.value).toBe(0);
expect(height.value).toBe(0);
handler([
{
contentRect: {
width: 150,
height: 150
}
}
]);
expect(width.value).toBe(150);
expect(height.value).toBe(150);
});
});
});

View File

@@ -0,0 +1,27 @@
import { Ref, ref, isRef, onMounted, onUnmounted } from '@vue/composition-api';
import { notEmpty } from '@/utils/is-empty';
import { ResizeObserver } from 'resize-observer';
export default function useElementSize<T extends Element>(target: T | Ref<T> | Ref<null>) {
const width = ref(0);
const height = ref(0);
const resizeObserver = new ResizeObserver(([entry]) => {
width.value = entry.contentRect.width;
height.value = entry.contentRect.height;
});
onMounted(() => {
const t = isRef(target) ? target.value : target;
if (notEmpty(t)) {
resizeObserver.observe(t);
}
});
onUnmounted(() => {
resizeObserver.disconnect();
});
return { width, height };
}

View File

@@ -12237,6 +12237,11 @@ resize-observer-polyfill@^1.5.1:
resolved "https://registry.yarnpkg.com/resize-observer-polyfill/-/resize-observer-polyfill-1.5.1.tgz#0e9020dd3d21024458d4ebd27e23e40269810464"
integrity sha512-LwZrotdHOo12nQuZlHEmtuXdqGoOD0OhaxopaNFxWzInpEgaLWoVuAMbTzixuosCx2nEG58ngzW3vxdWoxIgdg==
resize-observer@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/resize-observer/-/resize-observer-1.0.0.tgz#4f8380b73b411af4ed7d916fe85a2d59900e71ef"
integrity sha512-D7UFShDm2TgrEDEyeg+/tTEbvOgPWlvPAfJtxiKp+qutu6HowmcGJKjECgGru0PPDIj3SAucn3ZPpOx54fF7DQ==
resolve-cwd@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/resolve-cwd/-/resolve-cwd-2.0.0.tgz#00a9f7387556e27038eae232caa372a6a59b665a"