Compare commits
3 Commits
feature/ne
...
main
Author | SHA1 | Date |
---|---|---|
RaviAnand Mohabir | a3246fc972 | 3 months ago |
RaviAnand Mohabir | a884c6f300 | 3 months ago |
RaviAnand Mohabir | afcf58be2d | 3 months ago |
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,127 @@
|
||||
/* tslint:disable */
|
||||
/* eslint-disable */
|
||||
/**
|
||||
* This file was automatically generated by Payload.
|
||||
* DO NOT MODIFY IT BY HAND. Instead, modify your source Payload config,
|
||||
* and re-run `payload generate:types` to regenerate this file.
|
||||
*/
|
||||
|
||||
export interface Config {
|
||||
auth: {
|
||||
users: UserAuthOperations;
|
||||
};
|
||||
collections: {
|
||||
users: User;
|
||||
media: Media;
|
||||
'payload-preferences': PayloadPreference;
|
||||
'payload-migrations': PayloadMigration;
|
||||
};
|
||||
db: {
|
||||
defaultIDType: string;
|
||||
};
|
||||
globals: {};
|
||||
locale: null;
|
||||
user: User & {
|
||||
collection: 'users';
|
||||
};
|
||||
}
|
||||
export interface UserAuthOperations {
|
||||
forgotPassword: {
|
||||
email: string;
|
||||
password: string;
|
||||
};
|
||||
login: {
|
||||
email: string;
|
||||
password: string;
|
||||
};
|
||||
registerFirstUser: {
|
||||
email: string;
|
||||
password: string;
|
||||
};
|
||||
unlock: {
|
||||
email: string;
|
||||
password: string;
|
||||
};
|
||||
}
|
||||
/**
|
||||
* This interface was referenced by `Config`'s JSON-Schema
|
||||
* via the `definition` "users".
|
||||
*/
|
||||
export interface User {
|
||||
id: string;
|
||||
updatedAt: string;
|
||||
createdAt: string;
|
||||
email: string;
|
||||
resetPasswordToken?: string | null;
|
||||
resetPasswordExpiration?: string | null;
|
||||
salt?: string | null;
|
||||
hash?: string | null;
|
||||
loginAttempts?: number | null;
|
||||
lockUntil?: string | null;
|
||||
password?: string | null;
|
||||
}
|
||||
/**
|
||||
* This interface was referenced by `Config`'s JSON-Schema
|
||||
* via the `definition` "media".
|
||||
*/
|
||||
export interface Media {
|
||||
id: string;
|
||||
alt?: string | null;
|
||||
updatedAt: string;
|
||||
createdAt: string;
|
||||
url?: string | null;
|
||||
thumbnailURL?: string | null;
|
||||
filename?: string | null;
|
||||
mimeType?: string | null;
|
||||
filesize?: number | null;
|
||||
width?: number | null;
|
||||
height?: number | null;
|
||||
focalX?: number | null;
|
||||
focalY?: number | null;
|
||||
}
|
||||
/**
|
||||
* This interface was referenced by `Config`'s JSON-Schema
|
||||
* via the `definition` "payload-preferences".
|
||||
*/
|
||||
export interface PayloadPreference {
|
||||
id: string;
|
||||
user: {
|
||||
relationTo: 'users';
|
||||
value: string | User;
|
||||
};
|
||||
key?: string | null;
|
||||
value?:
|
||||
| {
|
||||
[k: string]: unknown;
|
||||
}
|
||||
| unknown[]
|
||||
| string
|
||||
| number
|
||||
| boolean
|
||||
| null;
|
||||
updatedAt: string;
|
||||
createdAt: string;
|
||||
}
|
||||
/**
|
||||
* This interface was referenced by `Config`'s JSON-Schema
|
||||
* via the `definition` "payload-migrations".
|
||||
*/
|
||||
export interface PayloadMigration {
|
||||
id: string;
|
||||
name?: string | null;
|
||||
batch?: number | null;
|
||||
updatedAt: string;
|
||||
createdAt: string;
|
||||
}
|
||||
/**
|
||||
* This interface was referenced by `Config`'s JSON-Schema
|
||||
* via the `definition` "auth".
|
||||
*/
|
||||
export interface Auth {
|
||||
[k: string]: unknown;
|
||||
}
|
||||
|
||||
|
||||
declare module 'payload' {
|
||||
export interface GeneratedTypes extends Config {}
|
||||
}
|
Binary file not shown.
@ -0,0 +1,39 @@
|
||||
import "../globals.css";
|
||||
|
||||
import Footer from "@/components/layout/footer";
|
||||
import { I18nProviderClient } from "@/i18n/client";
|
||||
import type { Metadata } from "next";
|
||||
import Navbar from "@/components/layout/navbar";
|
||||
import { Params } from "./params";
|
||||
import localFont from "next/font/local";
|
||||
import { styled } from "@styled-system/jsx";
|
||||
|
||||
const moderustic = localFont({
|
||||
src: "../Moderustic-VariableFont_wght.ttf",
|
||||
display: "swap",
|
||||
});
|
||||
|
||||
export const metadata: Metadata = {
|
||||
title: "Create Next App",
|
||||
description: "Generated by create next app",
|
||||
};
|
||||
|
||||
export default function RootLayout({
|
||||
params: { locale },
|
||||
children,
|
||||
}: Readonly<{
|
||||
children: React.ReactNode;
|
||||
params: Params;
|
||||
}>) {
|
||||
return (
|
||||
<html lang="en">
|
||||
<I18nProviderClient locale={locale}>
|
||||
<styled.body className={moderustic.className}>
|
||||
<Navbar />
|
||||
<styled.main pb={20}>{children}</styled.main>
|
||||
<Footer />
|
||||
</styled.body>
|
||||
</I18nProviderClient>
|
||||
</html>
|
||||
);
|
||||
}
|
@ -0,0 +1,8 @@
|
||||
import { Box } from "styled-system/jsx";
|
||||
import { getI18n } from "@/i18n/server";
|
||||
|
||||
export default async function Home() {
|
||||
const t = await getI18n();
|
||||
|
||||
return <Box></Box>;
|
||||
}
|
@ -0,0 +1,3 @@
|
||||
import { Locale } from "@/i18n/locales";
|
||||
|
||||
export type Params = { locale: Locale };
|
@ -1,33 +0,0 @@
|
||||
import type { Metadata } from "next";
|
||||
import localFont from "next/font/local";
|
||||
import "./globals.css";
|
||||
|
||||
const geistSans = localFont({
|
||||
src: "./fonts/GeistVF.woff",
|
||||
variable: "--font-geist-sans",
|
||||
weight: "100 900",
|
||||
});
|
||||
const geistMono = localFont({
|
||||
src: "./fonts/GeistMonoVF.woff",
|
||||
variable: "--font-geist-mono",
|
||||
weight: "100 900",
|
||||
});
|
||||
|
||||
export const metadata: Metadata = {
|
||||
title: "Create Next App",
|
||||
description: "Generated by create next app",
|
||||
};
|
||||
|
||||
export default function RootLayout({
|
||||
children,
|
||||
}: Readonly<{
|
||||
children: React.ReactNode;
|
||||
}>) {
|
||||
return (
|
||||
<html lang="en">
|
||||
<body className={`${geistSans.variable} ${geistMono.variable}`}>
|
||||
{children}
|
||||
</body>
|
||||
</html>
|
||||
);
|
||||
}
|
@ -1,168 +0,0 @@
|
||||
.page {
|
||||
--gray-rgb: 0, 0, 0;
|
||||
--gray-alpha-200: rgba(var(--gray-rgb), 0.08);
|
||||
--gray-alpha-100: rgba(var(--gray-rgb), 0.05);
|
||||
|
||||
--button-primary-hover: #383838;
|
||||
--button-secondary-hover: #f2f2f2;
|
||||
|
||||
display: grid;
|
||||
grid-template-rows: 20px 1fr 20px;
|
||||
align-items: center;
|
||||
justify-items: center;
|
||||
min-height: 100svh;
|
||||
padding: 80px;
|
||||
gap: 64px;
|
||||
font-family: var(--font-geist-sans);
|
||||
}
|
||||
|
||||
@media (prefers-color-scheme: dark) {
|
||||
.page {
|
||||
--gray-rgb: 255, 255, 255;
|
||||
--gray-alpha-200: rgba(var(--gray-rgb), 0.145);
|
||||
--gray-alpha-100: rgba(var(--gray-rgb), 0.06);
|
||||
|
||||
--button-primary-hover: #ccc;
|
||||
--button-secondary-hover: #1a1a1a;
|
||||
}
|
||||
}
|
||||
|
||||
.main {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 32px;
|
||||
grid-row-start: 2;
|
||||
}
|
||||
|
||||
.main ol {
|
||||
font-family: var(--font-geist-mono);
|
||||
padding-left: 0;
|
||||
margin: 0;
|
||||
font-size: 14px;
|
||||
line-height: 24px;
|
||||
letter-spacing: -0.01em;
|
||||
list-style-position: inside;
|
||||
}
|
||||
|
||||
.main li:not(:last-of-type) {
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
.main code {
|
||||
font-family: inherit;
|
||||
background: var(--gray-alpha-100);
|
||||
padding: 2px 4px;
|
||||
border-radius: 4px;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.ctas {
|
||||
display: flex;
|
||||
gap: 16px;
|
||||
}
|
||||
|
||||
.ctas a {
|
||||
appearance: none;
|
||||
border-radius: 128px;
|
||||
height: 48px;
|
||||
padding: 0 20px;
|
||||
border: none;
|
||||
border: 1px solid transparent;
|
||||
transition:
|
||||
background 0.2s,
|
||||
color 0.2s,
|
||||
border-color 0.2s;
|
||||
cursor: pointer;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-size: 16px;
|
||||
line-height: 20px;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
a.primary {
|
||||
background: var(--foreground);
|
||||
color: var(--background);
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
a.secondary {
|
||||
border-color: var(--gray-alpha-200);
|
||||
min-width: 180px;
|
||||
}
|
||||
|
||||
.footer {
|
||||
grid-row-start: 3;
|
||||
display: flex;
|
||||
gap: 24px;
|
||||
}
|
||||
|
||||
.footer a {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.footer img {
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
/* Enable hover only on non-touch devices */
|
||||
@media (hover: hover) and (pointer: fine) {
|
||||
a.primary:hover {
|
||||
background: var(--button-primary-hover);
|
||||
border-color: transparent;
|
||||
}
|
||||
|
||||
a.secondary:hover {
|
||||
background: var(--button-secondary-hover);
|
||||
border-color: transparent;
|
||||
}
|
||||
|
||||
.footer a:hover {
|
||||
text-decoration: underline;
|
||||
text-underline-offset: 4px;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 600px) {
|
||||
.page {
|
||||
padding: 32px;
|
||||
padding-bottom: 80px;
|
||||
}
|
||||
|
||||
.main {
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.main ol {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.ctas {
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.ctas a {
|
||||
font-size: 14px;
|
||||
height: 40px;
|
||||
padding: 0 16px;
|
||||
}
|
||||
|
||||
a.secondary {
|
||||
min-width: auto;
|
||||
}
|
||||
|
||||
.footer {
|
||||
flex-wrap: wrap;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
}
|
||||
|
||||
@media (prefers-color-scheme: dark) {
|
||||
.logo {
|
||||
filter: invert();
|
||||
}
|
||||
}
|
@ -1,95 +0,0 @@
|
||||
import Image from "next/image";
|
||||
import styles from "./page.module.css";
|
||||
|
||||
export default function Home() {
|
||||
return (
|
||||
<div className={styles.page}>
|
||||
<main className={styles.main}>
|
||||
<Image
|
||||
className={styles.logo}
|
||||
src="https://nextjs.org/icons/next.svg"
|
||||
alt="Next.js logo"
|
||||
width={180}
|
||||
height={38}
|
||||
priority
|
||||
/>
|
||||
<ol>
|
||||
<li>
|
||||
Get started by editing <code>src/app/page.tsx</code>.
|
||||
</li>
|
||||
<li>Save and see your changes instantly.</li>
|
||||
</ol>
|
||||
|
||||
<div className={styles.ctas}>
|
||||
<a
|
||||
className={styles.primary}
|
||||
href="https://vercel.com/new?utm_source=create-next-app&utm_medium=appdir-template&utm_campaign=create-next-app"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
>
|
||||
<Image
|
||||
className={styles.logo}
|
||||
src="https://nextjs.org/icons/vercel.svg"
|
||||
alt="Vercel logomark"
|
||||
width={20}
|
||||
height={20}
|
||||
/>
|
||||
Deploy now
|
||||
</a>
|
||||
<a
|
||||
href="https://nextjs.org/docs?utm_source=create-next-app&utm_medium=appdir-template&utm_campaign=create-next-app"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className={styles.secondary}
|
||||
>
|
||||
Read our docs
|
||||
</a>
|
||||
</div>
|
||||
</main>
|
||||
<footer className={styles.footer}>
|
||||
<a
|
||||
href="https://nextjs.org/learn?utm_source=create-next-app&utm_medium=appdir-template&utm_campaign=create-next-app"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
>
|
||||
<Image
|
||||
aria-hidden
|
||||
src="https://nextjs.org/icons/file.svg"
|
||||
alt="File icon"
|
||||
width={16}
|
||||
height={16}
|
||||
/>
|
||||
Learn
|
||||
</a>
|
||||
<a
|
||||
href="https://vercel.com/templates?framework=next.js&utm_source=create-next-app&utm_medium=appdir-template&utm_campaign=create-next-app"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
>
|
||||
<Image
|
||||
aria-hidden
|
||||
src="https://nextjs.org/icons/window.svg"
|
||||
alt="Window icon"
|
||||
width={16}
|
||||
height={16}
|
||||
/>
|
||||
Examples
|
||||
</a>
|
||||
<a
|
||||
href="https://nextjs.org?utm_source=create-next-app&utm_medium=appdir-template&utm_campaign=create-next-app"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
>
|
||||
<Image
|
||||
aria-hidden
|
||||
src="https://nextjs.org/icons/globe.svg"
|
||||
alt="Globe icon"
|
||||
width={16}
|
||||
height={16}
|
||||
/>
|
||||
Go to nextjs.org →
|
||||
</a>
|
||||
</footer>
|
||||
</div>
|
||||
);
|
||||
}
|
@ -0,0 +1,15 @@
|
||||
import { Text } from "@/components/ui/text";
|
||||
import { stack } from "@styled-system/patterns";
|
||||
import { styled } from "@styled-system/jsx";
|
||||
|
||||
export default async function Footer() {
|
||||
return (
|
||||
<styled.footer
|
||||
minH={60}
|
||||
p={8}
|
||||
className={stack({ gap: 4, justify: "end" })}
|
||||
>
|
||||
<Text textAlign="center">Powered by Jenyus</Text>
|
||||
</styled.footer>
|
||||
);
|
||||
}
|
@ -0,0 +1,41 @@
|
||||
"use client";
|
||||
|
||||
import { defaultLocale, locales } from "@/i18n/locales";
|
||||
import { useChangeLocale, useCurrentLocale, useI18n } from "@/i18n/client";
|
||||
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { Menu } from "@/components/ui/menu";
|
||||
|
||||
export default function LanguagePicker(props: Menu.RootProps) {
|
||||
const changeLocale = useChangeLocale();
|
||||
const locale = useCurrentLocale();
|
||||
const t = useI18n();
|
||||
|
||||
return (
|
||||
<Menu.Root {...props} positioning={{ offset: { crossAxis: -35 } }}>
|
||||
<Menu.Trigger asChild>
|
||||
<Button variant="outline" size={props.size}>
|
||||
{t(`general.${locale}`)}
|
||||
</Button>
|
||||
</Menu.Trigger>
|
||||
<Menu.Positioner>
|
||||
<Menu.Content right={0}>
|
||||
<Menu.ItemGroup>
|
||||
{locales.map((locale) => (
|
||||
<Menu.Item
|
||||
asChild
|
||||
key={locale.code}
|
||||
value={locale.code}
|
||||
onClick={() => changeLocale(locale.code)}
|
||||
>
|
||||
<Button>
|
||||
{locale.label[locale.code] ?? locale.label[defaultLocale]}
|
||||
</Button>
|
||||
</Menu.Item>
|
||||
))}
|
||||
</Menu.ItemGroup>
|
||||
</Menu.Content>
|
||||
</Menu.Positioner>
|
||||
</Menu.Root>
|
||||
);
|
||||
}
|
@ -0,0 +1,68 @@
|
||||
"use client";
|
||||
|
||||
import { Menu, X } from "lucide-react";
|
||||
|
||||
import { IconButton } from "@/components/ui/icon-button";
|
||||
import Image from "next/image";
|
||||
import Link from "next/link";
|
||||
import { Media } from "@/payload-types";
|
||||
import NavLink from "@/components/layout/nav-link";
|
||||
import { css } from "@styled-system/css";
|
||||
import { styled } from "@styled-system/jsx";
|
||||
import { useI18n } from "@/i18n/client";
|
||||
import { useState } from "react";
|
||||
|
||||
export default function MobileNav() {
|
||||
const [show, setShow] = useState(false);
|
||||
const t = useI18n();
|
||||
|
||||
return (
|
||||
<styled.div className={css({ display: "block", sm: { display: "none" } })}>
|
||||
<IconButton onClick={() => setShow((show) => !show)}>
|
||||
<Menu />
|
||||
</IconButton>
|
||||
<styled.div
|
||||
display={show ? "flex" : "none"}
|
||||
zIndex={600}
|
||||
position="fixed"
|
||||
top={0}
|
||||
left={0}
|
||||
right={0}
|
||||
bottom={0}
|
||||
height="100%"
|
||||
width="100%"
|
||||
flexDir="column"
|
||||
gap={4}
|
||||
p={12}
|
||||
bg="white"
|
||||
alignItems="center"
|
||||
onClick={() => setShow(false)}
|
||||
>
|
||||
<styled.div alignSelf="stretch" display="flex" justifyContent="end">
|
||||
<IconButton variant="ghost" onClick={() => setShow(false)}>
|
||||
<X />
|
||||
</IconButton>
|
||||
</styled.div>
|
||||
|
||||
<Link href="/" className={css({ fontSize: 24 })}>
|
||||
Localbites
|
||||
</Link>
|
||||
|
||||
<NavLink href="/">{t("general.home")}</NavLink>
|
||||
<NavLink href="/about">{t("general.about")}</NavLink>
|
||||
|
||||
<NavLink
|
||||
href="/contact"
|
||||
type="button"
|
||||
className={css({
|
||||
alignSelf: "stretch",
|
||||
textAlign: "center",
|
||||
marginTop: "auto",
|
||||
})}
|
||||
>
|
||||
{t("general.contact")}
|
||||
</NavLink>
|
||||
</styled.div>
|
||||
</styled.div>
|
||||
);
|
||||
}
|
@ -0,0 +1,36 @@
|
||||
import Link, { LinkProps } from "next/link";
|
||||
import { RecipeVariantProps, cva, cx } from "@styled-system/css";
|
||||
|
||||
import { AnchorHTMLAttributes } from "react";
|
||||
|
||||
const variants = cva({
|
||||
base: { _hover: { color: "gray.800" } },
|
||||
variants: {
|
||||
type: {
|
||||
button: {
|
||||
background: "accent.9",
|
||||
color: "white",
|
||||
p: 2,
|
||||
borderRadius: "md",
|
||||
_hover: {
|
||||
background: "accent.11",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
export default function NavLink({
|
||||
className,
|
||||
children,
|
||||
type,
|
||||
...props
|
||||
}: RecipeVariantProps<typeof variants> &
|
||||
Omit<AnchorHTMLAttributes<HTMLAnchorElement>, keyof LinkProps> &
|
||||
LinkProps) {
|
||||
return (
|
||||
<Link className={cx(variants({ type }), className)} {...props}>
|
||||
{children}
|
||||
</Link>
|
||||
);
|
||||
}
|
@ -0,0 +1,57 @@
|
||||
import { Box, styled } from "@styled-system/jsx";
|
||||
|
||||
import LanguagePicker from "./language-picker";
|
||||
import Link from "next/link";
|
||||
import MobileNav from "./mobile-nav";
|
||||
import NavLink from "./nav-link";
|
||||
import { css } from "@styled-system/css";
|
||||
import { flex } from "@styled-system/patterns";
|
||||
import { getI18n } from "@/i18n/server";
|
||||
|
||||
export default async function Navbar() {
|
||||
const t = await getI18n();
|
||||
|
||||
return (
|
||||
<>
|
||||
<styled.nav
|
||||
className={flex({ gap: 4 })}
|
||||
bg="white"
|
||||
h={20}
|
||||
px={4}
|
||||
boxShadow="lg"
|
||||
alignItems="center"
|
||||
position="fixed"
|
||||
zIndex={500}
|
||||
top={0}
|
||||
left={0}
|
||||
right={0}
|
||||
width="100%"
|
||||
>
|
||||
<Link href="/" className={css({ fontSize: 24 })}>
|
||||
Localbites
|
||||
</Link>
|
||||
<styled.div flexGrow={1} />
|
||||
|
||||
<NavLink
|
||||
href="/about"
|
||||
className={css({ display: "none", sm: { display: "block" } })}
|
||||
>
|
||||
{t("general.about")}
|
||||
</NavLink>
|
||||
|
||||
<NavLink
|
||||
href="/contact"
|
||||
type="button"
|
||||
className={css({ display: "none", sm: { display: "block" } })}
|
||||
>
|
||||
{t("general.contact")}
|
||||
</NavLink>
|
||||
|
||||
<LanguagePicker />
|
||||
|
||||
<MobileNav />
|
||||
</styled.nav>
|
||||
<Box h={20} />
|
||||
</>
|
||||
);
|
||||
}
|
@ -0,0 +1 @@
|
||||
export { Heading, type HeadingProps } from './styled/heading'
|
@ -0,0 +1 @@
|
||||
export { IconButton, type IconButtonProps } from './styled/icon-button'
|
@ -0,0 +1 @@
|
||||
export * as Menu from './styled/menu'
|
@ -0,0 +1,29 @@
|
||||
import { forwardRef } from 'react'
|
||||
import { styled } from 'styled-system/jsx'
|
||||
import { Spinner as StyledSpinner, type SpinnerProps as StyledSpinnerProps } from './styled/spinner'
|
||||
|
||||
export interface SpinnerProps extends StyledSpinnerProps {
|
||||
/**
|
||||
* For accessibility, it is important to add a fallback loading text.
|
||||
* This text will be visible to screen readers.
|
||||
* @default "Loading..."
|
||||
*/
|
||||
label?: string
|
||||
}
|
||||
|
||||
export const Spinner = forwardRef<HTMLDivElement, SpinnerProps>((props, ref) => {
|
||||
const { label = 'Loading...', ...rest } = props
|
||||
|
||||
return (
|
||||
<StyledSpinner
|
||||
ref={ref}
|
||||
borderBottomColor="transparent"
|
||||
borderLeftColor="transparent"
|
||||
{...rest}
|
||||
>
|
||||
{label && <styled.span srOnly>{label}</styled.span>}
|
||||
</StyledSpinner>
|
||||
)
|
||||
})
|
||||
|
||||
Spinner.displayName = 'Spinner'
|
@ -0,0 +1,10 @@
|
||||
import { styled } from 'styled-system/jsx'
|
||||
import { type TextVariantProps, text } from 'styled-system/recipes'
|
||||
import type { ComponentProps, StyledComponent } from 'styled-system/types'
|
||||
|
||||
type TextProps = TextVariantProps & { as?: React.ElementType }
|
||||
|
||||
export type HeadingProps = ComponentProps<typeof Heading>
|
||||
export const Heading = styled('h2', text, {
|
||||
defaultProps: { variant: 'heading' },
|
||||
}) as StyledComponent<'h2', TextProps>
|
@ -0,0 +1,9 @@
|
||||
import { ark } from '@ark-ui/react/factory'
|
||||
import { styled } from 'styled-system/jsx'
|
||||
import { type ButtonVariantProps, button } from 'styled-system/recipes'
|
||||
import type { ComponentProps } from 'styled-system/types'
|
||||
|
||||
export type IconButtonProps = ComponentProps<typeof IconButton>
|
||||
export const IconButton = styled(ark.button, button, {
|
||||
defaultProps: { px: '0' } as ButtonVariantProps,
|
||||
})
|
@ -0,0 +1,103 @@
|
||||
'use client'
|
||||
import type { Assign } from '@ark-ui/react'
|
||||
import { Menu } from '@ark-ui/react/menu'
|
||||
import { type MenuVariantProps, menu } from 'styled-system/recipes'
|
||||
import type { ComponentProps, HTMLStyledProps } from 'styled-system/types'
|
||||
import { createStyleContext } from './utils/create-style-context'
|
||||
|
||||
const { withRootProvider, withContext } = createStyleContext(menu)
|
||||
|
||||
export type RootProviderProps = ComponentProps<typeof RootProvider>
|
||||
export const RootProvider = withRootProvider<Assign<Menu.RootProviderProps, MenuVariantProps>>(
|
||||
Menu.RootProvider,
|
||||
)
|
||||
|
||||
export type RootProps = ComponentProps<typeof Root>
|
||||
export const Root = withRootProvider<Assign<Menu.RootProps, MenuVariantProps>>(Menu.Root)
|
||||
|
||||
export const Arrow = withContext<
|
||||
HTMLDivElement,
|
||||
Assign<HTMLStyledProps<'div'>, Menu.ArrowBaseProps>
|
||||
>(Menu.Arrow, 'arrow')
|
||||
|
||||
export const ArrowTip = withContext<
|
||||
HTMLDivElement,
|
||||
Assign<HTMLStyledProps<'div'>, Menu.ArrowTipBaseProps>
|
||||
>(Menu.ArrowTip, 'arrowTip')
|
||||
|
||||
export const CheckboxItem = withContext<
|
||||
HTMLDivElement,
|
||||
Assign<HTMLStyledProps<'div'>, Menu.CheckboxItemBaseProps>
|
||||
>(Menu.CheckboxItem, 'item')
|
||||
|
||||
export const Content = withContext<
|
||||
HTMLDivElement,
|
||||
Assign<HTMLStyledProps<'div'>, Menu.ContentBaseProps>
|
||||
>(Menu.Content, 'content')
|
||||
|
||||
export const ContextTrigger = withContext<
|
||||
HTMLButtonElement,
|
||||
Assign<HTMLStyledProps<'button'>, Menu.ContextTriggerBaseProps>
|
||||
>(Menu.ContextTrigger, 'contextTrigger')
|
||||
|
||||
export const Indicator = withContext<
|
||||
HTMLDivElement,
|
||||
Assign<HTMLStyledProps<'div'>, Menu.IndicatorBaseProps>
|
||||
>(Menu.Indicator, 'indicator')
|
||||
|
||||
export const ItemGroupLabel = withContext<
|
||||
HTMLDivElement,
|
||||
Assign<HTMLStyledProps<'div'>, Menu.ItemGroupLabelBaseProps>
|
||||
>(Menu.ItemGroupLabel, 'itemGroupLabel')
|
||||
|
||||
export const ItemGroup = withContext<
|
||||
HTMLDivElement,
|
||||
Assign<HTMLStyledProps<'div'>, Menu.ItemGroupBaseProps>
|
||||
>(Menu.ItemGroup, 'itemGroup')
|
||||
|
||||
export const ItemIndicator = withContext<
|
||||
HTMLDivElement,
|
||||
Assign<HTMLStyledProps<'div'>, Menu.ItemIndicatorBaseProps>
|
||||
>(Menu.ItemIndicator, 'itemIndicator')
|
||||
|
||||
export const Item = withContext<HTMLDivElement, Assign<HTMLStyledProps<'div'>, Menu.ItemBaseProps>>(
|
||||
Menu.Item,
|
||||
'item',
|
||||
)
|
||||
|
||||
export const ItemText = withContext<
|
||||
HTMLDivElement,
|
||||
Assign<HTMLStyledProps<'div'>, Menu.ItemTextBaseProps>
|
||||
>(Menu.ItemText, 'itemText')
|
||||
|
||||
export const Positioner = withContext<
|
||||
HTMLDivElement,
|
||||
Assign<HTMLStyledProps<'div'>, Menu.PositionerBaseProps>
|
||||
>(Menu.Positioner, 'positioner')
|
||||
|
||||
export const RadioItemGroup = withContext<
|
||||
HTMLDivElement,
|
||||
Assign<HTMLStyledProps<'div'>, Menu.RadioItemGroupBaseProps>
|
||||
>(Menu.RadioItemGroup, 'itemGroup')
|
||||
|
||||
export const RadioItem = withContext<
|
||||
HTMLDivElement,
|
||||
Assign<HTMLStyledProps<'div'>, Menu.RadioItemBaseProps>
|
||||
>(Menu.RadioItem, 'item')
|
||||
|
||||
export const Separator = withContext<
|
||||
HTMLHRElement,
|
||||
Assign<HTMLStyledProps<'hr'>, Menu.SeparatorBaseProps>
|
||||
>(Menu.Separator, 'separator')
|
||||
|
||||
export const TriggerItem = withContext<
|
||||
HTMLDivElement,
|
||||
Assign<HTMLStyledProps<'div'>, Menu.TriggerItemBaseProps>
|
||||
>(Menu.TriggerItem, 'triggerItem')
|
||||
|
||||
export const Trigger = withContext<
|
||||
HTMLButtonElement,
|
||||
Assign<HTMLStyledProps<'button'>, Menu.TriggerBaseProps>
|
||||
>(Menu.Trigger, 'trigger')
|
||||
|
||||
export { MenuContext as Context } from '@ark-ui/react/menu'
|
@ -0,0 +1,7 @@
|
||||
import { ark } from '@ark-ui/react/factory'
|
||||
import { styled } from 'styled-system/jsx'
|
||||
import { spinner } from 'styled-system/recipes'
|
||||
import type { ComponentProps } from 'styled-system/types'
|
||||
|
||||
export type SpinnerProps = ComponentProps<typeof Spinner>
|
||||
export const Spinner = styled(ark.div, spinner)
|
@ -0,0 +1,8 @@
|
||||
import { styled } from 'styled-system/jsx'
|
||||
import { type TextVariantProps, text } from 'styled-system/recipes'
|
||||
import type { ComponentProps, StyledComponent } from 'styled-system/types'
|
||||
|
||||
type ParagraphProps = TextVariantProps & { as?: React.ElementType }
|
||||
|
||||
export type TextProps = ComponentProps<typeof Text>
|
||||
export const Text = styled('p', text) as StyledComponent<'p', ParagraphProps>
|
@ -0,0 +1 @@
|
||||
export { Text, type TextProps } from './styled/text'
|
@ -0,0 +1,12 @@
|
||||
"use client";
|
||||
|
||||
import { createI18nClient } from "next-international/client";
|
||||
import { importedLocales } from "./locales";
|
||||
|
||||
export const {
|
||||
useI18n,
|
||||
useScopedI18n,
|
||||
I18nProviderClient,
|
||||
useChangeLocale,
|
||||
useCurrentLocale,
|
||||
} = createI18nClient(importedLocales);
|
@ -0,0 +1,6 @@
|
||||
export default {
|
||||
general: {
|
||||
home: "Startseite",
|
||||
getStarted: "Um zu starten bearbeiten Sie",
|
||||
},
|
||||
} as const;
|
@ -0,0 +1,6 @@
|
||||
export default {
|
||||
general: {
|
||||
home: "Home",
|
||||
getStarted: "Get started by editing",
|
||||
},
|
||||
} as const;
|
@ -0,0 +1,29 @@
|
||||
export const locales = [
|
||||
{
|
||||
label: {
|
||||
de: "Deutsch",
|
||||
en: "German",
|
||||
fr: "Allemand",
|
||||
it: "Tedesco",
|
||||
},
|
||||
code: "de",
|
||||
},
|
||||
{
|
||||
label: {
|
||||
de: "Englisch",
|
||||
en: "English",
|
||||
it: "Inglese",
|
||||
fr: "Anglais",
|
||||
},
|
||||
code: "en",
|
||||
},
|
||||
] as const;
|
||||
|
||||
export type Locale = (typeof locales)[number]["code"];
|
||||
|
||||
export const defaultLocale: Locale = "de";
|
||||
|
||||
export const importedLocales = {
|
||||
de: () => import("./de"),
|
||||
en: () => import("./en"),
|
||||
} as const;
|
@ -0,0 +1,16 @@
|
||||
import { Locale, importedLocales } from "./locales";
|
||||
import {
|
||||
createI18nServer,
|
||||
setStaticParamsLocale,
|
||||
} from "next-international/server";
|
||||
|
||||
export const { getI18n, getScopedI18n, getStaticParams, getCurrentLocale } =
|
||||
createI18nServer(importedLocales);
|
||||
|
||||
export const getLocalizedI18n = async (locale: Locale) => {
|
||||
const prevLocale = getCurrentLocale();
|
||||
|
||||
setStaticParamsLocale(locale);
|
||||
|
||||
return [await getI18n(), () => setStaticParamsLocale(prevLocale)] as const;
|
||||
};
|
@ -0,0 +1,18 @@
|
||||
import { defaultLocale, locales } from "@/i18n/locales";
|
||||
|
||||
import { NextRequest } from "next/server";
|
||||
import { createI18nMiddleware } from "next-international/middleware";
|
||||
|
||||
const I18nMiddleware = createI18nMiddleware({
|
||||
locales: locales.map(({ code }) => code),
|
||||
defaultLocale,
|
||||
urlMappingStrategy: "rewriteDefault",
|
||||
});
|
||||
|
||||
export function middleware(request: NextRequest) {
|
||||
return I18nMiddleware(request);
|
||||
}
|
||||
|
||||
export const config = {
|
||||
matcher: ["/((?!api|admin|static|.*\\..*|_next|favicon.ico|robots.txt).*)"],
|
||||
};
|
Loading…
Reference in New Issue