mirror of
https://github.com/AmruthPillai/Reactive-Resume.git
synced 2026-10-03 18:23:47 +10:00
* feat: add options.showLinkInTitle to baseItemSchema Add itemOptionsSchema with showLinkInTitle boolean property to control whether the website URL is rendered as a hyperlink on the title instead of a separate link at the bottom. The field is optional for backwards compatibility with existing resumes. Co-authored-by: Cursor <cursoragent@cursor.com> * feat: add hideLabelButton prop to URLInput When hideLabelButton is true, the tag/label button is hidden from the URL input. This is used when showLinkInTitle is enabled since the label is not needed when the link is shown in the title. Co-authored-by: Cursor <cursoragent@cursor.com> * feat: create LinkedTitle component for title-as-link rendering Add a reusable component that conditionally renders the title as a hyperlink when showLinkInTitle is true and a website URL is provided. Co-authored-by: Cursor <cursoragent@cursor.com> * feat: add showLinkInTitle option to experience section - Add Switch toggle in experience dialog for showLinkInTitle option - Update URLInput to hide label button when showLinkInTitle is enabled - Use LinkedTitle component in experience-item for conditional link rendering - Hide bottom website link when showLinkInTitle is enabled Co-authored-by: Cursor <cursoragent@cursor.com> * feat: add showLinkInTitle option to all section items - Update education, projects, awards, certifications, publications, volunteer, references, and profiles dialogs with Switch toggle - Add LinkedTitle component usage in all corresponding item components - Conditionally hide bottom website link when showLinkInTitle is enabled - Add hideLabelButton prop to URLInput when showLinkInTitle is enabled Co-authored-by: Cursor <cursoragent@cursor.com> * chore: extract i18n strings for showLinkInTitle feature Add "Show link in title" translation string to all locale catalogs. Co-authored-by: Cursor <cursoragent@cursor.com> * update dependencies, fix an issue with glalie template and non-clickable links, fix better-auth type error * remove unused export --------- Co-authored-by: Cursor <cursoragent@cursor.com>
86 lines
2.4 KiB
TypeScript
86 lines
2.4 KiB
TypeScript
import { t } from "@lingui/core/macro";
|
|
import { Trans } from "@lingui/react/macro";
|
|
import { TagIcon } from "@phosphor-icons/react";
|
|
import { useCallback, useMemo } from "react";
|
|
import type z from "zod";
|
|
import type { urlSchema } from "@/schema/resume/data";
|
|
import { cn } from "@/utils/style";
|
|
import { Input } from "../ui/input";
|
|
import { InputGroup, InputGroupAddon, InputGroupButton, InputGroupInput, InputGroupText } from "../ui/input-group";
|
|
import { Label } from "../ui/label";
|
|
import { Popover, PopoverContent, PopoverTrigger } from "../ui/popover";
|
|
|
|
const PREFIX = "https://";
|
|
|
|
function stripPrefix(url: string) {
|
|
return url.startsWith(PREFIX) ? url.slice(PREFIX.length) : url;
|
|
}
|
|
|
|
function ensurePrefix(url: string) {
|
|
if (url === "") return "";
|
|
return url.startsWith(PREFIX) ? url : PREFIX + url;
|
|
}
|
|
|
|
type Props = Omit<React.ComponentProps<"input">, "value" | "onChange"> & {
|
|
value: z.infer<typeof urlSchema>;
|
|
onChange: (value: z.infer<typeof urlSchema>) => void;
|
|
hideLabelButton?: boolean;
|
|
};
|
|
|
|
export function URLInput({ value, onChange, hideLabelButton, ...props }: Props) {
|
|
const handleUrlChange = useCallback(
|
|
(e: React.ChangeEvent<HTMLInputElement>) => {
|
|
onChange({
|
|
url: ensurePrefix(e.target.value),
|
|
label: value.label,
|
|
});
|
|
},
|
|
[onChange, value.label],
|
|
);
|
|
|
|
const handleLabelChange = useCallback(
|
|
(e: React.ChangeEvent<HTMLInputElement>) => {
|
|
onChange({ url: value.url, label: e.target.value });
|
|
},
|
|
[onChange, value.url],
|
|
);
|
|
|
|
const urlValue = useMemo(() => stripPrefix(value.url), [value.url]);
|
|
|
|
return (
|
|
<InputGroup>
|
|
<InputGroupAddon align="inline-start">
|
|
<InputGroupText>{PREFIX}</InputGroupText>
|
|
</InputGroupAddon>
|
|
|
|
<InputGroupInput
|
|
value={urlValue}
|
|
className={cn(props.className, "ps-0!")}
|
|
onChange={handleUrlChange}
|
|
{...props}
|
|
/>
|
|
|
|
{!hideLabelButton && (
|
|
<InputGroupAddon align="inline-end">
|
|
<Popover>
|
|
<PopoverTrigger asChild>
|
|
<InputGroupButton size="icon-sm" title={t`Add a label to the URL`}>
|
|
<TagIcon />
|
|
</InputGroupButton>
|
|
</PopoverTrigger>
|
|
|
|
<PopoverContent className="pt-3">
|
|
<div className="grid gap-2" onClick={(e) => e.stopPropagation()}>
|
|
<Label htmlFor="url-label">
|
|
<Trans>Label</Trans>
|
|
</Label>
|
|
<Input id="url-label" name="url-label" value={value.label} onChange={handleLabelChange} />
|
|
</div>
|
|
</PopoverContent>
|
|
</Popover>
|
|
</InputGroupAddon>
|
|
)}
|
|
</InputGroup>
|
|
);
|
|
}
|