* chore(release): v5.1.0

* feat: implement resume thumbnails

* fix: remove unused mcp tools

* docs: fix formatting of docs
This commit is contained in:
Amruth Pillai
2026-05-07 15:12:33 +02:00
committed by GitHub
parent 51c366310e
commit 50ba37a27f
1015 changed files with 106087 additions and 141872 deletions
+95
View File
@@ -0,0 +1,95 @@
import * as React from "react";
import {
AlertDialog,
AlertDialogAction,
AlertDialogCancel,
AlertDialogContent,
AlertDialogDescription,
AlertDialogFooter,
AlertDialogHeader,
AlertDialogTitle,
} from "@reactive-resume/ui/components/alert-dialog";
import { cn } from "@reactive-resume/utils/style";
interface ConfirmOptions {
description?: string;
confirmText?: string;
cancelText?: string;
}
interface ConfirmState extends ConfirmOptions {
open: boolean;
title: string;
resolve: ((value: boolean) => void) | null;
}
type ConfirmContextType = {
confirm: (title: string, options?: ConfirmOptions) => Promise<boolean>;
};
const ConfirmContext = React.createContext<ConfirmContextType | null>(null);
export function ConfirmDialogProvider({ children }: { children: React.ReactNode }) {
const [state, setState] = React.useState<ConfirmState>({
open: false,
resolve: null,
title: "",
});
const confirm = React.useCallback(async (title: string, options?: ConfirmOptions): Promise<boolean> => {
return new Promise<boolean>((resolve) => {
setState({
open: true,
resolve,
title,
...(options?.description !== undefined ? { description: options.description } : {}),
...(options?.confirmText !== undefined ? { confirmText: options.confirmText } : {}),
...(options?.cancelText !== undefined ? { cancelText: options.cancelText } : {}),
});
});
}, []);
const handleConfirm = React.useCallback(() => {
if (state.resolve) state.resolve(true);
setState((prev) => ({ ...prev, open: false, resolve: null }));
}, [state.resolve]);
const handleCancel = React.useCallback(() => {
if (state.resolve) state.resolve(false);
setState((prev) => ({ ...prev, open: false, resolve: null }));
}, [state.resolve]);
return (
<ConfirmContext.Provider value={{ confirm }}>
{children}
<AlertDialog open={state.open} onOpenChange={(open) => !open && handleCancel()}>
<AlertDialogContent>
<AlertDialogHeader>
<AlertDialogTitle>{state.title}</AlertDialogTitle>
<AlertDialogDescription className={cn(!state.description && "sr-only")}>
{state.description}
</AlertDialogDescription>
</AlertDialogHeader>
<AlertDialogFooter>
<AlertDialogCancel onClick={handleCancel}>{state.cancelText ?? "Cancel"}</AlertDialogCancel>
<AlertDialogAction onClick={handleConfirm}>{state.confirmText ?? "Confirm"}</AlertDialogAction>
</AlertDialogFooter>
</AlertDialogContent>
</AlertDialog>
</ConfirmContext.Provider>
);
}
export function useConfirm() {
const context = React.useContext(ConfirmContext);
if (!context) {
throw new Error("useConfirm must be used within a <ConfirmDialogProvider />.");
}
return context.confirm;
}
@@ -0,0 +1,32 @@
import { useCallback, useEffect, useState } from "react";
interface CommonControlledStateProps<T> {
value?: T;
defaultValue?: T;
}
type UseControlledStateProps<T, Rest extends unknown[] = []> = CommonControlledStateProps<T> & {
onChange?: (value: T, ...args: Rest) => void;
};
export function useControlledState<T, Rest extends unknown[] = []>(
props: UseControlledStateProps<T, Rest>,
): readonly [T, (next: T, ...args: Rest) => void] {
const { value, defaultValue, onChange } = props;
const [state, setInternalState] = useState<T>(value !== undefined ? value : (defaultValue as T));
useEffect(() => {
if (value !== undefined) setInternalState(value);
}, [value]);
const setState = useCallback(
(next: T, ...args: Rest) => {
setInternalState(next);
onChange?.(next, ...args);
},
[onChange],
);
return [state, setState] as const;
}
+20
View File
@@ -0,0 +1,20 @@
import { useEffect, useState } from "react";
const MOBILE_BREAKPOINT = 768;
const MOBILE_QUERY = `(max-width: ${MOBILE_BREAKPOINT - 1}px)`;
export function useIsMobile() {
const [isMobile, setIsMobile] = useState<boolean | undefined>(undefined);
useEffect(() => {
const mql = window.matchMedia(MOBILE_QUERY);
const onChange = (e: MediaQueryListEvent) => {
setIsMobile(e.matches);
};
mql.addEventListener("change", onChange);
setIsMobile(mql.matches);
return () => mql.removeEventListener("change", onChange);
}, []);
return !!isMobile;
}
+136
View File
@@ -0,0 +1,136 @@
import * as React from "react";
import {
AlertDialog,
AlertDialogAction,
AlertDialogCancel,
AlertDialogContent,
AlertDialogDescription,
AlertDialogFooter,
AlertDialogHeader,
AlertDialogTitle,
} from "@reactive-resume/ui/components/alert-dialog";
import { Input } from "@reactive-resume/ui/components/input";
import { cn } from "@reactive-resume/utils/style";
type PromptOptions = {
description?: string;
defaultValue?: string;
confirmText?: string;
cancelText?: string;
inputProps?: Omit<React.ComponentProps<typeof Input>, "value" | "onChange" | "onKeyDown">;
};
type PromptState = PromptOptions & {
open: boolean;
title: string;
value: string;
resolve: ((value: string | null) => void) | null;
};
type PromptContextType = {
prompt: (title: string, options?: PromptOptions) => Promise<string | null>;
};
const PromptContext = React.createContext<PromptContextType | null>(null);
export function PromptDialogProvider({ children }: { children: React.ReactNode }) {
const inputRef = React.useRef<HTMLInputElement>(null);
const [state, setState] = React.useState<PromptState>({
open: false,
resolve: null,
title: "",
value: "",
});
const cancelText = state.cancelText ?? "Cancel";
const confirmText = state.confirmText ?? "Confirm";
React.useEffect(() => {
if (!state.open) return;
setTimeout(() => {
if (!inputRef.current) return;
inputRef.current.focus();
}, 0);
}, [state.open]);
const prompt = React.useCallback(async (title: string, options?: PromptOptions): Promise<string | null> => {
return new Promise<string | null>((resolve) => {
setState({
open: true,
resolve,
title,
value: options?.defaultValue ?? "",
...(options?.description !== undefined ? { description: options.description } : {}),
...(options?.defaultValue !== undefined ? { defaultValue: options.defaultValue } : {}),
...(options?.confirmText !== undefined ? { confirmText: options.confirmText } : {}),
...(options?.cancelText !== undefined ? { cancelText: options.cancelText } : {}),
...(options?.inputProps !== undefined ? { inputProps: options.inputProps } : {}),
});
});
}, []);
const handleConfirm = React.useCallback(() => {
if (state.resolve) state.resolve(state.value);
setState((prev) => ({ ...prev, open: false, resolve: null }));
}, [state.resolve, state.value]);
const handleCancel = React.useCallback(() => {
if (state.resolve) state.resolve(null);
setState((prev) => ({ ...prev, open: false, resolve: null }));
}, [state.resolve]);
const handleValueChange = React.useCallback((e: React.ChangeEvent<HTMLInputElement>) => {
setState((prev) => ({ ...prev, value: e.target.value }));
}, []);
const handleKeyDown = React.useCallback(
(e: React.KeyboardEvent<HTMLInputElement>) => {
if (e.key === "Enter") handleConfirm();
},
[handleConfirm],
);
return (
<PromptContext.Provider value={{ prompt }}>
{children}
<AlertDialog open={state.open} onOpenChange={(open) => !open && handleCancel()}>
<AlertDialogContent>
<AlertDialogHeader>
<AlertDialogTitle>{state.title}</AlertDialogTitle>
<AlertDialogDescription className={cn(!state.description && "sr-only")}>
{state.description}
</AlertDialogDescription>
</AlertDialogHeader>
<Input
ref={inputRef}
value={state.value}
onKeyDown={handleKeyDown}
onChange={handleValueChange}
{...state.inputProps}
/>
<AlertDialogFooter>
<AlertDialogCancel onClick={handleCancel}>{cancelText}</AlertDialogCancel>
<AlertDialogAction onClick={handleConfirm}>{confirmText}</AlertDialogAction>
</AlertDialogFooter>
</AlertDialogContent>
</AlertDialog>
</PromptContext.Provider>
);
}
export function usePrompt() {
const context = React.useContext(PromptContext);
if (!context) {
throw new Error("usePrompt must be used within a <PromptDialogProvider />.");
}
return context.prompt;
}