Split out aliases components

This commit is contained in:
Joshua Coles 2023-10-13 17:17:31 +01:00
parent a7568c1bb2
commit 26d5677546
2 changed files with 122 additions and 119 deletions

View File

@ -1,18 +1,10 @@
import {
ChangeEventHandler, Dispatch,
KeyboardEventHandler,
MouseEventHandler,
ReactNode, SetStateAction,
useCallback,
useEffect,
useRef,
useState
} from "react";
import {ReactNode, useCallback, useState} from "react";
import {FixedSizeList as List} from "react-window";
import Select, {createFilter, MenuListProps} from "react-select";
import * as R from 'ramda';
import {useQuery} from "@tanstack/react-query";
import {Alias, CustomAlias, Option} from "./aliases";
// TODO: Fix this for wrapping items, esp on phones
const height = 35;
@ -44,15 +36,6 @@ function MenuList(props: MenuListProps) {
</List>);
}
interface Option {
label: string,
value: string,
data: {
backlinks: unknown[]
aliases?: string[]
}
}
export function LargeSelect() {
const {
data: options,
@ -110,103 +93,3 @@ export function LargeSelect() {
</div>
)
}
function CustomAlias({selected}: {
selected: Option
}) {
const [alias, setAlias] = useState('');
// Reset when selection changes
useEffect(() => {
setAlias('');
}, [selected.value]);
const onClick: MouseEventHandler = useCallback((e) => {
if ((e.target as HTMLElement).tagName == 'SPAN' && alias.length > 0) {
navigator.clipboard.writeText(`[[${selected!.label}|${alias}]]`);
}
}, [selected.value, selected.label, alias]);
return (
<span onClick={onClick} className={"rounded-md p-1 hover:bg-slate-100"}>
<span className={"text-slate-300 p-0.5"}>[[</span>
<span>{selected.label}</span>
<span className={"text-slate-300 p-0.5"}>|</span>
<span>
<CustomAliasField content={alias} setContent={setAlias} selected={selected}/>
</span>
<span className={"text-slate-300 p-0.5"}>]]</span>
</span>
)
}
function CustomAliasField({
selected,
content,
setContent
}: {
selected: Option,
content: string,
setContent: Dispatch<SetStateAction<string>>,
}) {
const [width, setWidth] = useState<any>(0);
const span = useRef<HTMLSpanElement>(null);
// Resize on change of content
useEffect(() => {
setWidth(span.current!.offsetWidth);
// setWidth(content.length + 'ch');
}, [content]);
const changeHandler: ChangeEventHandler<HTMLInputElement> = useCallback(evt => {
setContent(evt.target.value);
}, []);
const onCustomElementKeyDown: KeyboardEventHandler<HTMLInputElement> = useCallback((e) => {
if (e.key == 'Enter') {
navigator.clipboard.writeText(`[[${selected!.label}|${content}]]`);
(e.target as HTMLInputElement).blur()
}
}, [selected.value, selected.label, content]);
return (
<span>
<span style={{
position: 'absolute',
opacity: 0,
zIndex: -100,
whiteSpace: 'pre',
}} ref={span}>{content}</span>
<input
className={"border-none p-0 px-1"}
type="text" style={{width: `calc(${width}px + 0.25rem)`}} autoFocus onChange={changeHandler}
onKeyDown={onCustomElementKeyDown}/>
</span>
);
}
function Alias({
original,
alias
}: {
original: string,
alias?: string
}) {
const onClick = useCallback(() => {
if (alias) {
navigator.clipboard.writeText(`[[${original}|${alias}]]`)
} else {
navigator.clipboard.writeText(`[[${original}]]`)
}
}, [original, alias]);
return (
<span className={"rounded-md p-1 hover:bg-slate-100"} onClick={onClick}>
<span className={"text-slate-300 p-0.5"}>[[</span>
<span>{original}</span>
{alias && <><span className={"text-slate-300 p-0.5"}>|</span>
<span>{alias}</span></>}
<span className={"text-slate-300 p-0.5"}>]]</span>
</span>
);
}

120
src/aliases.tsx Normal file
View File

@ -0,0 +1,120 @@
import {
ChangeEventHandler,
Dispatch,
KeyboardEventHandler,
MouseEventHandler,
SetStateAction,
useCallback,
useEffect,
useRef,
useState
} from "react";
export interface Option {
label: string,
value: string,
data: {
backlinks: unknown[]
aliases?: string[]
}
}
export function CustomAlias({selected}: {
selected: Option
}) {
const [alias, setAlias] = useState('');
// Reset when selection changes
useEffect(() => {
setAlias('');
}, [selected.value]);
const onClick: MouseEventHandler = useCallback((e) => {
if ((e.target as HTMLElement).tagName == 'SPAN' && alias.length > 0) {
navigator.clipboard.writeText(`[[${selected!.label}|${alias}]]`);
}
}, [selected.value, selected.label, alias]);
return (
<span onClick={onClick} className={"rounded-md p-1 hover:bg-slate-100"}>
<span className={"text-slate-300 p-0.5"}>[[</span>
<span>{selected.label}</span>
<span className={"text-slate-300 p-0.5"}>|</span>
<span>
<CustomAliasField content={alias} setContent={setAlias} selected={selected}/>
</span>
<span className={"text-slate-300 p-0.5"}>]]</span>
</span>
)
}
function CustomAliasField({
selected,
content,
setContent
}: {
selected: Option,
content: string,
setContent: Dispatch<SetStateAction<string>>,
}) {
const [width, setWidth] = useState<any>(0);
const span = useRef<HTMLSpanElement>(null);
// Resize on change of content
useEffect(() => {
setWidth(span.current!.offsetWidth);
// setWidth(content.length + 'ch');
}, [content]);
const changeHandler: ChangeEventHandler<HTMLInputElement> = useCallback(evt => {
setContent(evt.target.value);
}, []);
const onCustomElementKeyDown: KeyboardEventHandler<HTMLInputElement> = useCallback((e) => {
if (e.key == 'Enter') {
navigator.clipboard.writeText(`[[${selected!.label}|${content}]]`);
(e.target as HTMLInputElement).blur()
}
}, [selected.value, selected.label, content]);
return (
<span>
<span style={{
position: 'absolute',
opacity: 0,
zIndex: -100,
whiteSpace: 'pre',
}} ref={span}>{content}</span>
<input
className={"border-none p-0 px-1"}
type="text" style={{width: `calc(${width}px + 0.25rem)`}} autoFocus onChange={changeHandler}
onKeyDown={onCustomElementKeyDown}/>
</span>
);
}
export function Alias({
original,
alias
}: {
original: string,
alias?: string
}) {
const onClick = useCallback(() => {
if (alias) {
navigator.clipboard.writeText(`[[${original}|${alias}]]`)
} else {
navigator.clipboard.writeText(`[[${original}]]`)
}
}, [original, alias]);
return (
<span className={"rounded-md p-1 hover:bg-slate-100"} onClick={onClick}>
<span className={"text-slate-300 p-0.5"}>[[</span>
<span>{original}</span>
{alias && <><span className={"text-slate-300 p-0.5"}>|</span>
<span>{alias}</span></>}
<span className={"text-slate-300 p-0.5"}>]]</span>
</span>
);
}