mirror of
https://gitea.gofwd.group/dstrawsb/ballistic-builder.git
synced 2025-12-06 02:36:44 -05:00
Merge branch 'develop' of ssh://gitea.gofwd.group:2225/dstrawsb/ballistic-builder into develop
This commit is contained in:
1374
package-lock.json
generated
1374
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -9,10 +9,6 @@
|
|||||||
"lint": "next lint"
|
"lint": "next lint"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@chakra-ui/form-control": "^2.2.0",
|
|
||||||
"@chakra-ui/next-js": "^2.4.2",
|
|
||||||
"@chakra-ui/react": "^3.1.2",
|
|
||||||
"@chakra-ui/toast": "^7.0.2",
|
|
||||||
"@emotion/react": "^11.13.5",
|
"@emotion/react": "^11.13.5",
|
||||||
"@emotion/styled": "^11.13.5",
|
"@emotion/styled": "^11.13.5",
|
||||||
"@headlessui/react": "^2.2.0",
|
"@headlessui/react": "^2.2.0",
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
import { Button } from "@components/ui/button";
|
|
||||||
|
|
||||||
|
|
||||||
export default function BuilderPage() {
|
export default function BuilderPage() {
|
||||||
@@ -28,7 +27,7 @@ export default function BuilderPage() {
|
|||||||
<td></td>
|
<td></td>
|
||||||
<td>Palmetto State</td>
|
<td>Palmetto State</td>
|
||||||
<td>101.99</td>
|
<td>101.99</td>
|
||||||
<td><Button>Buy Item</Button></td>
|
<td><button>Buy Item</button></td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
</tbody>
|
</tbody>
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
import { Button } from "@components/ui/button";
|
|
||||||
import { getPSA, getLowerBuildKits, getProductType } from "@queries/PSA";
|
import { getPSA, getLowerBuildKits, getProductType } from "@queries/PSA";
|
||||||
import { psa } from '@db/schema/Psa';
|
import { psa } from '@db/schema/Psa';
|
||||||
import partTypes from 'src/data/parts_cats.json';
|
import partTypes from 'src/data/parts_cats.json';
|
||||||
@@ -29,7 +28,7 @@ export default async function BarrelsPage() {
|
|||||||
<td className='text-slate-800'>{psa.modelnumber}</td>
|
<td className='text-slate-800'>{psa.modelnumber}</td>
|
||||||
<td className="text-slate-800 flex items-center gap-2">
|
<td className="text-slate-800 flex items-center gap-2">
|
||||||
${Number(psa.salePrice).toFixed(2)}
|
${Number(psa.salePrice).toFixed(2)}
|
||||||
<Button variant="outline">Buy</Button>
|
<button >Buy</button>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
))}
|
))}
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
import { Button } from "@components/ui/button";
|
|
||||||
import { getPSA, getLowerBuildKits, getGrips } from "@queries/PSA";
|
import { getPSA, getLowerBuildKits, getGrips } from "@queries/PSA";
|
||||||
import { psa } from '@db/schema/Psa';
|
import { psa } from '@db/schema/Psa';
|
||||||
import partTypes from 'src/data/parts_cats.json';
|
import partTypes from 'src/data/parts_cats.json';
|
||||||
@@ -31,7 +30,7 @@ export default async function GripsPage() {
|
|||||||
<td className='text-slate-800'>{psa.retailPrice}</td>
|
<td className='text-slate-800'>{psa.retailPrice}</td>
|
||||||
<td className="text-slate-800 flex items-center gap-2">
|
<td className="text-slate-800 flex items-center gap-2">
|
||||||
${Number(psa.salePrice).toFixed(2)}
|
${Number(psa.salePrice).toFixed(2)}
|
||||||
<Button variant="default">Buy</Button>
|
<button>Buy</button>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
))}
|
))}
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
import { Button } from "@components/ui/button";
|
|
||||||
import { getPSA, getLowerBuildKits, getARHandGuards } from "@queries/PSA";
|
import { getPSA, getLowerBuildKits, getARHandGuards } from "@queries/PSA";
|
||||||
import { psa } from '@db/schema/Psa';
|
import { psa } from '@db/schema/Psa';
|
||||||
import partTypes from 'src/data/parts_cats.json';
|
import partTypes from 'src/data/parts_cats.json';
|
||||||
@@ -29,7 +28,7 @@ export default async function HamdGuardsPage() {
|
|||||||
<td className='text-slate-800'>{psa.modelnumber}</td>
|
<td className='text-slate-800'>{psa.modelnumber}</td>
|
||||||
<td className='text-slate-800 flex items-center gap-2'>
|
<td className='text-slate-800 flex items-center gap-2'>
|
||||||
${Number(psa.salePrice).toFixed(2)}
|
${Number(psa.salePrice).toFixed(2)}
|
||||||
<Button variant="outline">Buy</Button>
|
<button >Buy</button>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
))}
|
))}
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
import { Button } from "@components/ui/button";
|
|
||||||
import { getARCompleteLowers, getProductType } from "@queries/PSA";
|
import { getARCompleteLowers, getProductType } from "@queries/PSA";
|
||||||
import partTypes from 'src/data/parts_cats.json';
|
import partTypes from 'src/data/parts_cats.json';
|
||||||
import { psa } from "@db/schema/Psa";
|
import { psa } from "@db/schema/Psa";
|
||||||
@@ -39,7 +38,7 @@ export default async function LowerReceiverPage() {
|
|||||||
${Number(psa.salePrice).toFixed(2)}
|
${Number(psa.salePrice).toFixed(2)}
|
||||||
{/* I dont think this is exactly correct but works for now? */}
|
{/* I dont think this is exactly correct but works for now? */}
|
||||||
<Link href={psa.buyLink} passHref={true}>
|
<Link href={psa.buyLink} passHref={true}>
|
||||||
<Button variant="default">Buy</Button>
|
<button >Buy</button>
|
||||||
</Link>
|
</Link>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
import { Button } from "@components/ui/button";
|
|
||||||
import { getMuzzleDevices } from "@queries/PSA";
|
import { getMuzzleDevices } from "@queries/PSA";
|
||||||
import { psa } from '@db/schema/Psa';
|
import { psa } from '@db/schema/Psa';
|
||||||
import partTypes from 'src/data/parts_cats.json';
|
import partTypes from 'src/data/parts_cats.json';
|
||||||
@@ -29,7 +28,7 @@ export default async function MuzzleDevices() {
|
|||||||
<td className='text-slate-800'>{psa.modelnumber}</td>
|
<td className='text-slate-800'>{psa.modelnumber}</td>
|
||||||
<td className='text-slate-800 flex items-center gap-2'>
|
<td className='text-slate-800 flex items-center gap-2'>
|
||||||
${Number(psa.salePrice).toFixed(2)}
|
${Number(psa.salePrice).toFixed(2)}
|
||||||
<Button variant="outline">Buy</Button>
|
<button >Buy</button>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
))}
|
))}
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
import { Button } from "@components/ui/button";
|
|
||||||
import { getPSA, getLowerBuildKits, getProductType} from "@queries/PSA";
|
import { getPSA, getLowerBuildKits, getProductType} from "@queries/PSA";
|
||||||
import { psa } from '@db/schema/Psa';
|
import { psa } from '@db/schema/Psa';
|
||||||
import partTypes from 'src/data/parts_cats.json';
|
import partTypes from 'src/data/parts_cats.json';
|
||||||
@@ -26,7 +25,7 @@ export default async function GripsPage() {
|
|||||||
<td>{psa.modelnumber}</td>
|
<td>{psa.modelnumber}</td>
|
||||||
<td className="flex items-center gap-2">
|
<td className="flex items-center gap-2">
|
||||||
${Number(psa.salePrice).toFixed(2)}
|
${Number(psa.salePrice).toFixed(2)}
|
||||||
<Button variant="outline">Buy</Button>
|
<button >Buy</button>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
))}
|
))}
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
import { Button } from "@components/ui/button";
|
|
||||||
import { getStocks } from "@queries/PSA";
|
import { getStocks } from "@queries/PSA";
|
||||||
import { psa } from '@db/schema/Psa';
|
import { psa } from '@db/schema/Psa';
|
||||||
import partTypes from 'src/data/parts_cats.json';
|
import partTypes from 'src/data/parts_cats.json';
|
||||||
@@ -29,7 +28,7 @@ export default async function StocksPage() {
|
|||||||
<td className='text-slate-800'>{psa.modelnumber}</td>
|
<td className='text-slate-800'>{psa.modelnumber}</td>
|
||||||
<td className='text-slate-800 flex items-center gap-2'>
|
<td className='text-slate-800 flex items-center gap-2'>
|
||||||
${Number(psa.salePrice).toFixed(2)}
|
${Number(psa.salePrice).toFixed(2)}
|
||||||
<Button variant="outline">Buy</Button>
|
<button >Buy</button>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
))}
|
))}
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
import { Button } from "@components/ui/button";
|
|
||||||
import { getARTriggers} from "@queries/PSA";
|
import { getARTriggers} from "@queries/PSA";
|
||||||
import { psa } from '@db/schema/Psa';
|
import { psa } from '@db/schema/Psa';
|
||||||
import partTypes from 'src/data/parts_cats.json';
|
import partTypes from 'src/data/parts_cats.json';
|
||||||
@@ -29,7 +28,7 @@ export default async function TriggersPage() {
|
|||||||
<td className='text-slate-800'>{psa.modelnumber}</td>
|
<td className='text-slate-800'>{psa.modelnumber}</td>
|
||||||
<td className='text-slate-800 flex items-center gap-2'>
|
<td className='text-slate-800 flex items-center gap-2'>
|
||||||
${Number(psa.salePrice).toFixed(2)}
|
${Number(psa.salePrice).toFixed(2)}
|
||||||
<Button variant="outline">Buy</Button>
|
<button>Buy</button>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
))}
|
))}
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
import { Button } from "@components/ui/button";
|
|
||||||
import { getPSA, getUpperReciever } from "@queries/PSA";
|
import { getPSA, getUpperReciever } from "@queries/PSA";
|
||||||
import { psa } from '@db/schema/Psa';
|
import { psa } from '@db/schema/Psa';
|
||||||
import styles from '../styles.module.css';
|
import styles from '../styles.module.css';
|
||||||
@@ -28,7 +27,7 @@ export default async function UpperReceiverPage() {
|
|||||||
<td className='text-slate-800'>{psa.modelnumber}</td>
|
<td className='text-slate-800'>{psa.modelnumber}</td>
|
||||||
<td className='text-slate-800 flex items-center gap-2'>
|
<td className='text-slate-800 flex items-center gap-2'>
|
||||||
${Number(psa.salePrice).toFixed(2)}
|
${Number(psa.salePrice).toFixed(2)}
|
||||||
<Button variant="outline">Buy</Button>
|
<button >Buy</button>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
))}
|
))}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { Provider } from "../components/ui/provider"
|
//import { Provider } from "../components/ui/provider"
|
||||||
import "../styles/globals.css";
|
import "../styles/globals.css";
|
||||||
import Navbar from "../components/Navbar";
|
import Navbar from "../components/Navbar";
|
||||||
import PopNav from "@src/components/PopNav/page";
|
import PopNav from "@src/components/PopNav/page";
|
||||||
@@ -22,10 +22,10 @@ export default function RootLayout(props: { children: React.ReactNode }) {
|
|||||||
return (
|
return (
|
||||||
<html suppressHydrationWarning className={inter.className}>
|
<html suppressHydrationWarning className={inter.className}>
|
||||||
<body className="bg-slate-200 ">
|
<body className="bg-slate-200 ">
|
||||||
<Provider>
|
|
||||||
<Navbar />
|
<Navbar />
|
||||||
<PopNav />
|
<PopNav />
|
||||||
{children}</Provider>
|
{children}
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -1,47 +0,0 @@
|
|||||||
import { Accordion, HStack } from "@chakra-ui/react"
|
|
||||||
import * as React from "react"
|
|
||||||
import { LuChevronDown } from "react-icons/lu"
|
|
||||||
|
|
||||||
interface AccordionItemTriggerProps extends Accordion.ItemTriggerProps {
|
|
||||||
indicatorPlacement?: "start" | "end"
|
|
||||||
}
|
|
||||||
|
|
||||||
export const AccordionItemTrigger = React.forwardRef<
|
|
||||||
HTMLButtonElement,
|
|
||||||
AccordionItemTriggerProps
|
|
||||||
>(function AccordionItemTrigger(props, ref) {
|
|
||||||
const { children, indicatorPlacement = "end", ...rest } = props
|
|
||||||
return (
|
|
||||||
<Accordion.ItemTrigger {...rest} ref={ref}>
|
|
||||||
{indicatorPlacement === "start" && (
|
|
||||||
<Accordion.ItemIndicator rotate={{ base: "-90deg", _open: "0deg" }}>
|
|
||||||
<LuChevronDown />
|
|
||||||
</Accordion.ItemIndicator>
|
|
||||||
)}
|
|
||||||
<HStack gap="4" flex="1" textAlign="start" width="full">
|
|
||||||
{children}
|
|
||||||
</HStack>
|
|
||||||
{indicatorPlacement === "end" && (
|
|
||||||
<Accordion.ItemIndicator>
|
|
||||||
<LuChevronDown />
|
|
||||||
</Accordion.ItemIndicator>
|
|
||||||
)}
|
|
||||||
</Accordion.ItemTrigger>
|
|
||||||
)
|
|
||||||
})
|
|
||||||
|
|
||||||
interface AccordionItemContentProps extends Accordion.ItemContentProps {}
|
|
||||||
|
|
||||||
export const AccordionItemContent = React.forwardRef<
|
|
||||||
HTMLDivElement,
|
|
||||||
AccordionItemContentProps
|
|
||||||
>(function AccordionItemContent(props, ref) {
|
|
||||||
return (
|
|
||||||
<Accordion.ItemContent>
|
|
||||||
<Accordion.ItemBody {...props} ref={ref} />
|
|
||||||
</Accordion.ItemContent>
|
|
||||||
)
|
|
||||||
})
|
|
||||||
|
|
||||||
export const AccordionRoot = Accordion.Root
|
|
||||||
export const AccordionItem = Accordion.Item
|
|
||||||
@@ -1,40 +0,0 @@
|
|||||||
import { ActionBar, Portal } from "@chakra-ui/react"
|
|
||||||
import { CloseButton } from "./close-button"
|
|
||||||
import * as React from "react"
|
|
||||||
|
|
||||||
interface ActionBarContentProps extends ActionBar.ContentProps {
|
|
||||||
portalled?: boolean
|
|
||||||
portalRef?: React.RefObject<HTMLElement>
|
|
||||||
}
|
|
||||||
|
|
||||||
export const ActionBarContent = React.forwardRef<
|
|
||||||
HTMLDivElement,
|
|
||||||
ActionBarContentProps
|
|
||||||
>(function ActionBarContent(props, ref) {
|
|
||||||
const { children, portalled = true, portalRef, ...rest } = props
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Portal disabled={!portalled} container={portalRef}>
|
|
||||||
<ActionBar.Positioner>
|
|
||||||
<ActionBar.Content ref={ref} {...rest} asChild={false}>
|
|
||||||
{children}
|
|
||||||
</ActionBar.Content>
|
|
||||||
</ActionBar.Positioner>
|
|
||||||
</Portal>
|
|
||||||
)
|
|
||||||
})
|
|
||||||
|
|
||||||
export const ActionBarCloseTrigger = React.forwardRef<
|
|
||||||
HTMLButtonElement,
|
|
||||||
ActionBar.CloseTriggerProps
|
|
||||||
>(function ActionBarCloseTrigger(props, ref) {
|
|
||||||
return (
|
|
||||||
<ActionBar.CloseTrigger {...props} asChild ref={ref}>
|
|
||||||
<CloseButton size="sm" />
|
|
||||||
</ActionBar.CloseTrigger>
|
|
||||||
)
|
|
||||||
})
|
|
||||||
|
|
||||||
export const ActionBarRoot = ActionBar.Root
|
|
||||||
export const ActionBarSelectionTrigger = ActionBar.SelectionTrigger
|
|
||||||
export const ActionBarSeparator = ActionBar.Separator
|
|
||||||
@@ -1,51 +0,0 @@
|
|||||||
import { Alert as ChakraAlert } from "@chakra-ui/react"
|
|
||||||
import { CloseButton } from "./close-button"
|
|
||||||
import * as React from "react"
|
|
||||||
|
|
||||||
export interface AlertProps extends Omit<ChakraAlert.RootProps, "title"> {
|
|
||||||
startElement?: React.ReactNode
|
|
||||||
endElement?: React.ReactNode
|
|
||||||
title?: React.ReactNode
|
|
||||||
icon?: React.ReactElement
|
|
||||||
closable?: boolean
|
|
||||||
onClose?: () => void
|
|
||||||
}
|
|
||||||
|
|
||||||
export const Alert = React.forwardRef<HTMLDivElement, AlertProps>(
|
|
||||||
function Alert(props, ref) {
|
|
||||||
const {
|
|
||||||
title,
|
|
||||||
children,
|
|
||||||
icon,
|
|
||||||
closable,
|
|
||||||
onClose,
|
|
||||||
startElement,
|
|
||||||
endElement,
|
|
||||||
...rest
|
|
||||||
} = props
|
|
||||||
return (
|
|
||||||
<ChakraAlert.Root ref={ref} {...rest}>
|
|
||||||
{startElement || <ChakraAlert.Indicator>{icon}</ChakraAlert.Indicator>}
|
|
||||||
{children ? (
|
|
||||||
<ChakraAlert.Content>
|
|
||||||
<ChakraAlert.Title>{title}</ChakraAlert.Title>
|
|
||||||
<ChakraAlert.Description>{children}</ChakraAlert.Description>
|
|
||||||
</ChakraAlert.Content>
|
|
||||||
) : (
|
|
||||||
<ChakraAlert.Title flex="1">{title}</ChakraAlert.Title>
|
|
||||||
)}
|
|
||||||
{endElement}
|
|
||||||
{closable && (
|
|
||||||
<CloseButton
|
|
||||||
size="sm"
|
|
||||||
pos="relative"
|
|
||||||
top="-2"
|
|
||||||
insetEnd="-2"
|
|
||||||
alignSelf="flex-start"
|
|
||||||
onClick={onClose}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
</ChakraAlert.Root>
|
|
||||||
)
|
|
||||||
},
|
|
||||||
)
|
|
||||||
@@ -1,74 +0,0 @@
|
|||||||
"use client"
|
|
||||||
|
|
||||||
import type { GroupProps, SlotRecipeProps } from "@chakra-ui/react"
|
|
||||||
import { Avatar as ChakraAvatar, Group } from "@chakra-ui/react"
|
|
||||||
import * as React from "react"
|
|
||||||
|
|
||||||
type ImageProps = React.ImgHTMLAttributes<HTMLImageElement>
|
|
||||||
|
|
||||||
export interface AvatarProps extends ChakraAvatar.RootProps {
|
|
||||||
name?: string
|
|
||||||
src?: string
|
|
||||||
srcSet?: string
|
|
||||||
loading?: ImageProps["loading"]
|
|
||||||
icon?: React.ReactElement
|
|
||||||
fallback?: React.ReactNode
|
|
||||||
}
|
|
||||||
|
|
||||||
export const Avatar = React.forwardRef<HTMLDivElement, AvatarProps>(
|
|
||||||
function Avatar(props, ref) {
|
|
||||||
const { name, src, srcSet, loading, icon, fallback, children, ...rest } =
|
|
||||||
props
|
|
||||||
return (
|
|
||||||
<ChakraAvatar.Root ref={ref} {...rest}>
|
|
||||||
<AvatarFallback name={name} icon={icon}>
|
|
||||||
{fallback}
|
|
||||||
</AvatarFallback>
|
|
||||||
<ChakraAvatar.Image src={src} srcSet={srcSet} loading={loading} />
|
|
||||||
{children}
|
|
||||||
</ChakraAvatar.Root>
|
|
||||||
)
|
|
||||||
},
|
|
||||||
)
|
|
||||||
|
|
||||||
interface AvatarFallbackProps extends ChakraAvatar.FallbackProps {
|
|
||||||
name?: string
|
|
||||||
icon?: React.ReactElement
|
|
||||||
}
|
|
||||||
|
|
||||||
const AvatarFallback = React.forwardRef<HTMLDivElement, AvatarFallbackProps>(
|
|
||||||
function AvatarFallback(props, ref) {
|
|
||||||
const { name, icon, children, ...rest } = props
|
|
||||||
return (
|
|
||||||
<ChakraAvatar.Fallback ref={ref} {...rest}>
|
|
||||||
{children}
|
|
||||||
{name != null && children == null && <>{getInitials(name)}</>}
|
|
||||||
{name == null && children == null && (
|
|
||||||
<ChakraAvatar.Icon asChild={!!icon}>{icon}</ChakraAvatar.Icon>
|
|
||||||
)}
|
|
||||||
</ChakraAvatar.Fallback>
|
|
||||||
)
|
|
||||||
},
|
|
||||||
)
|
|
||||||
|
|
||||||
function getInitials(name: string) {
|
|
||||||
const names = name.trim().split(" ")
|
|
||||||
const firstName = names[0] != null ? names[0] : ""
|
|
||||||
const lastName = names.length > 1 ? names[names.length - 1] : ""
|
|
||||||
return firstName && lastName
|
|
||||||
? `${firstName.charAt(0)}${lastName.charAt(0)}`
|
|
||||||
: firstName.charAt(0)
|
|
||||||
}
|
|
||||||
|
|
||||||
interface AvatarGroupProps extends GroupProps, SlotRecipeProps<"avatar"> {}
|
|
||||||
|
|
||||||
export const AvatarGroup = React.forwardRef<HTMLDivElement, AvatarGroupProps>(
|
|
||||||
function AvatarGroup(props, ref) {
|
|
||||||
const { size, variant, borderless, ...rest } = props
|
|
||||||
return (
|
|
||||||
<ChakraAvatar.PropsProvider value={{ size, variant, borderless }}>
|
|
||||||
<Group gap="0" spaceX="-3" ref={ref} {...rest} />
|
|
||||||
</ChakraAvatar.PropsProvider>
|
|
||||||
)
|
|
||||||
},
|
|
||||||
)
|
|
||||||
@@ -1,31 +0,0 @@
|
|||||||
import { Blockquote as ChakraBlockquote } from "@chakra-ui/react"
|
|
||||||
import * as React from "react"
|
|
||||||
|
|
||||||
export interface BlockquoteProps extends ChakraBlockquote.RootProps {
|
|
||||||
cite?: React.ReactNode
|
|
||||||
citeUrl?: string
|
|
||||||
icon?: React.ReactNode
|
|
||||||
showDash?: boolean
|
|
||||||
}
|
|
||||||
|
|
||||||
export const Blockquote = React.forwardRef<HTMLDivElement, BlockquoteProps>(
|
|
||||||
function Blockquote(props, ref) {
|
|
||||||
const { children, cite, citeUrl, showDash, icon, ...rest } = props
|
|
||||||
|
|
||||||
return (
|
|
||||||
<ChakraBlockquote.Root ref={ref} {...rest}>
|
|
||||||
{icon}
|
|
||||||
<ChakraBlockquote.Content cite={citeUrl}>
|
|
||||||
{children}
|
|
||||||
</ChakraBlockquote.Content>
|
|
||||||
{cite && (
|
|
||||||
<ChakraBlockquote.Caption>
|
|
||||||
{showDash ? <>—</> : null} <cite>{cite}</cite>
|
|
||||||
</ChakraBlockquote.Caption>
|
|
||||||
)}
|
|
||||||
</ChakraBlockquote.Root>
|
|
||||||
)
|
|
||||||
},
|
|
||||||
)
|
|
||||||
|
|
||||||
export const BlockquoteIcon = ChakraBlockquote.Icon
|
|
||||||
@@ -1,40 +0,0 @@
|
|||||||
import { Breadcrumb, type SystemStyleObject } from "@chakra-ui/react"
|
|
||||||
import * as React from "react"
|
|
||||||
|
|
||||||
export interface BreadcrumbRootProps extends Breadcrumb.RootProps {
|
|
||||||
separator?: React.ReactNode
|
|
||||||
separatorGap?: SystemStyleObject["gap"]
|
|
||||||
}
|
|
||||||
|
|
||||||
export const BreadcrumbRoot = React.forwardRef<
|
|
||||||
HTMLDivElement,
|
|
||||||
BreadcrumbRootProps
|
|
||||||
>(function BreadcrumbRoot(props, ref) {
|
|
||||||
const { separator, separatorGap, children, ...rest } = props
|
|
||||||
|
|
||||||
const validChildren = React.Children.toArray(children).filter(
|
|
||||||
React.isValidElement,
|
|
||||||
)
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Breadcrumb.Root ref={ref} {...rest}>
|
|
||||||
<Breadcrumb.List gap={separatorGap}>
|
|
||||||
{validChildren.map((child, index) => {
|
|
||||||
const last = index === validChildren.length - 1
|
|
||||||
return (
|
|
||||||
<React.Fragment key={index}>
|
|
||||||
<Breadcrumb.Item>{child}</Breadcrumb.Item>
|
|
||||||
{!last && (
|
|
||||||
<Breadcrumb.Separator>{separator}</Breadcrumb.Separator>
|
|
||||||
)}
|
|
||||||
</React.Fragment>
|
|
||||||
)
|
|
||||||
})}
|
|
||||||
</Breadcrumb.List>
|
|
||||||
</Breadcrumb.Root>
|
|
||||||
)
|
|
||||||
})
|
|
||||||
|
|
||||||
export const BreadcrumbLink = Breadcrumb.Link
|
|
||||||
export const BreadcrumbCurrentLink = Breadcrumb.CurrentLink
|
|
||||||
export const BreadcrumbEllipsis = Breadcrumb.Ellipsis
|
|
||||||
@@ -1,57 +0,0 @@
|
|||||||
import * as React from "react"
|
|
||||||
import { Slot } from "@radix-ui/react-slot"
|
|
||||||
import { cva, type VariantProps, } from "class-variance-authority"
|
|
||||||
import { cn } from "src/lib/utils"
|
|
||||||
|
|
||||||
|
|
||||||
const buttonVariants = cva(
|
|
||||||
"inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0",
|
|
||||||
{
|
|
||||||
variants: {
|
|
||||||
variant: {
|
|
||||||
default:
|
|
||||||
"bg-primary text-primary-foreground shadow hover:bg-primary/90",
|
|
||||||
destructive:
|
|
||||||
"bg-destructive text-destructive-foreground shadow-sm hover:bg-destructive/90",
|
|
||||||
outline:
|
|
||||||
"border border-input bg-background shadow-sm hover:bg-accent hover:text-accent-foreground",
|
|
||||||
secondary:
|
|
||||||
"bg-secondary text-secondary-foreground shadow-sm hover:bg-secondary/80",
|
|
||||||
ghost: "hover:bg-accent hover:text-accent-foreground",
|
|
||||||
link: "text-primary underline-offset-4 hover:underline",
|
|
||||||
},
|
|
||||||
size: {
|
|
||||||
default: "h-9 px-4 py-2",
|
|
||||||
sm: "h-8 rounded-md px-3 text-xs",
|
|
||||||
lg: "h-10 rounded-md px-8",
|
|
||||||
icon: "h-9 w-9",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
defaultVariants: {
|
|
||||||
variant: "default",
|
|
||||||
size: "default",
|
|
||||||
},
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
export interface ButtonProps
|
|
||||||
extends React.ButtonHTMLAttributes<HTMLButtonElement>,
|
|
||||||
VariantProps<typeof buttonVariants> {
|
|
||||||
asChild?: boolean
|
|
||||||
}
|
|
||||||
|
|
||||||
const Button = React.forwardRef<HTMLButtonElement, ButtonProps>(
|
|
||||||
({ className, variant, size, asChild = false, ...props }, ref) => {
|
|
||||||
const Comp = asChild ? Slot : "button"
|
|
||||||
return (
|
|
||||||
<Comp
|
|
||||||
className={cn(buttonVariants({ variant, size, className }))}
|
|
||||||
ref={ref}
|
|
||||||
{...props}
|
|
||||||
/>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
)
|
|
||||||
Button.displayName = "Button"
|
|
||||||
|
|
||||||
export { Button, buttonVariants }
|
|
||||||
@@ -1,58 +0,0 @@
|
|||||||
import { CheckboxCard as ChakraCheckboxCard } from "@chakra-ui/react"
|
|
||||||
import * as React from "react"
|
|
||||||
|
|
||||||
export interface CheckboxCardProps extends ChakraCheckboxCard.RootProps {
|
|
||||||
icon?: React.ReactElement
|
|
||||||
label?: React.ReactNode
|
|
||||||
description?: React.ReactNode
|
|
||||||
addon?: React.ReactNode
|
|
||||||
indicator?: React.ReactNode | null
|
|
||||||
indicatorPlacement?: "start" | "end" | "inside"
|
|
||||||
inputProps?: React.InputHTMLAttributes<HTMLInputElement>
|
|
||||||
}
|
|
||||||
|
|
||||||
export const CheckboxCard = React.forwardRef<
|
|
||||||
HTMLInputElement,
|
|
||||||
CheckboxCardProps
|
|
||||||
>(function CheckboxCard(props, ref) {
|
|
||||||
const {
|
|
||||||
inputProps,
|
|
||||||
label,
|
|
||||||
description,
|
|
||||||
icon,
|
|
||||||
addon,
|
|
||||||
indicator = <ChakraCheckboxCard.Indicator />,
|
|
||||||
indicatorPlacement = "end",
|
|
||||||
...rest
|
|
||||||
} = props
|
|
||||||
|
|
||||||
const hasContent = label || description || icon
|
|
||||||
const ContentWrapper = indicator ? ChakraCheckboxCard.Content : React.Fragment
|
|
||||||
|
|
||||||
return (
|
|
||||||
<ChakraCheckboxCard.Root {...rest}>
|
|
||||||
<ChakraCheckboxCard.HiddenInput ref={ref} {...inputProps} />
|
|
||||||
<ChakraCheckboxCard.Control>
|
|
||||||
{indicatorPlacement === "start" && indicator}
|
|
||||||
{hasContent && (
|
|
||||||
<ContentWrapper>
|
|
||||||
{icon}
|
|
||||||
{label && (
|
|
||||||
<ChakraCheckboxCard.Label>{label}</ChakraCheckboxCard.Label>
|
|
||||||
)}
|
|
||||||
{description && (
|
|
||||||
<ChakraCheckboxCard.Description>
|
|
||||||
{description}
|
|
||||||
</ChakraCheckboxCard.Description>
|
|
||||||
)}
|
|
||||||
{indicatorPlacement === "inside" && indicator}
|
|
||||||
</ContentWrapper>
|
|
||||||
)}
|
|
||||||
{indicatorPlacement === "end" && indicator}
|
|
||||||
</ChakraCheckboxCard.Control>
|
|
||||||
{addon && <ChakraCheckboxCard.Addon>{addon}</ChakraCheckboxCard.Addon>}
|
|
||||||
</ChakraCheckboxCard.Root>
|
|
||||||
)
|
|
||||||
})
|
|
||||||
|
|
||||||
export const CheckboxCardIndicator = ChakraCheckboxCard.Indicator
|
|
||||||
@@ -1,25 +0,0 @@
|
|||||||
import { Checkbox as ChakraCheckbox } from "@chakra-ui/react"
|
|
||||||
import * as React from "react"
|
|
||||||
|
|
||||||
export interface CheckboxProps extends ChakraCheckbox.RootProps {
|
|
||||||
icon?: React.ReactNode
|
|
||||||
inputProps?: React.InputHTMLAttributes<HTMLInputElement>
|
|
||||||
rootRef?: React.Ref<HTMLLabelElement>
|
|
||||||
}
|
|
||||||
|
|
||||||
export const Checkbox = React.forwardRef<HTMLInputElement, CheckboxProps>(
|
|
||||||
function Checkbox(props, ref) {
|
|
||||||
const { icon, children, inputProps, rootRef, ...rest } = props
|
|
||||||
return (
|
|
||||||
<ChakraCheckbox.Root ref={rootRef} {...rest}>
|
|
||||||
<ChakraCheckbox.HiddenInput ref={ref} {...inputProps} />
|
|
||||||
<ChakraCheckbox.Control>
|
|
||||||
{icon || <ChakraCheckbox.Indicator />}
|
|
||||||
</ChakraCheckbox.Control>
|
|
||||||
{children != null && (
|
|
||||||
<ChakraCheckbox.Label>{children}</ChakraCheckbox.Label>
|
|
||||||
)}
|
|
||||||
</ChakraCheckbox.Root>
|
|
||||||
)
|
|
||||||
},
|
|
||||||
)
|
|
||||||
@@ -1,108 +0,0 @@
|
|||||||
import type { ButtonProps, InputProps } from "@chakra-ui/react"
|
|
||||||
import {
|
|
||||||
Button,
|
|
||||||
Clipboard as ChakraClipboard,
|
|
||||||
IconButton,
|
|
||||||
Input,
|
|
||||||
} from "@chakra-ui/react"
|
|
||||||
import * as React from "react"
|
|
||||||
import { LuCheck, LuClipboard, LuLink } from "react-icons/lu"
|
|
||||||
|
|
||||||
const ClipboardIcon = React.forwardRef<
|
|
||||||
HTMLDivElement,
|
|
||||||
ChakraClipboard.IndicatorProps
|
|
||||||
>(function ClipboardIcon(props, ref) {
|
|
||||||
return (
|
|
||||||
<ChakraClipboard.Indicator copied={<LuCheck />} {...props} ref={ref}>
|
|
||||||
<LuClipboard />
|
|
||||||
</ChakraClipboard.Indicator>
|
|
||||||
)
|
|
||||||
})
|
|
||||||
|
|
||||||
const ClipboardCopyText = React.forwardRef<
|
|
||||||
HTMLDivElement,
|
|
||||||
ChakraClipboard.IndicatorProps
|
|
||||||
>(function ClipboardCopyText(props, ref) {
|
|
||||||
return (
|
|
||||||
<ChakraClipboard.Indicator copied="Copied" {...props} ref={ref}>
|
|
||||||
Copy
|
|
||||||
</ChakraClipboard.Indicator>
|
|
||||||
)
|
|
||||||
})
|
|
||||||
|
|
||||||
export const ClipboardLabel = React.forwardRef<
|
|
||||||
HTMLLabelElement,
|
|
||||||
ChakraClipboard.LabelProps
|
|
||||||
>(function ClipboardLabel(props, ref) {
|
|
||||||
return (
|
|
||||||
<ChakraClipboard.Label
|
|
||||||
textStyle="sm"
|
|
||||||
fontWeight="medium"
|
|
||||||
display="inline-block"
|
|
||||||
mb="1"
|
|
||||||
{...props}
|
|
||||||
ref={ref}
|
|
||||||
/>
|
|
||||||
)
|
|
||||||
})
|
|
||||||
|
|
||||||
export const ClipboardButton = React.forwardRef<HTMLButtonElement, ButtonProps>(
|
|
||||||
function ClipboardButton(props, ref) {
|
|
||||||
return (
|
|
||||||
<ChakraClipboard.Trigger asChild>
|
|
||||||
<Button ref={ref} size="sm" variant="surface" {...props}>
|
|
||||||
<ClipboardIcon />
|
|
||||||
<ClipboardCopyText />
|
|
||||||
</Button>
|
|
||||||
</ChakraClipboard.Trigger>
|
|
||||||
)
|
|
||||||
},
|
|
||||||
)
|
|
||||||
|
|
||||||
export const ClipboardLink = React.forwardRef<HTMLButtonElement, ButtonProps>(
|
|
||||||
function ClipboardLink(props, ref) {
|
|
||||||
return (
|
|
||||||
<ChakraClipboard.Trigger asChild>
|
|
||||||
<Button
|
|
||||||
unstyled
|
|
||||||
variant="plain"
|
|
||||||
size="xs"
|
|
||||||
display="inline-flex"
|
|
||||||
alignItems="center"
|
|
||||||
gap="2"
|
|
||||||
ref={ref}
|
|
||||||
{...props}
|
|
||||||
>
|
|
||||||
<LuLink />
|
|
||||||
<ClipboardCopyText />
|
|
||||||
</Button>
|
|
||||||
</ChakraClipboard.Trigger>
|
|
||||||
)
|
|
||||||
},
|
|
||||||
)
|
|
||||||
|
|
||||||
export const ClipboardIconButton = React.forwardRef<
|
|
||||||
HTMLButtonElement,
|
|
||||||
ButtonProps
|
|
||||||
>(function ClipboardIconButton(props, ref) {
|
|
||||||
return (
|
|
||||||
<ChakraClipboard.Trigger asChild>
|
|
||||||
<IconButton ref={ref} size="xs" variant="subtle" {...props}>
|
|
||||||
<ClipboardIcon />
|
|
||||||
<ClipboardCopyText srOnly />
|
|
||||||
</IconButton>
|
|
||||||
</ChakraClipboard.Trigger>
|
|
||||||
)
|
|
||||||
})
|
|
||||||
|
|
||||||
export const ClipboardInput = React.forwardRef<HTMLInputElement, InputProps>(
|
|
||||||
function ClipboardInputElement(props, ref) {
|
|
||||||
return (
|
|
||||||
<ChakraClipboard.Input asChild>
|
|
||||||
<Input ref={ref} {...props} />
|
|
||||||
</ChakraClipboard.Input>
|
|
||||||
)
|
|
||||||
},
|
|
||||||
)
|
|
||||||
|
|
||||||
export const ClipboardRoot = ChakraClipboard.Root
|
|
||||||
@@ -1,17 +0,0 @@
|
|||||||
import type { ButtonProps as ChakraCloseButtonProps } from "@chakra-ui/react"
|
|
||||||
import { IconButton as ChakraIconButton } from "@chakra-ui/react"
|
|
||||||
import * as React from "react"
|
|
||||||
import { LuX } from "react-icons/lu"
|
|
||||||
|
|
||||||
export interface CloseButtonProps extends ChakraCloseButtonProps {}
|
|
||||||
|
|
||||||
export const CloseButton = React.forwardRef<
|
|
||||||
HTMLButtonElement,
|
|
||||||
CloseButtonProps
|
|
||||||
>(function CloseButton(props, ref) {
|
|
||||||
return (
|
|
||||||
<ChakraIconButton variant="ghost" aria-label="Close" ref={ref} {...props}>
|
|
||||||
{props.children ?? <LuX />}
|
|
||||||
</ChakraIconButton>
|
|
||||||
)
|
|
||||||
})
|
|
||||||
@@ -1,67 +0,0 @@
|
|||||||
"use client"
|
|
||||||
|
|
||||||
import type { IconButtonProps } from "@chakra-ui/react"
|
|
||||||
import { ClientOnly, IconButton, Skeleton } from "@chakra-ui/react"
|
|
||||||
import { ThemeProvider, useTheme } from "next-themes"
|
|
||||||
import type { ThemeProviderProps } from "next-themes"
|
|
||||||
import * as React from "react"
|
|
||||||
import { LuMoon, LuSun } from "react-icons/lu"
|
|
||||||
|
|
||||||
export interface ColorModeProviderProps extends ThemeProviderProps {}
|
|
||||||
|
|
||||||
export function ColorModeProvider(props: ColorModeProviderProps) {
|
|
||||||
return (
|
|
||||||
<ThemeProvider attribute="class" disableTransitionOnChange {...props} />
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
export function useColorMode() {
|
|
||||||
const { resolvedTheme, setTheme } = useTheme()
|
|
||||||
const toggleColorMode = () => {
|
|
||||||
setTheme(resolvedTheme === "light" ? "dark" : "light")
|
|
||||||
}
|
|
||||||
return {
|
|
||||||
colorMode: resolvedTheme,
|
|
||||||
setColorMode: setTheme,
|
|
||||||
toggleColorMode,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export function useColorModeValue<T>(light: T, dark: T) {
|
|
||||||
const { colorMode } = useColorMode()
|
|
||||||
return colorMode === "light" ? light : dark
|
|
||||||
}
|
|
||||||
|
|
||||||
export function ColorModeIcon() {
|
|
||||||
const { colorMode } = useColorMode()
|
|
||||||
return colorMode === "light" ? <LuSun /> : <LuMoon />
|
|
||||||
}
|
|
||||||
|
|
||||||
interface ColorModeButtonProps extends Omit<IconButtonProps, "aria-label"> {}
|
|
||||||
|
|
||||||
export const ColorModeButton = React.forwardRef<
|
|
||||||
HTMLButtonElement,
|
|
||||||
ColorModeButtonProps
|
|
||||||
>(function ColorModeButton(props, ref) {
|
|
||||||
const { toggleColorMode } = useColorMode()
|
|
||||||
return (
|
|
||||||
<ClientOnly fallback={<Skeleton boxSize="8" />}>
|
|
||||||
<IconButton
|
|
||||||
onClick={toggleColorMode}
|
|
||||||
variant="ghost"
|
|
||||||
aria-label="Toggle color mode"
|
|
||||||
size="sm"
|
|
||||||
ref={ref}
|
|
||||||
{...props}
|
|
||||||
css={{
|
|
||||||
_icon: {
|
|
||||||
width: "5",
|
|
||||||
height: "5",
|
|
||||||
},
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<ColorModeIcon />
|
|
||||||
</IconButton>
|
|
||||||
</ClientOnly>
|
|
||||||
)
|
|
||||||
})
|
|
||||||
@@ -1,30 +0,0 @@
|
|||||||
import { DataList as ChakraDataList } from "@chakra-ui/react"
|
|
||||||
import { InfoTip } from "./toggle-tip"
|
|
||||||
import * as React from "react"
|
|
||||||
|
|
||||||
export const DataListRoot = ChakraDataList.Root
|
|
||||||
|
|
||||||
interface ItemProps extends ChakraDataList.ItemProps {
|
|
||||||
label: React.ReactNode
|
|
||||||
value: React.ReactNode
|
|
||||||
info?: React.ReactNode
|
|
||||||
grow?: boolean
|
|
||||||
}
|
|
||||||
|
|
||||||
export const DataListItem = React.forwardRef<HTMLDivElement, ItemProps>(
|
|
||||||
function DataListItem(props, ref) {
|
|
||||||
const { label, info, value, children, grow, ...rest } = props
|
|
||||||
return (
|
|
||||||
<ChakraDataList.Item ref={ref} {...rest}>
|
|
||||||
<ChakraDataList.ItemLabel flex={grow ? "1" : undefined}>
|
|
||||||
{label}
|
|
||||||
{info && <InfoTip>{info}</InfoTip>}
|
|
||||||
</ChakraDataList.ItemLabel>
|
|
||||||
<ChakraDataList.ItemValue flex={grow ? "1" : undefined}>
|
|
||||||
{value}
|
|
||||||
</ChakraDataList.ItemValue>
|
|
||||||
{children}
|
|
||||||
</ChakraDataList.Item>
|
|
||||||
)
|
|
||||||
},
|
|
||||||
)
|
|
||||||
@@ -1,62 +0,0 @@
|
|||||||
import { Dialog as ChakraDialog, Portal } from "@chakra-ui/react"
|
|
||||||
import { CloseButton } from "./close-button"
|
|
||||||
import * as React from "react"
|
|
||||||
|
|
||||||
interface DialogContentProps extends ChakraDialog.ContentProps {
|
|
||||||
portalled?: boolean
|
|
||||||
portalRef?: React.RefObject<HTMLElement>
|
|
||||||
backdrop?: boolean
|
|
||||||
}
|
|
||||||
|
|
||||||
export const DialogContent = React.forwardRef<
|
|
||||||
HTMLDivElement,
|
|
||||||
DialogContentProps
|
|
||||||
>(function DialogContent(props, ref) {
|
|
||||||
const {
|
|
||||||
children,
|
|
||||||
portalled = true,
|
|
||||||
portalRef,
|
|
||||||
backdrop = true,
|
|
||||||
...rest
|
|
||||||
} = props
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Portal disabled={!portalled} container={portalRef}>
|
|
||||||
{backdrop && <ChakraDialog.Backdrop />}
|
|
||||||
<ChakraDialog.Positioner>
|
|
||||||
<ChakraDialog.Content ref={ref} {...rest} asChild={false}>
|
|
||||||
{children}
|
|
||||||
</ChakraDialog.Content>
|
|
||||||
</ChakraDialog.Positioner>
|
|
||||||
</Portal>
|
|
||||||
)
|
|
||||||
})
|
|
||||||
|
|
||||||
export const DialogCloseTrigger = React.forwardRef<
|
|
||||||
HTMLButtonElement,
|
|
||||||
ChakraDialog.CloseTriggerProps
|
|
||||||
>(function DialogCloseTrigger(props, ref) {
|
|
||||||
return (
|
|
||||||
<ChakraDialog.CloseTrigger
|
|
||||||
position="absolute"
|
|
||||||
top="2"
|
|
||||||
insetEnd="2"
|
|
||||||
{...props}
|
|
||||||
asChild
|
|
||||||
>
|
|
||||||
<CloseButton size="sm" ref={ref}>
|
|
||||||
{props.children}
|
|
||||||
</CloseButton>
|
|
||||||
</ChakraDialog.CloseTrigger>
|
|
||||||
)
|
|
||||||
})
|
|
||||||
|
|
||||||
export const DialogRoot = ChakraDialog.Root
|
|
||||||
export const DialogFooter = ChakraDialog.Footer
|
|
||||||
export const DialogHeader = ChakraDialog.Header
|
|
||||||
export const DialogBody = ChakraDialog.Body
|
|
||||||
export const DialogBackdrop = ChakraDialog.Backdrop
|
|
||||||
export const DialogTitle = ChakraDialog.Title
|
|
||||||
export const DialogDescription = ChakraDialog.Description
|
|
||||||
export const DialogTrigger = ChakraDialog.Trigger
|
|
||||||
export const DialogActionTrigger = ChakraDialog.ActionTrigger
|
|
||||||
@@ -1,52 +0,0 @@
|
|||||||
import { Drawer as ChakraDrawer, Portal } from "@chakra-ui/react"
|
|
||||||
import { CloseButton } from "./close-button"
|
|
||||||
import * as React from "react"
|
|
||||||
|
|
||||||
interface DrawerContentProps extends ChakraDrawer.ContentProps {
|
|
||||||
portalled?: boolean
|
|
||||||
portalRef?: React.RefObject<HTMLElement>
|
|
||||||
offset?: ChakraDrawer.ContentProps["padding"]
|
|
||||||
}
|
|
||||||
|
|
||||||
export const DrawerContent = React.forwardRef<
|
|
||||||
HTMLDivElement,
|
|
||||||
DrawerContentProps
|
|
||||||
>(function DrawerContent(props, ref) {
|
|
||||||
const { children, portalled = true, portalRef, offset, ...rest } = props
|
|
||||||
return (
|
|
||||||
<Portal disabled={!portalled} container={portalRef}>
|
|
||||||
<ChakraDrawer.Positioner padding={offset}>
|
|
||||||
<ChakraDrawer.Content ref={ref} {...rest} asChild={false}>
|
|
||||||
{children}
|
|
||||||
</ChakraDrawer.Content>
|
|
||||||
</ChakraDrawer.Positioner>
|
|
||||||
</Portal>
|
|
||||||
)
|
|
||||||
})
|
|
||||||
|
|
||||||
export const DrawerCloseTrigger = React.forwardRef<
|
|
||||||
HTMLButtonElement,
|
|
||||||
ChakraDrawer.CloseTriggerProps
|
|
||||||
>(function DrawerCloseTrigger(props, ref) {
|
|
||||||
return (
|
|
||||||
<ChakraDrawer.CloseTrigger
|
|
||||||
position="absolute"
|
|
||||||
top="2"
|
|
||||||
insetEnd="2"
|
|
||||||
{...props}
|
|
||||||
asChild
|
|
||||||
>
|
|
||||||
<CloseButton size="sm" ref={ref} />
|
|
||||||
</ChakraDrawer.CloseTrigger>
|
|
||||||
)
|
|
||||||
})
|
|
||||||
|
|
||||||
export const DrawerTrigger = ChakraDrawer.Trigger
|
|
||||||
export const DrawerRoot = ChakraDrawer.Root
|
|
||||||
export const DrawerFooter = ChakraDrawer.Footer
|
|
||||||
export const DrawerHeader = ChakraDrawer.Header
|
|
||||||
export const DrawerBody = ChakraDrawer.Body
|
|
||||||
export const DrawerBackdrop = ChakraDrawer.Backdrop
|
|
||||||
export const DrawerDescription = ChakraDrawer.Description
|
|
||||||
export const DrawerTitle = ChakraDrawer.Title
|
|
||||||
export const DrawerActionTrigger = ChakraDrawer.ActionTrigger
|
|
||||||
@@ -1,34 +0,0 @@
|
|||||||
import { EmptyState as ChakraEmptyState, VStack } from "@chakra-ui/react"
|
|
||||||
import * as React from "react"
|
|
||||||
|
|
||||||
export interface EmptyStateProps extends ChakraEmptyState.RootProps {
|
|
||||||
title: string
|
|
||||||
description?: string
|
|
||||||
icon?: React.ReactNode
|
|
||||||
}
|
|
||||||
|
|
||||||
export const EmptyState = React.forwardRef<HTMLDivElement, EmptyStateProps>(
|
|
||||||
function EmptyState(props, ref) {
|
|
||||||
const { title, description, icon, children, ...rest } = props
|
|
||||||
return (
|
|
||||||
<ChakraEmptyState.Root ref={ref} {...rest}>
|
|
||||||
<ChakraEmptyState.Content>
|
|
||||||
{icon && (
|
|
||||||
<ChakraEmptyState.Indicator>{icon}</ChakraEmptyState.Indicator>
|
|
||||||
)}
|
|
||||||
{description ? (
|
|
||||||
<VStack textAlign="center">
|
|
||||||
<ChakraEmptyState.Title>{title}</ChakraEmptyState.Title>
|
|
||||||
<ChakraEmptyState.Description>
|
|
||||||
{description}
|
|
||||||
</ChakraEmptyState.Description>
|
|
||||||
</VStack>
|
|
||||||
) : (
|
|
||||||
<ChakraEmptyState.Title>{title}</ChakraEmptyState.Title>
|
|
||||||
)}
|
|
||||||
{children}
|
|
||||||
</ChakraEmptyState.Content>
|
|
||||||
</ChakraEmptyState.Root>
|
|
||||||
)
|
|
||||||
},
|
|
||||||
)
|
|
||||||
@@ -1,33 +0,0 @@
|
|||||||
import { Field as ChakraField } from "@chakra-ui/react"
|
|
||||||
import * as React from "react"
|
|
||||||
|
|
||||||
export interface FieldProps extends Omit<ChakraField.RootProps, "label"> {
|
|
||||||
label?: React.ReactNode
|
|
||||||
helperText?: React.ReactNode
|
|
||||||
errorText?: React.ReactNode
|
|
||||||
optionalText?: React.ReactNode
|
|
||||||
}
|
|
||||||
|
|
||||||
export const Field = React.forwardRef<HTMLDivElement, FieldProps>(
|
|
||||||
function Field(props, ref) {
|
|
||||||
const { label, children, helperText, errorText, optionalText, ...rest } =
|
|
||||||
props
|
|
||||||
return (
|
|
||||||
<ChakraField.Root ref={ref} {...rest}>
|
|
||||||
{label && (
|
|
||||||
<ChakraField.Label>
|
|
||||||
{label}
|
|
||||||
<ChakraField.RequiredIndicator fallback={optionalText} />
|
|
||||||
</ChakraField.Label>
|
|
||||||
)}
|
|
||||||
{children}
|
|
||||||
{helperText && (
|
|
||||||
<ChakraField.HelperText>{helperText}</ChakraField.HelperText>
|
|
||||||
)}
|
|
||||||
{errorText && (
|
|
||||||
<ChakraField.ErrorText>{errorText}</ChakraField.ErrorText>
|
|
||||||
)}
|
|
||||||
</ChakraField.Root>
|
|
||||||
)
|
|
||||||
},
|
|
||||||
)
|
|
||||||
@@ -1,170 +0,0 @@
|
|||||||
"use client"
|
|
||||||
|
|
||||||
import type { ButtonProps, RecipeProps } from "@chakra-ui/react"
|
|
||||||
import {
|
|
||||||
Button,
|
|
||||||
FileUpload as ChakraFileUpload,
|
|
||||||
Icon,
|
|
||||||
IconButton,
|
|
||||||
Span,
|
|
||||||
Text,
|
|
||||||
useFileUploadContext,
|
|
||||||
useRecipe,
|
|
||||||
} from "@chakra-ui/react"
|
|
||||||
import * as React from "react"
|
|
||||||
import { LuFile, LuUpload, LuX } from "react-icons/lu"
|
|
||||||
|
|
||||||
export interface FileUploadRootProps extends ChakraFileUpload.RootProps {
|
|
||||||
inputProps?: React.InputHTMLAttributes<HTMLInputElement>
|
|
||||||
}
|
|
||||||
|
|
||||||
export const FileUploadRoot = React.forwardRef<
|
|
||||||
HTMLInputElement,
|
|
||||||
FileUploadRootProps
|
|
||||||
>(function FileUploadRoot(props, ref) {
|
|
||||||
const { children, inputProps, ...rest } = props
|
|
||||||
return (
|
|
||||||
<ChakraFileUpload.Root {...rest}>
|
|
||||||
<ChakraFileUpload.HiddenInput ref={ref} {...inputProps} />
|
|
||||||
{children}
|
|
||||||
</ChakraFileUpload.Root>
|
|
||||||
)
|
|
||||||
})
|
|
||||||
|
|
||||||
export interface FileUploadDropzoneProps
|
|
||||||
extends ChakraFileUpload.DropzoneProps {
|
|
||||||
label: React.ReactNode
|
|
||||||
description?: React.ReactNode
|
|
||||||
}
|
|
||||||
|
|
||||||
export const FileUploadDropzone = React.forwardRef<
|
|
||||||
HTMLInputElement,
|
|
||||||
FileUploadDropzoneProps
|
|
||||||
>(function FileUploadDropzone(props, ref) {
|
|
||||||
const { children, label, description, ...rest } = props
|
|
||||||
return (
|
|
||||||
<ChakraFileUpload.Dropzone ref={ref} {...rest}>
|
|
||||||
<Icon fontSize="xl" color="fg.muted">
|
|
||||||
<LuUpload />
|
|
||||||
</Icon>
|
|
||||||
<ChakraFileUpload.DropzoneContent>
|
|
||||||
<div>{label}</div>
|
|
||||||
{description && <Text color="fg.muted">{description}</Text>}
|
|
||||||
</ChakraFileUpload.DropzoneContent>
|
|
||||||
{children}
|
|
||||||
</ChakraFileUpload.Dropzone>
|
|
||||||
)
|
|
||||||
})
|
|
||||||
|
|
||||||
interface VisibilityProps {
|
|
||||||
showSize?: boolean
|
|
||||||
clearable?: boolean
|
|
||||||
}
|
|
||||||
|
|
||||||
interface FileUploadItemProps extends VisibilityProps {
|
|
||||||
file: File
|
|
||||||
}
|
|
||||||
|
|
||||||
const FileUploadItem = React.forwardRef<HTMLLIElement, FileUploadItemProps>(
|
|
||||||
function FileUploadItem(props, ref) {
|
|
||||||
const { file, showSize, clearable } = props
|
|
||||||
return (
|
|
||||||
<ChakraFileUpload.Item file={file} ref={ref}>
|
|
||||||
<ChakraFileUpload.ItemPreview asChild>
|
|
||||||
<Icon fontSize="lg" color="fg.muted">
|
|
||||||
<LuFile />
|
|
||||||
</Icon>
|
|
||||||
</ChakraFileUpload.ItemPreview>
|
|
||||||
|
|
||||||
{showSize ? (
|
|
||||||
<ChakraFileUpload.ItemContent>
|
|
||||||
<ChakraFileUpload.ItemName />
|
|
||||||
<ChakraFileUpload.ItemSizeText />
|
|
||||||
</ChakraFileUpload.ItemContent>
|
|
||||||
) : (
|
|
||||||
<ChakraFileUpload.ItemName flex="1" />
|
|
||||||
)}
|
|
||||||
|
|
||||||
{clearable && (
|
|
||||||
<ChakraFileUpload.ItemDeleteTrigger asChild>
|
|
||||||
<IconButton variant="ghost" color="fg.muted" size="xs">
|
|
||||||
<LuX />
|
|
||||||
</IconButton>
|
|
||||||
</ChakraFileUpload.ItemDeleteTrigger>
|
|
||||||
)}
|
|
||||||
</ChakraFileUpload.Item>
|
|
||||||
)
|
|
||||||
},
|
|
||||||
)
|
|
||||||
|
|
||||||
interface FileUploadListProps
|
|
||||||
extends VisibilityProps,
|
|
||||||
ChakraFileUpload.ItemGroupProps {
|
|
||||||
files?: File[]
|
|
||||||
}
|
|
||||||
|
|
||||||
export const FileUploadList = React.forwardRef<
|
|
||||||
HTMLUListElement,
|
|
||||||
FileUploadListProps
|
|
||||||
>(function FileUploadList(props, ref) {
|
|
||||||
const { showSize, clearable, files, ...rest } = props
|
|
||||||
|
|
||||||
const fileUpload = useFileUploadContext()
|
|
||||||
const acceptedFiles = files ?? fileUpload.acceptedFiles
|
|
||||||
|
|
||||||
if (acceptedFiles.length === 0) return null
|
|
||||||
|
|
||||||
return (
|
|
||||||
<ChakraFileUpload.ItemGroup ref={ref} {...rest}>
|
|
||||||
{acceptedFiles.map((file) => (
|
|
||||||
<FileUploadItem
|
|
||||||
key={file.name}
|
|
||||||
file={file}
|
|
||||||
showSize={showSize}
|
|
||||||
clearable={clearable}
|
|
||||||
/>
|
|
||||||
))}
|
|
||||||
</ChakraFileUpload.ItemGroup>
|
|
||||||
)
|
|
||||||
})
|
|
||||||
|
|
||||||
type Assign<T, U> = Omit<T, keyof U> & U
|
|
||||||
|
|
||||||
interface FileInputProps extends Assign<ButtonProps, RecipeProps<"input">> {
|
|
||||||
placeholder?: React.ReactNode
|
|
||||||
}
|
|
||||||
|
|
||||||
export const FileInput = React.forwardRef<HTMLButtonElement, FileInputProps>(
|
|
||||||
function FileInput(props, ref) {
|
|
||||||
const inputRecipe = useRecipe({ key: "input" })
|
|
||||||
const [recipeProps, restProps] = inputRecipe.splitVariantProps(props)
|
|
||||||
const { placeholder = "Select file(s)", ...rest } = restProps
|
|
||||||
return (
|
|
||||||
<ChakraFileUpload.Trigger asChild>
|
|
||||||
<Button
|
|
||||||
unstyled
|
|
||||||
py="0"
|
|
||||||
ref={ref}
|
|
||||||
{...rest}
|
|
||||||
css={[inputRecipe(recipeProps), props.css]}
|
|
||||||
>
|
|
||||||
<ChakraFileUpload.Context>
|
|
||||||
{({ acceptedFiles }) => {
|
|
||||||
if (acceptedFiles.length === 1) {
|
|
||||||
return <span>{acceptedFiles[0].name}</span>
|
|
||||||
}
|
|
||||||
if (acceptedFiles.length > 1) {
|
|
||||||
return <span>{acceptedFiles.length} files</span>
|
|
||||||
}
|
|
||||||
return <Span color="fg.subtle">{placeholder}</Span>
|
|
||||||
}}
|
|
||||||
</ChakraFileUpload.Context>
|
|
||||||
</Button>
|
|
||||||
</ChakraFileUpload.Trigger>
|
|
||||||
)
|
|
||||||
},
|
|
||||||
)
|
|
||||||
|
|
||||||
export const FileUploadLabel = ChakraFileUpload.Label
|
|
||||||
export const FileUploadClearTrigger = ChakraFileUpload.ClearTrigger
|
|
||||||
export const FileUploadTrigger = ChakraFileUpload.Trigger
|
|
||||||
@@ -1,36 +0,0 @@
|
|||||||
import { HoverCard, Portal } from "@chakra-ui/react"
|
|
||||||
import * as React from "react"
|
|
||||||
|
|
||||||
interface HoverCardContentProps extends HoverCard.ContentProps {
|
|
||||||
portalled?: boolean
|
|
||||||
portalRef?: React.RefObject<HTMLElement>
|
|
||||||
}
|
|
||||||
|
|
||||||
export const HoverCardContent = React.forwardRef<
|
|
||||||
HTMLDivElement,
|
|
||||||
HoverCardContentProps
|
|
||||||
>(function HoverCardContent(props, ref) {
|
|
||||||
const { portalled = true, portalRef, ...rest } = props
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Portal disabled={!portalled} container={portalRef}>
|
|
||||||
<HoverCard.Positioner>
|
|
||||||
<HoverCard.Content ref={ref} {...rest} />
|
|
||||||
</HoverCard.Positioner>
|
|
||||||
</Portal>
|
|
||||||
)
|
|
||||||
})
|
|
||||||
|
|
||||||
export const HoverCardArrow = React.forwardRef<
|
|
||||||
HTMLDivElement,
|
|
||||||
HoverCard.ArrowProps
|
|
||||||
>(function HoverCardArrow(props, ref) {
|
|
||||||
return (
|
|
||||||
<HoverCard.Arrow ref={ref} {...props}>
|
|
||||||
<HoverCard.ArrowTip />
|
|
||||||
</HoverCard.Arrow>
|
|
||||||
)
|
|
||||||
})
|
|
||||||
|
|
||||||
export const HoverCardRoot = HoverCard.Root
|
|
||||||
export const HoverCardTrigger = HoverCard.Trigger
|
|
||||||
@@ -1,50 +0,0 @@
|
|||||||
import type { BoxProps, InputElementProps } from "@chakra-ui/react"
|
|
||||||
import { Group, InputElement } from "@chakra-ui/react"
|
|
||||||
import * as React from "react"
|
|
||||||
|
|
||||||
export interface InputGroupProps extends BoxProps {
|
|
||||||
startElementProps?: InputElementProps
|
|
||||||
endElementProps?: InputElementProps
|
|
||||||
startElement?: React.ReactNode
|
|
||||||
endElement?: React.ReactNode
|
|
||||||
children: React.ReactElement
|
|
||||||
startOffset?: InputElementProps["paddingStart"]
|
|
||||||
endOffset?: InputElementProps["paddingEnd"]
|
|
||||||
}
|
|
||||||
|
|
||||||
export const InputGroup = React.forwardRef<HTMLDivElement, InputGroupProps>(
|
|
||||||
function InputGroup(props, ref) {
|
|
||||||
const {
|
|
||||||
startElement,
|
|
||||||
startElementProps,
|
|
||||||
endElement,
|
|
||||||
endElementProps,
|
|
||||||
children,
|
|
||||||
startOffset = "6px",
|
|
||||||
endOffset = "6px",
|
|
||||||
...rest
|
|
||||||
} = props
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Group ref={ref} {...rest}>
|
|
||||||
{startElement && (
|
|
||||||
<InputElement pointerEvents="none" {...startElementProps}>
|
|
||||||
{startElement}
|
|
||||||
</InputElement>
|
|
||||||
)}
|
|
||||||
{React.cloneElement(children, {
|
|
||||||
...(startElement && {
|
|
||||||
ps: `calc(var(--input-height) - ${startOffset})`,
|
|
||||||
}),
|
|
||||||
...(endElement && { pe: `calc(var(--input-height) - ${endOffset})` }),
|
|
||||||
...children.props,
|
|
||||||
})}
|
|
||||||
{endElement && (
|
|
||||||
<InputElement placement="end" {...endElementProps}>
|
|
||||||
{endElement}
|
|
||||||
</InputElement>
|
|
||||||
)}
|
|
||||||
</Group>
|
|
||||||
)
|
|
||||||
},
|
|
||||||
)
|
|
||||||
@@ -1,12 +0,0 @@
|
|||||||
"use client"
|
|
||||||
|
|
||||||
import type { HTMLChakraProps, RecipeProps } from "@chakra-ui/react"
|
|
||||||
import { createRecipeContext } from "@chakra-ui/react"
|
|
||||||
|
|
||||||
export interface LinkButtonProps
|
|
||||||
extends HTMLChakraProps<"a", RecipeProps<"button">> {}
|
|
||||||
|
|
||||||
const { withContext } = createRecipeContext({ key: "button" })
|
|
||||||
|
|
||||||
// Replace "a" with your framework's link component
|
|
||||||
export const LinkButton = withContext<HTMLAnchorElement, LinkButtonProps>("a")
|
|
||||||
@@ -1,110 +0,0 @@
|
|||||||
"use client"
|
|
||||||
|
|
||||||
import { AbsoluteCenter, Menu as ChakraMenu, Portal } from "@chakra-ui/react"
|
|
||||||
import * as React from "react"
|
|
||||||
import { LuCheck, LuChevronRight } from "react-icons/lu"
|
|
||||||
|
|
||||||
interface MenuContentProps extends ChakraMenu.ContentProps {
|
|
||||||
portalled?: boolean
|
|
||||||
portalRef?: React.RefObject<HTMLElement>
|
|
||||||
}
|
|
||||||
|
|
||||||
export const MenuContent = React.forwardRef<HTMLDivElement, MenuContentProps>(
|
|
||||||
function MenuContent(props, ref) {
|
|
||||||
const { portalled = true, portalRef, ...rest } = props
|
|
||||||
return (
|
|
||||||
<Portal disabled={!portalled} container={portalRef}>
|
|
||||||
<ChakraMenu.Positioner>
|
|
||||||
<ChakraMenu.Content ref={ref} {...rest} />
|
|
||||||
</ChakraMenu.Positioner>
|
|
||||||
</Portal>
|
|
||||||
)
|
|
||||||
},
|
|
||||||
)
|
|
||||||
|
|
||||||
export const MenuArrow = React.forwardRef<
|
|
||||||
HTMLDivElement,
|
|
||||||
ChakraMenu.ArrowProps
|
|
||||||
>(function MenuArrow(props, ref) {
|
|
||||||
return (
|
|
||||||
<ChakraMenu.Arrow ref={ref} {...props}>
|
|
||||||
<ChakraMenu.ArrowTip />
|
|
||||||
</ChakraMenu.Arrow>
|
|
||||||
)
|
|
||||||
})
|
|
||||||
|
|
||||||
export const MenuCheckboxItem = React.forwardRef<
|
|
||||||
HTMLDivElement,
|
|
||||||
ChakraMenu.CheckboxItemProps
|
|
||||||
>(function MenuCheckboxItem(props, ref) {
|
|
||||||
return (
|
|
||||||
<ChakraMenu.CheckboxItem ref={ref} {...props}>
|
|
||||||
<ChakraMenu.ItemIndicator hidden={false}>
|
|
||||||
<LuCheck />
|
|
||||||
</ChakraMenu.ItemIndicator>
|
|
||||||
{props.children}
|
|
||||||
</ChakraMenu.CheckboxItem>
|
|
||||||
)
|
|
||||||
})
|
|
||||||
|
|
||||||
export const MenuRadioItem = React.forwardRef<
|
|
||||||
HTMLDivElement,
|
|
||||||
ChakraMenu.RadioItemProps
|
|
||||||
>(function MenuRadioItem(props, ref) {
|
|
||||||
const { children, ...rest } = props
|
|
||||||
return (
|
|
||||||
<ChakraMenu.RadioItem ps="8" ref={ref} {...rest}>
|
|
||||||
<AbsoluteCenter axis="horizontal" left="4" asChild>
|
|
||||||
<ChakraMenu.ItemIndicator>
|
|
||||||
<LuCheck />
|
|
||||||
</ChakraMenu.ItemIndicator>
|
|
||||||
</AbsoluteCenter>
|
|
||||||
<ChakraMenu.ItemText>{children}</ChakraMenu.ItemText>
|
|
||||||
</ChakraMenu.RadioItem>
|
|
||||||
)
|
|
||||||
})
|
|
||||||
|
|
||||||
export const MenuItemGroup = React.forwardRef<
|
|
||||||
HTMLDivElement,
|
|
||||||
ChakraMenu.ItemGroupProps
|
|
||||||
>(function MenuItemGroup(props, ref) {
|
|
||||||
const { title, children, ...rest } = props
|
|
||||||
return (
|
|
||||||
<ChakraMenu.ItemGroup ref={ref} {...rest}>
|
|
||||||
{title && (
|
|
||||||
<ChakraMenu.ItemGroupLabel userSelect="none">
|
|
||||||
{title}
|
|
||||||
</ChakraMenu.ItemGroupLabel>
|
|
||||||
)}
|
|
||||||
{children}
|
|
||||||
</ChakraMenu.ItemGroup>
|
|
||||||
)
|
|
||||||
})
|
|
||||||
|
|
||||||
export interface MenuTriggerItemProps extends ChakraMenu.ItemProps {
|
|
||||||
startIcon?: React.ReactNode
|
|
||||||
}
|
|
||||||
|
|
||||||
export const MenuTriggerItem = React.forwardRef<
|
|
||||||
HTMLDivElement,
|
|
||||||
MenuTriggerItemProps
|
|
||||||
>(function MenuTriggerItem(props, ref) {
|
|
||||||
const { startIcon, children, ...rest } = props
|
|
||||||
return (
|
|
||||||
<ChakraMenu.TriggerItem ref={ref} {...rest}>
|
|
||||||
{startIcon}
|
|
||||||
{children}
|
|
||||||
<LuChevronRight />
|
|
||||||
</ChakraMenu.TriggerItem>
|
|
||||||
)
|
|
||||||
})
|
|
||||||
|
|
||||||
export const MenuRadioItemGroup = ChakraMenu.RadioItemGroup
|
|
||||||
export const MenuContextTrigger = ChakraMenu.ContextTrigger
|
|
||||||
export const MenuRoot = ChakraMenu.Root
|
|
||||||
export const MenuSeparator = ChakraMenu.Separator
|
|
||||||
|
|
||||||
export const MenuItem = ChakraMenu.Item
|
|
||||||
export const MenuItemText = ChakraMenu.ItemText
|
|
||||||
export const MenuItemCommand = ChakraMenu.ItemCommand
|
|
||||||
export const MenuTrigger = ChakraMenu.Trigger
|
|
||||||
@@ -1,57 +0,0 @@
|
|||||||
"use client"
|
|
||||||
|
|
||||||
import { NativeSelect as Select } from "@chakra-ui/react"
|
|
||||||
import * as React from "react"
|
|
||||||
|
|
||||||
interface NativeSelectRootProps extends Select.RootProps {
|
|
||||||
icon?: React.ReactNode
|
|
||||||
}
|
|
||||||
|
|
||||||
export const NativeSelectRoot = React.forwardRef<
|
|
||||||
HTMLDivElement,
|
|
||||||
NativeSelectRootProps
|
|
||||||
>(function NativeSelect(props, ref) {
|
|
||||||
const { icon, children, ...rest } = props
|
|
||||||
return (
|
|
||||||
<Select.Root ref={ref} {...rest}>
|
|
||||||
{children}
|
|
||||||
<Select.Indicator>{icon}</Select.Indicator>
|
|
||||||
</Select.Root>
|
|
||||||
)
|
|
||||||
})
|
|
||||||
|
|
||||||
interface NativeSelectItem {
|
|
||||||
value: string
|
|
||||||
label: string
|
|
||||||
disabled?: boolean
|
|
||||||
}
|
|
||||||
|
|
||||||
interface NativeSelectField extends Select.FieldProps {
|
|
||||||
items?: Array<string | NativeSelectItem>
|
|
||||||
}
|
|
||||||
|
|
||||||
export const NativeSelectField = React.forwardRef<
|
|
||||||
HTMLSelectElement,
|
|
||||||
NativeSelectField
|
|
||||||
>(function NativeSelectField(props, ref) {
|
|
||||||
const { items: itemsProp, children, ...rest } = props
|
|
||||||
|
|
||||||
const items = React.useMemo(
|
|
||||||
() =>
|
|
||||||
itemsProp?.map((item) =>
|
|
||||||
typeof item === "string" ? { label: item, value: item } : item,
|
|
||||||
),
|
|
||||||
[itemsProp],
|
|
||||||
)
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Select.Field ref={ref} {...rest}>
|
|
||||||
{children}
|
|
||||||
{items?.map((item) => (
|
|
||||||
<option key={item.value} value={item.value} disabled={item.disabled}>
|
|
||||||
{item.label}
|
|
||||||
</option>
|
|
||||||
))}
|
|
||||||
</Select.Field>
|
|
||||||
)
|
|
||||||
})
|
|
||||||
@@ -1,24 +0,0 @@
|
|||||||
import { NumberInput as ChakraNumberInput } from "@chakra-ui/react"
|
|
||||||
import * as React from "react"
|
|
||||||
|
|
||||||
export interface NumberInputProps extends ChakraNumberInput.RootProps {}
|
|
||||||
|
|
||||||
export const NumberInputRoot = React.forwardRef<
|
|
||||||
HTMLDivElement,
|
|
||||||
NumberInputProps
|
|
||||||
>(function NumberInput(props, ref) {
|
|
||||||
const { children, ...rest } = props
|
|
||||||
return (
|
|
||||||
<ChakraNumberInput.Root ref={ref} variant="outline" {...rest}>
|
|
||||||
{children}
|
|
||||||
<ChakraNumberInput.Control>
|
|
||||||
<ChakraNumberInput.IncrementTrigger />
|
|
||||||
<ChakraNumberInput.DecrementTrigger />
|
|
||||||
</ChakraNumberInput.Control>
|
|
||||||
</ChakraNumberInput.Root>
|
|
||||||
)
|
|
||||||
})
|
|
||||||
|
|
||||||
export const NumberInputField = ChakraNumberInput.Input
|
|
||||||
export const NumberInputScruber = ChakraNumberInput.Scrubber
|
|
||||||
export const NumberInputLabel = ChakraNumberInput.Label
|
|
||||||
@@ -1,208 +0,0 @@
|
|||||||
"use client"
|
|
||||||
|
|
||||||
import type { ButtonProps, TextProps } from "@chakra-ui/react"
|
|
||||||
import {
|
|
||||||
Button,
|
|
||||||
Pagination as ChakraPagination,
|
|
||||||
IconButton,
|
|
||||||
Text,
|
|
||||||
createContext,
|
|
||||||
usePaginationContext,
|
|
||||||
} from "@chakra-ui/react"
|
|
||||||
import * as React from "react"
|
|
||||||
import {
|
|
||||||
HiChevronLeft,
|
|
||||||
HiChevronRight,
|
|
||||||
HiMiniEllipsisHorizontal,
|
|
||||||
} from "react-icons/hi2"
|
|
||||||
import { LinkButton } from "./link-button"
|
|
||||||
|
|
||||||
interface ButtonVariantMap {
|
|
||||||
current: ButtonProps["variant"]
|
|
||||||
default: ButtonProps["variant"]
|
|
||||||
ellipsis: ButtonProps["variant"]
|
|
||||||
}
|
|
||||||
|
|
||||||
type PaginationVariant = "outline" | "solid" | "subtle"
|
|
||||||
|
|
||||||
interface ButtonVariantContext {
|
|
||||||
size: ButtonProps["size"]
|
|
||||||
variantMap: ButtonVariantMap
|
|
||||||
getHref?: (page: number) => string
|
|
||||||
}
|
|
||||||
|
|
||||||
const [RootPropsProvider, useRootProps] = createContext<ButtonVariantContext>({
|
|
||||||
name: "RootPropsProvider",
|
|
||||||
})
|
|
||||||
|
|
||||||
export interface PaginationRootProps
|
|
||||||
extends Omit<ChakraPagination.RootProps, "type"> {
|
|
||||||
size?: ButtonProps["size"]
|
|
||||||
variant?: PaginationVariant
|
|
||||||
getHref?: (page: number) => string
|
|
||||||
}
|
|
||||||
|
|
||||||
const variantMap: Record<PaginationVariant, ButtonVariantMap> = {
|
|
||||||
outline: { default: "ghost", ellipsis: "plain", current: "outline" },
|
|
||||||
solid: { default: "outline", ellipsis: "outline", current: "solid" },
|
|
||||||
subtle: { default: "ghost", ellipsis: "plain", current: "subtle" },
|
|
||||||
}
|
|
||||||
|
|
||||||
export const PaginationRoot = React.forwardRef<
|
|
||||||
HTMLDivElement,
|
|
||||||
PaginationRootProps
|
|
||||||
>(function PaginationRoot(props, ref) {
|
|
||||||
const { size = "sm", variant = "outline", getHref, ...rest } = props
|
|
||||||
return (
|
|
||||||
<RootPropsProvider
|
|
||||||
value={{ size, variantMap: variantMap[variant], getHref }}
|
|
||||||
>
|
|
||||||
<ChakraPagination.Root
|
|
||||||
ref={ref}
|
|
||||||
type={getHref ? "link" : "button"}
|
|
||||||
{...rest}
|
|
||||||
/>
|
|
||||||
</RootPropsProvider>
|
|
||||||
)
|
|
||||||
})
|
|
||||||
|
|
||||||
export const PaginationEllipsis = React.forwardRef<
|
|
||||||
HTMLDivElement,
|
|
||||||
ChakraPagination.EllipsisProps
|
|
||||||
>(function PaginationEllipsis(props, ref) {
|
|
||||||
const { size, variantMap } = useRootProps()
|
|
||||||
return (
|
|
||||||
<ChakraPagination.Ellipsis ref={ref} {...props} asChild>
|
|
||||||
<Button as="span" variant={variantMap.ellipsis} size={size}>
|
|
||||||
<HiMiniEllipsisHorizontal />
|
|
||||||
</Button>
|
|
||||||
</ChakraPagination.Ellipsis>
|
|
||||||
)
|
|
||||||
})
|
|
||||||
|
|
||||||
export const PaginationItem = React.forwardRef<
|
|
||||||
HTMLButtonElement,
|
|
||||||
ChakraPagination.ItemProps
|
|
||||||
>(function PaginationItem(props, ref) {
|
|
||||||
const { page } = usePaginationContext()
|
|
||||||
const { size, variantMap, getHref } = useRootProps()
|
|
||||||
|
|
||||||
const current = page === props.value
|
|
||||||
const variant = current ? variantMap.current : variantMap.default
|
|
||||||
|
|
||||||
if (getHref) {
|
|
||||||
return (
|
|
||||||
<LinkButton href={getHref(props.value)} variant={variant} size={size}>
|
|
||||||
{props.value}
|
|
||||||
</LinkButton>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
|
||||||
<ChakraPagination.Item ref={ref} {...props} asChild>
|
|
||||||
<Button variant={variant} size={size}>
|
|
||||||
{props.value}
|
|
||||||
</Button>
|
|
||||||
</ChakraPagination.Item>
|
|
||||||
)
|
|
||||||
})
|
|
||||||
|
|
||||||
export const PaginationPrevTrigger = React.forwardRef<
|
|
||||||
HTMLButtonElement,
|
|
||||||
ChakraPagination.PrevTriggerProps
|
|
||||||
>(function PaginationPrevTrigger(props, ref) {
|
|
||||||
const { size, variantMap, getHref } = useRootProps()
|
|
||||||
const { previousPage } = usePaginationContext()
|
|
||||||
|
|
||||||
if (getHref) {
|
|
||||||
return (
|
|
||||||
<LinkButton
|
|
||||||
href={previousPage != null ? getHref(previousPage) : undefined}
|
|
||||||
variant={variantMap.default}
|
|
||||||
size={size}
|
|
||||||
>
|
|
||||||
<HiChevronLeft />
|
|
||||||
</LinkButton>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
|
||||||
<ChakraPagination.PrevTrigger ref={ref} asChild {...props}>
|
|
||||||
<IconButton variant={variantMap.default} size={size}>
|
|
||||||
<HiChevronLeft />
|
|
||||||
</IconButton>
|
|
||||||
</ChakraPagination.PrevTrigger>
|
|
||||||
)
|
|
||||||
})
|
|
||||||
|
|
||||||
export const PaginationNextTrigger = React.forwardRef<
|
|
||||||
HTMLButtonElement,
|
|
||||||
ChakraPagination.NextTriggerProps
|
|
||||||
>(function PaginationNextTrigger(props, ref) {
|
|
||||||
const { size, variantMap, getHref } = useRootProps()
|
|
||||||
const { nextPage } = usePaginationContext()
|
|
||||||
|
|
||||||
if (getHref) {
|
|
||||||
return (
|
|
||||||
<LinkButton
|
|
||||||
href={nextPage != null ? getHref(nextPage) : undefined}
|
|
||||||
variant={variantMap.default}
|
|
||||||
size={size}
|
|
||||||
>
|
|
||||||
<HiChevronRight />
|
|
||||||
</LinkButton>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
|
||||||
<ChakraPagination.NextTrigger ref={ref} asChild {...props}>
|
|
||||||
<IconButton variant={variantMap.default} size={size}>
|
|
||||||
<HiChevronRight />
|
|
||||||
</IconButton>
|
|
||||||
</ChakraPagination.NextTrigger>
|
|
||||||
)
|
|
||||||
})
|
|
||||||
|
|
||||||
export const PaginationItems = (props: React.HTMLAttributes<HTMLElement>) => {
|
|
||||||
return (
|
|
||||||
<ChakraPagination.Context>
|
|
||||||
{({ pages }) =>
|
|
||||||
pages.map((page, index) => {
|
|
||||||
return page.type === "ellipsis" ? (
|
|
||||||
<PaginationEllipsis key={index} index={index} {...props} />
|
|
||||||
) : (
|
|
||||||
<PaginationItem
|
|
||||||
key={index}
|
|
||||||
type="page"
|
|
||||||
value={page.value}
|
|
||||||
{...props}
|
|
||||||
/>
|
|
||||||
)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
</ChakraPagination.Context>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
interface PageTextProps extends TextProps {
|
|
||||||
format?: "short" | "compact" | "long"
|
|
||||||
}
|
|
||||||
|
|
||||||
export const PaginationPageText = React.forwardRef<
|
|
||||||
HTMLParagraphElement,
|
|
||||||
PageTextProps
|
|
||||||
>(function PaginationPageText(props, ref) {
|
|
||||||
const { format = "compact", ...rest } = props
|
|
||||||
const { page, totalPages, pageRange, count } = usePaginationContext()
|
|
||||||
const content = React.useMemo(() => {
|
|
||||||
if (format === "short") return `${page} / ${totalPages}`
|
|
||||||
if (format === "compact") return `${page} of ${totalPages}`
|
|
||||||
return `${pageRange.start + 1} - ${pageRange.end} of ${count}`
|
|
||||||
}, [format, page, totalPages, pageRange, count])
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Text fontWeight="medium" ref={ref} {...rest}>
|
|
||||||
{content}
|
|
||||||
</Text>
|
|
||||||
)
|
|
||||||
})
|
|
||||||
@@ -1,148 +0,0 @@
|
|||||||
"use client"
|
|
||||||
|
|
||||||
import type {
|
|
||||||
ButtonProps,
|
|
||||||
GroupProps,
|
|
||||||
InputProps,
|
|
||||||
StackProps,
|
|
||||||
} from "@chakra-ui/react"
|
|
||||||
import {
|
|
||||||
Box,
|
|
||||||
HStack,
|
|
||||||
IconButton,
|
|
||||||
Input,
|
|
||||||
Stack,
|
|
||||||
mergeRefs,
|
|
||||||
useControllableState,
|
|
||||||
} from "@chakra-ui/react"
|
|
||||||
import * as React from "react"
|
|
||||||
import { LuEye, LuEyeOff } from "react-icons/lu"
|
|
||||||
import { InputGroup } from "./input-group"
|
|
||||||
|
|
||||||
export interface PasswordVisibilityProps {
|
|
||||||
defaultVisible?: boolean
|
|
||||||
visible?: boolean
|
|
||||||
onVisibleChange?: (visible: boolean) => void
|
|
||||||
visibilityIcon?: { on: React.ReactNode; off: React.ReactNode }
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface PasswordInputProps
|
|
||||||
extends InputProps,
|
|
||||||
PasswordVisibilityProps {
|
|
||||||
rootProps?: GroupProps
|
|
||||||
}
|
|
||||||
|
|
||||||
export const PasswordInput = React.forwardRef<
|
|
||||||
HTMLInputElement,
|
|
||||||
PasswordInputProps
|
|
||||||
>(function PasswordInput(props, ref) {
|
|
||||||
const {
|
|
||||||
rootProps,
|
|
||||||
defaultVisible,
|
|
||||||
visible: visibleProp,
|
|
||||||
onVisibleChange,
|
|
||||||
visibilityIcon = { on: <LuEye />, off: <LuEyeOff /> },
|
|
||||||
...rest
|
|
||||||
} = props
|
|
||||||
|
|
||||||
const [visible, setVisible] = useControllableState({
|
|
||||||
value: visibleProp,
|
|
||||||
defaultValue: defaultVisible || false,
|
|
||||||
onChange: onVisibleChange,
|
|
||||||
})
|
|
||||||
|
|
||||||
const inputRef = React.useRef<HTMLInputElement>(null)
|
|
||||||
|
|
||||||
return (
|
|
||||||
<InputGroup
|
|
||||||
width="full"
|
|
||||||
endElement={
|
|
||||||
<VisibilityTrigger
|
|
||||||
disabled={rest.disabled}
|
|
||||||
onPointerDown={(e) => {
|
|
||||||
if (rest.disabled) return
|
|
||||||
if (e.button !== 0) return
|
|
||||||
e.preventDefault()
|
|
||||||
setVisible(!visible)
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{visible ? visibilityIcon.off : visibilityIcon.on}
|
|
||||||
</VisibilityTrigger>
|
|
||||||
}
|
|
||||||
{...rootProps}
|
|
||||||
>
|
|
||||||
<Input
|
|
||||||
{...rest}
|
|
||||||
ref={mergeRefs(ref, inputRef)}
|
|
||||||
type={visible ? "text" : "password"}
|
|
||||||
/>
|
|
||||||
</InputGroup>
|
|
||||||
)
|
|
||||||
})
|
|
||||||
|
|
||||||
const VisibilityTrigger = React.forwardRef<HTMLButtonElement, ButtonProps>(
|
|
||||||
function VisibilityTrigger(props, ref) {
|
|
||||||
return (
|
|
||||||
<IconButton
|
|
||||||
tabIndex={-1}
|
|
||||||
ref={ref}
|
|
||||||
me="-2"
|
|
||||||
aspectRatio="square"
|
|
||||||
size="sm"
|
|
||||||
variant="ghost"
|
|
||||||
height="calc(100% - {spacing.2})"
|
|
||||||
aria-label="Toggle password visibility"
|
|
||||||
{...props}
|
|
||||||
/>
|
|
||||||
)
|
|
||||||
},
|
|
||||||
)
|
|
||||||
|
|
||||||
interface PasswordStrengthMeterProps extends StackProps {
|
|
||||||
max?: number
|
|
||||||
value: number
|
|
||||||
}
|
|
||||||
|
|
||||||
export const PasswordStrengthMeter = React.forwardRef<
|
|
||||||
HTMLDivElement,
|
|
||||||
PasswordStrengthMeterProps
|
|
||||||
>(function PasswordStrengthMeter(props, ref) {
|
|
||||||
const { max = 4, value, ...rest } = props
|
|
||||||
|
|
||||||
const percent = (value / max) * 100
|
|
||||||
const { label, colorPalette } = getColorPalette(percent)
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Stack align="flex-end" gap="1" ref={ref} {...rest}>
|
|
||||||
<HStack width="full" ref={ref} {...rest}>
|
|
||||||
{Array.from({ length: max }).map((_, index) => (
|
|
||||||
<Box
|
|
||||||
key={index}
|
|
||||||
height="1"
|
|
||||||
flex="1"
|
|
||||||
rounded="sm"
|
|
||||||
data-selected={index < value ? "" : undefined}
|
|
||||||
layerStyle="fill.subtle"
|
|
||||||
colorPalette="gray"
|
|
||||||
_selected={{
|
|
||||||
colorPalette,
|
|
||||||
layerStyle: "fill.solid",
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
))}
|
|
||||||
</HStack>
|
|
||||||
{label && <HStack textStyle="xs">{label}</HStack>}
|
|
||||||
</Stack>
|
|
||||||
)
|
|
||||||
})
|
|
||||||
|
|
||||||
function getColorPalette(percent: number) {
|
|
||||||
switch (true) {
|
|
||||||
case percent < 33:
|
|
||||||
return { label: "Low", colorPalette: "red" }
|
|
||||||
case percent < 66:
|
|
||||||
return { label: "Medium", colorPalette: "orange" }
|
|
||||||
default:
|
|
||||||
return { label: "High", colorPalette: "green" }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,27 +0,0 @@
|
|||||||
import { PinInput as ChakraPinInput, Group } from "@chakra-ui/react"
|
|
||||||
import * as React from "react"
|
|
||||||
|
|
||||||
export interface PinInputProps extends ChakraPinInput.RootProps {
|
|
||||||
rootRef?: React.Ref<HTMLDivElement>
|
|
||||||
count?: number
|
|
||||||
inputProps?: React.InputHTMLAttributes<HTMLInputElement>
|
|
||||||
attached?: boolean
|
|
||||||
}
|
|
||||||
|
|
||||||
export const PinInput = React.forwardRef<HTMLInputElement, PinInputProps>(
|
|
||||||
function PinInput(props, ref) {
|
|
||||||
const { count = 4, inputProps, rootRef, attached, ...rest } = props
|
|
||||||
return (
|
|
||||||
<ChakraPinInput.Root ref={rootRef} {...rest}>
|
|
||||||
<ChakraPinInput.HiddenInput ref={ref} {...inputProps} />
|
|
||||||
<ChakraPinInput.Control>
|
|
||||||
<Group attached={attached}>
|
|
||||||
{Array.from({ length: count }).map((_, index) => (
|
|
||||||
<ChakraPinInput.Input key={index} index={index} />
|
|
||||||
))}
|
|
||||||
</Group>
|
|
||||||
</ChakraPinInput.Control>
|
|
||||||
</ChakraPinInput.Root>
|
|
||||||
)
|
|
||||||
},
|
|
||||||
)
|
|
||||||
@@ -1,59 +0,0 @@
|
|||||||
import { Popover as ChakraPopover, Portal } from "@chakra-ui/react"
|
|
||||||
import { CloseButton } from "./close-button"
|
|
||||||
import * as React from "react"
|
|
||||||
|
|
||||||
interface PopoverContentProps extends ChakraPopover.ContentProps {
|
|
||||||
portalled?: boolean
|
|
||||||
portalRef?: React.RefObject<HTMLElement>
|
|
||||||
}
|
|
||||||
|
|
||||||
export const PopoverContent = React.forwardRef<
|
|
||||||
HTMLDivElement,
|
|
||||||
PopoverContentProps
|
|
||||||
>(function PopoverContent(props, ref) {
|
|
||||||
const { portalled = true, portalRef, ...rest } = props
|
|
||||||
return (
|
|
||||||
<Portal disabled={!portalled} container={portalRef}>
|
|
||||||
<ChakraPopover.Positioner>
|
|
||||||
<ChakraPopover.Content ref={ref} {...rest} />
|
|
||||||
</ChakraPopover.Positioner>
|
|
||||||
</Portal>
|
|
||||||
)
|
|
||||||
})
|
|
||||||
|
|
||||||
export const PopoverArrow = React.forwardRef<
|
|
||||||
HTMLDivElement,
|
|
||||||
ChakraPopover.ArrowProps
|
|
||||||
>(function PopoverArrow(props, ref) {
|
|
||||||
return (
|
|
||||||
<ChakraPopover.Arrow {...props} ref={ref}>
|
|
||||||
<ChakraPopover.ArrowTip />
|
|
||||||
</ChakraPopover.Arrow>
|
|
||||||
)
|
|
||||||
})
|
|
||||||
|
|
||||||
export const PopoverCloseTrigger = React.forwardRef<
|
|
||||||
HTMLButtonElement,
|
|
||||||
ChakraPopover.CloseTriggerProps
|
|
||||||
>(function PopoverCloseTrigger(props, ref) {
|
|
||||||
return (
|
|
||||||
<ChakraPopover.CloseTrigger
|
|
||||||
position="absolute"
|
|
||||||
top="1"
|
|
||||||
insetEnd="1"
|
|
||||||
{...props}
|
|
||||||
asChild
|
|
||||||
ref={ref}
|
|
||||||
>
|
|
||||||
<CloseButton size="sm" />
|
|
||||||
</ChakraPopover.CloseTrigger>
|
|
||||||
)
|
|
||||||
})
|
|
||||||
|
|
||||||
export const PopoverTitle = ChakraPopover.Title
|
|
||||||
export const PopoverDescription = ChakraPopover.Description
|
|
||||||
export const PopoverFooter = ChakraPopover.Footer
|
|
||||||
export const PopoverHeader = ChakraPopover.Header
|
|
||||||
export const PopoverRoot = ChakraPopover.Root
|
|
||||||
export const PopoverBody = ChakraPopover.Body
|
|
||||||
export const PopoverTrigger = ChakraPopover.Trigger
|
|
||||||
@@ -1,37 +0,0 @@
|
|||||||
import type { SystemStyleObject } from "@chakra-ui/react"
|
|
||||||
import {
|
|
||||||
AbsoluteCenter,
|
|
||||||
ProgressCircle as ChakraProgressCircle,
|
|
||||||
} from "@chakra-ui/react"
|
|
||||||
import * as React from "react"
|
|
||||||
|
|
||||||
interface ProgressCircleRingProps extends ChakraProgressCircle.CircleProps {
|
|
||||||
trackColor?: SystemStyleObject["stroke"]
|
|
||||||
cap?: SystemStyleObject["strokeLinecap"]
|
|
||||||
}
|
|
||||||
|
|
||||||
export const ProgressCircleRing = React.forwardRef<
|
|
||||||
SVGSVGElement,
|
|
||||||
ProgressCircleRingProps
|
|
||||||
>(function ProgressCircleRing(props, ref) {
|
|
||||||
const { trackColor, cap, color, ...rest } = props
|
|
||||||
return (
|
|
||||||
<ChakraProgressCircle.Circle {...rest} ref={ref}>
|
|
||||||
<ChakraProgressCircle.Track stroke={trackColor} />
|
|
||||||
<ChakraProgressCircle.Range stroke={color} strokeLinecap={cap} />
|
|
||||||
</ChakraProgressCircle.Circle>
|
|
||||||
)
|
|
||||||
})
|
|
||||||
|
|
||||||
export const ProgressCircleValueText = React.forwardRef<
|
|
||||||
HTMLDivElement,
|
|
||||||
ChakraProgressCircle.ValueTextProps
|
|
||||||
>(function ProgressCircleValueText(props, ref) {
|
|
||||||
return (
|
|
||||||
<AbsoluteCenter>
|
|
||||||
<ChakraProgressCircle.ValueText {...props} ref={ref} />
|
|
||||||
</AbsoluteCenter>
|
|
||||||
)
|
|
||||||
})
|
|
||||||
|
|
||||||
export const ProgressCircleRoot = ChakraProgressCircle.Root
|
|
||||||
@@ -1,34 +0,0 @@
|
|||||||
import { Progress as ChakraProgress } from "@chakra-ui/react"
|
|
||||||
import { InfoTip } from "./toggle-tip"
|
|
||||||
import * as React from "react"
|
|
||||||
|
|
||||||
export const ProgressBar = React.forwardRef<
|
|
||||||
HTMLDivElement,
|
|
||||||
ChakraProgress.TrackProps
|
|
||||||
>(function ProgressBar(props, ref) {
|
|
||||||
return (
|
|
||||||
<ChakraProgress.Track {...props} ref={ref}>
|
|
||||||
<ChakraProgress.Range />
|
|
||||||
</ChakraProgress.Track>
|
|
||||||
)
|
|
||||||
})
|
|
||||||
|
|
||||||
export interface ProgressLabelProps extends ChakraProgress.LabelProps {
|
|
||||||
info?: React.ReactNode
|
|
||||||
}
|
|
||||||
|
|
||||||
export const ProgressLabel = React.forwardRef<
|
|
||||||
HTMLDivElement,
|
|
||||||
ProgressLabelProps
|
|
||||||
>(function ProgressLabel(props, ref) {
|
|
||||||
const { children, info, ...rest } = props
|
|
||||||
return (
|
|
||||||
<ChakraProgress.Label {...rest} ref={ref}>
|
|
||||||
{children}
|
|
||||||
{info && <InfoTip>{info}</InfoTip>}
|
|
||||||
</ChakraProgress.Label>
|
|
||||||
)
|
|
||||||
})
|
|
||||||
|
|
||||||
export const ProgressRoot = ChakraProgress.Root
|
|
||||||
export const ProgressValueText = ChakraProgress.ValueText
|
|
||||||
@@ -1,264 +0,0 @@
|
|||||||
"use client"
|
|
||||||
|
|
||||||
import { chakra } from "@chakra-ui/react"
|
|
||||||
|
|
||||||
export const Prose = chakra("div", {
|
|
||||||
base: {
|
|
||||||
color: "fg.muted",
|
|
||||||
maxWidth: "65ch",
|
|
||||||
fontSize: "sm",
|
|
||||||
lineHeight: "1.7em",
|
|
||||||
"& p": {
|
|
||||||
marginTop: "1em",
|
|
||||||
marginBottom: "1em",
|
|
||||||
},
|
|
||||||
"& blockquote": {
|
|
||||||
marginTop: "1.285em",
|
|
||||||
marginBottom: "1.285em",
|
|
||||||
paddingInline: "1.285em",
|
|
||||||
borderInlineStartWidth: "0.25em",
|
|
||||||
},
|
|
||||||
"& a": {
|
|
||||||
color: "fg",
|
|
||||||
textDecoration: "underline",
|
|
||||||
textUnderlineOffset: "3px",
|
|
||||||
textDecorationThickness: "2px",
|
|
||||||
textDecorationColor: "border.muted",
|
|
||||||
fontWeight: "500",
|
|
||||||
},
|
|
||||||
"& strong": {
|
|
||||||
fontWeight: "600",
|
|
||||||
},
|
|
||||||
"& a strong": {
|
|
||||||
color: "inherit",
|
|
||||||
},
|
|
||||||
"& h1": {
|
|
||||||
fontSize: "2.15em",
|
|
||||||
letterSpacing: "-0.02em",
|
|
||||||
marginTop: "0",
|
|
||||||
marginBottom: "0.8em",
|
|
||||||
lineHeight: "1.2em",
|
|
||||||
},
|
|
||||||
"& h2": {
|
|
||||||
fontSize: "1.4em",
|
|
||||||
letterSpacing: "-0.02em",
|
|
||||||
marginTop: "1.6em",
|
|
||||||
marginBottom: "0.8em",
|
|
||||||
lineHeight: "1.4em",
|
|
||||||
},
|
|
||||||
"& h3": {
|
|
||||||
fontSize: "1.285em",
|
|
||||||
letterSpacing: "-0.01em",
|
|
||||||
marginTop: "1.5em",
|
|
||||||
marginBottom: "0.4em",
|
|
||||||
lineHeight: "1.5em",
|
|
||||||
},
|
|
||||||
"& h4": {
|
|
||||||
marginTop: "1.4em",
|
|
||||||
marginBottom: "0.5em",
|
|
||||||
letterSpacing: "-0.01em",
|
|
||||||
lineHeight: "1.5em",
|
|
||||||
},
|
|
||||||
"& img": {
|
|
||||||
marginTop: "1.7em",
|
|
||||||
marginBottom: "1.7em",
|
|
||||||
borderRadius: "lg",
|
|
||||||
boxShadow: "inset",
|
|
||||||
},
|
|
||||||
"& picture": {
|
|
||||||
marginTop: "1.7em",
|
|
||||||
marginBottom: "1.7em",
|
|
||||||
},
|
|
||||||
"& picture > img": {
|
|
||||||
marginTop: "0",
|
|
||||||
marginBottom: "0",
|
|
||||||
},
|
|
||||||
"& video": {
|
|
||||||
marginTop: "1.7em",
|
|
||||||
marginBottom: "1.7em",
|
|
||||||
},
|
|
||||||
"& kbd": {
|
|
||||||
fontSize: "0.85em",
|
|
||||||
borderRadius: "xs",
|
|
||||||
paddingTop: "0.15em",
|
|
||||||
paddingBottom: "0.15em",
|
|
||||||
paddingInlineEnd: "0.35em",
|
|
||||||
paddingInlineStart: "0.35em",
|
|
||||||
fontFamily: "inherit",
|
|
||||||
color: "fg.muted",
|
|
||||||
"--shadow": "colors.border",
|
|
||||||
boxShadow: "0 0 0 1px var(--shadow),0 1px 0 1px var(--shadow)",
|
|
||||||
},
|
|
||||||
"& code": {
|
|
||||||
fontSize: "0.925em",
|
|
||||||
letterSpacing: "-0.01em",
|
|
||||||
borderRadius: "md",
|
|
||||||
borderWidth: "1px",
|
|
||||||
padding: "0.25em",
|
|
||||||
},
|
|
||||||
"& pre code": {
|
|
||||||
fontSize: "inherit",
|
|
||||||
letterSpacing: "inherit",
|
|
||||||
borderWidth: "inherit",
|
|
||||||
padding: "0",
|
|
||||||
},
|
|
||||||
"& h2 code": {
|
|
||||||
fontSize: "0.9em",
|
|
||||||
},
|
|
||||||
"& h3 code": {
|
|
||||||
fontSize: "0.8em",
|
|
||||||
},
|
|
||||||
"& pre": {
|
|
||||||
backgroundColor: "bg.subtle",
|
|
||||||
marginTop: "1.6em",
|
|
||||||
marginBottom: "1.6em",
|
|
||||||
borderRadius: "md",
|
|
||||||
fontSize: "0.9em",
|
|
||||||
paddingTop: "0.65em",
|
|
||||||
paddingBottom: "0.65em",
|
|
||||||
paddingInlineEnd: "1em",
|
|
||||||
paddingInlineStart: "1em",
|
|
||||||
overflowX: "auto",
|
|
||||||
fontWeight: "400",
|
|
||||||
},
|
|
||||||
"& ol": {
|
|
||||||
marginTop: "1em",
|
|
||||||
marginBottom: "1em",
|
|
||||||
paddingInlineStart: "1.5em",
|
|
||||||
},
|
|
||||||
"& ul": {
|
|
||||||
marginTop: "1em",
|
|
||||||
marginBottom: "1em",
|
|
||||||
paddingInlineStart: "1.5em",
|
|
||||||
},
|
|
||||||
"& li": {
|
|
||||||
marginTop: "0.285em",
|
|
||||||
marginBottom: "0.285em",
|
|
||||||
},
|
|
||||||
"& ol > li": {
|
|
||||||
paddingInlineStart: "0.4em",
|
|
||||||
listStyleType: "decimal",
|
|
||||||
"&::marker": {
|
|
||||||
color: "fg.muted",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
"& ul > li": {
|
|
||||||
paddingInlineStart: "0.4em",
|
|
||||||
listStyleType: "disc",
|
|
||||||
"&::marker": {
|
|
||||||
color: "fg.muted",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
"& > ul > li p": {
|
|
||||||
marginTop: "0.5em",
|
|
||||||
marginBottom: "0.5em",
|
|
||||||
},
|
|
||||||
"& > ul > li > p:first-of-type": {
|
|
||||||
marginTop: "1em",
|
|
||||||
},
|
|
||||||
"& > ul > li > p:last-of-type": {
|
|
||||||
marginBottom: "1em",
|
|
||||||
},
|
|
||||||
"& > ol > li > p:first-of-type": {
|
|
||||||
marginTop: "1em",
|
|
||||||
},
|
|
||||||
"& > ol > li > p:last-of-type": {
|
|
||||||
marginBottom: "1em",
|
|
||||||
},
|
|
||||||
"& ul ul, ul ol, ol ul, ol ol": {
|
|
||||||
marginTop: "0.5em",
|
|
||||||
marginBottom: "0.5em",
|
|
||||||
},
|
|
||||||
"& dl": {
|
|
||||||
marginTop: "1em",
|
|
||||||
marginBottom: "1em",
|
|
||||||
},
|
|
||||||
"& dt": {
|
|
||||||
fontWeight: "600",
|
|
||||||
marginTop: "1em",
|
|
||||||
},
|
|
||||||
"& dd": {
|
|
||||||
marginTop: "0.285em",
|
|
||||||
paddingInlineStart: "1.5em",
|
|
||||||
},
|
|
||||||
"& hr": {
|
|
||||||
marginTop: "2.25em",
|
|
||||||
marginBottom: "2.25em",
|
|
||||||
},
|
|
||||||
"& :is(h1,h2,h3,h4,h5,hr) + *": {
|
|
||||||
marginTop: "0",
|
|
||||||
},
|
|
||||||
"& table": {
|
|
||||||
width: "100%",
|
|
||||||
tableLayout: "auto",
|
|
||||||
textAlign: "start",
|
|
||||||
lineHeight: "1.5em",
|
|
||||||
marginTop: "2em",
|
|
||||||
marginBottom: "2em",
|
|
||||||
},
|
|
||||||
"& thead": {
|
|
||||||
borderBottomWidth: "1px",
|
|
||||||
color: "fg",
|
|
||||||
},
|
|
||||||
"& tbody tr": {
|
|
||||||
borderBottomWidth: "1px",
|
|
||||||
borderBottomColor: "border",
|
|
||||||
},
|
|
||||||
"& thead th": {
|
|
||||||
paddingInlineEnd: "1em",
|
|
||||||
paddingBottom: "0.65em",
|
|
||||||
paddingInlineStart: "1em",
|
|
||||||
fontWeight: "medium",
|
|
||||||
textAlign: "start",
|
|
||||||
},
|
|
||||||
"& thead th:first-of-type": {
|
|
||||||
paddingInlineStart: "0",
|
|
||||||
},
|
|
||||||
"& thead th:last-of-type": {
|
|
||||||
paddingInlineEnd: "0",
|
|
||||||
},
|
|
||||||
"& tbody td, tfoot td": {
|
|
||||||
paddingTop: "0.65em",
|
|
||||||
paddingInlineEnd: "1em",
|
|
||||||
paddingBottom: "0.65em",
|
|
||||||
paddingInlineStart: "1em",
|
|
||||||
},
|
|
||||||
"& tbody td:first-of-type, tfoot td:first-of-type": {
|
|
||||||
paddingInlineStart: "0",
|
|
||||||
},
|
|
||||||
"& tbody td:last-of-type, tfoot td:last-of-type": {
|
|
||||||
paddingInlineEnd: "0",
|
|
||||||
},
|
|
||||||
"& figure": {
|
|
||||||
marginTop: "1.625em",
|
|
||||||
marginBottom: "1.625em",
|
|
||||||
},
|
|
||||||
"& figure > *": {
|
|
||||||
marginTop: "0",
|
|
||||||
marginBottom: "0",
|
|
||||||
},
|
|
||||||
"& figcaption": {
|
|
||||||
fontSize: "0.85em",
|
|
||||||
lineHeight: "1.25em",
|
|
||||||
marginTop: "0.85em",
|
|
||||||
color: "fg.muted",
|
|
||||||
},
|
|
||||||
"& h1, h2, h3, h4": {
|
|
||||||
color: "fg",
|
|
||||||
fontWeight: "600",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
variants: {
|
|
||||||
size: {
|
|
||||||
md: {
|
|
||||||
fontSize: "sm",
|
|
||||||
},
|
|
||||||
lg: {
|
|
||||||
fontSize: "md",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
defaultVariants: {
|
|
||||||
size: "md",
|
|
||||||
},
|
|
||||||
})
|
|
||||||
@@ -1,15 +0,0 @@
|
|||||||
"use client"
|
|
||||||
|
|
||||||
import { ChakraProvider, defaultSystem } from "@chakra-ui/react"
|
|
||||||
import {
|
|
||||||
ColorModeProvider,
|
|
||||||
type ColorModeProviderProps,
|
|
||||||
} from "./color-mode"
|
|
||||||
|
|
||||||
export function Provider(props: ColorModeProviderProps) {
|
|
||||||
return (
|
|
||||||
<ChakraProvider value={defaultSystem}>
|
|
||||||
<ColorModeProvider {...props} />
|
|
||||||
</ChakraProvider>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
@@ -1,58 +0,0 @@
|
|||||||
import { RadioCard } from "@chakra-ui/react"
|
|
||||||
import * as React from "react"
|
|
||||||
|
|
||||||
interface RadioCardItemProps extends RadioCard.ItemProps {
|
|
||||||
icon?: React.ReactElement
|
|
||||||
label?: React.ReactNode
|
|
||||||
description?: React.ReactNode
|
|
||||||
addon?: React.ReactNode
|
|
||||||
indicator?: React.ReactNode | null
|
|
||||||
indicatorPlacement?: "start" | "end" | "inside"
|
|
||||||
inputProps?: React.InputHTMLAttributes<HTMLInputElement>
|
|
||||||
}
|
|
||||||
|
|
||||||
export const RadioCardItem = React.forwardRef<
|
|
||||||
HTMLInputElement,
|
|
||||||
RadioCardItemProps
|
|
||||||
>(function RadioCardItem(props, ref) {
|
|
||||||
const {
|
|
||||||
inputProps,
|
|
||||||
label,
|
|
||||||
description,
|
|
||||||
addon,
|
|
||||||
icon,
|
|
||||||
indicator = <RadioCard.ItemIndicator />,
|
|
||||||
indicatorPlacement = "end",
|
|
||||||
...rest
|
|
||||||
} = props
|
|
||||||
|
|
||||||
const hasContent = label || description || icon
|
|
||||||
const ContentWrapper = indicator ? RadioCard.ItemContent : React.Fragment
|
|
||||||
|
|
||||||
return (
|
|
||||||
<RadioCard.Item {...rest}>
|
|
||||||
<RadioCard.ItemHiddenInput ref={ref} {...inputProps} />
|
|
||||||
<RadioCard.ItemControl>
|
|
||||||
{indicatorPlacement === "start" && indicator}
|
|
||||||
{hasContent && (
|
|
||||||
<ContentWrapper>
|
|
||||||
{icon}
|
|
||||||
{label && <RadioCard.ItemText>{label}</RadioCard.ItemText>}
|
|
||||||
{description && (
|
|
||||||
<RadioCard.ItemDescription>
|
|
||||||
{description}
|
|
||||||
</RadioCard.ItemDescription>
|
|
||||||
)}
|
|
||||||
{indicatorPlacement === "inside" && indicator}
|
|
||||||
</ContentWrapper>
|
|
||||||
)}
|
|
||||||
{indicatorPlacement === "end" && indicator}
|
|
||||||
</RadioCard.ItemControl>
|
|
||||||
{addon && <RadioCard.ItemAddon>{addon}</RadioCard.ItemAddon>}
|
|
||||||
</RadioCard.Item>
|
|
||||||
)
|
|
||||||
})
|
|
||||||
|
|
||||||
export const RadioCardRoot = RadioCard.Root
|
|
||||||
export const RadioCardLabel = RadioCard.Label
|
|
||||||
export const RadioCardItemIndicator = RadioCard.ItemIndicator
|
|
||||||
@@ -1,24 +0,0 @@
|
|||||||
import { RadioGroup as ChakraRadioGroup } from "@chakra-ui/react"
|
|
||||||
import * as React from "react"
|
|
||||||
|
|
||||||
export interface RadioProps extends ChakraRadioGroup.ItemProps {
|
|
||||||
rootRef?: React.Ref<HTMLDivElement>
|
|
||||||
inputProps?: React.InputHTMLAttributes<HTMLInputElement>
|
|
||||||
}
|
|
||||||
|
|
||||||
export const Radio = React.forwardRef<HTMLInputElement, RadioProps>(
|
|
||||||
function Radio(props, ref) {
|
|
||||||
const { children, inputProps, rootRef, ...rest } = props
|
|
||||||
return (
|
|
||||||
<ChakraRadioGroup.Item ref={rootRef} {...rest}>
|
|
||||||
<ChakraRadioGroup.ItemHiddenInput ref={ref} {...inputProps} />
|
|
||||||
<ChakraRadioGroup.ItemIndicator />
|
|
||||||
{children && (
|
|
||||||
<ChakraRadioGroup.ItemText>{children}</ChakraRadioGroup.ItemText>
|
|
||||||
)}
|
|
||||||
</ChakraRadioGroup.Item>
|
|
||||||
)
|
|
||||||
},
|
|
||||||
)
|
|
||||||
|
|
||||||
export const RadioGroup = ChakraRadioGroup.Root
|
|
||||||
@@ -1,27 +0,0 @@
|
|||||||
import { RatingGroup } from "@chakra-ui/react"
|
|
||||||
import * as React from "react"
|
|
||||||
|
|
||||||
export interface RatingProps extends RatingGroup.RootProps {
|
|
||||||
icon?: React.ReactElement
|
|
||||||
count?: number
|
|
||||||
label?: React.ReactNode
|
|
||||||
}
|
|
||||||
|
|
||||||
export const Rating = React.forwardRef<HTMLDivElement, RatingProps>(
|
|
||||||
function Rating(props, ref) {
|
|
||||||
const { icon, count = 5, label, ...rest } = props
|
|
||||||
return (
|
|
||||||
<RatingGroup.Root ref={ref} count={count} {...rest}>
|
|
||||||
{label && <RatingGroup.Label>{label}</RatingGroup.Label>}
|
|
||||||
<RatingGroup.HiddenInput />
|
|
||||||
<RatingGroup.Control>
|
|
||||||
{Array.from({ length: count }).map((_, index) => (
|
|
||||||
<RatingGroup.Item key={index} index={index + 1}>
|
|
||||||
<RatingGroup.ItemIndicator icon={icon} />
|
|
||||||
</RatingGroup.Item>
|
|
||||||
))}
|
|
||||||
</RatingGroup.Control>
|
|
||||||
</RatingGroup.Root>
|
|
||||||
)
|
|
||||||
},
|
|
||||||
)
|
|
||||||
@@ -1,47 +0,0 @@
|
|||||||
"use client"
|
|
||||||
|
|
||||||
import { For, SegmentGroup } from "@chakra-ui/react"
|
|
||||||
import * as React from "react"
|
|
||||||
|
|
||||||
interface Item {
|
|
||||||
value: string
|
|
||||||
label: React.ReactNode
|
|
||||||
disabled?: boolean
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface SegmentedControlProps extends SegmentGroup.RootProps {
|
|
||||||
items: Array<string | Item>
|
|
||||||
}
|
|
||||||
|
|
||||||
function normalize(items: Array<string | Item>): Item[] {
|
|
||||||
return items.map((item) => {
|
|
||||||
if (typeof item === "string") return { value: item, label: item }
|
|
||||||
return item
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
export const SegmentedControl = React.forwardRef<
|
|
||||||
HTMLDivElement,
|
|
||||||
SegmentedControlProps
|
|
||||||
>(function SegmentedControl(props, ref) {
|
|
||||||
const { items, ...rest } = props
|
|
||||||
const data = React.useMemo(() => normalize(items), [items])
|
|
||||||
|
|
||||||
return (
|
|
||||||
<SegmentGroup.Root ref={ref} {...rest}>
|
|
||||||
<SegmentGroup.Indicator />
|
|
||||||
<For each={data}>
|
|
||||||
{(item) => (
|
|
||||||
<SegmentGroup.Item
|
|
||||||
key={item.value}
|
|
||||||
value={item.value}
|
|
||||||
disabled={item.disabled}
|
|
||||||
>
|
|
||||||
<SegmentGroup.ItemText>{item.label}</SegmentGroup.ItemText>
|
|
||||||
<SegmentGroup.ItemHiddenInput />
|
|
||||||
</SegmentGroup.Item>
|
|
||||||
)}
|
|
||||||
</For>
|
|
||||||
</SegmentGroup.Root>
|
|
||||||
)
|
|
||||||
})
|
|
||||||
@@ -1,143 +0,0 @@
|
|||||||
"use client"
|
|
||||||
|
|
||||||
import type { CollectionItem } from "@chakra-ui/react"
|
|
||||||
import { Select as ChakraSelect, Portal } from "@chakra-ui/react"
|
|
||||||
import { CloseButton } from "./close-button"
|
|
||||||
import * as React from "react"
|
|
||||||
|
|
||||||
interface SelectTriggerProps extends ChakraSelect.ControlProps {
|
|
||||||
clearable?: boolean
|
|
||||||
}
|
|
||||||
|
|
||||||
export const SelectTrigger = React.forwardRef<
|
|
||||||
HTMLButtonElement,
|
|
||||||
SelectTriggerProps
|
|
||||||
>(function SelectTrigger(props, ref) {
|
|
||||||
const { children, clearable, ...rest } = props
|
|
||||||
return (
|
|
||||||
<ChakraSelect.Control {...rest}>
|
|
||||||
<ChakraSelect.Trigger ref={ref}>{children}</ChakraSelect.Trigger>
|
|
||||||
<ChakraSelect.IndicatorGroup>
|
|
||||||
{clearable && <SelectClearTrigger />}
|
|
||||||
<ChakraSelect.Indicator />
|
|
||||||
</ChakraSelect.IndicatorGroup>
|
|
||||||
</ChakraSelect.Control>
|
|
||||||
)
|
|
||||||
})
|
|
||||||
|
|
||||||
const SelectClearTrigger = React.forwardRef<
|
|
||||||
HTMLButtonElement,
|
|
||||||
ChakraSelect.ClearTriggerProps
|
|
||||||
>(function SelectClearTrigger(props, ref) {
|
|
||||||
return (
|
|
||||||
<ChakraSelect.ClearTrigger asChild {...props} ref={ref}>
|
|
||||||
<CloseButton
|
|
||||||
size="xs"
|
|
||||||
variant="plain"
|
|
||||||
focusVisibleRing="inside"
|
|
||||||
focusRingWidth="2px"
|
|
||||||
pointerEvents="auto"
|
|
||||||
/>
|
|
||||||
</ChakraSelect.ClearTrigger>
|
|
||||||
)
|
|
||||||
})
|
|
||||||
|
|
||||||
interface SelectContentProps extends ChakraSelect.ContentProps {
|
|
||||||
portalled?: boolean
|
|
||||||
portalRef?: React.RefObject<HTMLElement>
|
|
||||||
}
|
|
||||||
|
|
||||||
export const SelectContent = React.forwardRef<
|
|
||||||
HTMLDivElement,
|
|
||||||
SelectContentProps
|
|
||||||
>(function SelectContent(props, ref) {
|
|
||||||
const { portalled = true, portalRef, ...rest } = props
|
|
||||||
return (
|
|
||||||
<Portal disabled={!portalled} container={portalRef}>
|
|
||||||
<ChakraSelect.Positioner>
|
|
||||||
<ChakraSelect.Content {...rest} ref={ref} />
|
|
||||||
</ChakraSelect.Positioner>
|
|
||||||
</Portal>
|
|
||||||
)
|
|
||||||
})
|
|
||||||
|
|
||||||
export const SelectItem = React.forwardRef<
|
|
||||||
HTMLDivElement,
|
|
||||||
ChakraSelect.ItemProps
|
|
||||||
>(function SelectItem(props, ref) {
|
|
||||||
const { item, children, ...rest } = props
|
|
||||||
return (
|
|
||||||
<ChakraSelect.Item key={item.value} item={item} {...rest} ref={ref}>
|
|
||||||
{children}
|
|
||||||
<ChakraSelect.ItemIndicator />
|
|
||||||
</ChakraSelect.Item>
|
|
||||||
)
|
|
||||||
})
|
|
||||||
|
|
||||||
interface SelectValueTextProps
|
|
||||||
extends Omit<ChakraSelect.ValueTextProps, "children"> {
|
|
||||||
children?(items: CollectionItem[]): React.ReactNode
|
|
||||||
}
|
|
||||||
|
|
||||||
export const SelectValueText = React.forwardRef<
|
|
||||||
HTMLSpanElement,
|
|
||||||
SelectValueTextProps
|
|
||||||
>(function SelectValueText(props, ref) {
|
|
||||||
const { children, ...rest } = props
|
|
||||||
return (
|
|
||||||
<ChakraSelect.ValueText {...rest} ref={ref}>
|
|
||||||
<ChakraSelect.Context>
|
|
||||||
{(select) => {
|
|
||||||
const items = select.selectedItems
|
|
||||||
if (items.length === 0) return props.placeholder
|
|
||||||
if (children) return children(items)
|
|
||||||
if (items.length === 1)
|
|
||||||
return select.collection.stringifyItem(items[0])
|
|
||||||
return `${items.length} selected`
|
|
||||||
}}
|
|
||||||
</ChakraSelect.Context>
|
|
||||||
</ChakraSelect.ValueText>
|
|
||||||
)
|
|
||||||
})
|
|
||||||
|
|
||||||
export const SelectRoot = React.forwardRef<
|
|
||||||
HTMLDivElement,
|
|
||||||
ChakraSelect.RootProps
|
|
||||||
>(function SelectRoot(props, ref) {
|
|
||||||
return (
|
|
||||||
<ChakraSelect.Root
|
|
||||||
{...props}
|
|
||||||
ref={ref}
|
|
||||||
positioning={{ sameWidth: true, ...props.positioning }}
|
|
||||||
>
|
|
||||||
{props.asChild ? (
|
|
||||||
props.children
|
|
||||||
) : (
|
|
||||||
<>
|
|
||||||
<ChakraSelect.HiddenSelect />
|
|
||||||
{props.children}
|
|
||||||
</>
|
|
||||||
)}
|
|
||||||
</ChakraSelect.Root>
|
|
||||||
)
|
|
||||||
}) as ChakraSelect.RootComponent
|
|
||||||
|
|
||||||
interface SelectItemGroupProps extends ChakraSelect.ItemGroupProps {
|
|
||||||
label: React.ReactNode
|
|
||||||
}
|
|
||||||
|
|
||||||
export const SelectItemGroup = React.forwardRef<
|
|
||||||
HTMLDivElement,
|
|
||||||
SelectItemGroupProps
|
|
||||||
>(function SelectItemGroup(props, ref) {
|
|
||||||
const { children, label, ...rest } = props
|
|
||||||
return (
|
|
||||||
<ChakraSelect.ItemGroup {...rest} ref={ref}>
|
|
||||||
<ChakraSelect.ItemGroupLabel>{label}</ChakraSelect.ItemGroupLabel>
|
|
||||||
{children}
|
|
||||||
</ChakraSelect.ItemGroup>
|
|
||||||
)
|
|
||||||
})
|
|
||||||
|
|
||||||
export const SelectLabel = ChakraSelect.Label
|
|
||||||
export const SelectItemText = ChakraSelect.ItemText
|
|
||||||
@@ -1,47 +0,0 @@
|
|||||||
import type {
|
|
||||||
SkeletonProps as ChakraSkeletonProps,
|
|
||||||
CircleProps,
|
|
||||||
} from "@chakra-ui/react"
|
|
||||||
import { Skeleton as ChakraSkeleton, Circle, Stack } from "@chakra-ui/react"
|
|
||||||
import * as React from "react"
|
|
||||||
|
|
||||||
export interface SkeletonCircleProps extends ChakraSkeletonProps {
|
|
||||||
size?: CircleProps["size"]
|
|
||||||
}
|
|
||||||
|
|
||||||
export const SkeletonCircle = React.forwardRef<
|
|
||||||
HTMLDivElement,
|
|
||||||
SkeletonCircleProps
|
|
||||||
>(function SkeletonCircle(props, ref) {
|
|
||||||
const { size, ...rest } = props
|
|
||||||
return (
|
|
||||||
<Circle size={size} asChild ref={ref}>
|
|
||||||
<ChakraSkeleton {...rest} />
|
|
||||||
</Circle>
|
|
||||||
)
|
|
||||||
})
|
|
||||||
|
|
||||||
export interface SkeletonTextProps extends ChakraSkeletonProps {
|
|
||||||
noOfLines?: number
|
|
||||||
}
|
|
||||||
|
|
||||||
export const SkeletonText = React.forwardRef<HTMLDivElement, SkeletonTextProps>(
|
|
||||||
function SkeletonText(props, ref) {
|
|
||||||
const { noOfLines = 3, gap, ...rest } = props
|
|
||||||
return (
|
|
||||||
<Stack gap={gap} width="full" ref={ref}>
|
|
||||||
{Array.from({ length: noOfLines }).map((_, index) => (
|
|
||||||
<ChakraSkeleton
|
|
||||||
height="4"
|
|
||||||
key={index}
|
|
||||||
{...props}
|
|
||||||
_last={{ maxW: "80%" }}
|
|
||||||
{...rest}
|
|
||||||
/>
|
|
||||||
))}
|
|
||||||
</Stack>
|
|
||||||
)
|
|
||||||
},
|
|
||||||
)
|
|
||||||
|
|
||||||
export const Skeleton = ChakraSkeleton
|
|
||||||
@@ -1,60 +0,0 @@
|
|||||||
import { Slider as ChakraSlider, HStack } from "@chakra-ui/react"
|
|
||||||
import * as React from "react"
|
|
||||||
|
|
||||||
export interface SliderProps extends ChakraSlider.RootProps {
|
|
||||||
marks?: Array<number | { value: number; label: React.ReactNode }>
|
|
||||||
label?: React.ReactNode
|
|
||||||
showValue?: boolean
|
|
||||||
}
|
|
||||||
|
|
||||||
export const Slider = React.forwardRef<HTMLDivElement, SliderProps>(
|
|
||||||
function Slider(props, ref) {
|
|
||||||
const { marks: marksProp, label, showValue, ...rest } = props
|
|
||||||
const value = props.defaultValue ?? props.value
|
|
||||||
|
|
||||||
const marks = marksProp?.map((mark) => {
|
|
||||||
if (typeof mark === "number") return { value: mark, label: undefined }
|
|
||||||
return mark
|
|
||||||
})
|
|
||||||
|
|
||||||
const hasMarkLabel = !!marks?.some((mark) => mark.label)
|
|
||||||
|
|
||||||
return (
|
|
||||||
<ChakraSlider.Root ref={ref} thumbAlignment="center" {...rest}>
|
|
||||||
{label && !showValue && (
|
|
||||||
<ChakraSlider.Label fontWeight="medium">{label}</ChakraSlider.Label>
|
|
||||||
)}
|
|
||||||
{label && showValue && (
|
|
||||||
<HStack justify="space-between">
|
|
||||||
<ChakraSlider.Label fontWeight="medium">{label}</ChakraSlider.Label>
|
|
||||||
<ChakraSlider.ValueText />
|
|
||||||
</HStack>
|
|
||||||
)}
|
|
||||||
<ChakraSlider.Control mb={hasMarkLabel ? "4" : undefined}>
|
|
||||||
<ChakraSlider.Track>
|
|
||||||
<ChakraSlider.Range />
|
|
||||||
</ChakraSlider.Track>
|
|
||||||
{value?.map((_, index) => (
|
|
||||||
<ChakraSlider.Thumb key={index} index={index}>
|
|
||||||
<ChakraSlider.HiddenInput />
|
|
||||||
</ChakraSlider.Thumb>
|
|
||||||
))}
|
|
||||||
</ChakraSlider.Control>
|
|
||||||
{marks?.length && (
|
|
||||||
<ChakraSlider.MarkerGroup>
|
|
||||||
{marks.map((mark, index) => {
|
|
||||||
const value = typeof mark === "number" ? mark : mark.value
|
|
||||||
const label = typeof mark === "number" ? undefined : mark.label
|
|
||||||
return (
|
|
||||||
<ChakraSlider.Marker key={index} value={value}>
|
|
||||||
<ChakraSlider.MarkerIndicator />
|
|
||||||
{label}
|
|
||||||
</ChakraSlider.Marker>
|
|
||||||
)
|
|
||||||
})}
|
|
||||||
</ChakraSlider.MarkerGroup>
|
|
||||||
)}
|
|
||||||
</ChakraSlider.Root>
|
|
||||||
)
|
|
||||||
},
|
|
||||||
)
|
|
||||||
@@ -1,68 +0,0 @@
|
|||||||
import {
|
|
||||||
Badge,
|
|
||||||
type BadgeProps,
|
|
||||||
Stat as ChakraStat,
|
|
||||||
FormatNumber,
|
|
||||||
} from "@chakra-ui/react"
|
|
||||||
import { InfoTip } from "./toggle-tip"
|
|
||||||
import * as React from "react"
|
|
||||||
|
|
||||||
interface StatLabelProps extends ChakraStat.LabelProps {
|
|
||||||
info?: React.ReactNode
|
|
||||||
}
|
|
||||||
|
|
||||||
export const StatLabel = React.forwardRef<HTMLDivElement, StatLabelProps>(
|
|
||||||
function StatLabel(props, ref) {
|
|
||||||
const { info, children, ...rest } = props
|
|
||||||
return (
|
|
||||||
<ChakraStat.Label {...rest} ref={ref}>
|
|
||||||
{children}
|
|
||||||
{info && <InfoTip>{info}</InfoTip>}
|
|
||||||
</ChakraStat.Label>
|
|
||||||
)
|
|
||||||
},
|
|
||||||
)
|
|
||||||
|
|
||||||
interface StatValueTextProps extends ChakraStat.ValueTextProps {
|
|
||||||
value?: number
|
|
||||||
formatOptions?: Intl.NumberFormatOptions
|
|
||||||
}
|
|
||||||
|
|
||||||
export const StatValueText = React.forwardRef<
|
|
||||||
HTMLDivElement,
|
|
||||||
StatValueTextProps
|
|
||||||
>(function StatValueText(props, ref) {
|
|
||||||
const { value, formatOptions, children, ...rest } = props
|
|
||||||
return (
|
|
||||||
<ChakraStat.ValueText {...rest} ref={ref}>
|
|
||||||
{children ||
|
|
||||||
(value != null && <FormatNumber value={value} {...formatOptions} />)}
|
|
||||||
</ChakraStat.ValueText>
|
|
||||||
)
|
|
||||||
})
|
|
||||||
|
|
||||||
export const StatUpTrend = React.forwardRef<HTMLDivElement, BadgeProps>(
|
|
||||||
function StatUpTrend(props, ref) {
|
|
||||||
return (
|
|
||||||
<Badge colorPalette="green" gap="0" {...props} ref={ref}>
|
|
||||||
<ChakraStat.UpIndicator />
|
|
||||||
{props.children}
|
|
||||||
</Badge>
|
|
||||||
)
|
|
||||||
},
|
|
||||||
)
|
|
||||||
|
|
||||||
export const StatDownTrend = React.forwardRef<HTMLDivElement, BadgeProps>(
|
|
||||||
function StatDownTrend(props, ref) {
|
|
||||||
return (
|
|
||||||
<Badge colorPalette="red" gap="0" {...props} ref={ref}>
|
|
||||||
<ChakraStat.DownIndicator />
|
|
||||||
{props.children}
|
|
||||||
</Badge>
|
|
||||||
)
|
|
||||||
},
|
|
||||||
)
|
|
||||||
|
|
||||||
export const StatRoot = ChakraStat.Root
|
|
||||||
export const StatHelpText = ChakraStat.HelpText
|
|
||||||
export const StatValueUnit = ChakraStat.ValueUnit
|
|
||||||
@@ -1,29 +0,0 @@
|
|||||||
import type { ColorPalette } from "@chakra-ui/react"
|
|
||||||
import { Status as ChakraStatus } from "@chakra-ui/react"
|
|
||||||
import * as React from "react"
|
|
||||||
|
|
||||||
type StatusValue = "success" | "error" | "warning" | "info"
|
|
||||||
|
|
||||||
export interface StatusProps extends ChakraStatus.RootProps {
|
|
||||||
value?: StatusValue
|
|
||||||
}
|
|
||||||
|
|
||||||
const statusMap: Record<StatusValue, ColorPalette> = {
|
|
||||||
success: "green",
|
|
||||||
error: "red",
|
|
||||||
warning: "orange",
|
|
||||||
info: "blue",
|
|
||||||
}
|
|
||||||
|
|
||||||
export const Status = React.forwardRef<HTMLDivElement, StatusProps>(
|
|
||||||
function Status(props, ref) {
|
|
||||||
const { children, value = "info", ...rest } = props
|
|
||||||
const colorPalette = rest.colorPalette ?? statusMap[value]
|
|
||||||
return (
|
|
||||||
<ChakraStatus.Root ref={ref} {...rest} colorPalette={colorPalette}>
|
|
||||||
<ChakraStatus.Indicator />
|
|
||||||
{children}
|
|
||||||
</ChakraStatus.Root>
|
|
||||||
)
|
|
||||||
},
|
|
||||||
)
|
|
||||||
@@ -1,49 +0,0 @@
|
|||||||
import { HStack, IconButton, NumberInput } from "@chakra-ui/react"
|
|
||||||
import * as React from "react"
|
|
||||||
import { LuMinus, LuPlus } from "react-icons/lu"
|
|
||||||
|
|
||||||
export interface StepperInputProps extends NumberInput.RootProps {
|
|
||||||
label?: React.ReactNode
|
|
||||||
}
|
|
||||||
|
|
||||||
export const StepperInput = React.forwardRef<HTMLDivElement, StepperInputProps>(
|
|
||||||
function StepperInput(props, ref) {
|
|
||||||
const { label, ...rest } = props
|
|
||||||
return (
|
|
||||||
<NumberInput.Root {...rest} unstyled ref={ref}>
|
|
||||||
{label && <NumberInput.Label>{label}</NumberInput.Label>}
|
|
||||||
<HStack gap="2">
|
|
||||||
<DecrementTrigger />
|
|
||||||
<NumberInput.ValueText textAlign="center" fontSize="lg" minW="3ch" />
|
|
||||||
<IncrementTrigger />
|
|
||||||
</HStack>
|
|
||||||
</NumberInput.Root>
|
|
||||||
)
|
|
||||||
},
|
|
||||||
)
|
|
||||||
|
|
||||||
const DecrementTrigger = React.forwardRef<
|
|
||||||
HTMLButtonElement,
|
|
||||||
NumberInput.DecrementTriggerProps
|
|
||||||
>(function DecrementTrigger(props, ref) {
|
|
||||||
return (
|
|
||||||
<NumberInput.DecrementTrigger {...props} asChild ref={ref}>
|
|
||||||
<IconButton variant="outline" size="sm">
|
|
||||||
<LuMinus />
|
|
||||||
</IconButton>
|
|
||||||
</NumberInput.DecrementTrigger>
|
|
||||||
)
|
|
||||||
})
|
|
||||||
|
|
||||||
const IncrementTrigger = React.forwardRef<
|
|
||||||
HTMLButtonElement,
|
|
||||||
NumberInput.IncrementTriggerProps
|
|
||||||
>(function IncrementTrigger(props, ref) {
|
|
||||||
return (
|
|
||||||
<NumberInput.IncrementTrigger {...props} asChild ref={ref}>
|
|
||||||
<IconButton variant="outline" size="sm">
|
|
||||||
<LuPlus />
|
|
||||||
</IconButton>
|
|
||||||
</NumberInput.IncrementTrigger>
|
|
||||||
)
|
|
||||||
})
|
|
||||||
@@ -1,82 +0,0 @@
|
|||||||
import { Box, Steps as ChakraSteps } from "@chakra-ui/react"
|
|
||||||
import * as React from "react"
|
|
||||||
import { LuCheck } from "react-icons/lu"
|
|
||||||
|
|
||||||
interface StepInfoProps {
|
|
||||||
title?: React.ReactNode
|
|
||||||
description?: React.ReactNode
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface StepsItemProps
|
|
||||||
extends Omit<ChakraSteps.ItemProps, "title">,
|
|
||||||
StepInfoProps {
|
|
||||||
completedIcon?: React.ReactNode
|
|
||||||
icon?: React.ReactNode
|
|
||||||
}
|
|
||||||
|
|
||||||
export const StepsItem = React.forwardRef<HTMLDivElement, StepsItemProps>(
|
|
||||||
function StepsItem(props, ref) {
|
|
||||||
const { title, description, completedIcon, icon, ...rest } = props
|
|
||||||
return (
|
|
||||||
<ChakraSteps.Item {...rest} ref={ref}>
|
|
||||||
<ChakraSteps.Trigger>
|
|
||||||
<ChakraSteps.Indicator>
|
|
||||||
<ChakraSteps.Status
|
|
||||||
complete={completedIcon || <LuCheck />}
|
|
||||||
incomplete={icon || <ChakraSteps.Number />}
|
|
||||||
/>
|
|
||||||
</ChakraSteps.Indicator>
|
|
||||||
<StepInfo title={title} description={description} />
|
|
||||||
</ChakraSteps.Trigger>
|
|
||||||
<ChakraSteps.Separator />
|
|
||||||
</ChakraSteps.Item>
|
|
||||||
)
|
|
||||||
},
|
|
||||||
)
|
|
||||||
|
|
||||||
const StepInfo = (props: StepInfoProps) => {
|
|
||||||
const { title, description } = props
|
|
||||||
|
|
||||||
if (title && description) {
|
|
||||||
return (
|
|
||||||
<Box>
|
|
||||||
<ChakraSteps.Title>{title}</ChakraSteps.Title>
|
|
||||||
<ChakraSteps.Description>{description}</ChakraSteps.Description>
|
|
||||||
</Box>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
{title && <ChakraSteps.Title>{title}</ChakraSteps.Title>}
|
|
||||||
{description && (
|
|
||||||
<ChakraSteps.Description>{description}</ChakraSteps.Description>
|
|
||||||
)}
|
|
||||||
</>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
interface StepsIndicatorProps {
|
|
||||||
completedIcon: React.ReactNode
|
|
||||||
icon?: React.ReactNode
|
|
||||||
}
|
|
||||||
|
|
||||||
export const StepsIndicator = React.forwardRef<
|
|
||||||
HTMLDivElement,
|
|
||||||
StepsIndicatorProps
|
|
||||||
>(function StepsIndicator(props, ref) {
|
|
||||||
const { icon = <ChakraSteps.Number />, completedIcon } = props
|
|
||||||
return (
|
|
||||||
<ChakraSteps.Indicator ref={ref}>
|
|
||||||
<ChakraSteps.Status complete={completedIcon} incomplete={icon} />
|
|
||||||
</ChakraSteps.Indicator>
|
|
||||||
)
|
|
||||||
})
|
|
||||||
|
|
||||||
export const StepsList = ChakraSteps.List
|
|
||||||
export const StepsRoot = ChakraSteps.Root
|
|
||||||
export const StepsContent = ChakraSteps.Content
|
|
||||||
export const StepsCompletedContent = ChakraSteps.CompletedContent
|
|
||||||
|
|
||||||
export const StepsNextTrigger = ChakraSteps.NextTrigger
|
|
||||||
export const StepsPrevTrigger = ChakraSteps.PrevTrigger
|
|
||||||
@@ -1,39 +0,0 @@
|
|||||||
import { Switch as ChakraSwitch } from "@chakra-ui/react"
|
|
||||||
import * as React from "react"
|
|
||||||
|
|
||||||
export interface SwitchProps extends ChakraSwitch.RootProps {
|
|
||||||
inputProps?: React.InputHTMLAttributes<HTMLInputElement>
|
|
||||||
rootRef?: React.Ref<HTMLLabelElement>
|
|
||||||
trackLabel?: { on: React.ReactNode; off: React.ReactNode }
|
|
||||||
thumbLabel?: { on: React.ReactNode; off: React.ReactNode }
|
|
||||||
}
|
|
||||||
|
|
||||||
export const Switch = React.forwardRef<HTMLInputElement, SwitchProps>(
|
|
||||||
function Switch(props, ref) {
|
|
||||||
const { inputProps, children, rootRef, trackLabel, thumbLabel, ...rest } =
|
|
||||||
props
|
|
||||||
|
|
||||||
return (
|
|
||||||
<ChakraSwitch.Root ref={rootRef} {...rest}>
|
|
||||||
<ChakraSwitch.HiddenInput ref={ref} {...inputProps} />
|
|
||||||
<ChakraSwitch.Control>
|
|
||||||
<ChakraSwitch.Thumb>
|
|
||||||
{thumbLabel && (
|
|
||||||
<ChakraSwitch.ThumbIndicator fallback={thumbLabel?.off}>
|
|
||||||
{thumbLabel?.on}
|
|
||||||
</ChakraSwitch.ThumbIndicator>
|
|
||||||
)}
|
|
||||||
</ChakraSwitch.Thumb>
|
|
||||||
{trackLabel && (
|
|
||||||
<ChakraSwitch.Indicator fallback={trackLabel.off}>
|
|
||||||
{trackLabel.on}
|
|
||||||
</ChakraSwitch.Indicator>
|
|
||||||
)}
|
|
||||||
</ChakraSwitch.Control>
|
|
||||||
{children != null && (
|
|
||||||
<ChakraSwitch.Label>{children}</ChakraSwitch.Label>
|
|
||||||
)}
|
|
||||||
</ChakraSwitch.Root>
|
|
||||||
)
|
|
||||||
},
|
|
||||||
)
|
|
||||||
@@ -1,39 +0,0 @@
|
|||||||
import { Tag as ChakraTag } from "@chakra-ui/react"
|
|
||||||
import * as React from "react"
|
|
||||||
|
|
||||||
export interface TagProps extends ChakraTag.RootProps {
|
|
||||||
startElement?: React.ReactNode
|
|
||||||
endElement?: React.ReactNode
|
|
||||||
onClose?: VoidFunction
|
|
||||||
closable?: boolean
|
|
||||||
}
|
|
||||||
|
|
||||||
export const Tag = React.forwardRef<HTMLSpanElement, TagProps>(
|
|
||||||
function Tag(props, ref) {
|
|
||||||
const {
|
|
||||||
startElement,
|
|
||||||
endElement,
|
|
||||||
onClose,
|
|
||||||
closable = !!onClose,
|
|
||||||
children,
|
|
||||||
...rest
|
|
||||||
} = props
|
|
||||||
|
|
||||||
return (
|
|
||||||
<ChakraTag.Root ref={ref} {...rest}>
|
|
||||||
{startElement && (
|
|
||||||
<ChakraTag.StartElement>{startElement}</ChakraTag.StartElement>
|
|
||||||
)}
|
|
||||||
<ChakraTag.Label>{children}</ChakraTag.Label>
|
|
||||||
{endElement && (
|
|
||||||
<ChakraTag.EndElement>{endElement}</ChakraTag.EndElement>
|
|
||||||
)}
|
|
||||||
{closable && (
|
|
||||||
<ChakraTag.EndElement>
|
|
||||||
<ChakraTag.CloseTrigger onClick={onClose} />
|
|
||||||
</ChakraTag.EndElement>
|
|
||||||
)}
|
|
||||||
</ChakraTag.Root>
|
|
||||||
)
|
|
||||||
},
|
|
||||||
)
|
|
||||||
@@ -1,21 +0,0 @@
|
|||||||
import { Timeline as ChakraTimeline } from "@chakra-ui/react"
|
|
||||||
import * as React from "react"
|
|
||||||
|
|
||||||
export const TimelineConnector = React.forwardRef<
|
|
||||||
HTMLDivElement,
|
|
||||||
ChakraTimeline.IndicatorProps
|
|
||||||
>(function TimelineConnector(props, ref) {
|
|
||||||
return (
|
|
||||||
<ChakraTimeline.Connector ref={ref}>
|
|
||||||
<ChakraTimeline.Separator />
|
|
||||||
<ChakraTimeline.Indicator {...props} />
|
|
||||||
</ChakraTimeline.Connector>
|
|
||||||
)
|
|
||||||
})
|
|
||||||
|
|
||||||
export const TimelineRoot = ChakraTimeline.Root
|
|
||||||
export const TimelineContent = ChakraTimeline.Content
|
|
||||||
export const TimelineItem = ChakraTimeline.Item
|
|
||||||
export const TimelineIndicator = ChakraTimeline.Indicator
|
|
||||||
export const TimelineTitle = ChakraTimeline.Title
|
|
||||||
export const TimelineDescription = ChakraTimeline.Description
|
|
||||||
@@ -1,43 +0,0 @@
|
|||||||
"use client"
|
|
||||||
|
|
||||||
import {
|
|
||||||
Toaster as ChakraToaster,
|
|
||||||
Portal,
|
|
||||||
Spinner,
|
|
||||||
Stack,
|
|
||||||
Toast,
|
|
||||||
createToaster,
|
|
||||||
} from "@chakra-ui/react"
|
|
||||||
|
|
||||||
export const toaster = createToaster({
|
|
||||||
placement: "bottom-end",
|
|
||||||
pauseOnPageIdle: true,
|
|
||||||
})
|
|
||||||
|
|
||||||
export const Toaster = () => {
|
|
||||||
return (
|
|
||||||
<Portal>
|
|
||||||
<ChakraToaster toaster={toaster} insetInline={{ mdDown: "4" }}>
|
|
||||||
{(toast) => (
|
|
||||||
<Toast.Root width={{ md: "sm" }}>
|
|
||||||
{toast.type === "loading" ? (
|
|
||||||
<Spinner size="sm" color="blue.solid" />
|
|
||||||
) : (
|
|
||||||
<Toast.Indicator />
|
|
||||||
)}
|
|
||||||
<Stack gap="1" flex="1" maxWidth="100%">
|
|
||||||
{toast.title && <Toast.Title>{toast.title}</Toast.Title>}
|
|
||||||
{toast.description && (
|
|
||||||
<Toast.Description>{toast.description}</Toast.Description>
|
|
||||||
)}
|
|
||||||
</Stack>
|
|
||||||
{toast.action && (
|
|
||||||
<Toast.ActionTrigger>{toast.action.label}</Toast.ActionTrigger>
|
|
||||||
)}
|
|
||||||
{toast.meta?.closable && <Toast.CloseTrigger />}
|
|
||||||
</Toast.Root>
|
|
||||||
)}
|
|
||||||
</ChakraToaster>
|
|
||||||
</Portal>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
@@ -1,70 +0,0 @@
|
|||||||
import { Popover as ChakraPopover, IconButton, Portal } from "@chakra-ui/react"
|
|
||||||
import * as React from "react"
|
|
||||||
import { HiOutlineInformationCircle } from "react-icons/hi"
|
|
||||||
|
|
||||||
export interface ToggleTipProps extends ChakraPopover.RootProps {
|
|
||||||
showArrow?: boolean
|
|
||||||
portalled?: boolean
|
|
||||||
portalRef?: React.RefObject<HTMLElement>
|
|
||||||
content?: React.ReactNode
|
|
||||||
}
|
|
||||||
|
|
||||||
export const ToggleTip = React.forwardRef<HTMLDivElement, ToggleTipProps>(
|
|
||||||
function ToggleTip(props, ref) {
|
|
||||||
const {
|
|
||||||
showArrow,
|
|
||||||
children,
|
|
||||||
portalled = true,
|
|
||||||
content,
|
|
||||||
portalRef,
|
|
||||||
...rest
|
|
||||||
} = props
|
|
||||||
|
|
||||||
return (
|
|
||||||
<ChakraPopover.Root
|
|
||||||
{...rest}
|
|
||||||
positioning={{ ...rest.positioning, gutter: 4 }}
|
|
||||||
>
|
|
||||||
<ChakraPopover.Trigger asChild>{children}</ChakraPopover.Trigger>
|
|
||||||
<Portal disabled={!portalled} container={portalRef}>
|
|
||||||
<ChakraPopover.Positioner>
|
|
||||||
<ChakraPopover.Content
|
|
||||||
width="auto"
|
|
||||||
px="2"
|
|
||||||
py="1"
|
|
||||||
textStyle="xs"
|
|
||||||
rounded="sm"
|
|
||||||
ref={ref}
|
|
||||||
>
|
|
||||||
{showArrow && (
|
|
||||||
<ChakraPopover.Arrow>
|
|
||||||
<ChakraPopover.ArrowTip />
|
|
||||||
</ChakraPopover.Arrow>
|
|
||||||
)}
|
|
||||||
{content}
|
|
||||||
</ChakraPopover.Content>
|
|
||||||
</ChakraPopover.Positioner>
|
|
||||||
</Portal>
|
|
||||||
</ChakraPopover.Root>
|
|
||||||
)
|
|
||||||
},
|
|
||||||
)
|
|
||||||
|
|
||||||
export const InfoTip = React.forwardRef<
|
|
||||||
HTMLDivElement,
|
|
||||||
Partial<ToggleTipProps>
|
|
||||||
>(function InfoTip(props, ref) {
|
|
||||||
const { children, ...rest } = props
|
|
||||||
return (
|
|
||||||
<ToggleTip content={children} {...rest} ref={ref}>
|
|
||||||
<IconButton
|
|
||||||
variant="ghost"
|
|
||||||
aria-label="info"
|
|
||||||
size="2xs"
|
|
||||||
colorPalette="gray"
|
|
||||||
>
|
|
||||||
<HiOutlineInformationCircle />
|
|
||||||
</IconButton>
|
|
||||||
</ToggleTip>
|
|
||||||
)
|
|
||||||
})
|
|
||||||
@@ -1,57 +0,0 @@
|
|||||||
"use client"
|
|
||||||
|
|
||||||
import type { ButtonProps } from "@chakra-ui/react"
|
|
||||||
import {
|
|
||||||
Button,
|
|
||||||
Toggle as ChakraToggle,
|
|
||||||
useToggleContext,
|
|
||||||
} from "@chakra-ui/react"
|
|
||||||
import * as React from "react"
|
|
||||||
|
|
||||||
interface ToggleProps extends ChakraToggle.RootProps {
|
|
||||||
variant?: keyof typeof variantMap
|
|
||||||
size?: ButtonProps["size"]
|
|
||||||
}
|
|
||||||
|
|
||||||
const variantMap = {
|
|
||||||
solid: { on: "solid", off: "outline" },
|
|
||||||
surface: { on: "surface", off: "outline" },
|
|
||||||
subtle: { on: "subtle", off: "ghost" },
|
|
||||||
ghost: { on: "subtle", off: "ghost" },
|
|
||||||
} as const
|
|
||||||
|
|
||||||
export const Toggle = React.forwardRef<HTMLButtonElement, ToggleProps>(
|
|
||||||
function Toggle(props, ref) {
|
|
||||||
const { variant = "subtle", size, children, ...rest } = props
|
|
||||||
const variantConfig = variantMap[variant]
|
|
||||||
|
|
||||||
return (
|
|
||||||
<ChakraToggle.Root asChild {...rest}>
|
|
||||||
<ToggleBaseButton size={size} variant={variantConfig} ref={ref}>
|
|
||||||
{children}
|
|
||||||
</ToggleBaseButton>
|
|
||||||
</ChakraToggle.Root>
|
|
||||||
)
|
|
||||||
},
|
|
||||||
)
|
|
||||||
|
|
||||||
interface ToggleBaseButtonProps extends Omit<ButtonProps, "variant"> {
|
|
||||||
variant: Record<"on" | "off", ButtonProps["variant"]>
|
|
||||||
}
|
|
||||||
|
|
||||||
const ToggleBaseButton = React.forwardRef<
|
|
||||||
HTMLButtonElement,
|
|
||||||
ToggleBaseButtonProps
|
|
||||||
>(function ToggleBaseButton(props, ref) {
|
|
||||||
const toggle = useToggleContext()
|
|
||||||
const { variant, ...rest } = props
|
|
||||||
return (
|
|
||||||
<Button
|
|
||||||
variant={toggle.pressed ? variant.on : variant.off}
|
|
||||||
ref={ref}
|
|
||||||
{...rest}
|
|
||||||
/>
|
|
||||||
)
|
|
||||||
})
|
|
||||||
|
|
||||||
export const ToggleIndicator = ChakraToggle.Indicator
|
|
||||||
@@ -1,46 +0,0 @@
|
|||||||
import { Tooltip as ChakraTooltip, Portal } from "@chakra-ui/react"
|
|
||||||
import * as React from "react"
|
|
||||||
|
|
||||||
export interface TooltipProps extends ChakraTooltip.RootProps {
|
|
||||||
showArrow?: boolean
|
|
||||||
portalled?: boolean
|
|
||||||
portalRef?: React.RefObject<HTMLElement>
|
|
||||||
content: React.ReactNode
|
|
||||||
contentProps?: ChakraTooltip.ContentProps
|
|
||||||
disabled?: boolean
|
|
||||||
}
|
|
||||||
|
|
||||||
export const Tooltip = React.forwardRef<HTMLDivElement, TooltipProps>(
|
|
||||||
function Tooltip(props, ref) {
|
|
||||||
const {
|
|
||||||
showArrow,
|
|
||||||
children,
|
|
||||||
disabled,
|
|
||||||
portalled,
|
|
||||||
content,
|
|
||||||
contentProps,
|
|
||||||
portalRef,
|
|
||||||
...rest
|
|
||||||
} = props
|
|
||||||
|
|
||||||
if (disabled) return children
|
|
||||||
|
|
||||||
return (
|
|
||||||
<ChakraTooltip.Root {...rest}>
|
|
||||||
<ChakraTooltip.Trigger asChild>{children}</ChakraTooltip.Trigger>
|
|
||||||
<Portal disabled={!portalled} container={portalRef}>
|
|
||||||
<ChakraTooltip.Positioner>
|
|
||||||
<ChakraTooltip.Content ref={ref} {...contentProps}>
|
|
||||||
{showArrow && (
|
|
||||||
<ChakraTooltip.Arrow>
|
|
||||||
<ChakraTooltip.ArrowTip />
|
|
||||||
</ChakraTooltip.Arrow>
|
|
||||||
)}
|
|
||||||
{content}
|
|
||||||
</ChakraTooltip.Content>
|
|
||||||
</ChakraTooltip.Positioner>
|
|
||||||
</Portal>
|
|
||||||
</ChakraTooltip.Root>
|
|
||||||
)
|
|
||||||
},
|
|
||||||
)
|
|
||||||
Reference in New Issue
Block a user