diff --git a/.changeset/tiny-apes-give.md b/.changeset/tiny-apes-give.md new file mode 100644 index 00000000..bad79c54 --- /dev/null +++ b/.changeset/tiny-apes-give.md @@ -0,0 +1,5 @@ +--- +"@starknet-react/core": patch +--- + +Fix wallet connection when wallet not authorized diff --git a/.changeset/tough-timers-rescue.md b/.changeset/tough-timers-rescue.md new file mode 100644 index 00000000..0172b4c2 --- /dev/null +++ b/.changeset/tough-timers-rescue.md @@ -0,0 +1,5 @@ +--- +"@starknet-react/core": patch +--- + +Add hook to detect injected connectors diff --git a/website/app/docs/layout.tsx b/website/app/docs/layout.tsx index 28ed13b0..476a741e 100644 --- a/website/app/docs/layout.tsx +++ b/website/app/docs/layout.tsx @@ -17,4 +17,3 @@ export default function DocLayout({ children }: { children: React.ReactNode }) { ); } - diff --git a/website/app/hooks/[[...slug]]/page.tsx b/website/app/hooks/[[...slug]]/page.tsx new file mode 100644 index 00000000..bbfdf58b --- /dev/null +++ b/website/app/hooks/[[...slug]]/page.tsx @@ -0,0 +1,58 @@ +import React from "react"; + +import { notFound, redirect } from "next/navigation"; + +import { allHooks } from "@/.contentlayer/generated"; +import { Mdx } from "@/components/mdx"; +import { DocContainer } from "@/components/container"; + +type DocPageProps = { + params: { + slug: string[]; + }; +}; + +async function getDocFromParams({ params }: DocPageProps) { + const slug = params.slug?.join("/") || ""; + + if (slug === "") { + const redirectTo = allHooks[0]?.slugAsParams; + return { doc: null, redirectTo }; + } + + const doc = allHooks.find((doc) => doc.slugAsParams === slug); + + if (!doc) { + return { doc: null, redirectTo: null }; + } + + return { doc, redirectTo: null }; +} + +export async function generateStaticParams(): Promise< + DocPageProps["params"][] +> { + return allHooks.map((doc) => ({ + slug: doc.slugAsParams.split("/"), + })); +} + +export default async function DocPage({ params }: DocPageProps) { + const { doc, redirectTo } = await getDocFromParams({ params }); + + if (!doc) { + if (redirectTo) { + redirect(`/hooks/${redirectTo}`); + } else { + notFound(); + } + } + + return ( + + + + ); +} + + diff --git a/website/app/hooks/layout.tsx b/website/app/hooks/layout.tsx new file mode 100644 index 00000000..32f269c2 --- /dev/null +++ b/website/app/hooks/layout.tsx @@ -0,0 +1,19 @@ +import React from "react"; + +import { Sidebar } from "@/components/sidebar"; +import { ScrollArea } from "@/components/ui/scroll-area"; +import { docsSidebar } from "@/lib/sidebar"; + +export default function HookLayout({ children }: { children: React.ReactNode }) { + return ( +
+ + {children} +
+ ); +} + diff --git a/website/components/starknet/provider.tsx b/website/components/starknet/provider.tsx index 3ac44e04..95b178c0 100644 --- a/website/components/starknet/provider.tsx +++ b/website/components/starknet/provider.tsx @@ -7,8 +7,8 @@ import { publicProvider, argent, braavos, + useInjectedConnectors, } from "@starknet-react/core"; -import { useInjectedConnectors } from "@/../packages/core/dist"; export function StarknetProvider({ children }: { children: React.ReactNode }) { const chains = [goerli, mainnet]; diff --git a/website/content/docs/getting-started.mdx b/website/content/docs/getting-started.mdx index 2f1a4561..b146f000 100644 --- a/website/content/docs/getting-started.mdx +++ b/website/content/docs/getting-started.mdx @@ -52,6 +52,9 @@ following: - _connectors_: the wallet connectors supported by your dapp. See the [wallets](/docs/wallets) page for more information. +Starknet React provides the `useInjectedConnectors` hook to merge a static list +of recommended connectors with a dynamic list of injected connectors. + ```tsx components/starknet-provider.tsx "use client"; import React from "react"; @@ -62,12 +65,23 @@ import { publicProvider, argent, braavos, + useInjectedConnectors, } from "@starknet-react/core"; export function StarknetProvider({ children }: { children: React.ReactNode }) { const chains = [goerli]; const providers = [publicProvider()]; - const connectors = [braavos(), argent()]; + const { connectors } = useInjectedConnectors({ + // Show these connectors if the user has no connector installed. + recommended: [ + argent(), + braavos(), + ], + // Hide recommended connectors if the user has any connector installed. + includeRecommended: "onlyIfNoConnectors", + // Randomize the order of the connectors. + order: "random" + }); return ( + {children} + + ); +} +``` + +## Options + + * `recommended?: Connector[]` + - List of recommended connectors. + + * `includeRecommended?: "always" | "onlyIfNoConnectors"` + - If `"always"`, the hook always returns the recommended connectors. + - If `"onlyIfNoConnectors"`, the recommended connectors are included only if + no other connector is installed. + + * `order?: "random" | "alphabetical"` + - Control the order in which connectors are returned. + - If `"random"`, connectors are shuffled. + - If `"alphabetical"`, connectors are alphabetically sorted by their id. + +## Returns + + * `connectors: Connector[]` + - Contains the list of injected connectors installed by the user. + - All connectors are unique and sorted. diff --git a/website/contentlayer.config.ts b/website/contentlayer.config.ts index c4d0f149..44c245d9 100644 --- a/website/contentlayer.config.ts +++ b/website/contentlayer.config.ts @@ -35,6 +35,23 @@ export const Doc = defineDocumentType(() => ({ }, })); +export const Hook = defineDocumentType(() => ({ + name: "Hook", + filePathPattern: "hooks/**/*.mdx", + contentType: "mdx", + computedFields, + fields: { + title: { + required: true, + type: "string", + }, + priority: { + required: true, + type: "number", + }, + }, +})); + export const Demo = defineDocumentType(() => ({ name: "Demo", filePathPattern: "demos/**/*.mdx", @@ -54,7 +71,7 @@ export const Demo = defineDocumentType(() => ({ export default makeSource({ contentDirPath: "content", - documentTypes: [Doc, Demo], + documentTypes: [Doc, Hook, Demo], mdx: { remarkPlugins: [ [ diff --git a/website/lib/sidebar.ts b/website/lib/sidebar.ts index 50a2ffcf..07bfe1ef 100644 --- a/website/lib/sidebar.ts +++ b/website/lib/sidebar.ts @@ -1,8 +1,9 @@ -import { allDemos, allDocs } from "@/.contentlayer/generated"; +import { allDemos, allDocs, allHooks } from "@/.contentlayer/generated"; import type { NavItemWithChildren } from "@/components/sidebar"; const sortedDemos = allDemos.sort((a, b) => b.priority - a.priority); +const sortedHooks = allHooks.sort((a, b) => b.priority - a.priority); export const demoSidebar: NavItemWithChildren[] = [ { @@ -26,4 +27,12 @@ export const docsSidebar: NavItemWithChildren[] = [ items: [], })), }, + { + title: "Hooks", + items: sortedHooks.map(({ title, slugAsParams }) => ({ + title, + href: `/hooks/${slugAsParams}`, + items: [], + })), + } ]; diff --git a/website/styles/globals.css b/website/styles/globals.css index b66b0b20..4e547904 100644 --- a/website/styles/globals.css +++ b/website/styles/globals.css @@ -90,3 +90,7 @@ @apply leading-6 font-mono; font-size: 15px; } + +.mdx :where(ul ul, ul ol, ol ul, ol ol) { + margin-top: 0; +}