Skip to content

Commit

Permalink
feat: sources
Browse files Browse the repository at this point in the history
  • Loading branch information
iamdin committed Aug 31, 2024
1 parent 5e04ffe commit 9478a19
Show file tree
Hide file tree
Showing 16 changed files with 259 additions and 189 deletions.
2 changes: 2 additions & 0 deletions apps/www/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
"@fontsource-variable/inter": "^5.0.20",
"@nanostores/react": "^0.7.3",
"@nanostores/vue": "^0.10.0",
"@ui/lib": "workspace:*",
"@ui/react": "workspace:*",
"@ui/vue": "workspace:*",
"astro": "^4.14.6",
Expand All @@ -30,6 +31,7 @@
"react": "catalog:",
"react-dom": "catalog:",
"recharts": "^2.12.7",
"scule": "^1.3.0",
"sharp": "^0.32.6",
"tailwind-merge": "catalog:"
},
Expand Down
2 changes: 2 additions & 0 deletions apps/www/src/atoms/framework.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,6 @@ import { atom } from "nanostores"

export type Framework = "react" | "vue"

export const frameworks: Framework[] = ["react", "vue"]

export const $framework = atom<Framework>("react")
10 changes: 7 additions & 3 deletions apps/www/src/components/content/code-wrapper/code-wrapper.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,10 @@ import { cn } from "@/lib/utils"

interface Props {
collapsible?: boolean
copy?: boolean
children?: React.ReactNode
className: string | undefined
src: string
className?: string
src?: string
[key: string]: unknown
}

Expand All @@ -17,6 +18,7 @@ export default function CodeWrapper({
className,
src,
collapsible,
copy = true,
...props
}: Props) {
const [open, setOpen] = useState(false)
Expand Down Expand Up @@ -45,7 +47,9 @@ export default function CodeWrapper({
</Button>
</div>
) : null}
<CopyButton className="absolute top-4 right-4" value={src} />
{copy ? (
<CopyButton className="absolute top-4 right-4" value={src} />
) : null}
</div>
)
}
18 changes: 7 additions & 11 deletions apps/www/src/components/content/code-wrapper/index.astro
Original file line number Diff line number Diff line change
@@ -1,25 +1,21 @@
---
import { Code } from "astro/components"
import type { HTMLAttributes } from "astro/types"
import type { BuiltinLanguage } from "shiki"
import CodeWrapper from "./code-wrapper"
interface Props extends HTMLAttributes<"div"> {
lang?: "tsx" | "vue" | "ts" | "json"
src?: string
lang?: BuiltinLanguage
className?: string
collapsible?: boolean
src: string
copy?: boolean
}
const { src, lang, className, collapsible, ...props } = Astro.props
const { src, lang, className, ...props } = Astro.props
---

<CodeWrapper
client:visible
src={src}
collapsible={!!collapsible}
className={className}
{...props}
>
<Code lang={lang || "plaintext"} theme="vesper" code={src} />
<CodeWrapper client:visible src={src} className={className} {...props}>
<Code lang={lang || "plaintext"} theme="vesper" code={src || "Not found"} />
</CodeWrapper>
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import { useStore } from "@nanostores/react"
import { useEffect, useState } from "react"
import { pascalCase } from "scule"

