aboutsummaryrefslogtreecommitdiff
path: root/src/lib/react.ts
diff options
context:
space:
mode:
authorFuwn <[email protected]>2026-01-24 13:09:50 +0000
committerFuwn <[email protected]>2026-01-24 13:09:50 +0000
commit396acf3bbbe00a192cb0ea0a9ccf91b1d8d2850b (patch)
treeb9df4ca6a70db45cfffbae6fdd7252e20fb8e93c /src/lib/react.ts
downloadumami-main.tar.xz
umami-main.zip
Initial commitHEADmain
Created from https://vercel.com/new
Diffstat (limited to 'src/lib/react.ts')
-rw-r--r--src/lib/react.ts77
1 files changed, 77 insertions, 0 deletions
diff --git a/src/lib/react.ts b/src/lib/react.ts
new file mode 100644
index 0000000..668cdf1
--- /dev/null
+++ b/src/lib/react.ts
@@ -0,0 +1,77 @@
+import {
+ Children,
+ cloneElement,
+ type FC,
+ Fragment,
+ isValidElement,
+ type ReactElement,
+ type ReactNode,
+} from 'react';
+
+export function getFragmentChildren(children: ReactNode) {
+ return (children as ReactElement)?.type === Fragment
+ ? (children as ReactElement).props.children
+ : children;
+}
+
+export function isValidChild(child: ReactElement, types: FC | FC[]) {
+ if (!isValidElement(child)) {
+ return false;
+ }
+ return (Array.isArray(types) ? types : [types]).find(type => type === child.type);
+}
+
+export function mapChildren(
+ children: ReactNode,
+ handler: (child: ReactElement, index: number) => any,
+) {
+ return Children.map(getFragmentChildren(children) as ReactElement[], (child, index) => {
+ if (!child?.props) {
+ return null;
+ }
+ return handler(child, index);
+ });
+}
+
+export function cloneChildren(
+ children: ReactNode,
+ handler: (child: ReactElement, index: number) => any,
+ options?: { validChildren?: any[]; onlyRenderValid?: boolean },
+): ReactNode {
+ if (!children) {
+ return null;
+ }
+
+ const { validChildren, onlyRenderValid = false } = options || {};
+
+ return mapChildren(children, (child, index) => {
+ const invalid = validChildren && !isValidChild(child as ReactElement, validChildren);
+
+ if (onlyRenderValid && invalid) {
+ return null;
+ }
+
+ if (!invalid && isValidElement(child)) {
+ return cloneElement(child, handler(child, index));
+ }
+
+ return child;
+ });
+}
+
+export function renderChildren(
+ children: ReactNode | ((item: any, index: number, array: any) => ReactNode),
+ items: any[],
+ handler: (child: ReactElement, index: number) => object | undefined,
+ options?: { validChildren?: any[]; onlyRenderValid?: boolean },
+): ReactNode {
+ if (typeof children === 'function' && items?.length > 0) {
+ return cloneChildren(items.map(children), handler, options);
+ }
+
+ return cloneChildren(getFragmentChildren(children as ReactNode), handler, options);
+}
+
+export function countChildren(children: ReactNode): number {
+ return Children.count(getFragmentChildren(children));
+}