feat: use eslint-plugin-react
This commit is contained in:
parent
083a7ac106
commit
b1405a614b
|
|
@ -1,5 +1,5 @@
|
|||
module.exports = {
|
||||
extends: ["next/core-web-vitals", "plugin:import/recommended"],
|
||||
extends: ["next/core-web-vitals", "plugin:import/recommended", "plugin:react/recommended"],
|
||||
root: true,
|
||||
settings: {
|
||||
"import/resolver": {
|
||||
|
|
@ -8,11 +8,12 @@ module.exports = {
|
|||
},
|
||||
plugins: ["unused-imports"],
|
||||
rules: {
|
||||
"no-unused-vars": "off",
|
||||
"@typescript-eslint/no-unused-vars": "off",
|
||||
"unused-imports/no-unused-imports": "error",
|
||||
"import/named": "off",
|
||||
"import/no-anonymous-default-export": "off",
|
||||
"import/no-named-as-default": "off",
|
||||
"react/react-in-jsx-scope": "off",
|
||||
"react-hooks/exhaustive-deps": "off",
|
||||
"import/no-named-as-default-member": "off",
|
||||
},
|
||||
}
|
||||
|
|
|
|||
|
|
@ -19,7 +19,8 @@
|
|||
"docker:db": "docker-compose -f docker-compose.db.yml up -d",
|
||||
"spell-check": "cspell lint . --no-progress",
|
||||
"analyze": "NODE_ENV=production ANALYZE=true BUNDLE_ANALYZE=browser next build",
|
||||
"postinstall": "prisma generate"
|
||||
"postinstall": "prisma generate",
|
||||
"lint": "next lint"
|
||||
},
|
||||
"lint-staged": {
|
||||
"*.{js,jsx,ts,tsx}": [
|
||||
|
|
@ -187,6 +188,7 @@
|
|||
"eslint": "8.42.0",
|
||||
"eslint-config-next": "13.4.4",
|
||||
"eslint-plugin-import": "2.27.5",
|
||||
"eslint-plugin-react": "7.32.2",
|
||||
"eslint-plugin-unused-imports": "2.0.0",
|
||||
"husky": "8.0.3",
|
||||
"lint-staged": "13.2.2",
|
||||
|
|
|
|||
|
|
@ -478,6 +478,9 @@ devDependencies:
|
|||
eslint-plugin-import:
|
||||
specifier: 2.27.5
|
||||
version: 2.27.5(@typescript-eslint/parser@5.59.8)(eslint-import-resolver-typescript@3.5.5)(eslint@8.42.0)
|
||||
eslint-plugin-react:
|
||||
specifier: 7.32.2
|
||||
version: 7.32.2(eslint@8.42.0)
|
||||
eslint-plugin-unused-imports:
|
||||
specifier: 2.0.0
|
||||
version: 2.0.0(eslint@8.42.0)
|
||||
|
|
@ -6439,7 +6442,7 @@ packages:
|
|||
dev: true
|
||||
|
||||
/concat-map@0.0.1:
|
||||
resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==}
|
||||
resolution: {integrity: sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=}
|
||||
|
||||
/configstore@5.0.1:
|
||||
resolution: {integrity: sha512-aMKprgk5YhBNyH25hj8wGt2+D52Sw1DRRIzqBwLp2Ya9mFmY8KPvvtvmna8SxVR9JMZ4kzMD68N22vlaRpkeFA==}
|
||||
|
|
|
|||
|
|
@ -288,6 +288,7 @@ async function Home() {
|
|||
href={getSiteLink({ subdomain: "xlog" })}
|
||||
role="button"
|
||||
className="button is-black rounded-lg"
|
||||
rel="noreferrer"
|
||||
>
|
||||
{t(`features.${feature.title}.extra.button`)}
|
||||
</a>
|
||||
|
|
|
|||
|
|
@ -6,7 +6,6 @@ import { nanoid } from "nanoid"
|
|||
import { useParams, useRouter, useSearchParams } from "next/navigation"
|
||||
import {
|
||||
ChangeEvent,
|
||||
FC,
|
||||
memo,
|
||||
useCallback,
|
||||
useEffect,
|
||||
|
|
@ -729,16 +728,7 @@ export default function SubdomainEditor() {
|
|||
)
|
||||
}
|
||||
|
||||
const EditorExtraProperties: FC<{
|
||||
updateValue: <K extends keyof Values>(key: K, value: Values[K]) => void
|
||||
isPost: boolean
|
||||
|
||||
subdomain: string
|
||||
defaultSlug: string
|
||||
userTags: string[]
|
||||
|
||||
openAdvancedOptions: () => void
|
||||
}> = memo(
|
||||
const EditorExtraProperties = memo(
|
||||
({
|
||||
isPost,
|
||||
updateValue,
|
||||
|
|
@ -746,6 +736,15 @@ const EditorExtraProperties: FC<{
|
|||
defaultSlug,
|
||||
userTags,
|
||||
openAdvancedOptions,
|
||||
}: {
|
||||
updateValue: <K extends keyof Values>(key: K, value: Values[K]) => void
|
||||
isPost: boolean
|
||||
|
||||
subdomain: string
|
||||
defaultSlug: string
|
||||
userTags: string[]
|
||||
|
||||
openAdvancedOptions: () => void
|
||||
}) => {
|
||||
const values = useEditorState(
|
||||
(state) =>
|
||||
|
|
@ -918,13 +917,17 @@ const EditorExtraProperties: FC<{
|
|||
|
||||
EditorExtraProperties.displayName = "EditorExtraProperties"
|
||||
|
||||
const EditorAdvancedOptions: FC<{
|
||||
updateValue: <K extends keyof Values>(key: K, value: Values[K]) => void
|
||||
const EditorAdvancedOptions = memo(
|
||||
({
|
||||
updateValue,
|
||||
isAdvancedOptionsOpen,
|
||||
setIsAdvancedOptionsOpen,
|
||||
}: {
|
||||
updateValue: <K extends keyof Values>(key: K, value: Values[K]) => void
|
||||
|
||||
isAdvancedOptionsOpen: boolean
|
||||
setIsAdvancedOptionsOpen: (state: boolean) => void
|
||||
}> = memo(
|
||||
({ updateValue, isAdvancedOptionsOpen, setIsAdvancedOptionsOpen }) => {
|
||||
isAdvancedOptionsOpen: boolean
|
||||
setIsAdvancedOptionsOpen: (state: boolean) => void
|
||||
}) => {
|
||||
const values = useEditorState(
|
||||
(state) => pick(state, ["disableAISummary"]),
|
||||
shallow,
|
||||
|
|
|
|||
|
|
@ -18,11 +18,15 @@ type UpdateItem = (id: string, newItem: Partial<SiteNavigationItem>) => void
|
|||
|
||||
type RemoveItem = (id: string) => void
|
||||
|
||||
const SortableNavigationItem: React.FC<{
|
||||
const SortableNavigationItem = ({
|
||||
item,
|
||||
updateItem,
|
||||
removeItem,
|
||||
}: {
|
||||
item: SiteNavigationItem
|
||||
updateItem: UpdateItem
|
||||
removeItem: RemoveItem
|
||||
}> = ({ item, updateItem, removeItem }) => {
|
||||
}) => {
|
||||
const { t } = useTranslation("dashboard")
|
||||
return (
|
||||
<div className="flex space-x-5 border-b p-5 bg-zinc-50 last:border-0">
|
||||
|
|
@ -172,6 +176,7 @@ export default function SiteSettingsNavigationPage() {
|
|||
/>
|
||||
)
|
||||
})}
|
||||
{/* eslint-disable-next-line react/no-unknown-property */}
|
||||
<style jsx global>{`
|
||||
.sortable-ghost {
|
||||
opacity: 0.4;
|
||||
|
|
|
|||
|
|
@ -27,12 +27,17 @@ import {
|
|||
|
||||
type RemoveItem = (operator: string) => void
|
||||
|
||||
const SortableNavigationItem: React.FC<{
|
||||
const SortableNavigationItem = ({
|
||||
item,
|
||||
removeItem,
|
||||
isLoading,
|
||||
disabled,
|
||||
}: {
|
||||
item: string
|
||||
removeItem: RemoveItem
|
||||
isLoading: boolean
|
||||
disabled?: boolean
|
||||
}> = ({ item, removeItem, isLoading, disabled }) => {
|
||||
}) => {
|
||||
const { t } = useTranslation("dashboard")
|
||||
return (
|
||||
<div className="flex space-x-5 border-b p-5 bg-zinc-50 last:border-0 items-center">
|
||||
|
|
@ -241,6 +246,7 @@ export default function SettingsOperatorPage() {
|
|||
/>
|
||||
)
|
||||
})}
|
||||
{/* eslint-disable-next-line react/no-unknown-property */}
|
||||
<style jsx global>{`
|
||||
.sortable-ghost {
|
||||
opacity: 0.4;
|
||||
|
|
|
|||
|
|
@ -27,11 +27,15 @@ type UpdateItem = (id: string, newItem: Partial<Item>) => void
|
|||
|
||||
type RemoveItem = (id: string) => void
|
||||
|
||||
const SortableNavigationItem: React.FC<{
|
||||
const SortableNavigationItem = ({
|
||||
item,
|
||||
updateItem,
|
||||
removeItem,
|
||||
}: {
|
||||
item: Item
|
||||
updateItem: UpdateItem
|
||||
removeItem: RemoveItem
|
||||
}> = ({ item, updateItem, removeItem }) => {
|
||||
}) => {
|
||||
const { t } = useTranslation("dashboard")
|
||||
return (
|
||||
<div className="flex space-x-5 border-b p-5 bg-zinc-50 last:border-0">
|
||||
|
|
@ -213,6 +217,7 @@ export default function SiteSettingsNavigationPage() {
|
|||
/>
|
||||
)
|
||||
})}
|
||||
{/* eslint-disable-next-line react/no-unknown-property */}
|
||||
<style jsx global>{`
|
||||
.sortable-ghost {
|
||||
opacity: 0.4;
|
||||
|
|
|
|||
|
|
@ -34,13 +34,19 @@ export const Badge = ({
|
|||
)
|
||||
}
|
||||
|
||||
export const AchievementItem: React.FC<{
|
||||
export const AchievementItem = ({
|
||||
group,
|
||||
layoutId,
|
||||
size,
|
||||
characterId,
|
||||
isOwner,
|
||||
}: {
|
||||
group: AchievementSection["groups"][number]
|
||||
layoutId: string
|
||||
size?: number
|
||||
characterId?: number
|
||||
isOwner: boolean
|
||||
}> = ({ group, layoutId, size, characterId, isOwner }) => {
|
||||
}) => {
|
||||
const date = useDate()
|
||||
const { t } = useTranslation("common")
|
||||
|
||||
|
|
|
|||
|
|
@ -12,14 +12,21 @@ import { cn } from "~/lib/utils"
|
|||
import type { AchievementSection } from "~/models/site.model"
|
||||
import { useMintAchievement } from "~/queries/site"
|
||||
|
||||
export const AchievementModal: React.FC<{
|
||||
export const AchievementModal = ({
|
||||
opened,
|
||||
setOpened,
|
||||
group,
|
||||
layoutId,
|
||||
isOwner,
|
||||
characterId,
|
||||
}: {
|
||||
opened: boolean
|
||||
setOpened: (value: boolean) => void
|
||||
group: AchievementSection["groups"][number]
|
||||
layoutId: string
|
||||
isOwner: boolean
|
||||
characterId?: number
|
||||
}> = ({ opened, setOpened, group, layoutId, isOwner, characterId }) => {
|
||||
}) => {
|
||||
const date = useDate()
|
||||
const { t } = useTranslation("common")
|
||||
|
||||
|
|
|
|||
|
|
@ -10,10 +10,13 @@ import { ExpandedCharacter, ExpandedNote } from "~/lib/types"
|
|||
import { cn } from "~/lib/utils"
|
||||
import { useGetGreenfieldId } from "~/queries/site"
|
||||
|
||||
export const BlockchainInfo: React.FC<{
|
||||
export const BlockchainInfo = ({
|
||||
site,
|
||||
page,
|
||||
}: {
|
||||
site?: ExpandedCharacter
|
||||
page?: ExpandedNote
|
||||
}> = ({ site, page }) => {
|
||||
}) => {
|
||||
const { t } = useTranslation("common")
|
||||
|
||||
const ipfs = (page ? page.metadata?.uri : site?.metadata?.uri) || ""
|
||||
|
|
|
|||
|
|
@ -8,15 +8,7 @@ import { useTranslation } from "~/lib/i18n/client"
|
|||
import { cn } from "~/lib/utils"
|
||||
import { useGetCharacterCard } from "~/queries/site"
|
||||
|
||||
export const CharacterCard: React.FC<{
|
||||
siteId?: string
|
||||
address?: string
|
||||
open?: boolean
|
||||
setButtonLoading?: (loading: boolean) => void
|
||||
hideFollowButton?: boolean
|
||||
simple?: boolean
|
||||
style?: "flat" | "normal"
|
||||
}> = ({
|
||||
export const CharacterCard = ({
|
||||
siteId,
|
||||
address,
|
||||
open,
|
||||
|
|
@ -24,6 +16,14 @@ export const CharacterCard: React.FC<{
|
|||
hideFollowButton,
|
||||
simple,
|
||||
style,
|
||||
}: {
|
||||
siteId?: string
|
||||
address?: string
|
||||
open?: boolean
|
||||
setButtonLoading?: (loading: boolean) => void
|
||||
hideFollowButton?: boolean
|
||||
simple?: boolean
|
||||
style?: "flat" | "normal"
|
||||
}) => {
|
||||
const date = useDate()
|
||||
const { t } = useTranslation("common")
|
||||
|
|
|
|||
|
|
@ -19,10 +19,13 @@ import { CharacterCard } from "~/components/common/CharacterCard"
|
|||
|
||||
import { Portal } from "./Portal"
|
||||
|
||||
export const CharacterFloatCard: React.FC<{
|
||||
export const CharacterFloatCard = ({
|
||||
siteId,
|
||||
children,
|
||||
}: {
|
||||
siteId?: string
|
||||
children: JSX.Element
|
||||
}> = ({ siteId, children }) => {
|
||||
}) => {
|
||||
const [open, setOpen] = useState(false)
|
||||
|
||||
const { x, y, refs, strategy, context } = useFloating({
|
||||
|
|
|
|||
|
|
@ -9,7 +9,14 @@ import { Button } from "../ui/Button"
|
|||
import CharacterListItem from "./CharacterListItem"
|
||||
import { PortalProvider } from "./Portal"
|
||||
|
||||
export const CharacterList: React.FC<{
|
||||
export const CharacterList = ({
|
||||
open,
|
||||
setOpen,
|
||||
hasMore,
|
||||
loadMore,
|
||||
list,
|
||||
title,
|
||||
}: {
|
||||
open: boolean
|
||||
setOpen: (open: boolean) => void
|
||||
hasMore: boolean
|
||||
|
|
@ -18,7 +25,7 @@ export const CharacterList: React.FC<{
|
|||
list: any[]
|
||||
} | null)[]
|
||||
title: string
|
||||
}> = ({ open, setOpen, hasMore, loadMore, list, title }) => {
|
||||
}) => {
|
||||
const { t } = useTranslation("common")
|
||||
const flattenList = list?.reduce(
|
||||
(acc, cur) => acc.concat(cur?.list || []),
|
||||
|
|
|
|||
|
|
@ -11,10 +11,13 @@ import { Avatar } from "../ui/Avatar"
|
|||
import { UniLink } from "../ui/UniLink"
|
||||
import { FollowingButton } from "./FollowingButton"
|
||||
|
||||
const CharacterListItem: React.FC<{
|
||||
const CharacterListItem = ({
|
||||
character,
|
||||
sub,
|
||||
}: {
|
||||
character: ExpandedCharacter
|
||||
sub: any
|
||||
}> = ({ character, sub }) => {
|
||||
}) => {
|
||||
return (
|
||||
<div className="py-3 flex items-center justify-between space-x-2 text-sm px-5">
|
||||
<div className="flex flex-1 overflow-hidden space-x-2">
|
||||
|
|
|
|||
|
|
@ -9,10 +9,13 @@ import { ExpandedNote } from "~/lib/types"
|
|||
import { cn } from "~/lib/utils"
|
||||
import { useGetComments } from "~/queries/page"
|
||||
|
||||
export const Comment: React.FC<{
|
||||
export const Comment = ({
|
||||
page,
|
||||
className,
|
||||
}: {
|
||||
page?: ExpandedNote
|
||||
className?: string
|
||||
}> = ({ page, className }) => {
|
||||
}) => {
|
||||
const comments = useGetComments({
|
||||
characterId: page?.characterId,
|
||||
noteId: page?.noteId,
|
||||
|
|
|
|||
|
|
@ -17,7 +17,14 @@ import { CodeMirrorEditor } from "../ui/CodeMirror"
|
|||
import { Input } from "../ui/Input"
|
||||
import { EmojiPicker } from "./EmojiPicker"
|
||||
|
||||
export const CommentInput: React.FC<{
|
||||
export const CommentInput = ({
|
||||
characterId,
|
||||
noteId,
|
||||
originalCharacterId,
|
||||
originalNoteId,
|
||||
onSubmitted,
|
||||
comment,
|
||||
}: {
|
||||
characterId?: number
|
||||
noteId?: number
|
||||
originalCharacterId?: number
|
||||
|
|
@ -26,13 +33,6 @@ export const CommentInput: React.FC<{
|
|||
comment?: NoteEntity & {
|
||||
character?: CharacterEntity | null
|
||||
}
|
||||
}> = ({
|
||||
characterId,
|
||||
noteId,
|
||||
originalCharacterId,
|
||||
originalNoteId,
|
||||
onSubmitted,
|
||||
comment,
|
||||
}) => {
|
||||
const account = useAccountState((s) => s.computed.account)
|
||||
const commentPage = useCommentPage()
|
||||
|
|
|
|||
|
|
@ -20,7 +20,13 @@ import { getSiteLink } from "~/lib/helpers"
|
|||
import { useTranslation } from "~/lib/i18n/client"
|
||||
import { cn } from "~/lib/utils"
|
||||
|
||||
export const CommentItem: React.FC<{
|
||||
export const CommentItem = ({
|
||||
comment,
|
||||
originalCharacterId,
|
||||
originalNoteId,
|
||||
depth,
|
||||
className,
|
||||
}: {
|
||||
comment: NoteEntity & {
|
||||
character?: CharacterEntity | null
|
||||
}
|
||||
|
|
@ -28,7 +34,7 @@ export const CommentItem: React.FC<{
|
|||
originalNoteId?: number
|
||||
depth: number
|
||||
className?: string
|
||||
}> = ({ comment, originalCharacterId, originalNoteId, depth, className }) => {
|
||||
}) => {
|
||||
const [replyOpen, setReplyOpen] = useState(false)
|
||||
const [editOpen, setEditOpen] = useState(false)
|
||||
|
||||
|
|
|
|||
|
|
@ -47,15 +47,7 @@ type HeaderLinkType = {
|
|||
}
|
||||
)
|
||||
|
||||
export const ConnectButton: React.FC<{
|
||||
left?: boolean
|
||||
variant?: Variant
|
||||
variantColor?: VariantColor
|
||||
size?: "base" | "sm"
|
||||
hideNotification?: boolean
|
||||
mobileSimplification?: boolean
|
||||
hideName?: boolean
|
||||
}> = ({
|
||||
export const ConnectButton = ({
|
||||
left,
|
||||
variant,
|
||||
variantColor,
|
||||
|
|
@ -63,6 +55,14 @@ export const ConnectButton: React.FC<{
|
|||
hideNotification,
|
||||
mobileSimplification,
|
||||
hideName,
|
||||
}: {
|
||||
left?: boolean
|
||||
variant?: Variant
|
||||
variantColor?: VariantColor
|
||||
size?: "base" | "sm"
|
||||
hideNotification?: boolean
|
||||
mobileSimplification?: boolean
|
||||
hideName?: boolean
|
||||
}) => {
|
||||
let avatarSize
|
||||
let sizeDecrease
|
||||
|
|
|
|||
|
|
@ -3,9 +3,11 @@ import { useTranslation } from "react-i18next"
|
|||
|
||||
import { useIsDark } from "~/hooks/useDarkMode"
|
||||
|
||||
export const EmojiPicker: React.FC<{
|
||||
export const EmojiPicker = ({
|
||||
onEmojiSelect,
|
||||
}: {
|
||||
onEmojiSelect: (e: any) => void
|
||||
}> = ({ onEmojiSelect }) => {
|
||||
}) => {
|
||||
const ref = useRef<any>()
|
||||
const isDark = useIsDark()
|
||||
|
||||
|
|
|
|||
|
|
@ -10,12 +10,17 @@ import { useTranslation } from "~/lib/i18n/client"
|
|||
import { getSubscriptionsFromList } from "~/models/site.model"
|
||||
import { useSubscribeToSites } from "~/queries/site"
|
||||
|
||||
export const FollowAllButton: React.FC<{
|
||||
export const FollowAllButton = ({
|
||||
size,
|
||||
characterIds = [],
|
||||
siteIds = [],
|
||||
className,
|
||||
}: {
|
||||
size?: "sm" | "xl"
|
||||
characterIds?: number[]
|
||||
siteIds?: string[]
|
||||
className?: string
|
||||
}> = ({ size, characterIds = [], siteIds = [], className }) => {
|
||||
}) => {
|
||||
const subscribeToSites = useSubscribeToSites()
|
||||
const { t } = useTranslation("index")
|
||||
const account = useAccountState((s) => s.computed.account)
|
||||
|
|
|
|||
|
|
@ -14,13 +14,19 @@ import {
|
|||
useUnsubscribeFromSite,
|
||||
} from "~/queries/site"
|
||||
|
||||
export const FollowingButton: React.FC<{
|
||||
export const FollowingButton = ({
|
||||
site,
|
||||
variant,
|
||||
className,
|
||||
size,
|
||||
loadingStatusChange,
|
||||
}: {
|
||||
site?: ExpandedCharacter
|
||||
variant?: Variant
|
||||
className?: string
|
||||
size?: "sm" | "xl"
|
||||
loadingStatusChange?: (status: boolean) => void
|
||||
}> = ({ site, variant, className, size, loadingStatusChange }) => {
|
||||
}) => {
|
||||
const subscribeToSite = useSubscribeToSite()
|
||||
const unsubscribeFromSite = useUnsubscribeFromSite()
|
||||
const { t, i18n } = useTranslation("common")
|
||||
|
|
|
|||
|
|
@ -8,10 +8,13 @@ import {
|
|||
useGetSiteToSubscriptions,
|
||||
} from "~/queries/site"
|
||||
|
||||
export const FollowingCount: React.FC<{
|
||||
export const FollowingCount = ({
|
||||
characterId,
|
||||
disableList,
|
||||
}: {
|
||||
characterId?: number
|
||||
disableList?: boolean
|
||||
}> = ({ characterId, disableList }) => {
|
||||
}) => {
|
||||
let [isFollowListOpen, setIsFollowListOpen] = useState(false)
|
||||
let [isToFollowListOpen, setIsToFollowListOpen] = useState(false)
|
||||
const { t } = useTranslation("common")
|
||||
|
|
|
|||
|
|
@ -7,13 +7,19 @@ import { Image } from "~/components/ui/Image"
|
|||
|
||||
import LogoLottieJSON from "../../../public/assets/logo.json"
|
||||
|
||||
export const Logo: React.FC<{
|
||||
export const Logo = ({
|
||||
type,
|
||||
width,
|
||||
height,
|
||||
loop,
|
||||
autoplay,
|
||||
}: {
|
||||
type: "svg" | "png" | "lottie"
|
||||
width?: number
|
||||
height?: number
|
||||
loop?: boolean
|
||||
autoplay?: boolean
|
||||
}> = ({ type, width, height, loop, autoplay }) => {
|
||||
}) => {
|
||||
const ref = useRef<LottieRefCurrentProps>(null)
|
||||
|
||||
switch (type) {
|
||||
|
|
|
|||
|
|
@ -10,19 +10,7 @@ import { ExpandedCharacter, ExpandedNote } from "~/lib/types"
|
|||
import { cn, scrollTo } from "~/lib/utils"
|
||||
import { renderPageContent } from "~/markdown"
|
||||
|
||||
export const PageContent: React.FC<{
|
||||
content?: string
|
||||
className?: string
|
||||
toc?: boolean
|
||||
inputRef?: MutableRefObject<HTMLDivElement | null>
|
||||
onScroll?: (scrollTop: number) => void
|
||||
onMouseEnter?: () => void
|
||||
parsedContent?: ReturnType<typeof renderPageContent>
|
||||
isComment?: boolean
|
||||
page?: ExpandedNote
|
||||
site?: ExpandedCharacter
|
||||
withActions?: boolean
|
||||
}> = ({
|
||||
export const PageContent = ({
|
||||
className,
|
||||
content,
|
||||
toc,
|
||||
|
|
@ -34,6 +22,18 @@ export const PageContent: React.FC<{
|
|||
page,
|
||||
site,
|
||||
withActions,
|
||||
}: {
|
||||
content?: string
|
||||
className?: string
|
||||
toc?: boolean
|
||||
inputRef?: MutableRefObject<HTMLDivElement | null>
|
||||
onScroll?: (scrollTop: number) => void
|
||||
onMouseEnter?: () => void
|
||||
parsedContent?: ReturnType<typeof renderPageContent>
|
||||
isComment?: boolean
|
||||
page?: ExpandedNote
|
||||
site?: ExpandedCharacter
|
||||
withActions?: boolean
|
||||
}) => {
|
||||
useCodeCopy()
|
||||
|
||||
|
|
|
|||
|
|
@ -6,12 +6,17 @@ import { useTranslation } from "~/lib/i18n/client"
|
|||
import { ExpandedCharacter } from "~/lib/types"
|
||||
import { cn } from "~/lib/utils"
|
||||
|
||||
export const PatronButton: React.FC<{
|
||||
export const PatronButton = ({
|
||||
site,
|
||||
className,
|
||||
size,
|
||||
loadingStatusChange,
|
||||
}: {
|
||||
site?: ExpandedCharacter
|
||||
className?: string
|
||||
size?: "sm" | "xl"
|
||||
loadingStatusChange?: (status: boolean) => void
|
||||
}> = ({ site, className, size, loadingStatusChange }) => {
|
||||
}) => {
|
||||
const { t } = useTranslation("common")
|
||||
const [open, setOpen] = useState(false)
|
||||
|
||||
|
|
|
|||
|
|
@ -18,12 +18,17 @@ import { Tabs } from "../ui/Tabs"
|
|||
import { UniLink } from "../ui/UniLink"
|
||||
import { CharacterFloatCard } from "./CharacterFloatCard"
|
||||
|
||||
export const PatronModal: React.FC<{
|
||||
export const PatronModal = ({
|
||||
site,
|
||||
page,
|
||||
open,
|
||||
setOpen,
|
||||
}: {
|
||||
site?: ExpandedCharacter
|
||||
page?: ExpandedNote
|
||||
open: boolean
|
||||
setOpen: (open: boolean) => void
|
||||
}> = ({ site, page, open, setOpen }) => {
|
||||
}) => {
|
||||
const { t } = useTranslation("common")
|
||||
const tipCharacter = useTipCharacter()
|
||||
const tips = useGetTips(
|
||||
|
|
|
|||
|
|
@ -7,10 +7,13 @@ import { useCheckComment, useGetComments } from "~/queries/page"
|
|||
|
||||
import { Button } from "../ui/Button"
|
||||
|
||||
export const ReactionComment: React.FC<{
|
||||
export const ReactionComment = ({
|
||||
characterId,
|
||||
noteId,
|
||||
}: {
|
||||
characterId?: number
|
||||
noteId?: number
|
||||
}> = ({ characterId, noteId }) => {
|
||||
}) => {
|
||||
const { t } = useTranslation("common")
|
||||
|
||||
const comments = useGetComments({
|
||||
|
|
|
|||
|
|
@ -20,12 +20,17 @@ import {
|
|||
import { AvatarStack } from "../ui/AvatarStack"
|
||||
import { Button } from "../ui/Button"
|
||||
|
||||
export const ReactionLike: React.FC<{
|
||||
export const ReactionLike = ({
|
||||
size,
|
||||
characterId,
|
||||
noteId,
|
||||
vertical,
|
||||
}: {
|
||||
size?: "sm" | "base"
|
||||
characterId?: number
|
||||
noteId?: number
|
||||
vertical?: boolean
|
||||
}> = ({ size, characterId, noteId, vertical }) => {
|
||||
}) => {
|
||||
const toggleLikePage = useToggleLikePage()
|
||||
const { t, i18n } = useTranslation("common")
|
||||
|
||||
|
|
|
|||
|
|
@ -18,12 +18,17 @@ import { useCheckMint, useGetMints, useMintPage } from "~/queries/page"
|
|||
import { AvatarStack } from "../ui/AvatarStack"
|
||||
import { Button } from "../ui/Button"
|
||||
|
||||
export const ReactionMint: React.FC<{
|
||||
export const ReactionMint = ({
|
||||
size,
|
||||
noteId,
|
||||
characterId,
|
||||
vertical,
|
||||
}: {
|
||||
size?: "sm" | "base"
|
||||
noteId?: number
|
||||
characterId?: number
|
||||
vertical?: boolean
|
||||
}> = ({ size, noteId, characterId, vertical }) => {
|
||||
}) => {
|
||||
const mintPage = useMintPage()
|
||||
const { t, i18n } = useTranslation("common")
|
||||
|
||||
|
|
|
|||
|
|
@ -15,13 +15,19 @@ import { useGetTips } from "~/queries/site"
|
|||
import { AvatarStack } from "../ui/AvatarStack"
|
||||
import { Button } from "../ui/Button"
|
||||
|
||||
export const ReactionTip: React.FC<{
|
||||
export const ReactionTip = ({
|
||||
characterId,
|
||||
noteId,
|
||||
site,
|
||||
page,
|
||||
vertical,
|
||||
}: {
|
||||
characterId?: number
|
||||
noteId?: number
|
||||
site?: ExpandedCharacter
|
||||
page?: ExpandedNote
|
||||
vertical?: boolean
|
||||
}> = ({ characterId, noteId, site, page, vertical }) => {
|
||||
}) => {
|
||||
const { t } = useTranslation("common")
|
||||
|
||||
const account = useAccountState((s) => s.computed.account)
|
||||
|
|
|
|||
|
|
@ -6,10 +6,13 @@ import { useForm } from "react-hook-form"
|
|||
import { useTranslation } from "~/lib/i18n/client"
|
||||
import { cn } from "~/lib/utils"
|
||||
|
||||
export const SearchInput: React.FC<{
|
||||
export const SearchInput = ({
|
||||
noBorder,
|
||||
onSubmit,
|
||||
}: {
|
||||
noBorder?: boolean
|
||||
onSubmit?: (value?: string) => void
|
||||
}> = ({ noBorder, onSubmit }) => {
|
||||
}) => {
|
||||
const router = useRouter()
|
||||
const searchParams = useSearchParams()
|
||||
const { t } = useTranslation("common")
|
||||
|
|
|
|||
|
|
@ -1,9 +1,12 @@
|
|||
import { toGateway } from "~/lib/ipfs-parser"
|
||||
|
||||
const Style: React.FC<{
|
||||
const Style = ({
|
||||
content,
|
||||
children,
|
||||
}: {
|
||||
content?: string
|
||||
children?: React.ReactNode[]
|
||||
}> = ({ content, children }) => {
|
||||
}) => {
|
||||
let css = content
|
||||
if (!css && typeof children?.[0] === "string") {
|
||||
css = children[0].trim()
|
||||
|
|
|
|||
|
|
@ -4,9 +4,7 @@ import { useEffect, useState } from "react"
|
|||
|
||||
import { useDate } from "~/hooks/useDate"
|
||||
|
||||
export const Time: React.FC<{
|
||||
isoString?: string
|
||||
}> = ({ isoString }) => {
|
||||
export const Time = ({ isoString }: { isoString?: string }) => {
|
||||
const date = useDate()
|
||||
const [isMounted, setIsMounted] = useState(false)
|
||||
|
||||
|
|
|
|||
|
|
@ -16,9 +16,7 @@ const icons: {
|
|||
},
|
||||
}
|
||||
|
||||
export const Titles: React.FC<{
|
||||
characterId?: number
|
||||
}> = ({ characterId }) => {
|
||||
export const Titles = ({ characterId }: { characterId?: number }) => {
|
||||
if (!characterId) {
|
||||
return null
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,12 +2,17 @@ import { useIsMobileLayout } from "~/hooks/useMobileLayout"
|
|||
import { useTranslation } from "~/lib/i18n/client"
|
||||
import { cn } from "~/lib/utils"
|
||||
|
||||
export const DashboardMain: React.FC<{
|
||||
export const DashboardMain = ({
|
||||
children,
|
||||
fullWidth,
|
||||
title,
|
||||
className,
|
||||
}: {
|
||||
children: React.ReactNode
|
||||
fullWidth?: boolean
|
||||
title?: string
|
||||
className?: string
|
||||
}> = ({ children, fullWidth, title, className }) => {
|
||||
}) => {
|
||||
const { t } = useTranslation("dashboard")
|
||||
const isMobileLayout = useIsMobileLayout()
|
||||
|
||||
|
|
|
|||
|
|
@ -2,9 +2,11 @@ import { useEffect, useState } from "react"
|
|||
|
||||
import { getStorage, setStorage } from "~/lib/storage"
|
||||
|
||||
export const DashboardSidebar: React.FC<{
|
||||
export const DashboardSidebar = ({
|
||||
children,
|
||||
}: {
|
||||
children: (isOpen: boolean) => React.ReactNode
|
||||
}> = ({ children }) => {
|
||||
}) => {
|
||||
const [isOpen, setIsOpen] = useState(true)
|
||||
|
||||
useEffect(() => {
|
||||
|
|
|
|||
|
|
@ -5,11 +5,15 @@ import { Bars3Icon } from "@heroicons/react/24/outline"
|
|||
|
||||
import { Logo } from "../common/Logo"
|
||||
|
||||
export const DashboardTopbar: React.FC<{
|
||||
export const DashboardTopbar = ({
|
||||
children,
|
||||
userWidget,
|
||||
drawerWidget,
|
||||
}: {
|
||||
children: (open: boolean) => React.ReactNode
|
||||
userWidget: React.ReactNode
|
||||
drawerWidget: (close: any) => React.ReactNode
|
||||
}> = ({ children, userWidget, drawerWidget }) => {
|
||||
}) => {
|
||||
const [isOpen, setIsOpen] = useState(false)
|
||||
|
||||
return (
|
||||
|
|
|
|||
|
|
@ -3,12 +3,17 @@ import { useTranslation } from "react-i18next"
|
|||
import { Button } from "../ui/Button"
|
||||
import { Modal } from "../ui/Modal"
|
||||
|
||||
export const DeleteConfirmationModal: React.FC<{
|
||||
export const DeleteConfirmationModal = ({
|
||||
open,
|
||||
setOpen,
|
||||
onConfirm,
|
||||
isPost,
|
||||
}: {
|
||||
open: boolean
|
||||
setOpen: (open: boolean) => void
|
||||
onConfirm: () => void
|
||||
isPost?: boolean
|
||||
}> = ({ open, setOpen, onConfirm, isPost }) => {
|
||||
}) => {
|
||||
const { t } = useTranslation("dashboard")
|
||||
|
||||
return (
|
||||
|
|
|
|||
|
|
@ -6,9 +6,7 @@ import { useTranslation } from "~/lib/i18n/client"
|
|||
|
||||
import { PageContent } from "../common/PageContent"
|
||||
|
||||
export const ImportPreview: React.FC<{
|
||||
note: NoteMetadata
|
||||
}> = ({ note }) => {
|
||||
export const ImportPreview = ({ note }: { note: NoteMetadata }) => {
|
||||
const date = useDate()
|
||||
const [showcaseMore, setShowcaseMore] = useState(false)
|
||||
const { t } = useTranslation("common")
|
||||
|
|
|
|||
|
|
@ -8,18 +8,7 @@ import { cn } from "~/lib/utils"
|
|||
|
||||
import { DeleteConfirmationModal } from "./DeleteConfirmationModal"
|
||||
|
||||
export const OptionsButton: React.FC<{
|
||||
visibility: PageVisibilityEnum | undefined
|
||||
previewPage: () => void
|
||||
renderPage: Dispatch<SetStateAction<boolean>>
|
||||
savePage: (published: boolean) => any
|
||||
propertiesWidget: React.ReactNode
|
||||
isRendering: boolean
|
||||
published: boolean
|
||||
isPost: boolean
|
||||
isModified: boolean
|
||||
discardChanges: () => void
|
||||
}> = ({
|
||||
export const OptionsButton = ({
|
||||
visibility,
|
||||
previewPage,
|
||||
savePage,
|
||||
|
|
@ -30,6 +19,17 @@ export const OptionsButton: React.FC<{
|
|||
isPost,
|
||||
isModified,
|
||||
discardChanges,
|
||||
}: {
|
||||
visibility: PageVisibilityEnum | undefined
|
||||
previewPage: () => void
|
||||
renderPage: Dispatch<SetStateAction<boolean>>
|
||||
savePage: (published: boolean) => any
|
||||
propertiesWidget: React.ReactNode
|
||||
isRendering: boolean
|
||||
published: boolean
|
||||
isPost: boolean
|
||||
isModified: boolean
|
||||
discardChanges: () => void
|
||||
}) => {
|
||||
const { t } = useTranslation("dashboard")
|
||||
|
||||
|
|
|
|||
|
|
@ -30,9 +30,7 @@ import { DashboardMain } from "./DashboardMain"
|
|||
import { PagesManagerBatchSelectActionTab } from "./PagesManagerBatchSelectActionTab"
|
||||
import { PagesManagerMenu } from "./PagesManagerMenu"
|
||||
|
||||
export const PagesManager: React.FC<{
|
||||
isPost: boolean
|
||||
}> = ({ isPost }) => {
|
||||
export const PagesManager = ({ isPost }: { isPost: boolean }) => {
|
||||
const params = useParams()
|
||||
const subdomain = params?.subdomain as string
|
||||
const site = useGetSite(subdomain)
|
||||
|
|
|
|||
|
|
@ -18,7 +18,13 @@ function getPageId(page: ExpandedNote) {
|
|||
return page.noteId || page.draftKey || 0
|
||||
}
|
||||
|
||||
export const PagesManagerBatchSelectActionTab: React.FC<{
|
||||
export const PagesManagerBatchSelectActionTab = ({
|
||||
isPost,
|
||||
isNotxLogContent,
|
||||
pages,
|
||||
batchSelected,
|
||||
setBatchSelected,
|
||||
}: {
|
||||
isPost: boolean
|
||||
isNotxLogContent: boolean
|
||||
pages?: InfiniteData<{
|
||||
|
|
@ -26,7 +32,7 @@ export const PagesManagerBatchSelectActionTab: React.FC<{
|
|||
}>
|
||||
batchSelected: (string | number)[]
|
||||
setBatchSelected: (selected: (string | number)[]) => void
|
||||
}> = ({ isPost, isNotxLogContent, pages, batchSelected, setBatchSelected }) => {
|
||||
}) => {
|
||||
const { t } = useTranslation("dashboard")
|
||||
|
||||
const params = useParams()
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import { useParams, useRouter } from "next/navigation"
|
||||
import { FC, useEffect, useState } from "react"
|
||||
import { useEffect, useState } from "react"
|
||||
import toast from "react-hot-toast"
|
||||
|
||||
import { Menu } from "@headlessui/react"
|
||||
|
|
@ -30,11 +30,15 @@ interface Item {
|
|||
icon: JSX.Element
|
||||
onClick: () => void
|
||||
}
|
||||
export const PagesManagerMenu: FC<{
|
||||
export const PagesManagerMenu = ({
|
||||
isPost,
|
||||
page,
|
||||
onClick: onClose,
|
||||
}: {
|
||||
isPost: boolean
|
||||
page: ExpandedNote
|
||||
onClick: () => void
|
||||
}> = ({ isPost, page, onClick: onClose }) => {
|
||||
}) => {
|
||||
const { t } = useTranslation("dashboard")
|
||||
|
||||
const isCrossbell = !page.metadata?.content?.sources?.includes("xlog")
|
||||
|
|
|
|||
|
|
@ -6,16 +6,7 @@ import { useTranslation } from "~/lib/i18n/client"
|
|||
import { Button, ButtonGroup } from "../ui/Button"
|
||||
import { DeleteConfirmationModal } from "./DeleteConfirmationModal"
|
||||
|
||||
export const PublishButton: React.FC<{
|
||||
save: (published: boolean) => void
|
||||
published: boolean
|
||||
isSaving: boolean
|
||||
isDisabled: boolean
|
||||
twitterShareUrl?: string
|
||||
isPost: boolean
|
||||
isModified: boolean
|
||||
discardChanges: () => void
|
||||
}> = ({
|
||||
export const PublishButton = ({
|
||||
save,
|
||||
discardChanges,
|
||||
published,
|
||||
|
|
@ -24,6 +15,15 @@ export const PublishButton: React.FC<{
|
|||
isModified,
|
||||
twitterShareUrl,
|
||||
isPost,
|
||||
}: {
|
||||
save: (published: boolean) => void
|
||||
published: boolean
|
||||
isSaving: boolean
|
||||
isDisabled: boolean
|
||||
twitterShareUrl?: string
|
||||
isPost: boolean
|
||||
isModified: boolean
|
||||
discardChanges: () => void
|
||||
}) => {
|
||||
const [showDropdown, setShowDropdown] = useState(false)
|
||||
const dropdownRef = useRef<HTMLDivElement | null>(null)
|
||||
|
|
|
|||
|
|
@ -8,10 +8,13 @@ import { useTranslation } from "~/lib/i18n/client"
|
|||
import { type TabItem, Tabs } from "../ui/Tabs"
|
||||
import { DashboardMain } from "./DashboardMain"
|
||||
|
||||
export const SettingsLayout: React.FC<{
|
||||
export const SettingsLayout = ({
|
||||
title,
|
||||
children,
|
||||
}: {
|
||||
title: string
|
||||
children: React.ReactNode
|
||||
}> = ({ title, children }) => {
|
||||
}) => {
|
||||
const { t } = useTranslation("dashboard")
|
||||
const xSettingsModal = useXSettingsModal()
|
||||
|
||||
|
|
|
|||
|
|
@ -225,10 +225,13 @@ const Post = ({
|
|||
|
||||
const MemoedPost = memo(Post)
|
||||
|
||||
export const HomeFeed: React.FC<{
|
||||
export const HomeFeed = ({
|
||||
noteIds,
|
||||
type,
|
||||
}: {
|
||||
noteIds?: string[]
|
||||
type?: FeedType
|
||||
}> = ({ noteIds, type }) => {
|
||||
}) => {
|
||||
const { t } = useTranslation("common")
|
||||
const searchParams = useSearchParams()
|
||||
|
||||
|
|
|
|||
|
|
@ -1,8 +1,6 @@
|
|||
import React from "react"
|
||||
|
||||
export const MintIcon: React.FC<React.ComponentPropsWithoutRef<"svg">> = (
|
||||
props,
|
||||
) => {
|
||||
export const MintIcon = (props: React.ComponentPropsWithoutRef<"svg">) => {
|
||||
return (
|
||||
<svg
|
||||
width="1em"
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ import { FABBase } from "../ui/FAB"
|
|||
const isShouldShow = () =>
|
||||
document.documentElement.scrollTop > document.documentElement.clientHeight
|
||||
|
||||
export const BackToTopFAB: React.FC<{}> = () => {
|
||||
export const BackToTopFAB = () => {
|
||||
const [shouldShow, setShouldShow] = useState(isShouldShow())
|
||||
useEffect(() => {
|
||||
const handler = throttle(() => {
|
||||
|
|
|
|||
|
|
@ -7,11 +7,15 @@ import { useUserRole } from "~/hooks/useUserRole"
|
|||
import { SITE_URL } from "~/lib/env"
|
||||
import { useTranslation } from "~/lib/i18n/client"
|
||||
|
||||
export const EditButton: React.FC<{
|
||||
export const EditButton = ({
|
||||
handle,
|
||||
noteId,
|
||||
isPost,
|
||||
}: {
|
||||
handle?: string
|
||||
noteId?: number
|
||||
isPost?: boolean
|
||||
}> = ({ handle, noteId, isPost }) => {
|
||||
}) => {
|
||||
const { t } = useTranslation("common")
|
||||
const [showEdit, setShowEdit] = useState(false)
|
||||
const userRole = useUserRole(handle)
|
||||
|
|
|
|||
|
|
@ -5,10 +5,13 @@ import React, { useCallback, useEffect, useState } from "react"
|
|||
import { useIsMobileLayout } from "~/hooks/useMobileLayout"
|
||||
import { useTranslation } from "~/lib/i18n/client"
|
||||
|
||||
export const OIAButton: React.FC<{
|
||||
export const OIAButton = ({
|
||||
link,
|
||||
isInRN,
|
||||
}: {
|
||||
link: `/${string}`
|
||||
isInRN: boolean
|
||||
}> = ({ link, isInRN }) => {
|
||||
}) => {
|
||||
const { t } = useTranslation("site")
|
||||
const [isVisible, setIsVisible] = useState(true)
|
||||
|
||||
|
|
|
|||
|
|
@ -135,11 +135,15 @@ export const PlatformsSyncMap: {
|
|||
},
|
||||
}
|
||||
|
||||
export const Platform: React.FC<{
|
||||
export const Platform = ({
|
||||
platform,
|
||||
username,
|
||||
className,
|
||||
}: {
|
||||
platform: string
|
||||
username: string
|
||||
className?: string
|
||||
}> = ({ platform, username, className }) => {
|
||||
}) => {
|
||||
platform = platform.toLowerCase()
|
||||
let link = PlatformsSyncMap[platform]?.url
|
||||
|
||||
|
|
|
|||
|
|
@ -10,10 +10,13 @@ import { ExpandedCharacter, ExpandedNote } from "~/lib/types"
|
|||
|
||||
import { usePostFooterInView } from "./PostFooter"
|
||||
|
||||
export const PostActions: React.FC<{
|
||||
export const PostActions = ({
|
||||
page,
|
||||
site,
|
||||
}: {
|
||||
page?: ExpandedNote
|
||||
site?: ExpandedCharacter
|
||||
}> = ({ page, site }) => {
|
||||
}) => {
|
||||
const containerRef = useRef<HTMLDivElement | null>(null)
|
||||
|
||||
const isPostFooterInView = usePostFooterInView()
|
||||
|
|
|
|||
|
|
@ -20,10 +20,13 @@ export const usePostFooterInView = () => {
|
|||
})
|
||||
return data
|
||||
}
|
||||
export const PostFooter: React.FC<{
|
||||
export const PostFooter = ({
|
||||
page,
|
||||
site,
|
||||
}: {
|
||||
page?: ExpandedNote
|
||||
site?: ExpandedCharacter
|
||||
}> = ({ page, site }) => {
|
||||
}) => {
|
||||
const actionElRef = useRef<HTMLDivElement>(null)
|
||||
const [isInView] = useInViewport(actionElRef)
|
||||
|
||||
|
|
|
|||
|
|
@ -128,9 +128,7 @@ function Items(props: ItemsProps) {
|
|||
)
|
||||
}
|
||||
|
||||
export const PostToc: React.FC<{
|
||||
data: TocResult
|
||||
}> = ({ data }) => {
|
||||
export const PostToc = ({ data }: { data: TocResult }) => {
|
||||
const containerRef = useRef<HTMLDivElement | null>(null)
|
||||
|
||||
const idList = getIds(data?.map)
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ import { useGetSite } from "~/queries/site"
|
|||
import { EmptyState } from "../ui/EmptyState"
|
||||
import { UniLink } from "../ui/UniLink"
|
||||
|
||||
export const SiteArchives: React.FC = () => {
|
||||
export const SiteArchives = () => {
|
||||
let currentLength = 0
|
||||
const date = useDate()
|
||||
const { t } = useTranslation("site")
|
||||
|
|
|
|||
|
|
@ -32,7 +32,7 @@ type HeaderLinkType = {
|
|||
onClick?: () => void
|
||||
}
|
||||
|
||||
const HeaderLink: React.FC<{ link: HeaderLinkType }> = ({ link }) => {
|
||||
const HeaderLink = ({ link }: { link: HeaderLinkType }) => {
|
||||
const pathname = usePathname()
|
||||
const { t } = useTranslation("site")
|
||||
|
||||
|
|
@ -51,9 +51,7 @@ const HeaderLink: React.FC<{ link: HeaderLinkType }> = ({ link }) => {
|
|||
)
|
||||
}
|
||||
|
||||
export const SiteHeader: React.FC<{
|
||||
handle: string
|
||||
}> = ({ handle }) => {
|
||||
export const SiteHeader = ({ handle }: { handle: string }) => {
|
||||
const site = useGetSite(handle)
|
||||
const { t } = useTranslation("site")
|
||||
const leftLinks: HeaderLinkType[] =
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ import { useGetSite } from "~/queries/site"
|
|||
|
||||
import { EmptyState } from "../ui/EmptyState"
|
||||
|
||||
export const SiteSearch: React.FC = () => {
|
||||
export const SiteSearch = () => {
|
||||
const router = useRouter()
|
||||
const { t } = useTranslation("site")
|
||||
const date = useDate()
|
||||
|
|
|
|||
|
|
@ -4,14 +4,7 @@ import { memo } from "react"
|
|||
|
||||
import { toGateway } from "~/lib/ipfs-parser"
|
||||
|
||||
const APlayer: React.FC<
|
||||
{
|
||||
name?: string
|
||||
artist?: string
|
||||
cover?: string
|
||||
lrc?: string
|
||||
} & React.AudioHTMLAttributes<HTMLAudioElement>
|
||||
> = memo(function APlayer({
|
||||
const APlayer = memo(function APlayer({
|
||||
src,
|
||||
name,
|
||||
artist,
|
||||
|
|
@ -20,7 +13,12 @@ const APlayer: React.FC<
|
|||
muted,
|
||||
autoPlay,
|
||||
loop,
|
||||
}) {
|
||||
}: {
|
||||
name?: string
|
||||
artist?: string
|
||||
cover?: string
|
||||
lrc?: string
|
||||
} & React.AudioHTMLAttributes<HTMLAudioElement>) {
|
||||
if (!src) return null
|
||||
|
||||
src = toGateway(src)
|
||||
|
|
|
|||
|
|
@ -4,15 +4,22 @@ import { Image } from "~/components/ui/Image"
|
|||
import { toGateway } from "~/lib/ipfs-parser"
|
||||
import { cn } from "~/lib/utils"
|
||||
|
||||
export const Avatar: React.FC<
|
||||
{
|
||||
images: (string | null | undefined)[]
|
||||
name?: string | null
|
||||
size?: number
|
||||
rounded?: boolean
|
||||
imageRef?: React.MutableRefObject<HTMLImageElement>
|
||||
} & React.HTMLAttributes<HTMLSpanElement>
|
||||
> = ({ images, size, name, className, rounded, imageRef, ...props }) => {
|
||||
export const Avatar = ({
|
||||
images,
|
||||
size,
|
||||
name,
|
||||
className,
|
||||
rounded,
|
||||
imageRef,
|
||||
...props
|
||||
}: {
|
||||
images: (string | null | undefined)[]
|
||||
name?: string | null
|
||||
size?: number
|
||||
rounded?: boolean
|
||||
imageRef?: React.MutableRefObject<HTMLImageElement>
|
||||
className?: string
|
||||
} & React.HTMLAttributes<HTMLSpanElement>) => {
|
||||
size = size || 60
|
||||
|
||||
const fontSize = size * 0.5
|
||||
|
|
|
|||
|
|
@ -2,10 +2,13 @@ import React from "react"
|
|||
|
||||
import { cn } from "~/lib/utils"
|
||||
|
||||
export const Badge: React.FC<{
|
||||
export const Badge = ({
|
||||
children,
|
||||
className,
|
||||
}: {
|
||||
children: React.ReactNode
|
||||
className?: string
|
||||
}> = ({ children, className }) => {
|
||||
}) => {
|
||||
return (
|
||||
<span
|
||||
className={cn(
|
||||
|
|
|
|||
|
|
@ -18,11 +18,15 @@ export type RadioItem = {
|
|||
default?: boolean
|
||||
}
|
||||
|
||||
export const BoxRadio: React.FC<{
|
||||
export const BoxRadio = ({
|
||||
value,
|
||||
setValue,
|
||||
items,
|
||||
}: {
|
||||
value: string
|
||||
setValue: Dispatch<SetStateAction<string>>
|
||||
items: RadioItem[]
|
||||
}> = ({ value, setValue, items }) => {
|
||||
}) => {
|
||||
const { t } = useTranslation("common")
|
||||
const randomId = useMemo(() => nanoid(), [])
|
||||
const [isCustom, setIsCustom] = useState(false)
|
||||
|
|
|
|||
|
|
@ -1,12 +1,13 @@
|
|||
/* eslint-disable react/prop-types */
|
||||
"use client"
|
||||
|
||||
import React, { memo } from "react"
|
||||
|
||||
import { cn } from "~/lib/utils"
|
||||
|
||||
export const ButtonGroup: React.FC<{ children: React.ReactNode }> = ({
|
||||
children,
|
||||
}) => {
|
||||
/* eslint-disable react/prop-types */
|
||||
|
||||
export const ButtonGroup = ({ children }: { children: React.ReactNode }) => {
|
||||
return <div className="button-group">{children}</div>
|
||||
}
|
||||
|
||||
|
|
@ -60,7 +61,7 @@ export const Button = memo(
|
|||
rounded,
|
||||
isAutoWidth,
|
||||
...props
|
||||
},
|
||||
}: React.ButtonHTMLAttributes<HTMLButtonElement> & ButtonProps,
|
||||
ref,
|
||||
) {
|
||||
return (
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
import {
|
||||
CSSProperties,
|
||||
FC,
|
||||
Suspense,
|
||||
createElement,
|
||||
forwardRef,
|
||||
|
|
@ -47,7 +46,7 @@ interface XLogCodeMirrorEditorProps {
|
|||
onUpdate?: (update: ViewUpdate) => void
|
||||
onCreateEditor?: (view: EditorView, state: EditorState) => void
|
||||
onMouseEnter?: () => void
|
||||
LoadingComponent?: FC
|
||||
LoadingComponent?: () => JSX.Element
|
||||
}
|
||||
|
||||
export const CodeMirrorEditor = forwardRef<
|
||||
|
|
|
|||
|
|
@ -1,15 +1,17 @@
|
|||
import { DPlayerProps, Player as RcDPlayer } from "rc-dplayer"
|
||||
import { FC, memo } from "react"
|
||||
import { memo } from "react"
|
||||
import { ReactElement } from "rehype-react/lib"
|
||||
|
||||
import { toGateway } from "~/lib/ipfs-parser"
|
||||
|
||||
const DPlayer: FC<
|
||||
{
|
||||
src?: string
|
||||
children?: ReactElement[]
|
||||
} & DPlayerProps
|
||||
> = memo(function DPlayer({ src, children, ...props }) {
|
||||
const DPlayer = memo(function DPlayer({
|
||||
src,
|
||||
children,
|
||||
...props
|
||||
}: {
|
||||
src?: string
|
||||
children?: ReactElement[]
|
||||
} & DPlayerProps) {
|
||||
const sources = children?.filter(
|
||||
(child) =>
|
||||
child && typeof child.type === "string" && child.type === "source",
|
||||
|
|
|
|||
|
|
@ -1,10 +1,11 @@
|
|||
import { FC, memo, useCallback, useState } from "react"
|
||||
/* eslint-disable react/prop-types */
|
||||
import { memo, useCallback, useState } from "react"
|
||||
import { usePopper } from "react-popper"
|
||||
|
||||
import { EditorView } from "@codemirror/view"
|
||||
import { Popover } from "@headlessui/react"
|
||||
|
||||
import { ICommand } from "~/editor"
|
||||
import type { ICommand } from "~/editor"
|
||||
import { useTranslation } from "~/lib/i18n/client"
|
||||
|
||||
import { Tooltip } from "./Tooltip"
|
||||
|
|
@ -21,14 +22,14 @@ enum ToolbarMode {
|
|||
|
||||
type IToolbarItemProps = ICommand<any> & { view?: EditorView }
|
||||
|
||||
const ToolbarItemWithPopover: FC<IToolbarItemProps> = ({
|
||||
const ToolbarItemWithPopover = ({
|
||||
name,
|
||||
icon,
|
||||
label,
|
||||
execute,
|
||||
ui,
|
||||
view,
|
||||
}) => {
|
||||
}: IToolbarItemProps) => {
|
||||
const { t } = useTranslation("dashboard")
|
||||
let [popoverButtonRef, setPopoverButtonRef] =
|
||||
useState<HTMLButtonElement | null>(null)
|
||||
|
|
@ -79,56 +80,54 @@ const ToolbarItemWithPopover: FC<IToolbarItemProps> = ({
|
|||
)
|
||||
}
|
||||
|
||||
export const EditorToolbar: FC<EditorToolbarProps> = memo(
|
||||
({ view, toolbars }) => {
|
||||
const { t } = useTranslation("dashboard")
|
||||
const renderToolbar = useCallback(
|
||||
(mode: ToolbarMode) =>
|
||||
// eslint-disable-next-line react/display-name
|
||||
({ name, icon, label, execute, ui }: ICommand) => {
|
||||
return ui ? (
|
||||
<ToolbarItemWithPopover
|
||||
export const EditorToolbar = memo(({ view, toolbars }: EditorToolbarProps) => {
|
||||
const { t } = useTranslation("dashboard")
|
||||
const renderToolbar = useCallback(
|
||||
(mode: ToolbarMode) =>
|
||||
// eslint-disable-next-line react/display-name
|
||||
({ name, icon, label, execute, ui }: ICommand) => {
|
||||
return ui ? (
|
||||
<ToolbarItemWithPopover
|
||||
key={name}
|
||||
name={name}
|
||||
icon={icon}
|
||||
label={label}
|
||||
execute={execute}
|
||||
ui={ui}
|
||||
view={view}
|
||||
/>
|
||||
) : (
|
||||
<Tooltip key={name} label={t(label)} placement="bottom">
|
||||
<button
|
||||
key={name}
|
||||
name={name}
|
||||
icon={icon}
|
||||
label={label}
|
||||
execute={execute}
|
||||
ui={ui}
|
||||
view={view}
|
||||
/>
|
||||
) : (
|
||||
<Tooltip key={name} label={t(label)} placement="bottom">
|
||||
<button
|
||||
key={name}
|
||||
title={name}
|
||||
type="button"
|
||||
className={
|
||||
"w-9 h-9 transition-colors text-lg border border-transparent rounded flex items-center justify-center text-zinc-500 group-hover:text-zinc-600 hover:text-zinc-500 hover:border-zinc-300 hover:bg-zinc-100"
|
||||
}
|
||||
onClick={() => {
|
||||
view &&
|
||||
execute({
|
||||
view,
|
||||
options: { container: view.dom },
|
||||
})
|
||||
}}
|
||||
>
|
||||
<span className={icon}></span>
|
||||
</button>
|
||||
</Tooltip>
|
||||
)
|
||||
},
|
||||
[view, t],
|
||||
)
|
||||
title={name}
|
||||
type="button"
|
||||
className={
|
||||
"w-9 h-9 transition-colors text-lg border border-transparent rounded flex items-center justify-center text-zinc-500 group-hover:text-zinc-600 hover:text-zinc-500 hover:border-zinc-300 hover:bg-zinc-100"
|
||||
}
|
||||
onClick={() => {
|
||||
view &&
|
||||
execute({
|
||||
view,
|
||||
options: { container: view.dom },
|
||||
})
|
||||
}}
|
||||
>
|
||||
<span className={icon}></span>
|
||||
</button>
|
||||
</Tooltip>
|
||||
)
|
||||
},
|
||||
[view, t],
|
||||
)
|
||||
|
||||
return (
|
||||
<div className="flex group">
|
||||
<div className="flex-1 flex space-x-1">
|
||||
{toolbars?.map(renderToolbar(ToolbarMode.Normal))}
|
||||
</div>
|
||||
return (
|
||||
<div className="flex group">
|
||||
<div className="flex-1 flex space-x-1">
|
||||
{toolbars?.map(renderToolbar(ToolbarMode.Normal))}
|
||||
</div>
|
||||
)
|
||||
},
|
||||
)
|
||||
</div>
|
||||
)
|
||||
})
|
||||
|
||||
EditorToolbar.displayName = "EditorToolbar"
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
export const EmptyState: React.FC<{ resource?: string }> = ({ resource }) => {
|
||||
export const EmptyState = ({ resource }: { resource?: string }) => {
|
||||
return (
|
||||
<div className="text-center py-10 mb-10 text-2xl text-zinc-300 font-medium flex justify-center flex-col items-center">
|
||||
<span className="icon-[mingcute--ghost-line] text-5xl mb-2"></span>
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
"use client"
|
||||
|
||||
import React, { FC, PropsWithChildren, useEffect, useState } from "react"
|
||||
import React, { PropsWithChildren, useEffect, useState } from "react"
|
||||
|
||||
import { useGetState } from "~/hooks/useGetState"
|
||||
import { cn } from "~/lib/utils"
|
||||
|
|
@ -52,8 +52,8 @@ export const useFAB = (fabConfig: FABConfig) => {
|
|||
}, [])
|
||||
}
|
||||
|
||||
export const FABBase: FC<
|
||||
PropsWithChildren<
|
||||
export const FABBase = (
|
||||
props: PropsWithChildren<
|
||||
{
|
||||
id: string
|
||||
show?: boolean
|
||||
|
|
@ -62,8 +62,8 @@ export const FABBase: FC<
|
|||
React.ButtonHTMLAttributes<HTMLButtonElement>,
|
||||
HTMLButtonElement
|
||||
>
|
||||
>
|
||||
> = (props) => {
|
||||
>,
|
||||
) => {
|
||||
const { children, id, show = true, ...extra } = props
|
||||
const { className, onTransitionEnd, ...rest } = extra
|
||||
|
||||
|
|
@ -106,9 +106,9 @@ export const FABBase: FC<
|
|||
)
|
||||
}
|
||||
|
||||
export const FABContainer: FC<{
|
||||
export const FABContainer = (props: {
|
||||
children: JSX.Element | JSX.Element[]
|
||||
}> = (props) => {
|
||||
}) => {
|
||||
const [fabConfig, setFabConfig] = useState<FABConfig[]>([])
|
||||
useEffect(() => {
|
||||
fab.register(setFabConfig)
|
||||
|
|
|
|||
|
|
@ -1,7 +1,4 @@
|
|||
export const FieldLabel: React.FC<{ id?: string; label: string }> = ({
|
||||
id,
|
||||
label,
|
||||
}) => {
|
||||
export const FieldLabel = ({ id, label }: { id?: string; label: string }) => {
|
||||
return (
|
||||
<label className="form-label" htmlFor={id}>
|
||||
{label}
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ type TImageProps = {
|
|||
} & React.HTMLAttributes<HTMLImageElement> &
|
||||
ImageProps
|
||||
|
||||
export const Image: React.FC<TImageProps> = ({
|
||||
export const Image = ({
|
||||
fill,
|
||||
className,
|
||||
alt,
|
||||
|
|
@ -29,7 +29,7 @@ export const Image: React.FC<TImageProps> = ({
|
|||
imageRef,
|
||||
zoom,
|
||||
...props
|
||||
}) => {
|
||||
}: TImageProps) => {
|
||||
src = toIPFS(src)
|
||||
const [paddingTop, setPaddingTop] = React.useState("0")
|
||||
const [autoWidth, setAutoWidth] = React.useState(0)
|
||||
|
|
@ -152,7 +152,7 @@ export const Image: React.FC<TImageProps> = ({
|
|||
)
|
||||
}
|
||||
|
||||
export const ZoomedImage: React.FC<TImageProps> = (props) => {
|
||||
export const ZoomedImage = (props: TImageProps) => {
|
||||
const info = useGetImageInfo(props.src)
|
||||
const autoProps = info?.data
|
||||
? {
|
||||
|
|
|
|||
|
|
@ -18,11 +18,8 @@ const getSiteId = ({ id, children }: { id: string; children?: any }) => {
|
|||
}
|
||||
}
|
||||
|
||||
const Mention: React.FC<{
|
||||
id: string
|
||||
children?: any
|
||||
}> = memo(
|
||||
function Mention({ id, children }) {
|
||||
const Mention = memo(
|
||||
function Mention({ id, children }: { id: string; children?: any }) {
|
||||
let siteId = getSiteId({ id, children })
|
||||
|
||||
const site = useGetSite(siteId)
|
||||
|
|
|
|||
|
|
@ -1,17 +1,15 @@
|
|||
"use client"
|
||||
|
||||
import { nanoid } from "nanoid"
|
||||
import { FC, memo, useEffect, useState } from "react"
|
||||
import { memo, useEffect, useState } from "react"
|
||||
|
||||
import { useIsDark } from "~/hooks/useDarkMode"
|
||||
import { useIsUnmounted } from "~/hooks/useLifecycle"
|
||||
|
||||
import { ZoomedImage } from "./Image"
|
||||
|
||||
const Mermaid: FC<{
|
||||
children: [string]
|
||||
}> = memo(
|
||||
function Mermaid(props) {
|
||||
const Mermaid = memo(
|
||||
function Mermaid(props: { children: [string] }) {
|
||||
const [loading, setLoading] = useState(true)
|
||||
const [error, setError] = useState("")
|
||||
const [svg, setSvg] = useState("")
|
||||
|
|
|
|||
|
|
@ -15,9 +15,12 @@ export type TabItem = {
|
|||
tooltip?: string
|
||||
}
|
||||
|
||||
export const Tabs: React.FC<{ items: TabItem[]; className?: string }> = ({
|
||||
export const Tabs = ({
|
||||
items,
|
||||
className,
|
||||
}: {
|
||||
items: TabItem[]
|
||||
className?: string
|
||||
}) => {
|
||||
const { t } = useTranslation("dashboard")
|
||||
|
||||
|
|
|
|||
|
|
@ -3,8 +3,8 @@ import { Tweet as ReactTweet } from "react-tweet"
|
|||
import type { TweetComponents } from "react-tweet"
|
||||
|
||||
const components: TweetComponents = {
|
||||
AvatarImg: (props) => <Image {...props} />,
|
||||
MediaImg: (props) => <Image {...props} fill unoptimized />,
|
||||
AvatarImg: (props) => <Image {...props} alt="avatar" />,
|
||||
MediaImg: (props) => <Image {...props} fill unoptimized alt="tweet-media" />,
|
||||
}
|
||||
|
||||
export default function Tweet({ id }: { id: string }) {
|
||||
|
|
|
|||
|
|
@ -8,14 +8,14 @@ export type UniLinkProps = {
|
|||
target?: string
|
||||
}
|
||||
|
||||
export const UniLink: React.FC<UniLinkProps> = ({
|
||||
export const UniLink = ({
|
||||
href,
|
||||
onClick,
|
||||
children,
|
||||
className,
|
||||
target,
|
||||
...props
|
||||
}) => {
|
||||
}: UniLinkProps) => {
|
||||
if (onClick) {
|
||||
return (
|
||||
<button className={className} onClick={onClick} {...props}>
|
||||
|
|
|
|||
|
|
@ -5,10 +5,13 @@ import React, { useState } from "react"
|
|||
import { Image } from "~/components/ui/Image"
|
||||
import { IPFS_GATEWAY } from "~/lib/env"
|
||||
|
||||
export const UniMedia: React.FC<{
|
||||
export const UniMedia = ({
|
||||
src,
|
||||
mime_type,
|
||||
}: {
|
||||
src: string
|
||||
mime_type?: string
|
||||
}> = ({ src, mime_type }) => {
|
||||
}) => {
|
||||
const [errorHandled, setErrorHandled] = useState(false)
|
||||
|
||||
const [type, setType] = useState(mime_type)
|
||||
|
|
|
|||
|
|
@ -38,10 +38,10 @@ export type ICommand<P = any> = {
|
|||
// While the `ui` field exists, the ui component will be rendered in a popover first,
|
||||
// then you can call `transferPayload` to transfer the payload to the `execute` function.
|
||||
// You can find a sample usage in `./Emoji.tsx`.
|
||||
ui?: React.FC<{
|
||||
ui?: (props: {
|
||||
transferPayload: (payload: P) => void
|
||||
view: EditorView
|
||||
}>
|
||||
}) => JSX.Element
|
||||
}
|
||||
|
||||
export type IPrependExecute = {
|
||||
|
|
|
|||
Loading…
Reference in New Issue