@porsche-design-system/components-react
Version:
Porsche Design System is a component library designed to help developers create the best experience for software or services distributed by Dr. Ing. h.c. F. Porsche AG.
73 lines (70 loc) • 2.82 kB
JavaScript
"use client";
import { useLayoutEffect, useEffect, useContext, useRef, useMemo } from 'react';
import { PorscheDesignSystemContext } from './provider.mjs';
import { getMergedClassName } from './utils.mjs';
let skipCheck = false;
/**
* sets a flag that skips the need for `PorscheDesignSystemProvider` during testing
* when `process.env.NODE_ENV === 'test'`
*/
const skipCheckForPorscheDesignSystemProviderDuringTests = () => {
skipCheck = true;
};
const usePrefix = (tagName) => {
if (process.env.NODE_ENV === 'test' && skipCheck) {
return tagName;
}
else {
const { prefix } = useContext(PorscheDesignSystemContext); // eslint-disable-line react-hooks/rules-of-hooks
if (prefix === undefined) {
throw new Error('It appears the <PorscheDesignSystemProvider /> is missing. Make sure to wrap your App in it.');
}
return prefix ? prefix + '-' + tagName : tagName;
}
};
const useTheme = () => {
if (process.env.NODE_ENV === 'test' && skipCheck) {
return 'light';
}
else {
return useContext(PorscheDesignSystemContext).theme; // eslint-disable-line react-hooks/rules-of-hooks
}
};
const useEventCallback = (ref, eventName, eventHandler) => {
// @ts-expect-error
useEffect(() => {
const { current } = ref;
if (current && eventHandler) {
current.addEventListener(eventName, eventHandler);
return () => current?.removeEventListener(eventName, eventHandler);
}
}, [eventHandler]); // eslint-disable-line react-hooks/exhaustive-deps
};
const useMergedClass = (ref, className) => {
const prevComponentClassName = useRef(undefined);
return useMemo(() => {
if (!className) {
return undefined;
}
const { current } = ref;
let newClassName = className;
if (current) {
newClassName = getMergedClassName(current.className, prevComponentClassName.current, className);
// the jsx does not override className when the attribute changes
current.className = newClassName;
}
prevComponentClassName.current = className;
return newClassName;
}, [className]); // eslint-disable-line react-hooks/exhaustive-deps
};
const useBrowserLayoutEffect = typeof window !== 'undefined' ? useLayoutEffect : useEffect;
const useToastManager = () => {
const tagName = usePrefix('p-toast');
return {
addMessage: (message) => {
const toast = document.body.querySelector(tagName);
customElements.whenDefined(tagName).then(() => toast.addMessage(message));
},
};
};
export { skipCheckForPorscheDesignSystemProviderDuringTests, useBrowserLayoutEffect, useEventCallback, useMergedClass, usePrefix, useTheme, useToastManager };