mirror of
https://github.com/robonen/tools.git
synced 2026-03-20 10:54:44 +00:00
Merge pull request #94 from robonen/feat/vue/unrefElement
feat(web/vue): unrefElement
This commit is contained in:
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@robonen/vue",
|
"name": "@robonen/vue",
|
||||||
"version": "0.0.10",
|
"version": "0.0.11",
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
"description": "Collection of powerful tools for Vue",
|
"description": "Collection of powerful tools for Vue",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
|
|||||||
61
web/vue/src/composables/unrefElement/index.test.ts
Normal file
61
web/vue/src/composables/unrefElement/index.test.ts
Normal file
@@ -0,0 +1,61 @@
|
|||||||
|
import { describe, expect, it } from 'vitest';
|
||||||
|
import { computed, defineComponent, nextTick, ref, shallowRef } from 'vue';
|
||||||
|
import { mount } from '@vue/test-utils'
|
||||||
|
import { unrefElement } from '.';
|
||||||
|
|
||||||
|
describe('unrefElement', () => {
|
||||||
|
it('returns a plain element when passed a raw element', () => {
|
||||||
|
const htmlEl = document.createElement('div');
|
||||||
|
const svgEl = document.createElementNS('http://www.w3.org/2000/svg', 'svg');
|
||||||
|
|
||||||
|
expect(unrefElement(htmlEl)).toBe(htmlEl);
|
||||||
|
expect(unrefElement(svgEl)).toBe(svgEl);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('returns element when passed a ref or shallowRef to an element', () => {
|
||||||
|
const el = document.createElement('div');
|
||||||
|
const elRef = ref<HTMLElement | null>(el);
|
||||||
|
const shallowElRef = shallowRef<HTMLElement | null>(el);
|
||||||
|
|
||||||
|
expect(unrefElement(elRef)).toBe(el);
|
||||||
|
expect(unrefElement(shallowElRef)).toBe(el);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('returns element when passed a computed ref or getter function', () => {
|
||||||
|
const el = document.createElement('div');
|
||||||
|
const computedElRef = computed(() => el);
|
||||||
|
const elGetter = () => el;
|
||||||
|
|
||||||
|
expect(unrefElement(computedElRef)).toBe(el);
|
||||||
|
expect(unrefElement(elGetter)).toBe(el);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('returns component $el when passed a component instance', async () => {
|
||||||
|
const Child = defineComponent({
|
||||||
|
template: `<span class="child-el">child</span>`,
|
||||||
|
});
|
||||||
|
|
||||||
|
const Parent = defineComponent({
|
||||||
|
components: { Child },
|
||||||
|
template: `<Child ref="childRef" />`,
|
||||||
|
});
|
||||||
|
|
||||||
|
const wrapper = mount(Parent);
|
||||||
|
await nextTick();
|
||||||
|
|
||||||
|
const childInstance = (wrapper.vm as any).$refs.childRef;
|
||||||
|
const result = unrefElement(childInstance);
|
||||||
|
|
||||||
|
expect(result).toBe(childInstance.$el);
|
||||||
|
expect((result as HTMLElement).classList.contains('child-el')).toBe(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('handles null and undefined values', () => {
|
||||||
|
expect(unrefElement(undefined)).toBe(undefined);
|
||||||
|
expect(unrefElement(null)).toBe(null);
|
||||||
|
expect(unrefElement(ref(null))).toBe(null);
|
||||||
|
expect(unrefElement(ref(undefined))).toBe(undefined);
|
||||||
|
expect(unrefElement(() => null)).toBe(null);
|
||||||
|
expect(unrefElement(() => undefined)).toBe(undefined);
|
||||||
|
});
|
||||||
|
});
|
||||||
33
web/vue/src/composables/unrefElement/index.ts
Normal file
33
web/vue/src/composables/unrefElement/index.ts
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
import type { ComponentPublicInstance, MaybeRef, MaybeRefOrGetter } from 'vue';
|
||||||
|
import { toValue } from 'vue';
|
||||||
|
|
||||||
|
export type VueInstance = ComponentPublicInstance;
|
||||||
|
export type MaybeElement = HTMLElement | SVGElement | VueInstance | undefined | null;
|
||||||
|
|
||||||
|
export type MaybeElementRef<El extends MaybeElement = MaybeElement> = MaybeRef<El>;
|
||||||
|
export type MaybeComputedElementRef<El extends MaybeElement = MaybeElement> = MaybeRefOrGetter<El>;
|
||||||
|
|
||||||
|
export type UnRefElementReturn<T extends MaybeElement = MaybeElement> = T extends VueInstance ? Exclude<MaybeElement, VueInstance> : T | undefined;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @name unrefElement
|
||||||
|
* @category Components
|
||||||
|
* @description Unwraps a Vue element reference to get the underlying instance or DOM element.
|
||||||
|
*
|
||||||
|
* @param {MaybeComputedElementRef<El>} elRef - The element reference to unwrap.
|
||||||
|
* @returns {UnRefElementReturn<El>} - The unwrapped element or undefined.
|
||||||
|
*
|
||||||
|
* @example
|
||||||
|
* const element = useTemplateRef<HTMLElement>('element');
|
||||||
|
* const result = unrefElement(element); // result is the element instance
|
||||||
|
*
|
||||||
|
* @example
|
||||||
|
* const component = useTemplateRef<Component>('component');
|
||||||
|
* const result = unrefElement(component); // result is the component instance
|
||||||
|
*
|
||||||
|
* @since 0.0.11
|
||||||
|
*/
|
||||||
|
export function unrefElement<El extends MaybeElement>(elRef: MaybeComputedElementRef<El>): UnRefElementReturn<El> {
|
||||||
|
const plain = toValue(elRef);
|
||||||
|
return (plain as VueInstance)?.$el ?? plain;
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user