import { $framework, type Framework } from "@/atoms/framework"
import { $framework, type Framework, frameworks } from "@/atoms/framework"
import {
Select,
SelectContent,
Expand All @@ -12,21 +13,10 @@ import {
SelectValueText,
} from "@ui/react/select"

const frameworks = [
{
value: "react",
label: "React",
},
{
value: "vue",
label: "Vue",
},
{
value: "solid",
label: "Solid (WIP)",
disabled: true,
},
]
const frameworksItems = frameworks.map((framework) => ({
value: framework,
label: pascalCase(framework),
}))

export function FrameworkSwitcher() {
const framework = useStore($framework)
Expand All @@ -45,7 +35,7 @@ export function FrameworkSwitcher() {
}}
className="w-[160px]"
positioning={{ sameWidth: true }}
items={frameworks}
items={frameworksItems}
>
<SelectControl>
<SelectTrigger className="h-7 text-xs">
Expand All @@ -55,13 +45,9 @@ export function FrameworkSwitcher() {
</SelectControl>
<SelectContent>
<SelectItemGroup>
{frameworks.map((framework) => (
<SelectItem
className="text-xs"
item={framework}
key={framework.value}
>
{framework.label}
{frameworksItems.map((item) => (
<SelectItem className="text-xs" item={item} key={item.value}>
{item.label}
</SelectItem>
))}
</SelectItemGroup>
Expand Down
118 changes: 44 additions & 74 deletions apps/www/src/components/content/component-preview/index.astro
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
import { CopyButton } from "@/components/copy-button"
import { getExampleSource } from "@/lib/source"
import { frameworks } from "@/atoms/framework"
import CodeWrapper from "../code-wrapper/index.astro"
import { FrameworkSwitcher } from "./framework-switcher"
import NotFound from "./not-found.astro"
Expand All @@ -14,8 +15,11 @@ interface Props {
}
const { name } = Astro.props
const source = await getExampleSource("react", name)
const sourceVue = await getExampleSource("vue", name)
const frameworkSources = await Promise.all(
frameworks.map(async (framework) => {
return await getExampleSource(framework, name)
})
)
---

<div class="group relative my-4 flex flex-col space-y-2">
Expand All @@ -24,84 +28,50 @@ const sourceVue = await getExampleSource("vue", name)
<div class="relative rounded-md border">
<div class="flex items-center justify-between p-4">
<FrameworkSwitcher client:load />
<CopyButton
client:load
value={source || ""}
variant="outline"
className="h-7 w-7 text-foreground opacity-100 hover:bg-muted hover:text-foreground [&_svg]:h-3.5 [&_svg]:w-3.5"
data-framework="react"
/>
<CopyButton
client:load
value={sourceVue || ""}
variant="outline"
className="h-7 w-7 text-foreground opacity-100 hover:bg-muted hover:text-foreground [&_svg]:h-3.5 [&_svg]:w-3.5"
data-framework="vue"
hidden
/>
</div>
<div
class="preview flex min-h-[350px] w-full items-center justify-center p-10"
data-framework="react"
>
{
source ? (
<Preview client:visible name={name} />
) : (
<NotFound component={name} />
)
}
</div>
<div
class="preview flex min-h-[350px] w-full items-center justify-center p-10"
hidden
data-framework="vue"
>
{
sourceVue ? (
<PreviewVue client:visible name={name} />
) : (
<NotFound component={name} />
)
frameworks.map((framework, index) => (
<CopyButton
client:load
value={frameworkSources[index]?.source}
variant="outline"
className="h-7 w-7 text-foreground opacity-100 hover:bg-muted hover:text-foreground [&_svg]:h-3.5 [&_svg]:w-3.5"
data-framework={framework}
/>
))
}
</div>
{
frameworks.map((framework, index) => (
<div
class="preview flex min-h-[350px] w-full items-center justify-center p-10"
data-framework={framework}
hidden={framework !== "react"}
>
{frameworkSources[index] ? (
framework === "react" ? (
<Preview client:visible name={name} />
) : (
<PreviewVue client:visible name={name} />
)
) : (
<NotFound component={name} />
)}
</div>
))
}
</div>
</Fragment>
<Fragment slot="code">
<CodeWrapper data-framework="react" lang="tsx" src={source || ""} />
<CodeWrapper
data-framework="vue"
lang="vue"
src={sourceVue || ""}
hidden
/>
{
frameworks.map((framework, index) => (
<CodeWrapper
data-framework={framework}
lang={frameworkSources[index]?.lang}
src={frameworkSources[index]?.source}
hidden={framework !== "react"}
/>
))
}
</Fragment>
</Tabs>
</div>

<script>
import { $framework } from "@/atoms/framework";

let unsubscribe: () => void;

document.addEventListener("astro:page-load", () => {
if (typeof unsubscribe === "function") {
unsubscribe();
}

unsubscribe = $framework.subscribe((value) => {
const previewReact = document.querySelectorAll(
`[data-framework="react"]`
);
const previewVue = document.querySelectorAll(`[data-framework="vue"]`);
previewReact.forEach((el) => {
// @ts-ignore
el.hidden = value !== "react";
});
previewVue.forEach((el) => {
// @ts-ignore
el.hidden = value !== "vue";
});
});
});
</script>
39 changes: 22 additions & 17 deletions apps/www/src/components/content/component-source.astro
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
---
import { frameworks } from "@/atoms/framework"
import { getComponentSource } from "@/lib/source"
import CodeWrapper from "./code-wrapper/index.astro"
Expand All @@ -7,25 +8,29 @@ export interface Props {
}
const { component } = Astro.props
const source = await getComponentSource("react", component)
const sourceVue = await getComponentSource("vue", component)
const frameworkSources = await Promise.all(
frameworks.map((framework) => getComponentSource(framework, component))
)
---

{
source.map((src) => (
<CodeWrapper
lang="tsx"
src={typeof src === "string" ? src : "Not Found"}
collapsible
/>
))
}
{
sourceVue.map((src) => (
<CodeWrapper
lang="vue"
src={typeof src === "string" ? src : "Not Found"}
collapsible
/>
frameworks.map((framework, index) => (
<div data-framework={framework}>
{frameworkSources[index]?.length ? (
frameworkSources[index]?.map((src) => (
<div data-framework={framework}>
<p class="mb-2">{src.filename}</p>
<CodeWrapper
className="mt-0"
lang={src.lang}
src={src.source}
collapsible
/>
</div>
))
) : (
<CodeWrapper src={"Not Found"} />
)}
</div>
))
}
6 changes: 2 additions & 4 deletions apps/www/src/components/copy-button.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,7 @@ import { cn } from "@/lib/utils"
import { Button, type ButtonProps } from "@ui/react/button"

interface CopyButtonProps extends ButtonProps {
value: string
src?: string
value?: string | undefined
}

export async function copyToClipboardWithMeta(value: string) {
Expand All @@ -16,7 +15,6 @@ export async function copyToClipboardWithMeta(value: string) {
export function CopyButton({
value,
className,
src,
variant = "ghost",
...props
}: CopyButtonProps) {
Expand All @@ -42,7 +40,7 @@ export function CopyButton({
className
)}
onClick={() => {
copyToClipboardWithMeta(value)
copyToClipboardWithMeta(value || "")
setHasCopied(true)
}}
{...props}
Expand Down
Loading

0 comments on commit 9478a19

Please sign in to comment.