Skip to content

Commit

Permalink
✨ Add faker page
Browse files Browse the repository at this point in the history
  • Loading branch information
wancup committed Nov 16, 2024
1 parent 27cec51 commit 88a3c6c
Show file tree
Hide file tree
Showing 6 changed files with 190 additions and 0 deletions.
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
},
"dependencies": {
"@ark-ui/solid": "^4.1.0",
"@faker-js/faker": "9.2.0",
"@solidjs/meta": "0.29.4",
"@solidjs/router": "0.14.3",
"@solidjs/start": "1.0.6",
Expand Down
9 changes: 9 additions & 0 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

52 changes: 52 additions & 0 deletions src/features/faker/components/faker-playground.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
import { css } from "$panda/css";
import { Clipboard } from "$park/clipboard";
import { IconButton } from "$park/icon-button";
import { CheckIcon, ClipboardCopyIcon, RefreshCwIcon } from "lucide-solid";
import { createEffect, createSignal, type JSX } from "solid-js";

interface FakerPlaygroundProps {
name: string;
generate: () => string;
}

export function FakerPlayground(props: FakerPlaygroundProps): JSX.Element {
const [value, setValue] = createSignal("");

createEffect(() => {
setValue(props.generate());
});

return (
<div class={css({ display: "flex", columnGap: "1rem", alignItems: "center" })}>
<span>{props.name}</span>
<span class={css({ whiteSpace: "pre-wrap" })}>{value()}</span>

<div class={css({ display: "flex", columnGap: "0.5rem" })}>
<Clipboard.Root value={value()}>
<Clipboard.Control>
<Clipboard.Trigger
asChild={(triggerProps) => (
<IconButton variant="outline" size="sm" {...triggerProps()}>
<Clipboard.Indicator copied={<CheckIcon />}>
<ClipboardCopyIcon />
</Clipboard.Indicator>
</IconButton>
)}
/>
</Clipboard.Control>
</Clipboard.Root>
<IconButton
aria-label={`Reflesh ${props.name}`}
size="sm"
variant="outline"
onClick={() => {
const v = props.generate();
setValue(v);
}}
>
<RefreshCwIcon />
</IconButton>
</div>
</div>
);
}
1 change: 1 addition & 0 deletions src/features/faker/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from "./components/faker-playground";
123 changes: 123 additions & 0 deletions src/routes/faker.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
import { css } from "$panda/css";
import { Heading } from "$park/heading";
import { Select } from "$park/select";
import { createListCollection } from "@ark-ui/solid";
import { allFakers, allLocales, fakerEN } from "@faker-js/faker";
import { Title } from "@solidjs/meta";
import { CheckIcon, ChevronsUpDownIcon } from "lucide-solid";
import { createMemo, createSignal, For, type JSX } from "solid-js";
import { Container } from "~/components";
import { FakerPlayground } from "~/features/faker";
import { makePageTitle, PAGES } from "~/site";

const PAGE_TITLE = makePageTitle(PAGES["faker"].name);

const ALL_LOCALE_LIST = Object.keys(allLocales);

type FakerLocale = keyof typeof allLocales;
export default function FakerPage(): JSX.Element {
const [selectedLocale, setSelectedLocale] = createSignal<FakerLocale>("en");
const localeCollection = createListCollection({ items: ALL_LOCALE_LIST });

const localeFaker = createMemo(() => allFakers[selectedLocale()]);

const generateAddress = (): string => {
let state: string | undefined;
try {
state = localeFaker().location.state();
} catch {
// Some locales does not have state
}
return [state, localeFaker().location.city(), localeFaker().location.streetAddress()].join(" ");
};

return (
<main>
<Title>{PAGE_TITLE}</Title>
<Container>
<Heading as="h1" size="xl" class={css({ marginBottom: "1rem" })}>
{PAGES["faker"].name}
</Heading>
<div class={css({ display: "flex", flexDir: "column", rowGap: "1rem" })}>
<Select.Root
class={css({ width: "10rem" })}
positioning={{ sameWidth: true }}
collection={localeCollection}
value={[selectedLocale()]}
onValueChange={(v) => {
const value = v.value[0];
if (typeof value !== "undefined") {
setSelectedLocale(value as FakerLocale);
}
}}
>
<Select.Label>Locale</Select.Label>
<Select.Control>
<Select.Trigger>
<Select.ValueText placeholder="Select a base locale" />
<ChevronsUpDownIcon />
</Select.Trigger>
</Select.Control>
<Select.Positioner>
<Select.Content>
<Select.ItemGroup class={css({ maxHeight: "20rem", overflowY: "auto" })}>
<For each={localeCollection.items}>
{(item) => (
<Select.Item item={item}>
<Select.ItemText>{item}</Select.ItemText>
<Select.ItemIndicator>
<CheckIcon />
</Select.ItemIndicator>
</Select.Item>
)}
</For>
</Select.ItemGroup>
</Select.Content>
</Select.Positioner>
</Select.Root>

<FakerPlayground
name="URL:"
generate={() => `https://example.com/${fakerEN.word.words().replaceAll(" ", "/")}`}
/>
<FakerPlayground
name="Nano ID:"
generate={() => fakerEN.string.nanoid()}
/>
<FakerPlayground
name="UUID v4:"
generate={() => fakerEN.string.uuid()}
/>
<FakerPlayground
name="Name:"
generate={() => localeFaker().person.fullName()}
/>
<FakerPlayground
name="DisplayName:"
generate={() => localeFaker().internet.displayName()}
/>
<FakerPlayground
name="Email:"
generate={() => (fakerEN.internet.exampleEmail())}
/>
<FakerPlayground
name="Date:"
generate={() => (localeFaker().date.anytime().toLocaleString(selectedLocale().replace("_", "-")))}
/>
<FakerPlayground
name="ZipCode:"
generate={() => (localeFaker().location.zipCode())}
/>
<FakerPlayground
name="Address:"
generate={generateAddress}
/>
<FakerPlayground
name="Paragraphs:"
generate={() => (localeFaker().lorem.lines())}
/>
</div>
</Container>
</main>
);
}
4 changes: 4 additions & 0 deletions src/site/pages.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,10 @@ export const PAGES = {
name: "Keyboard Event",
path: "/keyboard-event",
},
"faker": {
name: "Faker",
path: "/faker",
},
"qr-code": {
name: "QR code",
path: "/qr-code",
Expand Down

0 comments on commit 88a3c6c

Please sign in to comment.