refactor, added slate, added editor, added book
This commit is contained in:
parent
bc250e73bb
commit
029b7e9353
33 changed files with 714 additions and 496 deletions
|
|
@ -1,16 +1,18 @@
|
|||
import { gql } from '@apollo/client';
|
||||
import { Skeleton, Stack } from '@chakra-ui/react';
|
||||
import { Stack } from '@chakra-ui/react';
|
||||
import { BooksListQuery } from '@generated/types';
|
||||
import { useState } from 'react';
|
||||
import { Pagination } from '../components/Pagination';
|
||||
import { WorkingList } from '../components/WorkingList';
|
||||
import { WorkingListSearch } from '../components/WorkingListSearch';
|
||||
import { ListSearch } from '../components/ListSearch';
|
||||
import { bookFragment } from '../fragments';
|
||||
import { usePaginatedQuery } from '../hooks/usePaginatedQuery';
|
||||
import { PaginatedListSkeleton } from './PaginatedListSkeleton';
|
||||
|
||||
export function BookSearchList() {
|
||||
const [workingSearchValue, setWorkingSearchValue] = useState<string>('');
|
||||
const [workingsListPage, setWorkingsListPage] = useState<number>(1);
|
||||
const [workingsListPageSize, setWorkingsListPageSize] = useState<number>(2);
|
||||
const [workingsListPageSize, setWorkingsListPageSize] = useState<number>(10);
|
||||
const startIndex = (workingsListPage - 1) * workingsListPageSize;
|
||||
|
||||
const { data } = usePaginatedQuery<BooksListQuery>({
|
||||
|
|
@ -26,35 +28,24 @@ export function BookSearchList() {
|
|||
|
||||
return (
|
||||
<>
|
||||
<ListSearch placeholder="Search works..." onSubmit={value => setWorkingSearchValue(value)} />
|
||||
{data != null ? (
|
||||
<>
|
||||
<WorkingListSearch
|
||||
onSubmit={value => {
|
||||
setWorkingSearchValue(value);
|
||||
}}
|
||||
/>
|
||||
|
||||
<WorkingList workingsList={[...data.bookMany.items]} />
|
||||
|
||||
{data.bookMany.items.length !== 0 && (
|
||||
<Pagination
|
||||
total={data.bookMany.total}
|
||||
page={workingsListPage}
|
||||
setPage={setWorkingsListPage}
|
||||
pageSize={workingsListPageSize}
|
||||
/>
|
||||
{data.bookMany.total > workingsListPageSize && (
|
||||
<Stack justifyContent="center" alignItems="center">
|
||||
<Pagination
|
||||
total={data.bookMany.total}
|
||||
page={workingsListPage}
|
||||
setPage={setWorkingsListPage}
|
||||
pageSize={workingsListPageSize}
|
||||
setPageSize={setWorkingsListPageSize}
|
||||
/>
|
||||
</Stack>
|
||||
)}
|
||||
</>
|
||||
) : (
|
||||
<>
|
||||
<Stack direction="row" justifyContent="center" alignItems="center" gap={2}>
|
||||
<Skeleton height={10} width="80%" />
|
||||
<Skeleton height={10} width="calc(20% - 6px)" />
|
||||
</Stack>
|
||||
<Skeleton height={20} />
|
||||
<Skeleton height={20} />
|
||||
<Skeleton height={20} />
|
||||
</>
|
||||
<PaginatedListSkeleton />
|
||||
)}
|
||||
</>
|
||||
);
|
||||
|
|
@ -64,21 +55,10 @@ const query = gql`
|
|||
query BooksList($input: BookManyInput!) {
|
||||
bookMany(input: $input) {
|
||||
items {
|
||||
id
|
||||
title
|
||||
description
|
||||
author {
|
||||
id
|
||||
username
|
||||
}
|
||||
updatedAt
|
||||
progressStatus
|
||||
ratingTotal
|
||||
reviewsTotal
|
||||
wordsTotal
|
||||
chaptersTotal
|
||||
...Book
|
||||
}
|
||||
total
|
||||
}
|
||||
}
|
||||
${bookFragment}
|
||||
`;
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import { Button, Card, Stack, Text, Wrap } from '@chakra-ui/react';
|
||||
import isHotkey from 'is-hotkey';
|
||||
import React, { KeyboardEvent, MouseEvent, useCallback, useMemo, useState } from 'react';
|
||||
import React, { KeyboardEvent, MouseEvent, useCallback, useMemo } from 'react';
|
||||
import { createEditor, Descendant, Editor, Element as SlateElement, Transforms } from 'slate';
|
||||
import { withHistory } from 'slate-history';
|
||||
import {
|
||||
|
|
@ -44,7 +44,7 @@ export function EditorSlate() {
|
|||
}
|
||||
}}
|
||||
>
|
||||
<RichTextExample />
|
||||
<EditorViewport />
|
||||
</Card.Body>
|
||||
</Card.Root>
|
||||
</>
|
||||
|
|
@ -65,7 +65,7 @@ type AlignType = (typeof TEXT_ALIGN_TYPES)[number];
|
|||
type ListType = (typeof LIST_TYPES)[number];
|
||||
type CustomElementFormat = CustomElementType | AlignType | ListType;
|
||||
|
||||
const RichTextExample = () => {
|
||||
function EditorViewport() {
|
||||
const renderElement = useCallback((props: RenderElementProps) => <Element {...props} />, []);
|
||||
const renderLeaf = useCallback((props: RenderLeafProps) => <Leaf {...props} />, []);
|
||||
const editor = useMemo(() => withHistory(withReact(createEditor())), []);
|
||||
|
|
@ -123,12 +123,17 @@ const RichTextExample = () => {
|
|||
<BlockButton format="right" icon="nf nf-fa-align_right" />
|
||||
<BlockButton format="justify" icon="nf nf-fa-align_justify" />
|
||||
</Wrap>
|
||||
<Stack width="100%" display="flex" justifyContent="center" alignItems="center">
|
||||
<Stack
|
||||
width="100%"
|
||||
maxWidth="100%"
|
||||
paddingX={3}
|
||||
display="flex"
|
||||
justifyContent="center"
|
||||
alignItems="center"
|
||||
>
|
||||
<Prose
|
||||
width="100%"
|
||||
height="100%"
|
||||
maxWidth="unset"
|
||||
maxHeight="unset"
|
||||
minWidth="100%"
|
||||
display="flex"
|
||||
justifyContent="center"
|
||||
alignItems="center"
|
||||
|
|
@ -137,7 +142,11 @@ const RichTextExample = () => {
|
|||
className="slate-editor"
|
||||
style={{
|
||||
outline: 'none',
|
||||
minWidth: '100%'
|
||||
minWidth: '100%',
|
||||
maxWidth: 'unset',
|
||||
maxHeight: '75vh',
|
||||
padding: 0,
|
||||
overflowY: 'auto'
|
||||
}}
|
||||
renderElement={renderElement}
|
||||
renderLeaf={renderLeaf}
|
||||
|
|
@ -158,9 +167,9 @@ const RichTextExample = () => {
|
|||
</Stack>
|
||||
</Slate>
|
||||
);
|
||||
};
|
||||
}
|
||||
|
||||
const toggleBlock = (editor: CustomEditor, format: CustomElementFormat) => {
|
||||
function toggleBlock(editor: CustomEditor, format: CustomElementFormat) {
|
||||
const isActive = isBlockActive(editor, format, isAlignType(format) ? 'align' : 'type');
|
||||
const isList = isListType(format);
|
||||
|
||||
|
|
@ -188,9 +197,9 @@ const toggleBlock = (editor: CustomEditor, format: CustomElementFormat) => {
|
|||
const block = { type: format, children: [] };
|
||||
Transforms.wrapNodes(editor, block);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
const toggleMark = (editor: CustomEditor, format: CustomTextKey) => {
|
||||
function toggleMark(editor: CustomEditor, format: CustomTextKey) {
|
||||
const isActive = isMarkActive(editor, format);
|
||||
|
||||
if (isActive) {
|
||||
|
|
@ -198,13 +207,13 @@ const toggleMark = (editor: CustomEditor, format: CustomTextKey) => {
|
|||
} else {
|
||||
Editor.addMark(editor, format, true);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
const isBlockActive = (
|
||||
function isBlockActive(
|
||||
editor: CustomEditor,
|
||||
format: CustomElementFormat,
|
||||
blockType: 'type' | 'align' = 'type'
|
||||
) => {
|
||||
) {
|
||||
const { selection } = editor;
|
||||
if (!selection) return false;
|
||||
|
||||
|
|
@ -223,15 +232,15 @@ const isBlockActive = (
|
|||
})
|
||||
);
|
||||
|
||||
return !!match;
|
||||
};
|
||||
return Boolean(match);
|
||||
}
|
||||
|
||||
const isMarkActive = (editor: CustomEditor, format: CustomTextKey) => {
|
||||
function isMarkActive(editor: CustomEditor, format: CustomTextKey) {
|
||||
const marks = Editor.marks(editor);
|
||||
return marks ? marks[format] === true : false;
|
||||
};
|
||||
}
|
||||
|
||||
const Element = ({ attributes, children, element }: RenderElementProps) => {
|
||||
function Element({ attributes, children, element }: RenderElementProps) {
|
||||
const style: React.CSSProperties = {};
|
||||
if (isAlignElement(element)) {
|
||||
style.textAlign = element.align as AlignType;
|
||||
|
|
@ -280,9 +289,9 @@ const Element = ({ attributes, children, element }: RenderElementProps) => {
|
|||
</p>
|
||||
);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
const Leaf = ({ attributes, children, leaf }: RenderLeafProps) => {
|
||||
function Leaf({ attributes, children, leaf }: RenderLeafProps) {
|
||||
if (leaf.bold) {
|
||||
children = <strong>{children}</strong>;
|
||||
}
|
||||
|
|
@ -300,7 +309,7 @@ const Leaf = ({ attributes, children, leaf }: RenderLeafProps) => {
|
|||
}
|
||||
|
||||
return <span {...attributes}>{children}</span>;
|
||||
};
|
||||
}
|
||||
|
||||
interface BlockButtonProps {
|
||||
format: CustomElementFormat;
|
||||
|
|
@ -308,7 +317,7 @@ interface BlockButtonProps {
|
|||
text?: string;
|
||||
}
|
||||
|
||||
const BlockButton = ({ format, icon, text }: BlockButtonProps) => {
|
||||
function BlockButton({ format, icon, text }: BlockButtonProps) {
|
||||
const editor = useSlate();
|
||||
return (
|
||||
<Button
|
||||
|
|
@ -325,7 +334,7 @@ const BlockButton = ({ format, icon, text }: BlockButtonProps) => {
|
|||
</Stack>
|
||||
</Button>
|
||||
);
|
||||
};
|
||||
}
|
||||
|
||||
interface MarkButtonProps {
|
||||
format: CustomTextKey;
|
||||
|
|
@ -333,7 +342,7 @@ interface MarkButtonProps {
|
|||
text?: string;
|
||||
}
|
||||
|
||||
const MarkButton = ({ format, icon, text }: MarkButtonProps) => {
|
||||
function MarkButton({ format, icon, text }: MarkButtonProps) {
|
||||
const editor = useSlate();
|
||||
return (
|
||||
<Button
|
||||
|
|
@ -347,16 +356,16 @@ const MarkButton = ({ format, icon, text }: MarkButtonProps) => {
|
|||
{text}
|
||||
</Button>
|
||||
);
|
||||
};
|
||||
}
|
||||
|
||||
const isAlignType = (format: CustomElementFormat): format is AlignType => {
|
||||
function isAlignType(format: CustomElementFormat): format is AlignType {
|
||||
return TEXT_ALIGN_TYPES.includes(format as AlignType);
|
||||
};
|
||||
}
|
||||
|
||||
const isListType = (format: CustomElementFormat): format is ListType => {
|
||||
function isListType(format: CustomElementFormat): format is ListType {
|
||||
return LIST_TYPES.includes(format as ListType);
|
||||
};
|
||||
}
|
||||
|
||||
const isAlignElement = (element: CustomElement): element is CustomElementWithAlign => {
|
||||
function isAlignElement(element: CustomElement): element is CustomElementWithAlign {
|
||||
return 'align' in element;
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,56 +0,0 @@
|
|||
import { Card, Heading } from '@chakra-ui/react';
|
||||
import { useState } from 'react';
|
||||
import { BaseEditor, createEditor, Descendant } from 'slate';
|
||||
import { Editable, ReactEditor, Slate, withReact } from 'slate-react';
|
||||
|
||||
type CustomElement = { type: 'paragraph'; children: CustomText[] };
|
||||
type CustomText = { text: string };
|
||||
|
||||
declare module 'slate' {
|
||||
interface CustomTypes {
|
||||
Editor: BaseEditor & ReactEditor;
|
||||
Element: CustomElement;
|
||||
Text: CustomText;
|
||||
}
|
||||
}
|
||||
|
||||
export function EditorSlate() {
|
||||
const initialValue: Descendant[] = [
|
||||
{
|
||||
type: 'paragraph',
|
||||
children: [{ text: 'A line of text in a paragraph.' }]
|
||||
}
|
||||
];
|
||||
|
||||
const [editor] = useState(() => withReact(createEditor()));
|
||||
return (
|
||||
// Add the editable component inside the context.
|
||||
<>
|
||||
<Card.Root
|
||||
variant={'subtle'}
|
||||
width="100%"
|
||||
maxWidth="840px"
|
||||
minHeight="sm"
|
||||
justifyContent="center"
|
||||
alignItems="center"
|
||||
>
|
||||
<Card.Header>
|
||||
<Heading textAlign="center">Editor</Heading>
|
||||
</Card.Header>
|
||||
<Card.Body
|
||||
width="90%"
|
||||
css={{
|
||||
'& *': {
|
||||
fontSize: 'revert',
|
||||
fontWeight: 'revert'
|
||||
}
|
||||
}}
|
||||
>
|
||||
<Slate editor={editor} initialValue={initialValue}>
|
||||
<Editable />
|
||||
</Slate>
|
||||
</Card.Body>
|
||||
</Card.Root>
|
||||
</>
|
||||
);
|
||||
}
|
||||
25
app/client/components/Link.tsx
Normal file
25
app/client/components/Link.tsx
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
import { Text } from '@chakra-ui/react';
|
||||
import { LinkProps as LinkExtended, Link as TanstackLink } from '@tanstack/react-router';
|
||||
import { ReactNode } from 'react';
|
||||
|
||||
interface LinkProps {
|
||||
children: ReactNode;
|
||||
to: LinkExtended['to'];
|
||||
link?: LinkExtended;
|
||||
}
|
||||
|
||||
export function Link(props: LinkProps) {
|
||||
return (
|
||||
<TanstackLink {...props}>
|
||||
<Text
|
||||
color="colorPalette.500"
|
||||
_hover={{
|
||||
textDecoration: 'underline',
|
||||
textDecorationColor: 'colorPalette.700'
|
||||
}}
|
||||
>
|
||||
{props.children}
|
||||
</Text>
|
||||
</TanstackLink>
|
||||
);
|
||||
}
|
||||
|
|
@ -1,7 +1,13 @@
|
|||
import { Button, Icon, Input, InputGroup, Stack } from '@chakra-ui/react';
|
||||
import { useState } from 'react';
|
||||
|
||||
export function WorkingListSearch({ onSubmit }: { onSubmit: (value: string) => void }) {
|
||||
export function ListSearch({
|
||||
placeholder,
|
||||
onSubmit
|
||||
}: {
|
||||
readonly placeholder?: string;
|
||||
readonly onSubmit: (value: string) => void;
|
||||
}) {
|
||||
const [searchValue, setSearchValue] = useState<string>('');
|
||||
return (
|
||||
<form
|
||||
|
|
@ -22,7 +28,8 @@ export function WorkingListSearch({ onSubmit }: { onSubmit: (value: string) => v
|
|||
<Input
|
||||
value={searchValue}
|
||||
onChange={event => setSearchValue(event.currentTarget.value)}
|
||||
placeholder="Search works..."
|
||||
onSubmit={event => event.preventDefault()}
|
||||
placeholder={placeholder}
|
||||
/>
|
||||
</InputGroup>
|
||||
<Button type="submit" border="none">
|
||||
17
app/client/components/PaginatedListSkeleton.tsx
Normal file
17
app/client/components/PaginatedListSkeleton.tsx
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
import { Skeleton, Stack } from '@chakra-ui/react';
|
||||
|
||||
export function PaginatedListSkeleton({ disableSearch }: { readonly disableSearch?: boolean }) {
|
||||
return (
|
||||
<>
|
||||
{!disableSearch && (
|
||||
<Stack direction="row" justifyContent="center" alignItems="center" gap={2}>
|
||||
<Skeleton height={10} width="80%" />
|
||||
<Skeleton height={10} width="calc(20% - 6px)" />
|
||||
</Stack>
|
||||
)}
|
||||
<Skeleton height={20} />
|
||||
<Skeleton height={20} />
|
||||
<Skeleton height={20} />
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
|
@ -11,6 +11,7 @@ export function Pagination({
|
|||
page: number;
|
||||
setPage: (value: number) => void;
|
||||
pageSize?: number;
|
||||
setPageSize?: (value: number) => void;
|
||||
}) {
|
||||
return (
|
||||
<ChakraPagination.Root
|
||||
|
|
|
|||
|
|
@ -1,7 +1,8 @@
|
|||
import { Card, List, Text } from '@chakra-ui/react';
|
||||
import { WorkingCardProps, WorkingListCard } from './WorkingListCard';
|
||||
import { WorkingListCard } from './WorkingListCard';
|
||||
import { BookOne } from '../interfaces';
|
||||
|
||||
export function WorkingList({ workingsList }: { workingsList: WorkingCardProps[] }) {
|
||||
export function WorkingList({ workingsList }: { workingsList: BookOne[] }) {
|
||||
return (
|
||||
<List.Root variant="plain" gap={4}>
|
||||
{workingsList.length !== 0 ? (
|
||||
|
|
|
|||
|
|
@ -1,23 +1,14 @@
|
|||
import { Badge, Box, Card, Heading, Link, Stack, Text } from '@chakra-ui/react';
|
||||
import { WorkingProgressStatus } from '@generated/types';
|
||||
import { Badge, Box, Card, Heading, Stack, Text } from '@chakra-ui/react';
|
||||
import { Link } from '@tanstack/react-router';
|
||||
import { toFormattedDate } from '../helpers';
|
||||
import { BookOne } from '../interfaces';
|
||||
import { IconBadge } from './IconBadge';
|
||||
import { WorkingProgressStatusBadge } from './WorkingProgressStatusBadge';
|
||||
import { WorkingRatingBadge } from './WorkingRatingBadge';
|
||||
|
||||
export interface WorkingCardProps {
|
||||
id: string;
|
||||
title: string;
|
||||
description: string;
|
||||
author: { id: string; username: string };
|
||||
progressStatus: WorkingProgressStatus;
|
||||
updatedAt: string;
|
||||
chaptersTotal: number;
|
||||
wordsTotal: number;
|
||||
ratingTotal: number;
|
||||
reviewsTotal: number;
|
||||
}
|
||||
import { WorkingReviewsBadge } from './WorkingReviewsTotalBadge';
|
||||
|
||||
export function WorkingListCard({
|
||||
id,
|
||||
title,
|
||||
description,
|
||||
author,
|
||||
|
|
@ -27,29 +18,47 @@ export function WorkingListCard({
|
|||
wordsTotal,
|
||||
ratingTotal,
|
||||
reviewsTotal
|
||||
}: WorkingCardProps) {
|
||||
}: BookOne) {
|
||||
return (
|
||||
<Card.Root width="100%" variant="elevated">
|
||||
<Card.Body>
|
||||
<Stack>
|
||||
<Stack direction="row" justifyContent="space-between">
|
||||
<Link>
|
||||
<Heading size="lg">{title}</Heading>
|
||||
</Link>
|
||||
<Text as="div" minWidth={0}>
|
||||
<Link to={`/work/book/${id}`}>
|
||||
<Heading
|
||||
color="colorPalette.400"
|
||||
_hover={{
|
||||
textDecoration: 'underline',
|
||||
textDecorationColor: 'colorPalette.700'
|
||||
}}
|
||||
>
|
||||
{title}
|
||||
</Heading>
|
||||
</Link>
|
||||
</Text>
|
||||
|
||||
<Stack direction="row" justifyContent="center" alignItems="center">
|
||||
<WorkingRatingBadge ratingTotal={ratingTotal} />
|
||||
<IconBadge backgroundColor="orange.400" iconClass="nf nf-oct-comment">
|
||||
<Text>{reviewsTotal}</Text>
|
||||
</IconBadge>
|
||||
<WorkingReviewsBadge reviewsTotal={reviewsTotal} />
|
||||
<WorkingProgressStatusBadge progressStatus={progressStatus} />
|
||||
</Stack>
|
||||
</Stack>
|
||||
|
||||
<Stack>
|
||||
<Stack direction="row">
|
||||
<Text>by:</Text>
|
||||
<Link>{author.username}</Link>
|
||||
<Link>by:</Link>
|
||||
<Link to={`/profile/${author.username}`}>
|
||||
<Text
|
||||
color="colorPalette.400"
|
||||
_hover={{
|
||||
textDecoration: 'underline',
|
||||
textDecorationColor: 'colorPalette.700'
|
||||
}}
|
||||
>
|
||||
{author.username}
|
||||
</Text>
|
||||
</Link>
|
||||
</Stack>
|
||||
|
||||
<Stack direction="row">
|
||||
|
|
@ -57,7 +66,7 @@ export function WorkingListCard({
|
|||
<Badge size="md" variant="solid">
|
||||
<Stack direction="row">
|
||||
<Text>last updated:</Text>
|
||||
<Text>{updatedAt}</Text>
|
||||
<Text>{toFormattedDate({ value: updatedAt })}</Text>
|
||||
</Stack>
|
||||
</Badge>
|
||||
</Box>
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ export function WorkingProgressStatusBadge({
|
|||
progressStatus: WorkingProgressStatus;
|
||||
}) {
|
||||
return (
|
||||
<Box flex={1} justifyContent="center" alignItems="center">
|
||||
<Box>
|
||||
<Badge
|
||||
variant="solid"
|
||||
backgroundColor={toBgColorByProgressStatus(progressStatus)}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { BadgeProps, Text } from '@chakra-ui/react';
|
||||
import { BadgeProps, Box, Text } from '@chakra-ui/react';
|
||||
import { IconBadge } from './IconBadge';
|
||||
|
||||
interface WorkingRatingParams {
|
||||
|
|
@ -21,8 +21,10 @@ export function WorkingRatingBadge({ ratingTotal }: { ratingTotal: number }) {
|
|||
iconClass: 'nf nf-fa-angle_down'
|
||||
};
|
||||
return (
|
||||
<IconBadge backgroundColor={ratingParams.color} iconClass={ratingParams.iconClass}>
|
||||
<Text>{ratingParams.rating}</Text>
|
||||
</IconBadge>
|
||||
<Box>
|
||||
<IconBadge backgroundColor={ratingParams.color} iconClass={ratingParams.iconClass}>
|
||||
<Text>{ratingParams.rating}</Text>
|
||||
</IconBadge>
|
||||
</Box>
|
||||
);
|
||||
}
|
||||
|
|
|
|||
12
app/client/components/WorkingReviewsTotalBadge.tsx
Normal file
12
app/client/components/WorkingReviewsTotalBadge.tsx
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
import { Box, Text } from '@chakra-ui/react';
|
||||
import { IconBadge } from './IconBadge';
|
||||
|
||||
export function WorkingReviewsBadge({ reviewsTotal }: { readonly reviewsTotal: number }) {
|
||||
return (
|
||||
<Box>
|
||||
<IconBadge backgroundColor="orange.400" iconClass="nf nf-oct-comment">
|
||||
<Text>{reviewsTotal}</Text>
|
||||
</IconBadge>
|
||||
</Box>
|
||||
);
|
||||
}
|
||||
|
|
@ -1,26 +1,22 @@
|
|||
import { Link as ChakraLink } from "@chakra-ui/react";
|
||||
import { createLink, LinkComponent } from "@tanstack/react-router";
|
||||
import * as React from "react";
|
||||
import { Link as ChakraLink } from '@chakra-ui/react';
|
||||
import { createLink, LinkComponent } from '@tanstack/react-router';
|
||||
import * as React from 'react';
|
||||
|
||||
interface ChakraLinkProps
|
||||
extends Omit<React.ComponentPropsWithoutRef<typeof ChakraLink>, "href"> {}
|
||||
interface ChakraLinkProps extends Omit<React.ComponentPropsWithoutRef<typeof ChakraLink>, 'href'> {}
|
||||
|
||||
const ChakraLinkComponent = React.forwardRef<
|
||||
HTMLAnchorElement,
|
||||
ChakraLinkProps
|
||||
>((props, ref) => {
|
||||
const ChakraLinkComponent = React.forwardRef<HTMLAnchorElement, ChakraLinkProps>((props, ref) => {
|
||||
return <ChakraLink ref={ref} {...props} />;
|
||||
});
|
||||
|
||||
const CreatedLinkComponent = createLink(ChakraLinkComponent);
|
||||
|
||||
export const Link: LinkComponent<typeof ChakraLinkComponent> = (props) => {
|
||||
export const Link: LinkComponent<typeof ChakraLinkComponent> = props => {
|
||||
return (
|
||||
<CreatedLinkComponent
|
||||
textDecoration={"underline"}
|
||||
_hover={{ textDecoration: "none" }}
|
||||
_focus={{ textDecoration: "none" }}
|
||||
preload={"intent"}
|
||||
textDecoration={'underline'}
|
||||
_hover={{ textDecoration: 'none' }}
|
||||
_focus={{ textDecoration: 'none' }}
|
||||
preload={'intent'}
|
||||
{...props}
|
||||
/>
|
||||
);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue