This commit is contained in:
2024-04-21 14:42:52 +02:00
parent 4b69674ede
commit 8a25f53c99
10700 changed files with 55767 additions and 14201 deletions

View File

@ -0,0 +1,130 @@
import useCollectionStore from "@/store/collections";
import { useRouter } from "next/router";
import { useEffect, useState } from "react";
import { styles } from "./styles";
import { Options } from "./types";
import CreatableSelect from "react-select/creatable";
import Select from "react-select";
type Props = {
onChange: any;
showDefaultValue?: boolean;
defaultValue?:
| {
label: string;
value?: number;
}
| undefined;
creatable?: boolean;
};
export default function CollectionSelection({
onChange,
defaultValue,
showDefaultValue = true,
creatable = true,
}: Props) {
const { collections } = useCollectionStore();
const router = useRouter();
const [options, setOptions] = useState<Options[]>([]);
const collectionId = Number(router.query.id);
const activeCollection = collections.find((e) => {
return e.id === collectionId;
});
if (activeCollection && !defaultValue) {
defaultValue = {
value: activeCollection?.id,
label: activeCollection?.name,
};
}
useEffect(() => {
const formatedCollections = collections.map((e) => {
return {
value: e.id,
label: e.name,
ownerId: e.ownerId,
count: e._count,
parentId: e.parentId,
};
});
setOptions(formatedCollections);
}, [collections]);
const getParentNames = (parentId: number): string[] => {
const parentNames = [];
const parent = collections.find((e) => e.id === parentId);
if (parent) {
parentNames.push(parent.name);
if (parent.parentId) {
parentNames.push(...getParentNames(parent.parentId));
}
}
// Have the top level parent at beginning
return parentNames.reverse();
};
const customOption = ({ data, innerProps }: any) => {
return (
<div
{...innerProps}
className="px-2 py-2 last:border-0 border-b border-neutral-content hover:bg-neutral-content cursor-pointer"
>
<div className="flex w-full justify-between items-center">
<span>{data.label}</span>
<span className="text-sm text-neutral">{data.count?.links}</span>
</div>
<div className="text-xs text-gray-600 dark:text-gray-300">
{getParentNames(data?.parentId).length > 0 ? (
<>
{getParentNames(data.parentId).join(" > ")} {">"} {data.label}
</>
) : (
data.label
)}
</div>
</div>
);
};
if (creatable) {
return (
<CreatableSelect
isClearable={false}
className="react-select-container"
classNamePrefix="react-select"
onChange={onChange}
options={options}
styles={styles}
defaultValue={showDefaultValue ? defaultValue : null}
components={{
Option: customOption,
}}
// menuPosition="fixed"
/>
);
} else {
return (
<Select
isClearable={false}
className="react-select-container"
classNamePrefix="react-select"
onChange={onChange}
options={options}
styles={styles}
defaultValue={showDefaultValue ? defaultValue : null}
components={{
Option: customOption,
}}
// menuPosition="fixed"
/>
);
}
}

View File

@ -0,0 +1,41 @@
import useTagStore from "@/store/tags";
import { useEffect, useState } from "react";
import CreatableSelect from "react-select/creatable";
import { styles } from "./styles";
import { Options } from "./types";
type Props = {
onChange: any;
defaultValue?: {
value: number;
label: string;
}[];
};
export default function TagSelection({ onChange, defaultValue }: Props) {
const { tags } = useTagStore();
const [options, setOptions] = useState<Options[]>([]);
useEffect(() => {
const formatedCollections = tags.map((e) => {
return { value: e.id, label: e.name };
});
setOptions(formatedCollections);
}, [tags]);
return (
<CreatableSelect
isClearable={false}
className="react-select-container"
classNamePrefix="react-select"
onChange={onChange}
options={options}
styles={styles}
defaultValue={defaultValue}
// menuPosition="fixed"
isMulti
/>
);
}

View File

@ -0,0 +1,69 @@
import { StylesConfig } from "react-select";
const font =
"ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Helvetica Neue, Arial, Noto Sans, sans-serif, Apple Color Emoji, Segoe UI Emoji, Segoe UI Symbol, Noto Color Emoji";
export const styles: StylesConfig = {
option: (styles, state) => ({
...styles,
fontFamily: font,
cursor: "pointer",
backgroundColor: state.isSelected ? "oklch(var(--p))" : "inherit",
"&:hover": {
backgroundColor: state.isSelected
? "oklch(var(--p))"
: "oklch(var(--nc))",
},
transition: "all 50ms",
}),
control: (styles, state) => ({
...styles,
fontFamily: font,
borderRadius: "0.375rem",
border: state.isFocused
? "1px solid oklch(var(--p))"
: "1px solid oklch(var(--nc))",
boxShadow: "none",
minHeight: "2.6rem",
}),
container: (styles, state) => ({
...styles,
height: "full",
borderRadius: "0.375rem",
lineHeight: "1.25rem",
// "@media screen and (min-width: 1024px)": {
// fontSize: "0.875rem",
// },
}),
input: (styles) => ({
...styles,
cursor: "text",
}),
dropdownIndicator: (styles) => ({
...styles,
cursor: "pointer",
}),
placeholder: (styles) => ({
...styles,
borderColor: "black",
}),
multiValue: (styles) => {
return {
...styles,
backgroundColor: "#0ea5e9",
color: "white",
};
},
multiValueLabel: (styles) => ({
...styles,
color: "white",
}),
multiValueRemove: (styles) => ({
...styles,
":hover": {
color: "white",
backgroundColor: "#38bdf8",
},
}),
menuPortal: (base) => ({ ...base, zIndex: 9999 }),
};

View File

@ -0,0 +1,4 @@
export interface Options {
label: string;
value?: string | number;
}