+
{isIndeterminate ?
: isSelected ?
: null}
@@ -89,15 +92,21 @@ const Checkbox = ({ className, ...props }: CheckboxProps) => {
<>
- {props.label ? {props.label} : (props.children as React.ReactNode)}
+ {props.label ? (
+
+ {props.label}
+
+ ) : (
+ (props.children as React.ReactNode)
+ )}
{props.description && {props.description} }
>
)}
- );
-};
+ )
+}
-export { Checkbox, CheckboxGroup };
-export type { CheckboxGroupProps, CheckboxProps };
+export { Checkbox, CheckboxGroup }
+export type { CheckboxGroupProps, CheckboxProps }
diff --git a/resources/js/components/ui/container.tsx b/resources/js/components/ui/container.tsx
index c8caf97..ccc8572 100644
--- a/resources/js/components/ui/container.tsx
+++ b/resources/js/components/ui/container.tsx
@@ -1,26 +1,26 @@
-import { tv } from 'tailwind-variants';
+import { tv } from "tailwind-variants"
const containerStyles = tv({
- base: '@container mx-auto w-full max-w-7xl lg:max-w-(--breakpoint-xl) 2xl:max-w-(--breakpoint-2xl)',
+ base: "@container mx-auto w-full max-w-7xl lg:max-w-(--breakpoint-xl) 2xl:max-w-(--breakpoint-2xl)",
variants: {
intent: {
- constrained: 'sm:px-6 lg:px-8',
- 'padded-content': 'px-4 sm:px-6 lg:px-8'
- }
+ constrained: "sm:px-6 lg:px-8",
+ "padded-content": "px-4 sm:px-6 lg:px-8",
+ },
},
defaultVariants: {
- intent: 'padded-content'
- }
-});
+ intent: "padded-content",
+ },
+})
interface ContainerProps extends React.HTMLAttributes
{
- intent?: 'constrained' | 'padded-content';
- ref?: React.Ref;
+ intent?: "constrained" | "padded-content"
+ ref?: React.Ref
}
const Container = ({ className, intent, ref, ...props }: ContainerProps) => (
-);
+)
-export { Container };
-export type { ContainerProps };
+export { Container }
+export type { ContainerProps }
diff --git a/resources/js/components/ui/dialog.tsx b/resources/js/components/ui/dialog.tsx
index 7f9219c..f3ed909 100644
--- a/resources/js/components/ui/dialog.tsx
+++ b/resources/js/components/ui/dialog.tsx
@@ -1,145 +1,171 @@
-import { useEffect, useRef } from 'react';
+import { useEffect, useRef } from "react"
-import { IconX } from 'justd-icons';
-import type { ButtonProps as ButtonPrimitiveProps, DialogProps, HeadingProps } from 'react-aria-components';
-import { Button as ButtonPrimitive, Dialog as DialogPrimitive, Heading } from 'react-aria-components';
-import { tv } from 'tailwind-variants';
+import { IconX } from "justd-icons"
+import type { HeadingProps } from "react-aria-components"
+import {
+ Button as ButtonPrimitive,
+ Dialog as DialogPrimitive,
+ Heading,
+ Text,
+} from "react-aria-components"
+import { tv } from "tailwind-variants"
-import { useMediaQuery } from '@/utils/use-media-query';
-import { Button, type ButtonProps } from './button';
+import { useMediaQuery } from "@/utils/use-media-query"
+import { Button, type ButtonProps } from "./button"
const dialogStyles = tv({
slots: {
root: [
- 'peer/dialog group/dialog relative flex max-h-[inherit] flex-col overflow-hidden outline-hidden [scrollbar-width:thin] [&::-webkit-scrollbar]:size-0.5'
+ "peer/dialog group/dialog relative flex max-h-[inherit] flex-col overflow-hidden outline-hidden [scrollbar-width:thin] [&::-webkit-scrollbar]:size-0.5",
],
header:
- 'relative flex flex-col gap-0.5 p-4 sm:gap-1 sm:p-6 [&[data-slot=dialog-header]:has(+[data-slot=dialog-footer])]:pb-0',
- description: 'text-muted-fg text-sm',
+ "relative flex flex-col gap-0.5 p-4 sm:gap-1 sm:p-6 [&[data-slot=dialog-header]:has(+[data-slot=dialog-footer])]:pb-0",
+ description: "text-muted-fg text-sm",
body: [
- 'isolate flex flex-1 flex-col overflow-auto px-4 sm:px-6',
- 'max-h-[calc(var(--visual-viewport-height)-var(--visual-viewport-vertical-padding)-var(--dialog-header-height,0px)-var(--dialog-footer-height,0px))]'
+ "isolate flex flex-1 flex-col overflow-auto px-4 py-1 sm:px-6",
+ "max-h-[calc(var(--visual-viewport-height)-var(--visual-viewport-vertical-padding)-var(--dialog-header-height,0px)-var(--dialog-footer-height,0px))]",
],
- footer: 'isolate mt-auto flex flex-col-reverse justify-between gap-3 p-4 sm:flex-row sm:p-6',
+ footer:
+ "isolate mt-auto flex flex-col-reverse justify-between gap-3 p-4 pt-3 sm:flex-row sm:p-6 sm:pt-5",
closeIndicator:
- 'close absolute top-1 right-1 z-50 grid size-8 place-content-center rounded-xl data-focused:bg-secondary data-hovered:bg-secondary data-focused:outline-hidden data-focus-visible:ring-1 data-focus-visible:ring-primary sm:top-2 sm:right-2 sm:size-7 sm:rounded-md'
- }
-});
-
-const { root, header, description, body, footer, closeIndicator } = dialogStyles();
-
-const Dialog = ({ role, className, ...props }: DialogProps) => {
- return ;
-};
+ "close absolute top-1 right-1 z-50 grid size-8 place-content-center rounded-xl data-focused:bg-secondary data-hovered:bg-secondary data-focused:outline-hidden data-focus-visible:ring-1 data-focus-visible:ring-primary sm:top-2 sm:right-2 sm:size-7 sm:rounded-md",
+ },
+})
+
+const { root, header, description, body, footer, closeIndicator } = dialogStyles()
+
+const Dialog = ({
+ role = "dialog",
+ className,
+ ...props
+}: React.ComponentProps) => {
+ return
+}
-const Trigger = (props: ButtonPrimitiveProps) => ;
+const Trigger = (props: React.ComponentProps) => (
+
+)
type DialogHeaderProps = React.HTMLAttributes & {
- title?: string;
- description?: string;
-};
+ title?: string
+ description?: string
+}
const Header = ({ className, ...props }: DialogHeaderProps) => {
- const headerRef = useRef(null);
+ const headerRef = useRef(null)
useEffect(() => {
- const header = headerRef.current;
+ const header = headerRef.current
if (!header) {
- return;
+ return
}
const observer = new ResizeObserver((entries) => {
for (const entry of entries) {
- header.parentElement?.style.setProperty('--dialog-header-height', `${entry.target.clientHeight}px`);
+ header.parentElement?.style.setProperty(
+ "--dialog-header-height",
+ `${entry.target.clientHeight}px`,
+ )
}
- });
+ })
- observer.observe(header);
- return () => observer.unobserve(header);
- }, []);
+ observer.observe(header)
+ return () => observer.unobserve(header)
+ }, [])
return (
{props.title &&
{props.title} }
{props.description && {props.description} }
- {!props.title && typeof props.children === 'string' ? : props.children}
+ {!props.title && typeof props.children === "string" ? : props.children}
- );
-};
+ )
+}
const titleStyles = tv({
- base: 'flex flex-1 items-center text-fg',
+ base: "flex flex-1 items-center text-fg",
variants: {
level: {
- 1: 'font-semibold text-lg sm:text-xl',
- 2: 'font-semibold text-lg sm:text-xl',
- 3: 'font-semibold text-base sm:text-lg',
- 4: 'font-semibold text-base'
- }
- }
-});
-
-interface DialogTitleProps extends Omit {
- level?: 1 | 2 | 3 | 4;
- ref?: React.Ref;
+ 1: "font-semibold text-lg sm:text-xl",
+ 2: "font-semibold text-lg sm:text-xl",
+ 3: "font-semibold text-base sm:text-lg",
+ 4: "font-semibold text-base",
+ },
+ },
+})
+
+interface DialogTitleProps extends Omit {
+ level?: 1 | 2 | 3 | 4
+ ref?: React.Ref
}
const Title = ({ level = 2, className, ref, ...props }: DialogTitleProps) => (
-
-);
-
-type DialogDescriptionProps = React.ComponentProps<'div'>;
+
+)
+
+type DialogDescriptionProps = React.ComponentProps<"div">
const Description = ({ className, ref, ...props }: DialogDescriptionProps) => (
-
-);
+
+)
-type DialogBodyProps = React.ComponentProps<'div'>;
+type DialogBodyProps = React.ComponentProps<"div">
const Body = ({ className, ref, ...props }: DialogBodyProps) => (
-);
+)
-type DialogFooterProps = React.ComponentProps<'div'>;
+type DialogFooterProps = React.ComponentProps<"div">
const Footer = ({ className, ...props }: DialogFooterProps) => {
- const footerRef = useRef(null);
+ const footerRef = useRef(null)
useEffect(() => {
- const footer = footerRef.current;
+ const footer = footerRef.current
if (!footer) {
- return;
+ return
}
const observer = new ResizeObserver((entries) => {
for (const entry of entries) {
- footer.parentElement?.style.setProperty('--dialog-footer-height', `${entry.target.clientHeight}px`);
+ footer.parentElement?.style.setProperty(
+ "--dialog-footer-height",
+ `${entry.target.clientHeight}px`,
+ )
}
- });
+ })
- observer.observe(footer);
+ observer.observe(footer)
return () => {
- observer.unobserve(footer);
- };
- }, []);
- return
;
-};
+ observer.unobserve(footer)
+ }
+ }, [])
+ return (
+
+ )
+}
-const Close = ({ className, appearance = 'outline', ref, ...props }: ButtonProps) => {
- return ;
-};
+const Close = ({ className, appearance = "outline", ref, ...props }: ButtonProps) => {
+ return
+}
interface CloseButtonIndicatorProps extends ButtonProps {
- className?: string;
- isDismissable?: boolean | undefined;
+ className?: string
+ isDismissable?: boolean | undefined
}
const CloseIndicator = ({ className, ...props }: CloseButtonIndicatorProps) => {
- const isMobile = useMediaQuery('(max-width: 600px)');
- const buttonRef = useRef(null);
+ const isMobile = useMediaQuery("(max-width: 600px)")
+ const buttonRef = useRef(null)
useEffect(() => {
if (isMobile && buttonRef.current) {
- buttonRef.current.focus();
+ buttonRef.current.focus()
}
- }, [isMobile]);
+ }, [isMobile])
return props.isDismissable ? (
{
>
- ) : null;
-};
-
-Dialog.Trigger = Trigger;
-Dialog.Header = Header;
-Dialog.Title = Title;
-Dialog.Description = Description;
-Dialog.Body = Body;
-Dialog.Footer = Footer;
-Dialog.Close = Close;
-Dialog.CloseIndicator = CloseIndicator;
-
-export { Dialog };
+ ) : null
+}
+
+Dialog.Trigger = Trigger
+Dialog.Header = Header
+Dialog.Title = Title
+Dialog.Description = Description
+Dialog.Body = Body
+Dialog.Footer = Footer
+Dialog.Close = Close
+Dialog.CloseIndicator = CloseIndicator
+
+export { Dialog }
export type {
CloseButtonIndicatorProps,
DialogBodyProps,
DialogDescriptionProps,
DialogFooterProps,
DialogHeaderProps,
- DialogTitleProps
-};
+ DialogTitleProps,
+}
diff --git a/resources/js/components/ui/dropdown.tsx b/resources/js/components/ui/dropdown.tsx
index 4898dfa..6229f78 100644
--- a/resources/js/components/ui/dropdown.tsx
+++ b/resources/js/components/ui/dropdown.tsx
@@ -1,8 +1,7 @@
-import { cn } from '@/utils/classes';
-import { IconCheck } from 'justd-icons';
+import { cn } from "@/utils/classes"
+import { IconCheck } from "justd-icons"
import {
Collection,
- composeRenderProps,
Header,
ListBoxItem as ListBoxItemPrimitive,
type ListBoxItemProps,
@@ -11,107 +10,122 @@ import {
Separator,
type SeparatorProps,
Text,
- type TextProps
-} from 'react-aria-components';
-import { tv } from 'tailwind-variants';
-import { Keyboard } from './keyboard';
+ type TextProps,
+ composeRenderProps,
+} from "react-aria-components"
+import { tv } from "tailwind-variants"
+import { Keyboard } from "./keyboard"
const dropdownItemStyles = tv({
base: [
- 'col-span-full grid grid-cols-[auto_1fr_1.5rem_0.5rem_auto] not-has-data-[slot=dropdown-item-details]:items-center has-data-[slot=dropdown-item-details]:**:data-[slot=checked-icon]:mt-[1.5px] supports-[grid-template-columns:subgrid]:grid-cols-subgrid',
- 'group relative cursor-default select-none rounded-[calc(var(--radius-lg)-1px)] px-[calc(var(--spacing)*2.3)] py-[calc(var(--spacing)*1.3)] forced-color:text-[Highlight] text-base text-fg outline-0 forced-color-adjust-none sm:text-sm/6 forced-colors:text-[LinkText]',
- '**:data-[slot=avatar]:*:mr-2 **:data-[slot=avatar]:*:size-6 **:data-[slot=avatar]:mr-2 **:data-[slot=avatar]:size-6 sm:**:data-[slot=avatar]:*:size-5 sm:**:data-[slot=avatar]:size-5',
- 'data-danger:**:data-[slot=icon]:text-danger/60 **:data-[slot=icon]:size-4 **:data-[slot=icon]:shrink-0 **:data-[slot=icon]:text-muted-fg data-focused:data-danger:**:data-[slot=icon]:text-danger',
- 'data-[slot=menu-radio]:*:data-[slot=icon]:size-3 *:data-[slot=icon]:mr-2',
- 'forced-colors:**:data-[slot=icon]:text-[CanvasText] forced-colors:group-data-focused:**:data-[slot=icon]:text-[Canvas] ',
- '[&>[slot=label]+[data-slot=icon]]:absolute [&>[slot=label]+[data-slot=icon]]:right-0'
+ "col-span-full grid grid-cols-[auto_1fr_1.5rem_0.5rem_auto] not-has-data-[slot=dropdown-item-details]:items-center has-data-[slot=dropdown-item-details]:**:data-[slot=checked-icon]:mt-[1.5px] supports-[grid-template-columns:subgrid]:grid-cols-subgrid",
+ "group relative cursor-default select-none rounded-[calc(var(--radius-lg)-1px)] px-[calc(var(--spacing)*2.3)] py-[calc(var(--spacing)*1.3)] forced-color:text-[Highlight] text-base text-fg outline-0 forced-color-adjust-none sm:text-sm/6 forced-colors:text-[LinkText]",
+ "**:data-[slot=avatar]:*:mr-2 **:data-[slot=avatar]:*:size-6 **:data-[slot=avatar]:mr-2 **:data-[slot=avatar]:size-6 sm:**:data-[slot=avatar]:*:size-5 sm:**:data-[slot=avatar]:size-5",
+ "data-danger:**:data-[slot=icon]:text-danger/60 **:data-[slot=icon]:size-4 **:data-[slot=icon]:shrink-0 **:data-[slot=icon]:text-muted-fg data-focused:data-danger:**:data-[slot=icon]:text-danger",
+ "data-[slot=menu-radio]:*:data-[slot=icon]:size-3 *:data-[slot=icon]:mr-2",
+ "forced-colors:**:data-[slot=icon]:text-[CanvasText] forced-colors:group-data-focused:**:data-[slot=icon]:text-[Canvas] ",
+ "[&>[slot=label]+[data-slot=icon]]:absolute [&>[slot=label]+[data-slot=icon]]:right-0",
],
variants: {
isDisabled: {
- true: 'text-muted-fg forced-colors:text-[GrayText]'
+ true: "text-muted-fg forced-colors:text-[GrayText]",
},
isSelected: {
- true: '**:data-[slot=avatar]:*:hidden **:data-[slot=avatar]:hidden **:data-[slot=icon]:hidden'
+ true: "**:data-[slot=avatar]:*:hidden **:data-[slot=avatar]:hidden **:data-[slot=icon]:hidden",
},
isFocused: {
- false: 'data-danger:text-danger',
+ false: "data-danger:text-danger",
true: [
- '**:data-[slot=icon]:text-accent-fg **:[kbd]:text-accent-fg',
- 'bg-accent text-accent-fg forced-colors:bg-[Highlight] forced-colors:text-[HighlightText]',
- 'data-danger:bg-danger/10 data-danger:text-danger',
- 'data-[slot=description]:text-accent-fg data-[slot=label]:text-accent-fg [&_.text-muted-fg]:text-accent-fg/80'
- ]
- }
- }
-});
+ "**:data-[slot=icon]:text-accent-fg **:[kbd]:text-accent-fg",
+ "bg-accent text-accent-fg forced-colors:bg-[Highlight] forced-colors:text-[HighlightText]",
+ "data-danger:bg-danger/10 data-danger:text-danger",
+ "data-[slot=description]:text-accent-fg data-[slot=label]:text-accent-fg [&_.text-muted-fg]:text-accent-fg/80",
+ ],
+ },
+ },
+})
const dropdownSectionStyles = tv({
slots: {
- section: 'col-span-full grid grid-cols-[auto_1fr]',
- header: 'col-span-full px-2.5 py-1 font-medium text-muted-fg text-sm sm:text-xs'
- }
-});
+ section: "col-span-full grid grid-cols-[auto_1fr]",
+ header: "col-span-full px-2.5 py-1 font-medium text-muted-fg text-sm sm:text-xs",
+ },
+})
-const { section, header } = dropdownSectionStyles();
+const { section, header } = dropdownSectionStyles()
interface DropdownSectionProps extends SectionProps {
- title?: string;
+ title?: string
}
const DropdownSection = ({ className, ...props }: DropdownSectionProps) => {
return (
- {'title' in props && }
+ {"title" in props && }
{props.children}
- );
-};
+ )
+}
-type DropdownItemProps = ListBoxItemProps;
+type DropdownItemProps = ListBoxItemProps
const DropdownItem = ({ className, ...props }: DropdownItemProps) => {
- const textValue = props.textValue || (typeof props.children === 'string' ? props.children : undefined);
+ const textValue =
+ props.textValue || (typeof props.children === "string" ? props.children : undefined)
return (
- dropdownItemStyles({ ...renderProps, className })
+ dropdownItemStyles({ ...renderProps, className }),
)}
{...props}
>
{composeRenderProps(props.children, (children, { isSelected }) => (
<>
{isSelected && }
- {typeof children === 'string' ? {children} : children}
+ {typeof children === "string" ? {children} : children}
>
))}
- );
-};
+ )
+}
interface DropdownItemDetailProps extends TextProps {
- label?: TextProps['children'];
- description?: TextProps['children'];
+ label?: TextProps["children"]
+ description?: TextProps["children"]
classNames?: {
- label?: TextProps['className'];
- description?: TextProps['className'];
- };
+ label?: TextProps["className"]
+ description?: TextProps["className"]
+ }
}
-const DropdownItemDetails = ({ label, description, classNames, ...props }: DropdownItemDetailProps) => {
- const { slot, children, title, ...restProps } = props;
+const DropdownItemDetails = ({
+ label,
+ description,
+ classNames,
+ ...props
+}: DropdownItemDetailProps) => {
+ const { slot, children, title, ...restProps } = props
return (
-
+
{label && (
-
+
{label}
)}
{description && (
{description}
@@ -119,24 +133,28 @@ const DropdownItemDetails = ({ label, description, classNames, ...props }: Dropd
)}
{!title && children}
- );
-};
+ )
+}
interface MenuLabelProps extends TextProps {
- ref?: React.Ref
;
+ ref?: React.Ref
}
const DropdownLabel = ({ className, ref, ...props }: MenuLabelProps) => (
-
-);
+
+)
const DropdownSeparator = ({ className, ...props }: SeparatorProps) => (
-
-);
+
+)
const DropdownKeyboard = ({ className, ...props }: React.ComponentProps) => {
- return ;
-};
+ return
+}
/**
* Note: This is not exposed component, but it's used in other components to render dropdowns.
@@ -145,11 +163,11 @@ const DropdownKeyboard = ({ className, ...props }: React.ComponentProps string);
- 'aria-label'?: TextFieldPrimitiveProps['aria-label'];
- 'aria-labelledby'?: TextFieldPrimitiveProps['aria-labelledby'];
+ label?: string
+ placeholder?: string
+ description?: string
+ errorMessage?: string | ((validation: ValidationResult) => string)
+ "aria-label"?: TextFieldPrimitiveProps["aria-label"]
+ "aria-labelledby"?: TextFieldPrimitiveProps["aria-labelledby"]
}
const fieldStyles = tv({
slots: {
- description: 'text-pretty text-muted-fg text-sm/6',
- label: 'w-fit cursor-default font-medium text-secondary-fg text-sm',
- fieldError: 'text-danger text-sm/6 forced-colors:text-[Mark]',
- input: [
- 'w-full min-w-0 bg-transparent px-2.5 py-2 text-base text-fg placeholder-muted-fg outline-hidden data-focused:outline-hidden sm:text-sm [&::-ms-reveal]:hidden'
- ]
- }
-});
+ description: "text-pretty text-muted-fg text-sm/6",
+ label: "w-fit cursor-default font-medium text-secondary-fg text-sm/6",
+ fieldError: "text-danger text-sm/6 forced-colors:text-[Mark]",
+ },
+})
-const { description, label, fieldError, input } = fieldStyles();
+const { description, label, fieldError } = fieldStyles()
const Label = ({ className, ...props }: LabelProps) => {
- return ;
-};
+ return
+}
interface DescriptionProps extends TextProps {
- isWarning?: boolean;
- ref?: React.RefObject;
+ isWarning?: boolean
+ ref?: React.RefObject
}
const Description = ({ ref, className, ...props }: DescriptionProps) => {
- const isWarning = props.isWarning ?? false;
+ const isWarning = props.isWarning ?? false
return (
- );
-};
+ )
+}
interface FieldErrorProps extends FieldErrorPrimitiveProps {
- ref?: React.RefObject;
+ ref?: React.RefObject
}
const FieldError = ({ className, ref, ...props }: FieldErrorProps) => {
- return ;
-};
+ return (
+
+ )
+}
const fieldGroupStyles = tv({
base: [
- 'group flex h-10 items-center overflow-hidden rounded-lg border border-input transition duration-200 ease-out',
- 'focus-within:ring-4 group-data-invalid:focus-within:border-danger group-data-invalid:focus-within:ring-danger/20',
- '[&>[role=progressbar]]:mr-2.5',
- '**:data-[slot=icon]:size-4 **:data-[slot=icon]:shrink-0',
- '*:data-[slot=suffix]:mr-2.5 *:data-[slot=suffix]:text-muted-fg',
- '*:data-[slot=prefix]:ml-2.5 *:data-[slot=prefix]:text-muted-fg'
+ "group flex h-10 items-center overflow-hidden rounded-lg border border-input shadow-xs transition duration-200 ease-out",
+ "relative focus-within:ring-4 group-data-invalid:focus-within:border-danger group-data-invalid:focus-within:ring-danger/20",
+ "[&>[role=progressbar]:first-child]:ml-2.5 [&>[role=progressbar]:last-child]:mr-2.5",
+ "**:data-[slot=icon]:size-4 **:data-[slot=icon]:shrink-0 **:[button]:shrink-0",
+ "[&>button:has([data-slot=icon]):first-child]:left-0 [&>button:has([data-slot=icon]):last-child]:right-0 [&>button:has([data-slot=icon])]:absolute",
+ "*:data-[slot=icon]:pointer-events-none *:data-[slot=icon]:absolute *:data-[slot=icon]:top-[calc(var(--spacing)*2.7)] *:data-[slot=icon]:z-10 *:data-[slot=icon]:size-4 *:data-[slot=icon]:text-muted-fg",
+ "[&>[data-slot=icon]:first-child]:left-2.5 [&>[data-slot=icon]:last-child]:right-2.5",
+ "[&:has([data-slot=icon]+input)]:pl-6 [&:has(input+[data-slot=icon])]:pr-6",
+ "[&:has([data-slot=icon]+[role=group])]:pl-6 [&:has([role=group]+[data-slot=icon])]:pr-6",
+ "has-[[data-slot=icon]:last-child]:[&_input]:pr-7",
+ "*:[button]:h-8 *:[button]:rounded-[calc(var(--radius-sm)-1px)] *:[button]:px-2.5",
+ "[&>button:first-child]:ml-[calc(var(--spacing)*0.7)] [&>button:last-child]:mr-[calc(var(--spacing)*0.7)]",
],
variants: {
isFocusWithin: focusStyles.variants.isFocused,
isInvalid: focusStyles.variants.isInvalid,
isDisabled: {
- true: 'opacity-50 forced-colors:border-[GrayText]'
- }
- }
-});
+ true: "opacity-50 forced-colors:border-[GrayText]",
+ },
+ },
+})
const FieldGroup = ({ className, ...props }: GroupProps) => {
return (
@@ -94,19 +103,29 @@ const FieldGroup = ({ className, ...props }: GroupProps) => {
className={composeRenderProps(className, (className, renderProps) =>
fieldGroupStyles({
...renderProps,
- className
- })
+ className,
+ }),
)}
/>
- );
-};
+ )
+}
interface InputProps extends InputPrimitiveProps {
- ref?: React.RefObject;
+ ref?: React.RefObject
}
+
const Input = ({ className, ref, ...props }: InputProps) => {
- return ;
-};
+ return (
+
+ )
+}
-export { Description, FieldError, FieldGroup, Input, Label };
-export type { FieldErrorProps, FieldProps, InputProps };
+export { Description, FieldError, FieldGroup, Input, Label }
+export type { FieldErrorProps, FieldProps, InputProps }
diff --git a/resources/js/components/ui/form.tsx b/resources/js/components/ui/form.tsx
index 5ec069d..be50876 100644
--- a/resources/js/components/ui/form.tsx
+++ b/resources/js/components/ui/form.tsx
@@ -1,12 +1,12 @@
-import type { FormProps as FormPrimitiveProps } from 'react-aria-components';
-import { Form as FormPrimitive } from 'react-aria-components';
+import type { FormProps as FormPrimitiveProps } from "react-aria-components"
+import { Form as FormPrimitive } from "react-aria-components"
interface FormProps extends FormPrimitiveProps {
- ref?: React.RefObject;
+ ref?: React.RefObject
}
const Form = ({ ref, ...props }: FormProps) => {
- return ;
-};
+ return
+}
-export { Form };
-export type { FormProps };
+export { Form }
+export type { FormProps }
diff --git a/resources/js/components/ui/heading.tsx b/resources/js/components/ui/heading.tsx
index 33aea73..77e0b6c 100644
--- a/resources/js/components/ui/heading.tsx
+++ b/resources/js/components/ui/heading.tsx
@@ -1,44 +1,46 @@
-import { tv } from 'tailwind-variants';
+import { tv } from "tailwind-variants"
const headingStyles = tv({
- base: 'font-sans text-fg tracking-tight',
+ base: "font-sans text-fg tracking-tight",
variants: {
level: {
- 1: 'font-bold text-xl sm:text-2xl',
- 2: 'font-semibold text-lg sm:text-xl',
- 3: 'font-semibold text-base sm:text-lg',
- 4: 'font-semibold text-base'
+ 1: "font-bold text-xl sm:text-2xl",
+ 2: "font-semibold text-lg sm:text-xl",
+ 3: "font-semibold text-base sm:text-lg",
+ 4: "font-semibold text-base",
},
tracking: {
- tighter: 'tracking-tighter',
- tight: 'tracking-tight',
- normal: 'tracking-normal',
- wide: 'tracking-wide',
- wider: 'tracking-wider',
- widest: 'tracking-widest'
- }
- }
-});
-type HeadingType = { level?: 1 | 2 | 3 | 4 } & React.ComponentPropsWithoutRef<'h1' | 'h2' | 'h3' | 'h4'>;
+ tighter: "tracking-tighter",
+ tight: "tracking-tight",
+ normal: "tracking-normal",
+ wide: "tracking-wide",
+ wider: "tracking-wider",
+ widest: "tracking-widest",
+ },
+ },
+})
+type HeadingType = { level?: 1 | 2 | 3 | 4 } & React.ComponentPropsWithoutRef<
+ "h1" | "h2" | "h3" | "h4"
+>
interface HeadingProps extends HeadingType {
- tracking?: 'tighter' | 'tight' | 'normal' | 'wide' | 'wider' | 'widest';
- className?: string | undefined;
+ tracking?: "tighter" | "tight" | "normal" | "wide" | "wider" | "widest"
+ className?: string | undefined
}
-const Heading = ({ className, tracking = 'normal', level = 1, ...props }: HeadingProps) => {
- const Element: `h${typeof level}` = `h${level}`;
+const Heading = ({ className, tracking = "normal", level = 1, ...props }: HeadingProps) => {
+ const Element: `h${typeof level}` = `h${level}`
return (
- );
-};
+ )
+}
-export { Heading };
-export type { HeadingProps };
+export { Heading }
+export type { HeadingProps }
diff --git a/resources/js/components/ui/index.ts b/resources/js/components/ui/index.ts
index 01a66c0..52678ab 100644
--- a/resources/js/components/ui/index.ts
+++ b/resources/js/components/ui/index.ts
@@ -1,27 +1,27 @@
-export * from './avatar';
-export * from './button';
-export * from './card';
-export * from './checkbox';
-export * from './container';
-export * from './dialog';
-export * from './dropdown';
-export * from './field';
-export * from './form';
-export * from './heading';
-export * from './keyboard';
-export * from './link';
-export * from './list-box';
-export * from './loader';
-export * from './menu';
-export * from './modal';
-export * from './navbar';
-export * from './pagination';
-export * from './popover';
-export * from './primitive';
-export * from './select';
-export * from './separator';
-export * from './sheet';
-export * from './table';
-export * from './text-field';
-export * from './toast';
-export * from './visually-hidden';
+export * from "./avatar"
+export * from "./button"
+export * from "./card"
+export * from "./checkbox"
+export * from "./container"
+export * from "./dialog"
+export * from "./dropdown"
+export * from "./field"
+export * from "./form"
+export * from "./heading"
+export * from "./keyboard"
+export * from "./link"
+export * from "./list-box"
+export * from "./loader"
+export * from "./menu"
+export * from "./modal"
+export * from "./navbar"
+export * from "./pagination"
+export * from "./popover"
+export * from "./primitive"
+export * from "./select"
+export * from "./separator"
+export * from "./sheet"
+export * from "./table"
+export * from "./text-field"
+export * from "./toast"
+export * from "./visually-hidden"
diff --git a/resources/js/components/ui/keyboard.tsx b/resources/js/components/ui/keyboard.tsx
index 1006390..ed46ef6 100644
--- a/resources/js/components/ui/keyboard.tsx
+++ b/resources/js/components/ui/keyboard.tsx
@@ -1,34 +1,37 @@
-import { Keyboard as KeyboardPrimitive } from 'react-aria-components';
-import { tv } from 'tailwind-variants';
+import { Keyboard as KeyboardPrimitive } from "react-aria-components"
+import { tv } from "tailwind-variants"
const keyboardStyles = tv({
slots: {
- base: 'hidden text-current/70 group-data-focused:text-fg group-data-hovered:text-fg group-data-disabled:opacity-50 group-data-focused:opacity-90 lg:inline-flex lg:inline-flex forced-colors:group-data-focused:text-[HighlightText]',
- kbd: 'inline-grid min-h-5 min-w-[2ch] place-content-center rounded text-center font-sans text-[.75rem] uppercase'
- }
-});
+ base: "hidden text-current/70 group-data-focused:text-fg group-data-hovered:text-fg group-data-disabled:opacity-50 group-data-focused:opacity-90 lg:inline-flex forced-colors:group-data-focused:text-[HighlightText]",
+ kbd: "inline-grid min-h-5 min-w-[2ch] place-content-center rounded text-center font-sans text-[.75rem] uppercase",
+ },
+})
-const { base, kbd } = keyboardStyles();
+const { base, kbd } = keyboardStyles()
interface KeyboardProps extends React.HTMLAttributes {
- keys: string | string[];
+ keys: string | string[]
classNames?: {
- base?: string;
- kbd?: string;
- };
+ base?: string
+ kbd?: string
+ }
}
const Keyboard = ({ keys, classNames, className, ...props }: KeyboardProps) => {
return (
- {(Array.isArray(keys) ? keys : keys.split('')).map((char, index) => (
- 0 && char.length > 1 ? 'pl-1' : classNames?.kbd })}>
+ {(Array.isArray(keys) ? keys : keys.split("")).map((char, index) => (
+ 0 && char.length > 1 ? "pl-1" : classNames?.kbd })}
+ >
{char}
))}
- );
-};
+ )
+}
-export { Keyboard };
-export type { KeyboardProps };
+export { Keyboard }
+export type { KeyboardProps }
diff --git a/resources/js/components/ui/link.tsx b/resources/js/components/ui/link.tsx
index 117e0b1..1881a21 100644
--- a/resources/js/components/ui/link.tsx
+++ b/resources/js/components/ui/link.tsx
@@ -1,26 +1,30 @@
-import { composeRenderProps, Link as LinkPrimitive, type LinkProps as LinkPrimitiveProps } from 'react-aria-components';
-import { tv } from 'tailwind-variants';
+import {
+ Link as LinkPrimitive,
+ type LinkProps as LinkPrimitiveProps,
+ composeRenderProps,
+} from "react-aria-components"
+import { tv } from "tailwind-variants"
-import { focusButtonStyles } from './primitive';
+import { focusButtonStyles } from "./primitive"
const linkStyles = tv({
extend: focusButtonStyles,
- base: 'transition-[color,_opacity] data-disabled:cursor-default data-disabled:opacity-60 forced-colors:data-disabled:text-[GrayText]',
+ base: "transition-[color,_opacity] data-disabled:cursor-default data-disabled:opacity-60 forced-colors:data-disabled:text-[GrayText]",
variants: {
intent: {
- unstyled: 'text-current',
- primary: 'text-fg data-hovered:underline',
- secondary: 'text-muted-fg data-hovered:text-secondary-fg'
- }
+ unstyled: "text-current",
+ primary: "text-fg data-hovered:underline",
+ secondary: "text-muted-fg data-hovered:text-secondary-fg",
+ },
},
defaultVariants: {
- intent: 'unstyled'
- }
-});
+ intent: "unstyled",
+ },
+})
interface LinkProps extends LinkPrimitiveProps {
- intent?: 'primary' | 'secondary' | 'unstyled';
- ref?: React.RefObject;
+ intent?: "primary" | "secondary" | "unstyled"
+ ref?: React.RefObject
}
const Link = ({ className, ref, ...props }: LinkProps) => {
@@ -29,13 +33,15 @@ const Link = ({ className, ref, ...props }: LinkProps) => {
ref={ref}
{...props}
className={composeRenderProps(className, (className, renderProps) =>
- linkStyles({ ...renderProps, intent: props.intent, className })
+ linkStyles({ ...renderProps, intent: props.intent, className }),
)}
>
- {(values) => <>{typeof props.children === 'function' ? props.children(values) : props.children}>}
+ {(values) => (
+ <>{typeof props.children === "function" ? props.children(values) : props.children}>
+ )}
- );
-};
+ )
+}
-export { Link };
-export type { LinkProps };
+export { Link, linkStyles }
+export type { LinkProps }
diff --git a/resources/js/components/ui/list-box.tsx b/resources/js/components/ui/list-box.tsx
index 1e460ea..bc8783f 100644
--- a/resources/js/components/ui/list-box.tsx
+++ b/resources/js/components/ui/list-box.tsx
@@ -1,114 +1,104 @@
-import { IconCheck, IconHamburger } from 'justd-icons';
-import type { ListBoxItemProps as ListBoxItemPrimitiveProps, ListBoxProps } from 'react-aria-components';
-import { composeRenderProps, ListBoxItem, ListBox as ListBoxPrimitive } from 'react-aria-components';
-import { tv } from 'tailwind-variants';
+import { IconCheck, IconHamburger } from "justd-icons"
+import type {
+ ListBoxItemProps as ListBoxItemPrimitiveProps,
+ ListBoxProps,
+} from "react-aria-components"
+import {
+ ListBoxItem as ListBoxItemPrimitive,
+ ListBox as ListBoxPrimitive,
+ composeRenderProps,
+} from "react-aria-components"
-import { cn } from '@/utils/classes';
-import { DropdownItemDetails, DropdownSection } from './dropdown';
-import { composeTailwindRenderProps } from './primitive';
-
-const listBoxStyles = tv({
- base: 'flex max-h-96 w-full min-w-56 flex-col gap-y-1 overflow-y-auto rounded-xl border p-1 shadow-lg outline-hidden [scrollbar-width:thin] [&::-webkit-scrollbar]:size-0.5'
-});
+import { cn } from "@/utils/classes"
+import { DropdownItemDetails, DropdownLabel, DropdownSection, dropdownItemStyles } from "./dropdown"
const ListBox = ({ className, ...props }: ListBoxProps) => (
listBoxStyles({ ...renderProps, className }))}
+ className={composeRenderProps(className, (className) =>
+ cn(
+ [
+ "flex max-h-96 w-full min-w-56 flex-col gap-y-1 overflow-y-auto rounded-xl border p-1 shadow-lg outline-hidden [scrollbar-width:thin] [&::-webkit-scrollbar]:size-0.5",
+ "grid grid-cols-[auto_1fr] overflow-auto *:[[role='group']+[role=group]]:mt-4 *:[[role='group']+[role=separator]]:mt-1",
+ ],
+ className,
+ ),
+ )}
/>
-);
+)
-const listBoxItemStyles = tv({
- base: 'lbi relative cursor-pointer rounded-[calc(var(--radius-lg)-1px)] p-2 text-base outline-hidden sm:text-sm',
- variants: {
- isFocusVisible: {
- true: 'bg-secondary text-accent-fg text-accent-fg/70'
- },
- isHovered: {
- true: 'bg-accent text-accent-fg [&:hover_[slot=description]]:text-accent-fg/70 [&:hover_[slot=label]]:text-accent-fg [&_.text-muted-fg]:text-accent-fg/80'
- },
- isFocused: {
- true: 'bg-accent text-accent-fg **:data-[slot=icon]:text-accent-fg **:data-[slot=label]:text-accent-fg [&_.text-muted-fg]:text-accent-fg/80'
- },
- isSelected: {
- true: 'bg-accent text-accent-fg **:data-[slot=icon]:text-accent-fg **:data-[slot=label]:text-accent-fg [&_.text-muted-fg]:text-accent-fg/80'
- },
- isDragging: { true: 'cursor-grabbing bg-secondary text-secondary-fg' },
- isDisabled: {
- true: 'cursor-default text-muted-fg opacity-70'
- }
- }
-});
+// const listBoxItemStyles = tv({
+// base: "lbi col-span-full relative cursor-pointer rounded-[calc(var(--radius-lg)-1px)] p-2 text-base outline-hidden sm:text-sm",
+// variants: {
+// isFocusVisible: {
+// true: "bg-secondary text-accent-fg",
+// },
+// isHovered: {
+// true: "bg-accent text-accent-fg [&:hover_[slot=description]]:text-accent-fg/70 [&:hover_[slot=label]]:text-accent-fg [&_.text-muted-fg]:text-accent-fg/80",
+// },
+// isFocused: {
+// true: "bg-accent text-accent-fg **:data-[slot=icon]:text-accent-fg **:data-[slot=label]:text-accent-fg [&_.text-muted-fg]:text-accent-fg/80",
+// },
+// isSelected: {
+// true: "bg-accent text-accent-fg **:data-[slot=icon]:text-accent-fg **:data-[slot=label]:text-accent-fg [&_.text-muted-fg]:text-accent-fg/80",
+// },
+// isDragging: { true: "cursor-grabbing bg-secondary text-secondary-fg" },
+// isDisabled: {
+// true: "cursor-default text-muted-fg opacity-70",
+// },
+// },
+// })
interface ListBoxItemProps extends ListBoxItemPrimitiveProps {
- className?: string;
+ className?: string
}
-const Item = ({ children, className, ...props }: ListBoxItemProps) => {
- const textValue = typeof children === 'string' ? children : undefined;
+const ListBoxItem = ({ children, className, ...props }: ListBoxItemProps) => {
+ const textValue = typeof children === "string" ? children : undefined
return (
-
- listBoxItemStyles({
+ dropdownItemStyles({
...renderProps,
- className
- })
+ className,
+ }),
)}
>
- {(values) => (
-
- <>
- {values.allowsDragging && (
-
- )}
-
- {typeof children === 'function' ? children(values) : children}
-
- {values.isSelected && (
-
-
-
+ {({ allowsDragging, isSelected, isFocused, isDragging }) => (
+ <>
+ {allowsDragging && (
+
- >
-
+ />
+ )}
+ {isSelected &&
}
+ {typeof children === "string" ?
{children} : children}
+ >
)}
-
- );
-};
-
-type ListBoxPickerProps
= ListBoxProps;
+
+ )
+}
-const ListBoxPicker = ({ className, ...props }: ListBoxPickerProps) => {
+type ListBoxSectionProps = React.ComponentProps
+const ListBoxSection = ({ className, ...props }: ListBoxSectionProps) => {
return (
-
- );
-};
+
+ )
+}
-const Section = ({ className, ...props }: React.ComponentProps) => {
- return ;
-};
+const ListBoxItemDetails = DropdownItemDetails
-ListBox.Section = Section;
-ListBox.ItemDetails = DropdownItemDetails;
-ListBox.Item = Item;
-ListBox.Picker = ListBoxPicker;
+ListBox.Section = ListBoxSection
+ListBox.ItemDetails = ListBoxItemDetails
+ListBox.Item = ListBoxItem
-export { ListBox, listBoxStyles };
-export type { ListBoxItemProps, ListBoxPickerProps };
+export { ListBox }
+export type { ListBoxItemProps, ListBoxSectionProps }
diff --git a/resources/js/components/ui/loader.tsx b/resources/js/components/ui/loader.tsx
index 7a5056f..24bddd4 100644
--- a/resources/js/components/ui/loader.tsx
+++ b/resources/js/components/ui/loader.tsx
@@ -1,38 +1,38 @@
-import { cn } from '@/utils/classes';
-import { IconLoader } from 'justd-icons';
-import { ProgressBar } from 'react-aria-components';
-import type { VariantProps } from 'tailwind-variants';
-import { tv } from 'tailwind-variants';
+import { cn } from "@/utils/classes"
+import { IconLoader } from "justd-icons"
+import { ProgressBar } from "react-aria-components"
+import type { VariantProps } from "tailwind-variants"
+import { tv } from "tailwind-variants"
const loaderStyles = tv({
- base: 'relative',
+ base: "relative",
variants: {
intent: {
- current: 'text-current',
- primary: 'text-primary',
- secondary: 'text-muted-fg',
- success: 'text-success',
- warning: 'text-warning',
- danger: 'text-danger'
+ current: "text-current",
+ primary: "text-primary",
+ secondary: "text-muted-fg",
+ success: "text-success",
+ warning: "text-warning",
+ danger: "text-danger",
},
size: {
- small: 'size-4',
- medium: 'size-6',
- large: 'size-8',
- 'extra-large': 'size-10'
- }
+ small: "size-4",
+ medium: "size-6",
+ large: "size-8",
+ "extra-large": "size-10",
+ },
},
defaultVariants: {
- intent: 'current',
- size: 'small'
- }
-});
+ intent: "current",
+ size: "small",
+ },
+})
-type LoaderVariantProps = VariantProps;
+type LoaderVariantProps = VariantProps
const Bars = ({ className, ...props }: React.SVGProps) => (
) => (
/>
-);
-const Ring = (props: React.SVGProps) => ;
+)
+const Ring = (props: React.SVGProps) =>
const Spin = ({ className, ...props }: React.SVGProps) => (
-
+
@@ -160,33 +160,33 @@ const Spin = ({ className, ...props }: React.SVGProps) => (
/>
-);
+)
const LOADERS = {
bars: Bars,
ring: Ring,
- spin: Spin
-};
+ spin: Spin,
+}
-const DEFAULT_SPINNER = 'spin';
+const DEFAULT_SPINNER = "spin"
interface LoaderProps
- extends Omit, 'display' | 'opacity' | 'intent'>,
+ extends Omit, "display" | "opacity" | "intent">,
LoaderVariantProps {
- variant?: keyof typeof LOADERS;
- percentage?: number;
- isIndeterminate?: boolean;
- formatOptions?: Intl.NumberFormatOptions;
- ref?: React.RefObject;
+ variant?: keyof typeof LOADERS
+ percentage?: number
+ isIndeterminate?: boolean
+ formatOptions?: Intl.NumberFormatOptions
+ ref?: React.RefObject
}
const Loader = ({ isIndeterminate = true, ref, ...props }: LoaderProps) => {
- const { className, variant = DEFAULT_SPINNER, intent, size, ...spinnerProps } = props;
- const LoaderPrimitive = LOADERS[variant in LOADERS ? variant : DEFAULT_SPINNER];
+ const { className, variant = DEFAULT_SPINNER, intent, size, ...spinnerProps } = props
+ const LoaderPrimitive = LOADERS[variant in LOADERS ? variant : DEFAULT_SPINNER]
return (
@@ -196,16 +196,16 @@ const Loader = ({ isIndeterminate = true, ref, ...props }: LoaderProps) => {
intent,
size,
className: cn([
- ['ring'].includes(variant) && 'animate-spin',
- variant === 'spin' && 'stroke-current',
- className
- ])
+ ["ring"].includes(variant) && "animate-spin",
+ variant === "spin" && "stroke-current",
+ className,
+ ]),
})}
ref={ref}
{...spinnerProps}
/>
- );
-};
+ )
+}
-export { Loader };
+export { Loader }
diff --git a/resources/js/components/ui/menu.tsx b/resources/js/components/ui/menu.tsx
index 59e67ad..75f4220 100644
--- a/resources/js/components/ui/menu.tsx
+++ b/resources/js/components/ui/menu.tsx
@@ -1,47 +1,47 @@
-import { createContext, use } from 'react';
+import { createContext, use } from "react"
-import { IconBulletFill, IconCheck, IconChevronLgRight } from 'justd-icons';
+import { IconBulletFill, IconCheck, IconChevronLgRight } from "justd-icons"
import type {
ButtonProps,
MenuItemProps as MenuItemPrimitiveProps,
MenuProps as MenuPrimitiveProps,
MenuSectionProps as MenuSectionPrimitiveProps,
MenuTriggerProps as MenuTriggerPrimitiveProps,
- PopoverProps
-} from 'react-aria-components';
+ PopoverProps,
+} from "react-aria-components"
import {
Button,
Collection,
- composeRenderProps,
Header,
MenuItem as MenuItemPrimitive,
Menu as MenuPrimitive,
MenuSection as MenuSectionPrimitive,
MenuTrigger as MenuTriggerPrimitive,
- SubmenuTrigger as SubmenuTriggerPrimitive
-} from 'react-aria-components';
-import type { VariantProps } from 'tailwind-variants';
-import { tv } from 'tailwind-variants';
+ SubmenuTrigger as SubmenuTriggerPrimitive,
+ composeRenderProps,
+} from "react-aria-components"
+import type { VariantProps } from "tailwind-variants"
+import { tv } from "tailwind-variants"
-import { cn } from '@/utils/classes';
+import { cn } from "@/utils/classes"
import {
DropdownItemDetails,
- dropdownItemStyles,
DropdownKeyboard,
DropdownLabel,
+ DropdownSeparator,
+ dropdownItemStyles,
dropdownSectionStyles,
- DropdownSeparator
-} from './dropdown';
-import { Popover } from './popover';
+} from "./dropdown"
+import { Popover } from "./popover"
interface MenuContextProps {
- respectScreen: boolean;
+ respectScreen: boolean
}
-const MenuContext = createContext({ respectScreen: true });
+const MenuContext = createContext({ respectScreen: true })
interface MenuProps extends MenuTriggerPrimitiveProps {
- respectScreen?: boolean;
+ respectScreen?: boolean
}
const Menu = ({ respectScreen = true, ...props }: MenuProps) => {
@@ -49,41 +49,47 @@ const Menu = ({ respectScreen = true, ...props }: MenuProps) => {
{props.children}
- );
-};
+ )
+}
const MenuSubMenu = ({ delay = 0, ...props }) => (
{props.children}
-);
+)
const menuStyles = tv({
slots: {
menu: "grid max-h-[calc(var(--visual-viewport-height)-10rem)] grid-cols-[auto_1fr] overflow-auto rounded-xl p-1 outline-hidden [clip-path:inset(0_0_0_0_round_calc(var(--radius-lg)-2px))] sm:max-h-[inherit] *:[[role='group']+[role=group]]:mt-4 *:[[role='group']+[role=separator]]:mt-1",
- popover: 'z-50 p-0 shadow-xs outline-hidden sm:min-w-40',
- trigger: ['relative inline text-left outline-hidden data-focus-visible:ring-1 data-focus-visible:ring-primary']
- }
-});
+ popover: "z-50 p-0 shadow-xs outline-hidden sm:min-w-40",
+ trigger: [
+ "relative inline text-left outline-hidden data-focus-visible:ring-1 data-focus-visible:ring-primary",
+ ],
+ },
+})
-const { menu, popover, trigger } = menuStyles();
+const { menu, popover, trigger } = menuStyles()
interface MenuTriggerProps extends ButtonProps {
- className?: string;
- ref?: React.Ref;
+ className?: string
+ ref?: React.Ref
}
const MenuTrigger = ({ className, ref, ...props }: MenuTriggerProps) => (
- {(values) => <>{typeof props.children === 'function' ? props.children(values) : props.children}>}
+ {(values) => (
+ <>{typeof props.children === "function" ? props.children(values) : props.children}>
+ )}
-);
-
-interface MenuContentProps extends Omit, MenuPrimitiveProps {
- className?: string;
- popoverClassName?: string;
- showArrow?: boolean;
- respectScreen?: boolean;
+)
+
+interface MenuContentProps
+ extends Omit,
+ MenuPrimitiveProps {
+ className?: string
+ popoverClassName?: string
+ showArrow?: boolean
+ respectScreen?: boolean
}
const MenuContent = ({
@@ -92,27 +98,27 @@ const MenuContent = ({
popoverClassName,
...props
}: MenuContentProps) => {
- const { respectScreen } = use(MenuContext);
+ const { respectScreen } = use(MenuContext)
return (
- );
-};
+ )
+}
interface MenuItemProps extends MenuItemPrimitiveProps, VariantProps {
- isDanger?: boolean;
+ isDanger?: boolean
}
const MenuItem = ({ className, isDanger = false, children, ...props }: MenuItemProps) => {
- const textValue = props.textValue || (typeof children === 'string' ? children : undefined);
+ const textValue = props.textValue || (typeof children === "string" ? children : undefined)
return (
@@ -120,22 +126,22 @@ const MenuItem = ({ className, isDanger = false, children, ...props }: MenuItemP
...renderProps,
className: renderProps.hasSubmenu
? cn([
- 'data-open:data-danger:bg-danger/10 data-open:data-danger:text-danger',
- 'data-open:bg-accent data-open:text-accent-fg data-open:*:data-[slot=icon]:text-accent-fg data-open:*:[.text-muted-fg]:text-accent-fg',
- className
+ "data-open:data-danger:bg-danger/10 data-open:data-danger:text-danger",
+ "data-open:bg-accent data-open:text-accent-fg data-open:*:data-[slot=icon]:text-accent-fg data-open:*:[.text-muted-fg]:text-accent-fg",
+ className,
])
- : className
- })
+ : className,
+ }),
)}
textValue={textValue}
- data-danger={isDanger ? 'true' : undefined}
+ data-danger={isDanger ? "true" : undefined}
{...props}
>
{(values) => (
<>
{values.isSelected && (
<>
- {values.selectionMode === 'single' && (
+ {values.selectionMode === "single" && (
)}
- {values.selectionMode === 'multiple' && (
+ {values.selectionMode === "multiple" && (
)}
>
)}
- {typeof children === 'function' ? children(values) : children}
+ {typeof children === "function" ? children(values) : children}
- {values.hasSubmenu && }
+ {values.hasSubmenu && (
+
+ )}
>
)}
- );
-};
+ )
+}
export interface MenuHeaderProps extends React.ComponentProps {
- separator?: boolean;
+ separator?: boolean
}
const MenuHeader = ({ className, separator = false, ...props }: MenuHeaderProps) => (
-);
+)
-const { section, header } = dropdownSectionStyles();
+const { section, header } = dropdownSectionStyles()
interface MenuSectionProps extends MenuSectionPrimitiveProps {
- ref?: React.Ref;
- title?: string;
+ ref?: React.Ref
+ title?: string
}
const MenuSection = ({ className, ref, ...props }: MenuSectionProps) => {
return (
- {'title' in props && }
+ {"title" in props && }
{props.children}
- );
-};
-
-const MenuSeparator = DropdownSeparator;
-const MenuItemDetails = DropdownItemDetails;
-const MenuKeyboard = DropdownKeyboard;
-const MenuLabel = DropdownLabel;
-
-Menu.Keyboard = MenuKeyboard;
-Menu.Content = MenuContent;
-Menu.Header = MenuHeader;
-Menu.Item = MenuItem;
-Menu.Section = MenuSection;
-Menu.Separator = MenuSeparator;
-Menu.ItemDetails = MenuItemDetails;
-Menu.Label = MenuLabel;
-Menu.Trigger = MenuTrigger;
-Menu.Submenu = MenuSubMenu;
-
-export { Menu };
-export type { MenuContentProps, MenuItemProps, MenuProps, MenuSectionProps, MenuTriggerProps };
+ )
+}
+
+const MenuSeparator = DropdownSeparator
+const MenuItemDetails = DropdownItemDetails
+const MenuKeyboard = DropdownKeyboard
+const MenuLabel = DropdownLabel
+
+Menu.Keyboard = MenuKeyboard
+Menu.Content = MenuContent
+Menu.Header = MenuHeader
+Menu.Item = MenuItem
+Menu.Section = MenuSection
+Menu.Separator = MenuSeparator
+Menu.ItemDetails = MenuItemDetails
+Menu.Label = MenuLabel
+Menu.Trigger = MenuTrigger
+Menu.Submenu = MenuSubMenu
+
+export { Menu }
+export type { MenuContentProps, MenuItemProps, MenuProps, MenuSectionProps, MenuTriggerProps }
diff --git a/resources/js/components/ui/modal.tsx b/resources/js/components/ui/modal.tsx
index 1bc88a0..6aa91d6 100644
--- a/resources/js/components/ui/modal.tsx
+++ b/resources/js/components/ui/modal.tsx
@@ -1,128 +1,145 @@
-import type { DialogProps, DialogTriggerProps, ModalOverlayProps } from 'react-aria-components';
-import { composeRenderProps, DialogTrigger, ModalOverlay, Modal as ModalPrimitive } from 'react-aria-components';
-import { tv, type VariantProps } from 'tailwind-variants';
+import type { DialogProps, DialogTriggerProps, ModalOverlayProps } from "react-aria-components"
+import {
+ DialogTrigger,
+ ModalOverlay,
+ Modal as ModalPrimitive,
+ composeRenderProps,
+} from "react-aria-components"
+import { type VariantProps, tv } from "tailwind-variants"
-import { Dialog } from './dialog';
+import { Dialog } from "./dialog"
-const overlay = tv({
+const Modal = (props: DialogTriggerProps) => {
+ return
+}
+
+const modalOverlayStyles = tv({
base: [
- 'fixed top-0 left-0 isolate z-50 h-(--visual-viewport-height) w-full',
- 'flex items-end justify-end bg-fg/15 text-center sm:items-center sm:justify-center dark:bg-bg/40',
- '[--visual-viewport-vertical-padding:16px] sm:[--visual-viewport-vertical-padding:32px]'
+ "fixed top-0 left-0 isolate z-50 h-(--visual-viewport-height) w-full",
+ "flex items-end justify-end bg-fg/15 text-center sm:items-center sm:justify-center dark:bg-bg/40",
+ "[--visual-viewport-vertical-padding:16px] sm:[--visual-viewport-vertical-padding:32px]",
],
variants: {
isBlurred: {
- true: 'bg-bg supports-backdrop-filter:bg-bg/15 supports-backdrop-filter:backdrop-blur dark:supports-backdrop-filter:bg-bg/40'
+ true: "bg-bg supports-backdrop-filter:bg-bg/15 supports-backdrop-filter:backdrop-blur dark:supports-backdrop-filter:bg-bg/40",
},
isEntering: {
- true: 'fade-in animate-in duration-200 ease-out'
+ true: "fade-in animate-in duration-200 ease-out",
},
isExiting: {
- true: 'fade-out animate-out duration-150 ease-in'
- }
- }
-});
-const content = tv({
+ true: "fade-out animate-out ease-in",
+ },
+ },
+})
+const modalContentStyles = tv({
base: [
- 'max-h-full w-full rounded-t-2xl bg-overlay text-left align-middle text-overlay-fg shadow-lg ring-1 ring-fg/5',
- 'overflow-hidden sm:rounded-2xl dark:ring-border'
+ "max-h-full w-full rounded-t-2xl bg-overlay text-left align-middle text-overlay-fg shadow-lg ring-1 ring-fg/5",
+ "overflow-hidden sm:rounded-2xl dark:ring-border",
],
variants: {
isEntering: {
- true: ['fade-in slide-in-from-bottom animate-in duration-200 ease-out', 'sm:zoom-in-95 sm:slide-in-from-bottom-0']
+ true: [
+ "fade-in slide-in-from-bottom animate-in duration-200 ease-out",
+ "sm:zoom-in-95 sm:slide-in-from-bottom-0",
+ ],
},
isExiting: {
- true: ['slide-out-to-bottom sm:slide-out-to-bottom-0 sm:zoom-out-95 animate-out duration-150 ease-in']
+ true: [
+ "slide-out-to-bottom sm:slide-out-to-bottom-0 sm:zoom-out-95 animate-out duration-150 ease-in",
+ ],
},
size: {
- xs: 'sm:max-w-xs',
- sm: 'sm:max-w-sm',
- md: 'sm:max-w-md',
- lg: 'sm:max-w-lg',
- xl: 'sm:max-w-xl',
- '2xl': 'sm:max-w-2xl',
- '3xl': 'sm:max-w-3xl',
- '4xl': 'sm:max-w-4xl',
- '5xl': 'sm:max-w-5xl'
- }
+ xs: "sm:max-w-xs",
+ sm: "sm:max-w-sm",
+ md: "sm:max-w-md",
+ lg: "sm:max-w-lg",
+ xl: "sm:max-w-xl",
+ "2xl": "sm:max-w-2xl",
+ "3xl": "sm:max-w-3xl",
+ "4xl": "sm:max-w-4xl",
+ "5xl": "sm:max-w-5xl",
+ },
},
defaultVariants: {
- size: 'lg'
- }
-});
-
-const Modal = (props: DialogTriggerProps) => {
- return ;
-};
+ size: "lg",
+ },
+})
interface ModalContentProps
- extends Omit, 'children'>,
- Omit,
- VariantProps {
- 'aria-label'?: DialogProps['aria-label'];
- 'aria-labelledby'?: DialogProps['aria-labelledby'];
- role?: DialogProps['role'];
- children?: DialogProps['children'];
- closeButton?: boolean;
- isBlurred?: boolean;
+ extends Omit,
+ Pick,
+ VariantProps {
+ closeButton?: boolean
+ isBlurred?: boolean
classNames?: {
- overlay?: ModalOverlayProps['className'];
- content?: ModalOverlayProps['className'];
- };
+ overlay?: ModalOverlayProps["className"]
+ content?: ModalOverlayProps["className"]
+ }
}
const ModalContent = ({
classNames,
- isDismissable = true,
+ isDismissable: isDismissableInternal,
isBlurred = false,
children,
size,
- role,
+ role = "dialog",
closeButton = true,
...props
}: ModalContentProps) => {
- const _isDismissable = role === 'alertdialog' ? false : isDismissable;
+ const isDismissable = isDismissableInternal ?? role !== "alertdialog"
+
return (
{
- return overlay({
+ isDismissable={isDismissable}
+ className={composeRenderProps(classNames?.overlay, (className, renderProps) =>
+ modalOverlayStyles({
...renderProps,
isBlurred,
- className
- });
- })}
+ className,
+ }),
+ )}
{...props}
>
- content({
+ modalContentStyles({
...renderProps,
size,
- className
- })
+ className,
+ }),
)}
+ {...props}
>
-
+
{(values) => (
<>
- {typeof children === 'function' ? children(values) : children}
- {closeButton && }
+ {typeof children === "function" ? children(values) : children}
+ {closeButton && }
>
)}
- );
-};
+ )
+}
+
+const ModalTrigger = Dialog.Trigger
+const ModalHeader = Dialog.Header
+const ModalTitle = Dialog.Title
+const ModalDescription = Dialog.Description
+const ModalFooter = Dialog.Footer
+const ModalBody = Dialog.Body
+const ModalClose = Dialog.Close
-Modal.Trigger = Dialog.Trigger;
-Modal.Header = Dialog.Header;
-Modal.Title = Dialog.Title;
-Modal.Description = Dialog.Description;
-Modal.Footer = Dialog.Footer;
-Modal.Body = Dialog.Body;
-Modal.Close = Dialog.Close;
-Modal.Content = ModalContent;
+Modal.Trigger = ModalTrigger
+Modal.Header = ModalHeader
+Modal.Title = ModalTitle
+Modal.Description = ModalDescription
+Modal.Footer = ModalFooter
+Modal.Body = ModalBody
+Modal.Close = ModalClose
+Modal.Content = ModalContent
-export { Modal };
+export { Modal }
diff --git a/resources/js/components/ui/navbar.tsx b/resources/js/components/ui/navbar.tsx
index de9478a..4b80a00 100644
--- a/resources/js/components/ui/navbar.tsx
+++ b/resources/js/components/ui/navbar.tsx
@@ -1,57 +1,57 @@
-import { createContext, use, useCallback, useId, useMemo, useState } from 'react';
+import { createContext, use, useCallback, useId, useMemo, useState } from "react"
-import { IconHamburger } from 'justd-icons';
-import { LayoutGroup, motion } from 'motion/react';
-import type { LinkProps } from 'react-aria-components';
-import { composeRenderProps, Link } from 'react-aria-components';
-import { tv, type VariantProps } from 'tailwind-variants';
+import { IconHamburger } from "justd-icons"
+import { LayoutGroup, motion } from "motion/react"
+import type { LinkProps } from "react-aria-components"
+import { Link, composeRenderProps } from "react-aria-components"
+import { type VariantProps, tv } from "tailwind-variants"
-import { cn } from '@/utils/classes';
-import { useMediaQuery } from '@/utils/use-media-query';
-import { Button, type ButtonProps } from './button';
-import { composeTailwindRenderProps } from './primitive';
-import { Sheet } from './sheet';
+import { cn } from "@/utils/classes"
+import { useMediaQuery } from "@/utils/use-media-query"
+import { Button, type ButtonProps } from "./button"
+import { composeTailwindRenderProps } from "./primitive"
+import { Sheet } from "./sheet"
type NavbarOptions = {
- side?: 'left' | 'right';
- isSticky?: boolean;
- intent?: 'navbar' | 'floating' | 'inset';
-};
+ side?: "left" | "right"
+ isSticky?: boolean
+ intent?: "navbar" | "floating" | "inset"
+}
type NavbarContextProps = {
- open: boolean;
- setOpen: (open: boolean) => void;
- isCompact: boolean;
- toggleNavbar: () => void;
-} & NavbarOptions;
+ open: boolean
+ setOpen: (open: boolean) => void
+ isCompact: boolean
+ toggleNavbar: () => void
+} & NavbarOptions
-const NavbarContext = createContext(null);
+const NavbarContext = createContext(null)
function useNavbar() {
- const context = use(NavbarContext);
+ const context = use(NavbarContext)
if (!context) {
- throw new Error('useNavbar must be used within a Navbar.');
+ throw new Error("useNavbar must be used within a Navbar.")
}
- return context;
+ return context
}
-interface NavbarProps extends React.ComponentProps<'header'>, NavbarOptions {
- defaultOpen?: boolean;
- isOpen?: boolean;
- onOpenChange?: (open: boolean) => void;
+interface NavbarProps extends React.ComponentProps<"header">, NavbarOptions {
+ defaultOpen?: boolean
+ isOpen?: boolean
+ onOpenChange?: (open: boolean) => void
}
const navbarStyles = tv({
- base: '@container relative isolate flex w-full flex-col',
+ base: "relative isolate flex w-full flex-col",
variants: {
intent: {
- floating: 'px-2.5 pt-2',
- navbar: '',
- inset: 'min-h-svh bg-navbar dark:bg-bg'
- }
- }
-});
+ floating: "px-2.5 pt-2",
+ navbar: "",
+ inset: "min-h-svh bg-navbar dark:bg-bg",
+ },
+ },
+})
const Navbar = ({
children,
@@ -59,29 +59,29 @@ const Navbar = ({
onOpenChange: setOpenProp,
defaultOpen = false,
className,
- side = 'left',
+ side = "left",
isSticky = false,
- intent = 'navbar',
+ intent = "navbar",
...props
}: NavbarProps) => {
- const isCompact = useMediaQuery('(max-width: 765px)');
- const [_open, _setOpen] = useState(defaultOpen);
- const open = openProp ?? _open;
+ const isCompact = useMediaQuery("(max-width: 768px)")
+ const [_open, _setOpen] = useState(defaultOpen)
+ const open = openProp ?? _open
const setOpen = useCallback(
(value: boolean | ((value: boolean) => boolean)) => {
if (setOpenProp) {
- return setOpenProp?.(typeof value === 'function' ? value(open) : value);
+ return setOpenProp?.(typeof value === "function" ? value(open) : value)
}
- _setOpen(value);
+ _setOpen(value)
},
- [setOpenProp, open]
- );
+ [setOpenProp, open],
+ )
const toggleNavbar = useCallback(() => {
- setOpen((open) => !open);
- }, [setOpen]);
+ setOpen((open) => !open)
+ }, [setOpen])
const contextValue = useMemo(
() => ({
@@ -91,50 +91,55 @@ const Navbar = ({
toggleNavbar,
intent,
isSticky,
- side
+ side,
}),
- [open, setOpen, isCompact, toggleNavbar, intent, isSticky, side]
- );
+ [open, setOpen, isCompact, toggleNavbar, intent, isSticky, side],
+ )
return (
-
- );
-};
+ )
+}
const navStyles = tv({
base: [
- 'group peer @md:flex hidden h-(--navbar-height) w-full items-center px-4 [--navbar-height:3.5rem]',
- '[&>div]:mx-auto @md:[&>div]:flex [&>div]:w-full [&>div]:max-w-[1680px] [&>div]:items-center'
+ "group peer hidden h-(--navbar-height) w-full items-center px-4 [--navbar-height:3.5rem] md:flex",
+ "[&>div]:mx-auto [&>div]:w-full [&>div]:max-w-[1680px] [&>div]:items-center md:[&>div]:flex",
],
variants: {
isSticky: {
- true: 'sticky top-0 z-40'
+ true: "sticky top-0 z-40",
},
intent: {
floating:
- 'mx-auto w-full max-w-7xl rounded-xl border bg-navbar @md:px-4 text-navbar-fg 2xl:max-w-(--breakpoint-2xl)',
- navbar: 'border-b bg-navbar @md:px-6 text-navbar-fg',
+ "mx-auto w-full max-w-7xl rounded-xl border bg-navbar text-navbar-fg md:px-4 2xl:max-w-(--breakpoint-2xl)",
+ navbar: "border-b bg-navbar text-navbar-fg md:px-6",
inset: [
- 'mx-auto @md:px-6',
- '[&>div]:mx-auto @md:[&>div]:flex [&>div]:w-full [&>div]:items-center 2xl:[&>div]:max-w-(--breakpoint-2xl)'
- ]
- }
- }
-});
-
-interface NavbarNavProps extends React.ComponentProps<'div'> {
- intent?: 'navbar' | 'floating' | 'inset';
- isSticky?: boolean;
- side?: 'left' | 'right';
+ "mx-auto md:px-6",
+ "[&>div]:mx-auto [&>div]:w-full [&>div]:items-center md:[&>div]:flex 2xl:[&>div]:max-w-(--breakpoint-2xl)",
+ ],
+ },
+ },
+})
+
+interface NavbarNavProps extends React.ComponentProps<"div"> {
+ intent?: "navbar" | "floating" | "inset"
+ isSticky?: boolean
+ side?: "left" | "right"
+ useDefaultResponsive?: boolean
}
-const NavbarNav = ({ className, ref, ...props }: NavbarNavProps) => {
- const { isCompact, side, intent, isSticky, open, setOpen } = useNavbar();
+const NavbarNav = ({ useDefaultResponsive = true, className, ref, ...props }: NavbarNavProps) => {
+ const { isCompact, side, intent, isSticky, open, setOpen } = useNavbar()
- if (isCompact) {
+ if (isCompact && useDefaultResponsive) {
return (
{
aria-label="Compact Navbar"
data-navbar="compact"
classNames={{
- content: 'text-fg [&>button]:hidden'
+ content: "text-fg [&>button]:hidden",
}}
- isFloat={intent === 'floating'}
+ isFloat={intent === "floating"}
>
- {props.children}
+ {props.children}
- );
+ )
}
return (
-
+
- );
-};
+ )
+}
interface NavbarTriggerProps extends ButtonProps {
- ref?: React.RefObject
;
+ ref?: React.RefObject
}
const NavbarTrigger = ({ className, onPress, ref, ...props }: NavbarTriggerProps) => {
- const { toggleNavbar } = useNavbar();
+ const { toggleNavbar } = useNavbar()
return (
{
- onPress?.(event);
- toggleNavbar();
+ onPress?.(event)
+ toggleNavbar()
}}
{...props}
>
Toggle Navbar
- );
-};
+ )
+}
-const Section = ({ className, ...props }: React.ComponentProps<'div'>) => {
- const { isCompact } = useNavbar();
- const id = useId();
+const NavbarSection = ({ className, ...props }: React.ComponentProps<"div">) => {
+ const { isCompact } = useNavbar()
+ const id = useId()
return (
{props.children}
- );
-};
+ )
+}
const navItemStyles = tv({
base: [
- '*:data-[slot=icon]:-mx-0.5 relative flex cursor-pointer items-center gap-x-2 px-2 @md:text-sm text-muted-fg no-underline outline-hidden transition-colors forced-colors:transform-none forced-colors:outline-0 forced-colors:data-disabled:text-[GrayText]',
- 'data-focused:text-fg data-hovered:text-fg data-pressed:text-fg data-focus-visible:outline-1 data-focus-visible:outline-primary',
- '**:data-[slot=chevron]:size-4 **:data-[slot=chevron]:transition-transform',
- 'data-pressed:**:data-[slot=chevron]:rotate-180 *:data-[slot=icon]:size-4 *:data-[slot=icon]:shrink-0',
- 'data-disabled:cursor-default data-disabled:opacity-50 data-disabled:forced-colors:text-[GrayText]'
+ "*:data-[slot=icon]:-mx-0.5 relative flex cursor-pointer items-center gap-x-2 px-2 text-muted-fg no-underline outline-hidden transition-colors md:text-sm forced-colors:transform-none forced-colors:outline-0 forced-colors:data-disabled:text-[GrayText]",
+ "data-focused:text-fg data-hovered:text-fg data-pressed:text-fg data-focus-visible:outline-1 data-focus-visible:outline-primary",
+ "**:data-[slot=chevron]:size-4 **:data-[slot=chevron]:transition-transform",
+ "data-pressed:**:data-[slot=chevron]:rotate-180 *:data-[slot=icon]:size-4 *:data-[slot=icon]:shrink-0",
+ "data-disabled:cursor-default data-disabled:opacity-50 data-disabled:forced-colors:text-[GrayText]",
],
variants: {
isCurrent: {
- true: 'cursor-default text-navbar-fg'
- }
- }
-});
+ true: "cursor-default text-navbar-fg",
+ },
+ },
+})
interface NavbarItemProps extends LinkProps {
- isCurrent?: boolean;
+ isCurrent?: boolean
}
-const Item = ({ className, isCurrent, ...props }: NavbarItemProps) => {
- const { intent, isCompact } = useNavbar();
+const NavbarItem = ({ className, isCurrent, ...props }: NavbarItemProps) => {
+ const { intent, isCompact } = useNavbar()
return (
- navItemStyles({ ...renderProps, isCurrent, className })
+ navItemStyles({ ...renderProps, isCurrent, className }),
)}
{...props}
>
{(values) => (
<>
- {typeof props.children === 'function' ? props.children(values) : props.children}
+ {typeof props.children === "function" ? props.children(values) : props.children}
- {(isCurrent || values.isCurrent) && !isCompact && intent !== 'floating' && (
+ {(isCurrent || values.isCurrent) && !isCompact && intent !== "floating" && (
)}
>
)}
- );
-};
+ )
+}
-const Logo = ({ className, ...props }: LinkProps) => {
+const NavbarLogo = ({ className, ...props }: LinkProps) => {
return (
- );
-};
+ )
+}
-const Flex = ({ className, ref, ...props }: React.ComponentProps<'div'>) => {
- return
;
-};
+const NavbarFlex = ({ className, ref, ...props }: React.ComponentProps<"div">) => {
+ return
+}
const compactStyles = tv({
- base: 'flex @md:hidden justify-between bg-navbar text-navbar-fg peer-has-[[data-navbar-intent=floating]]:border',
+ base: "flex justify-between bg-navbar text-navbar-fg peer-has-[[data-navbar-intent=floating]]:border md:hidden",
variants: {
intent: {
- floating: 'h-12 rounded-lg border px-3.5',
- inset: 'h-14 border-b px-4',
- navbar: 'h-14 border-b px-4'
- }
- }
-});
+ floating: "h-12 rounded-lg border px-3.5",
+ inset: "h-14 border-b px-4",
+ navbar: "h-14 border-b px-4",
+ },
+ },
+})
-interface NavbarCompactProps extends React.ComponentProps<'div'>, VariantProps {
- ref?: React.RefObject;
+interface NavbarCompactProps
+ extends React.ComponentProps<"div">,
+ VariantProps {
+ ref?: React.RefObject
}
const NavbarCompact = ({ className, ref, ...props }: NavbarCompactProps) => {
- const { intent } = useNavbar();
- return
;
-};
+ const { intent } = useNavbar()
+ return
+}
const insetStyles = tv({
- base: 'grow',
+ base: "grow",
variants: {
intent: {
- floating: '',
- inset: '@md:rounded-lg bg-bg @md:shadow-xs @md:ring-1 @md:ring-fg/15 dark:bg-navbar @md:dark:ring-border',
- navbar: ''
- }
- }
-});
+ floating: "",
+ inset:
+ "bg-bg md:rounded-lg md:shadow-xs md:ring-1 md:ring-fg/15 dark:bg-navbar md:dark:ring-border",
+ navbar: "",
+ },
+ },
+})
-const Inset = ({ className, ref, ...props }: React.ComponentProps<'div'>) => {
- const { intent } = useNavbar();
+const NavbarInset = ({ className, ref, ...props }: React.ComponentProps<"div">) => {
+ const { intent } = useNavbar()
return (
{props.children}
- );
-};
-
-Navbar.Nav = NavbarNav;
-Navbar.Inset = Inset;
-Navbar.Compact = NavbarCompact;
-Navbar.Flex = Flex;
-Navbar.Trigger = NavbarTrigger;
-Navbar.Logo = Logo;
-Navbar.Item = Item;
-Navbar.Section = Section;
-
-export { Navbar };
-export type { NavbarCompactProps, NavbarItemProps, NavbarNavProps, NavbarProps, NavbarTriggerProps };
+ )
+}
+
+Navbar.Nav = NavbarNav
+Navbar.Inset = NavbarInset
+Navbar.Compact = NavbarCompact
+Navbar.Flex = NavbarFlex
+Navbar.Trigger = NavbarTrigger
+Navbar.Logo = NavbarLogo
+Navbar.Item = NavbarItem
+Navbar.Section = NavbarSection
+
+export { Navbar }
+export type { NavbarCompactProps, NavbarItemProps, NavbarNavProps, NavbarProps, NavbarTriggerProps }
diff --git a/resources/js/components/ui/pagination.tsx b/resources/js/components/ui/pagination.tsx
index dc214aa..c1d1ff2 100644
--- a/resources/js/components/ui/pagination.tsx
+++ b/resources/js/components/ui/pagination.tsx
@@ -1,34 +1,40 @@
import {
IconChevronLgLeft,
IconChevronLgRight,
- IconChevronsLgLeft,
- IconChevronsLgRight,
- IconDotsHorizontal
-} from 'justd-icons';
-import type { ListBoxItemProps, ListBoxProps, ListBoxSectionProps } from 'react-aria-components';
-import { composeRenderProps, ListBox, ListBoxItem, ListBoxSection, Separator } from 'react-aria-components';
+ IconChevronWallLeft,
+ IconChevronWallRight,
+ IconDotsHorizontal,
+} from "justd-icons"
+import type { ListBoxItemProps, ListBoxProps, ListBoxSectionProps } from "react-aria-components"
+import {
+ ListBox,
+ ListBoxItem,
+ ListBoxSection,
+ Separator,
+ composeRenderProps,
+} from "react-aria-components"
-import { cn } from '@/utils/classes';
-import { tv } from 'tailwind-variants';
-import { buttonStyles } from './button';
+import { cn } from "@/utils/classes"
+import { tv } from "tailwind-variants"
+import { buttonStyles } from "./button"
const paginationStyles = tv({
slots: {
- pagination: 'mx-auto flex w-full justify-center gap-[5px]',
- section: 'flex h-9 gap-[5px]',
- list: 'flex flex-row items-center gap-[5px]',
+ pagination: "mx-auto flex w-full justify-center gap-[5px]",
+ section: "flex h-9 gap-[5px]",
+ list: "flex flex-row items-center gap-[5px]",
itemButton:
- 'cursor-pointer font-normal text-fg data-focus-visible:border-primary data-focus-visible:bg-primary/10 data-focus-visible:ring-4 data-focus-visible:ring-primary/20',
- itemLabel: 'grid h-9 place-content-center px-3.5 tabular-nums',
- itemSeparator: 'grid h-9 place-content-center',
+ "cursor-pointer font-normal text-fg data-focus-visible:border-primary data-focus-visible:bg-primary/10 data-focus-visible:ring-4 data-focus-visible:ring-primary/20",
+ itemLabel: "grid h-9 place-content-center px-3.5 tabular-nums",
+ itemSeparator: "grid h-9 place-content-center",
itemEllipsis:
- 'flex size-9 items-center justify-center rounded-lg border border-transparent data-focus-visible:border-primary data-focus-visible:bg-primary/10 data-focused:outline-hidden data-focus-visible:ring-4 data-focus-visible:ring-primary/20',
- itemEllipsisIcon: 'flex size-9 items-center justify-center',
+ "flex size-9 items-center justify-center rounded-lg border border-transparent data-focus-visible:border-primary data-focus-visible:bg-primary/10 data-focused:outline-hidden data-focus-visible:ring-4 data-focus-visible:ring-primary/20",
+ itemEllipsisIcon: "flex size-9 items-center justify-center",
defaultItem:
- 'cursor-pointer font-normal tabular-nums disabled:cursor-default disabled:opacity-100 data-focus-visible:border-primary data-focus-visible:bg-primary/10 data-focus-visible:ring-4 data-focus-visible:ring-primary/20',
- itemSeparatorLine: 'h-5 w-[1.5px] shrink-0 rotate-[14deg] bg-secondary-fg/40'
- }
-});
+ "cursor-pointer font-normal tabular-nums disabled:cursor-default disabled:opacity-100 data-focus-visible:border-primary data-focus-visible:bg-primary/10 data-focus-visible:ring-4 data-focus-visible:ring-primary/20",
+ itemSeparatorLine: "h-5 w-[1.5px] shrink-0 rotate-[14deg] bg-secondary-fg/40",
+ },
+})
const {
pagination,
@@ -40,62 +46,66 @@ const {
itemEllipsis,
itemEllipsisIcon,
defaultItem,
- itemSeparatorLine
-} = paginationStyles();
+ itemSeparatorLine,
+} = paginationStyles()
-type PagginationProps = React.ComponentProps<'nav'>;
+type PagginationProps = React.ComponentProps<"nav">
const Pagination = ({ className, ref, ...props }: PagginationProps) => (
-);
+)
interface PaginationSectionProps extends ListBoxSectionProps {
- ref?: React.RefObject;
+ ref?: React.RefObject
}
-const PaginationSection = ({ className, ref, ...props }: PaginationSectionProps) => (
+const PaginationSection = ({
+ className,
+ ref,
+ ...props
+}: PaginationSectionProps) => (
-);
+)
interface PaginationListProps extends ListBoxProps {
- ref?: React.RefObject;
+ ref?: React.RefObject
}
-const List = ({ className, ref, ...props }: PaginationListProps) => {
+const PaginationList = ({ className, ref, ...props }: PaginationListProps) => {
return (
list({ className }))}
{...props}
/>
- );
-};
+ )
+}
const renderListItem = (
props: ListBoxItemProps & {
- textValue?: string;
- 'aria-current'?: string | undefined;
- isDisabled?: boolean;
- className?: string;
+ textValue?: string
+ "aria-current"?: string | undefined
+ isDisabled?: boolean
+ className?: string
},
- children: React.ReactNode
-) => {children} ;
+ children: React.ReactNode,
+) => {children}
interface PaginationItemProps extends ListBoxItemProps {
- children?: React.ReactNode;
- className?: string;
- intent?: 'primary' | 'secondary';
- size?: 'medium' | 'large' | 'square-petite' | 'extra-small' | 'small';
- shape?: 'square' | 'circle';
- appearance?: 'solid' | 'outline' | 'plain';
- isCurrent?: boolean;
- segment?: 'label' | 'separator' | 'ellipsis' | 'default' | 'last' | 'first' | 'previous' | 'next';
+ children?: React.ReactNode
+ className?: string
+ intent?: "primary" | "secondary"
+ size?: "medium" | "large" | "square-petite" | "extra-small" | "small"
+ shape?: "square" | "circle"
+ appearance?: "solid" | "outline" | "plain"
+ isCurrent?: boolean
+ segment?: "label" | "separator" | "ellipsis" | "default" | "last" | "first" | "previous" | "next"
}
-const Item = ({
- segment = 'default',
- size = 'small',
- appearance = 'outline',
+const PaginationItem = ({
+ segment = "default",
+ size = "small",
+ appearance = "outline",
intent,
className,
isCurrent,
@@ -103,90 +113,94 @@ const Item = ({
...props
}: PaginationItemProps) => {
const textValue =
- typeof children === 'string' ? children : typeof children === 'number' ? children.toString() : undefined;
+ typeof children === "string"
+ ? children
+ : typeof children === "number"
+ ? children.toString()
+ : undefined
const renderPaginationIndicator = (indicator: React.ReactNode) =>
renderListItem(
{
textValue: segment,
- 'aria-current': isCurrent ? 'page' : undefined,
+ "aria-current": isCurrent ? "page" : undefined,
isDisabled: isCurrent,
className: cn(
buttonStyles({
- appearance: 'outline',
- size: 'small',
- className: itemButton()
+ appearance: "outline",
+ size: "small",
+ className: itemButton(),
}),
- className
+ className,
),
- ...props
+ ...props,
},
- indicator
- );
+ indicator,
+ )
switch (segment) {
- case 'label':
+ case "label":
return renderListItem(
{
textValue: textValue,
className: itemLabel({ className }),
- ...props
+ ...props,
},
- children
- );
- case 'separator':
+ children,
+ )
+ case "separator":
return renderListItem(
{
- textValue: 'Separator',
+ textValue: "Separator",
className: itemSeparator({ className }),
- ...props
+ ...props,
},
-
- );
- case 'ellipsis':
+ ,
+ )
+ case "ellipsis":
return renderListItem(
{
- textValue: 'More pages',
+ textValue: "More pages",
className: itemEllipsis({ className }),
- ...props
+ ...props,
},
-
- );
- case 'previous':
- return renderPaginationIndicator( );
- case 'next':
- return renderPaginationIndicator( );
- case 'first':
- return renderPaginationIndicator( );
- case 'last':
- return renderPaginationIndicator( );
+ ,
+ )
+ case "previous":
+ return renderPaginationIndicator( )
+ case "next":
+ return renderPaginationIndicator( )
+ case "first":
+ return renderPaginationIndicator( )
+ case "last":
+ return renderPaginationIndicator( )
default:
return renderListItem(
{
textValue: textValue,
- 'aria-current': isCurrent ? 'page' : undefined,
+ "aria-current": isCurrent ? "page" : undefined,
isDisabled: isCurrent,
className: cn(
buttonStyles({
- intent: isCurrent ? 'primary' : intent,
- appearance: isCurrent ? 'solid' : appearance,
+ intent: isCurrent ? "primary" : intent,
+ appearance: isCurrent ? "solid" : appearance,
size,
- className: defaultItem({ className })
+ className: defaultItem({ className }),
}),
- className
+ className,
),
- ...props
+ ...props,
},
- children
- );
+ children,
+ )
}
-};
+}
-Pagination.Item = Item;
-Pagination.List = List;
-Pagination.Section = PaginationSection;
+Pagination.Item = PaginationItem
+Pagination.List = PaginationList
+Pagination.Section = PaginationSection
-export { Pagination };
-export type { PagginationProps, PaginationItemProps, PaginationListProps, PaginationSectionProps };
+export { Pagination }
+export type { PagginationProps, PaginationItemProps, PaginationListProps, PaginationSectionProps }
diff --git a/resources/js/components/ui/popover.tsx b/resources/js/components/ui/popover.tsx
index 30e93b7..5cf6111 100644
--- a/resources/js/components/ui/popover.tsx
+++ b/resources/js/components/ui/popover.tsx
@@ -1,10 +1,9 @@
import type {
DialogTriggerProps,
ModalOverlayProps,
- PopoverProps as PopoverPrimitiveProps
-} from 'react-aria-components';
+ PopoverProps as PopoverPrimitiveProps,
+} from "react-aria-components"
import {
- composeRenderProps,
type DialogProps,
DialogTrigger,
Modal,
@@ -12,98 +11,105 @@ import {
OverlayArrow,
PopoverContext,
Popover as PopoverPrimitive,
- useSlottedContext
-} from 'react-aria-components';
-import { tv } from 'tailwind-variants';
+ composeRenderProps,
+ useSlottedContext,
+} from "react-aria-components"
+import { tv } from "tailwind-variants"
-import { cn } from '@/utils/classes';
-import { useMediaQuery } from '@/utils/use-media-query';
-import { twMerge } from 'tailwind-merge';
-import type { DialogBodyProps, DialogFooterProps, DialogHeaderProps, DialogTitleProps } from './dialog';
-import { Dialog } from './dialog';
+import { cn } from "@/utils/classes"
+import { useMediaQuery } from "@/utils/use-media-query"
+import { twMerge } from "tailwind-merge"
+import type {
+ DialogBodyProps,
+ DialogFooterProps,
+ DialogHeaderProps,
+ DialogTitleProps,
+} from "./dialog"
+import { Dialog } from "./dialog"
-type PopoverProps = DialogTriggerProps;
-const Popover = ({ children, ...props }: PopoverProps) => {
- return {children} ;
-};
+type PopoverProps = DialogTriggerProps
+const Popover = (props: PopoverProps) => {
+ return
+}
-const Title = ({ level = 2, className, ...props }: DialogTitleProps) => (
-
-);
+const PopoverTitle = ({ level = 2, className, ...props }: DialogTitleProps) => (
+
+)
-const Header = ({ className, ...props }: DialogHeaderProps) => (
-
-);
+const PopoverHeader = ({ className, ...props }: DialogHeaderProps) => (
+
+)
-const Footer = ({ className, ...props }: DialogFooterProps) => (
-
-);
+const PopoverFooter = ({ className, ...props }: DialogFooterProps) => (
+
+)
-const Body = ({ className, ref, ...props }: DialogBodyProps) => (
-
-);
+const PopoverBody = ({ className, ref, ...props }: DialogBodyProps) => (
+
+)
const content = tv({
base: [
- 'peer/popover-content max-w-xs rounded-xl border bg-overlay bg-clip-padding text-overlay-fg shadow-xs transition-transform [scrollbar-width:thin] sm:max-w-3xl sm:text-sm dark:backdrop-saturate-200 forced-colors:bg-[Canvas] [&::-webkit-scrollbar]:size-0.5'
+ "peer/popover-content max-w-xs rounded-xl border bg-overlay bg-clip-padding text-overlay-fg shadow-xs transition-transform [scrollbar-width:thin] sm:max-w-3xl sm:text-sm dark:backdrop-saturate-200 forced-colors:bg-[Canvas] [&::-webkit-scrollbar]:size-0.5",
],
variants: {
isPicker: {
- true: 'max-h-72 min-w-(--trigger-width) overflow-y-auto',
- false: 'min-w-80'
+ true: "max-h-72 min-w-(--trigger-width) overflow-y-auto",
+ false: "min-w-80",
},
isMenu: {
- true: 'p-0'
+ true: "",
},
isEntering: {
true: [
- 'fade-in animate-in duration-150 ease-out',
- 'data-[placement=left]:slide-in-from-right-1 data-[placement=right]:slide-in-from-left-1 data-[placement=top]:slide-in-from-bottom-1 data-[placement=bottom]:slide-in-from-top-1'
- ]
+ "fade-in animate-in duration-150 ease-out",
+ "data-[placement=left]:slide-in-from-right-1 data-[placement=right]:slide-in-from-left-1 data-[placement=top]:slide-in-from-bottom-1 data-[placement=bottom]:slide-in-from-top-1",
+ ],
},
isExiting: {
true: [
- 'fade-out animate-out duration-100 ease-in',
- 'data-[placement=left]:slide-out-to-right-1 data-[placement=right]:slide-out-to-left-1 data-[placement=top]:slide-out-to-bottom-1 data-[placement=bottom]:slide-out-to-top-1'
- ]
- }
- }
-});
+ "fade-out animate-out duration-100 ease-in",
+ "data-[placement=left]:slide-out-to-right-1 data-[placement=right]:slide-out-to-left-1 data-[placement=top]:slide-out-to-bottom-1 data-[placement=bottom]:slide-out-to-top-1",
+ ],
+ },
+ },
+})
const drawer = tv({
base: [
- 'fixed top-auto bottom-0 z-50 max-h-full w-full max-w-2xl border border-b-transparent bg-overlay outline-hidden'
+ "fixed top-auto bottom-0 z-50 max-h-full w-full max-w-2xl border border-b-transparent bg-overlay outline-hidden",
],
variants: {
isMenu: {
- true: 'rounded-t-xl p-0 [&_[role=dialog]]:*:not-has-[[data-slot=dialog-body]]:px-1',
- false: 'rounded-t-2xl'
+ true: "rounded-t-xl p-0 [&_[role=dialog]]:*:not-has-[[data-slot=dialog-body]]:px-1",
+ false: "rounded-t-2xl",
},
isEntering: {
true: [
- '[transition:transform_0.5s_cubic-bezier(0.32,_0.72,_0,_1)] [will-change:transform]',
- 'fade-in-0 slide-in-from-bottom-56 animate-in duration-200',
- '[transition:translate3d(0,_100%,_0)]',
- 'sm:slide-in-from-bottom-auto sm:slide-in-from-top-[20%]'
- ]
+ "[transition:transform_0.5s_cubic-bezier(0.32,_0.72,_0,_1)] [will-change:transform]",
+ "fade-in-0 slide-in-from-bottom-56 animate-in duration-200",
+ "[transition:translate3d(0,_100%,_0)]",
+ "sm:slide-in-from-bottom-auto sm:slide-in-from-top-[20%]",
+ ],
},
isExiting: {
- true: 'slide-out-to-bottom-56 animate-out duration-200 ease-in'
- }
- }
-});
+ true: "slide-out-to-bottom-56 animate-out duration-200 ease-in",
+ },
+ },
+})
interface PopoverContentProps
- extends Omit, 'children'>,
- Omit,
- Omit {
- children: React.ReactNode;
- showArrow?: boolean;
- style?: React.CSSProperties;
- respectScreen?: boolean;
- 'aria-label'?: DialogProps['aria-label'];
- 'aria-labelledby'?: DialogProps['aria-labelledby'];
- className?: string | ((values: { defaultClassName?: string }) => string);
+ extends Omit,
+ Omit,
+ Pick {
+ children: React.ReactNode
+ showArrow?: boolean
+ style?: React.CSSProperties
+ respectScreen?: boolean
+ className?: string | ((values: { defaultClassName?: string }) => string)
}
const PopoverContent = ({
@@ -113,13 +119,13 @@ const PopoverContent = ({
className,
...props
}: PopoverContentProps) => {
- const isMobile = useMediaQuery('(max-width: 600px)');
- const popoverContext = useSlottedContext(PopoverContext)!;
- const isMenuTrigger = popoverContext?.trigger === 'MenuTrigger';
- const isSubmenuTrigger = popoverContext?.trigger === 'SubmenuTrigger';
- const isMenu = isMenuTrigger || isSubmenuTrigger;
- const offset = showArrow ? 12 : 8;
- const effectiveOffset = isSubmenuTrigger ? offset - 5 : offset;
+ const isMobile = useMediaQuery("(max-width: 600px)")
+ const popoverContext = useSlottedContext(PopoverContext)!
+ const isMenuTrigger = popoverContext?.trigger === "MenuTrigger"
+ const isSubmenuTrigger = popoverContext?.trigger === "SubmenuTrigger"
+ const isMenu = isMenuTrigger || isSubmenuTrigger
+ const offset = showArrow ? 12 : 8
+ const effectiveOffset = isSubmenuTrigger ? offset - 5 : offset
return isMobile && respectScreen ? (
- drawer({ ...renderProps, isMenu, className })
+ drawer({ ...renderProps, isMenu, className }),
)}
>
-
+
{children}
@@ -139,13 +145,13 @@ const PopoverContent = ({
) : (
content({
...renderProps,
- className
- })
+ className,
+ }),
)}
+ {...props}
>
{showArrow && (
@@ -159,40 +165,25 @@ const PopoverContent = ({
)}
-
+
{children}
- );
-};
+ )
+}
-const Picker = ({ children, className, ...props }: PopoverContentProps) => {
- return (
-
- content({
- ...renderProps,
- isPicker: true,
- className
- })
- )}
- >
- {children}
-
- );
-};
+const PopoverTrigger = Dialog.Trigger
+const PopoverClose = Dialog.Close
+const PopoverDescription = Dialog.Description
-Popover.Primitive = PopoverPrimitive;
-Popover.Trigger = Dialog.Trigger;
-Popover.Close = Dialog.Close;
-Popover.Content = PopoverContent;
-Popover.Description = Dialog.Description;
-Popover.Body = Body;
-Popover.Footer = Footer;
-Popover.Header = Header;
-Popover.Picker = Picker;
-Popover.Title = Title;
+Popover.Trigger = PopoverTrigger
+Popover.Close = PopoverClose
+Popover.Description = PopoverDescription
+Popover.Content = PopoverContent
+Popover.Body = PopoverBody
+Popover.Footer = PopoverFooter
+Popover.Header = PopoverHeader
+Popover.Title = PopoverTitle
-export { Popover };
-export type { PopoverContentProps, PopoverProps };
+export { Popover, PopoverContent }
+export type { PopoverContentProps, PopoverProps }
diff --git a/resources/js/components/ui/primitive.tsx b/resources/js/components/ui/primitive.tsx
index 0d07ce7..190d16b 100644
--- a/resources/js/components/ui/primitive.tsx
+++ b/resources/js/components/ui/primitive.tsx
@@ -1,38 +1,38 @@
-import { composeRenderProps } from 'react-aria-components';
-import { twMerge } from 'tailwind-merge';
-import { tv } from 'tailwind-variants';
+import { composeRenderProps } from "react-aria-components"
+import { twMerge } from "tailwind-merge"
+import { tv } from "tailwind-variants"
function composeTailwindRenderProps(
className: string | ((v: T) => string) | undefined,
- tailwind: string
+ tailwind: string,
): string | ((v: T) => string) {
- return composeRenderProps(className, (className) => twMerge(tailwind, className));
+ return composeRenderProps(className, (className) => twMerge(tailwind, className))
}
const focusRing = tv({
variants: {
- isFocused: { true: 'outline-hidden ring-4 ring-ring/20 data-invalid:ring-danger/20' },
- isFocusVisible: { true: 'outline-hidden ring-4 ring-ring/20' },
- isInvalid: { true: 'ring-4 ring-danger/20' }
- }
-});
+ isFocused: { true: "outline-hidden ring-4 ring-ring/20 data-invalid:ring-danger/20" },
+ isFocusVisible: { true: "outline-hidden ring-4 ring-ring/20" },
+ isInvalid: { true: "ring-4 ring-danger/20" },
+ },
+})
const focusStyles = tv({
extend: focusRing,
variants: {
- isFocused: { true: 'border-ring/70 forced-colors:border-[Highlight]' },
- isInvalid: { true: 'border-danger/70 forced-colors:border-[Mark]' }
- }
-});
+ isFocused: { true: "border-ring/70 forced-colors:border-[Highlight]" },
+ isInvalid: { true: "border-danger/70 forced-colors:border-[Mark]" },
+ },
+})
const focusButtonStyles = tv({
- base: 'outline outline-ring outline-offset-2 forced-colors:outline-[Highlight]',
+ base: "outline outline-ring outline-offset-2 forced-colors:outline-[Highlight]",
variants: {
isFocusVisible: {
- false: 'outline-0',
- true: 'outline-2'
- }
- }
-});
+ false: "outline-0",
+ true: "outline-2",
+ },
+ },
+})
-export { composeTailwindRenderProps, focusButtonStyles, focusRing, focusStyles };
+export { composeTailwindRenderProps, focusButtonStyles, focusRing, focusStyles }
diff --git a/resources/js/components/ui/select.tsx b/resources/js/components/ui/select.tsx
index 67055a9..d40e8a7 100644
--- a/resources/js/components/ui/select.tsx
+++ b/resources/js/components/ui/select.tsx
@@ -1,78 +1,107 @@
-import { IconChevronLgDown } from 'justd-icons';
-import type { ListBoxProps, SelectProps as SelectPrimitiveProps, ValidationResult } from 'react-aria-components';
-import { Button, composeRenderProps, Select as SelectPrimitive, SelectValue } from 'react-aria-components';
-import { tv } from 'tailwind-variants';
-
-import type { Placement } from '@react-types/overlays';
-import { DropdownItem, DropdownItemDetails, DropdownLabel, DropdownSection, DropdownSeparator } from './dropdown';
-import { Description, FieldError, Label } from './field';
-import { ListBox } from './list-box';
-import { Popover } from './popover';
-import { composeTailwindRenderProps, focusStyles } from './primitive';
+import { cn } from "@/utils/classes"
+import { IconChevronLgDown } from "justd-icons"
+import type {
+ ListBoxProps,
+ PopoverProps,
+ SelectProps as SelectPrimitiveProps,
+ ValidationResult,
+} from "react-aria-components"
+import {
+ Button,
+ Select as SelectPrimitive,
+ SelectValue,
+ composeRenderProps,
+} from "react-aria-components"
+import { tv } from "tailwind-variants"
+import {
+ DropdownItem,
+ DropdownItemDetails,
+ DropdownLabel,
+ DropdownSection,
+ DropdownSeparator,
+} from "./dropdown"
+import { Description, FieldError, Label } from "./field"
+import { ListBox } from "./list-box"
+import { PopoverContent } from "./popover"
+import { composeTailwindRenderProps, focusStyles } from "./primitive"
const selectTriggerStyles = tv({
extend: focusStyles,
base: [
- 'btr flex h-10 w-full cursor-default items-center items-center gap-4 gap-x-2 rounded-lg border border-input py-2 pr-2 pl-3 text-start shadow-[inset_0_1px_0_0_rgba(255,255,255,0.1)] transition **:data-[slot=icon]:size-4 group-data-disabled:opacity-50 dark:shadow-none',
- 'group-data-open:border-ring/70 group-data-open:ring-4 group-data-open:ring-ring/20',
- 'text-fg group-data-invalid:border-danger group-data-invalid:ring-danger/20 forced-colors:group-data-invalid:border-[Mark]'
+ "btr flex h-10 w-full cursor-default items-center gap-4 gap-x-2 rounded-lg border border-input py-2 pr-2 pl-3 text-start shadow-[inset_0_1px_0_0_rgba(255,255,255,0.1)] transition **:data-[slot=icon]:size-4 group-data-disabled:opacity-50 dark:shadow-none",
+ "group-data-open:border-ring/70 group-data-open:ring-4 group-data-open:ring-ring/20",
+ "text-fg group-data-invalid:border-danger group-data-invalid:ring-danger/20 forced-colors:group-data-invalid:border-[Mark]",
],
variants: {
isDisabled: {
- true: 'opacity-50 forced-colors:border-[GrayText] forced-colors:text-[GrayText]'
- }
- }
-});
+ true: "opacity-50 forced-colors:border-[GrayText] forced-colors:text-[GrayText]",
+ },
+ },
+})
interface SelectProps extends SelectPrimitiveProps {
- label?: string;
- description?: string;
- errorMessage?: string | ((validation: ValidationResult) => string);
- items?: Iterable;
- className?: string;
+ label?: string
+ description?: string
+ errorMessage?: string | ((validation: ValidationResult) => string)
+ items?: Iterable
+ className?: string
}
const Select = ({
label,
description,
errorMessage,
- children,
className,
...props
}: SelectProps) => {
return (
- {label && {label} }
- {children as React.ReactNode}
- {description && {description} }
- {errorMessage}
+ {(values) => (
+ <>
+ {label && {label} }
+ {typeof props.children === "function" ? props.children(values) : props.children}
+ {description && {description} }
+ {errorMessage}
+ >
+ )}
- );
-};
+ )
+}
-interface ListProps extends ListBoxProps {
- items?: Iterable;
- placement?: Placement;
- children: React.ReactNode | ((item: T) => React.ReactNode);
- className?: string;
+interface SelectListProps
+ extends ListBoxProps,
+ Pick {
+ items?: Iterable
+ popoverClassName?: PopoverProps["className"]
}
-const List = ({ className, children, items, placement, ...props }: ListProps) => {
+const SelectList = ({
+ children,
+ items,
+ className,
+ popoverClassName,
+ ...props
+}: SelectListProps) => {
return (
-
-
+
+
{children}
-
-
- );
-};
+
+
+ )
+}
interface SelectTriggerProps extends React.ComponentProps {
- prefix?: React.ReactNode;
- className?: string;
+ prefix?: React.ReactNode
+ className?: string
}
const SelectTrigger = ({ className, ...props }: SelectTriggerProps) => {
@@ -81,8 +110,8 @@ const SelectTrigger = ({ className, ...props }: SelectTriggerProps) => {
className={composeRenderProps(className, (className, renderProps) =>
selectTriggerStyles({
...renderProps,
- className
- })
+ className,
+ }),
)}
>
{props.prefix && {props.prefix} }
@@ -92,16 +121,22 @@ const SelectTrigger = ({ className, ...props }: SelectTriggerProps) => {
className="size-4 shrink-0 text-muted-fg duration-300 group-data-open:rotate-180 group-data-open:text-fg group-data-disabled:opacity-50 forced-colors:text-[ButtonText] forced-colors:group-data-disabled:text-[GrayText]"
/>
- );
-};
+ )
+}
+
+const SelectSection = DropdownSection
+const SelectSeparator = DropdownSeparator
+const SelectLabel = DropdownLabel
+const SelectOptionDetails = DropdownItemDetails
+const SelectOption = DropdownItem
-Select.OptionDetails = DropdownItemDetails;
-Select.Option = DropdownItem;
-Select.Label = DropdownLabel;
-Select.Separator = DropdownSeparator;
-Select.Section = DropdownSection;
-Select.Trigger = SelectTrigger;
-Select.List = List;
+Select.OptionDetails = SelectOptionDetails
+Select.Option = SelectOption
+Select.Label = SelectLabel
+Select.Separator = SelectSeparator
+Select.Section = SelectSection
+Select.Trigger = SelectTrigger
+Select.List = SelectList
-export { Select };
-export type { SelectProps, SelectTriggerProps };
+export { Select }
+export type { SelectProps, SelectTriggerProps }
diff --git a/resources/js/components/ui/separator.tsx b/resources/js/components/ui/separator.tsx
index ebaec4c..c8f2be0 100644
--- a/resources/js/components/ui/separator.tsx
+++ b/resources/js/components/ui/separator.tsx
@@ -1,21 +1,21 @@
-import { Separator as Divider, type SeparatorProps as DividerProps } from 'react-aria-components';
-import { tv } from 'tailwind-variants';
+import { Separator as Divider, type SeparatorProps as DividerProps } from "react-aria-components"
+import { tv } from "tailwind-variants"
const separatorStyles = tv({
- base: 'shrink-0 bg-border forced-colors:bg-[ButtonBorder]',
+ base: "shrink-0 bg-border forced-colors:bg-[ButtonBorder]",
variants: {
orientation: {
- horizontal: 'h-px w-full',
- vertical: 'w-px'
- }
+ horizontal: "h-px w-full",
+ vertical: "w-px",
+ },
},
defaultVariants: {
- orientation: 'horizontal'
- }
-});
+ orientation: "horizontal",
+ },
+})
interface SeparatorProps extends DividerProps {
- className?: string;
+ className?: string
}
const Separator = ({ className, ...props }: SeparatorProps) => {
@@ -24,11 +24,11 @@ const Separator = ({ className, ...props }: SeparatorProps) => {
{...props}
className={separatorStyles({
orientation: props.orientation,
- className: className
+ className: className,
})}
/>
- );
-};
+ )
+}
-export { Separator };
-export type { SeparatorProps };
+export { Separator }
+export type { SeparatorProps }
diff --git a/resources/js/components/ui/sheet.tsx b/resources/js/components/ui/sheet.tsx
index d5966c3..c80415e 100644
--- a/resources/js/components/ui/sheet.tsx
+++ b/resources/js/components/ui/sheet.tsx
@@ -1,101 +1,101 @@
-import type { DialogProps, DialogTriggerProps, ModalOverlayProps } from 'react-aria-components';
-import { composeRenderProps, DialogTrigger, Modal, ModalOverlay } from 'react-aria-components';
-import { tv, type VariantProps } from 'tailwind-variants';
+import type { DialogProps, DialogTriggerProps, ModalOverlayProps } from "react-aria-components"
+import { DialogTrigger, Modal, ModalOverlay, composeRenderProps } from "react-aria-components"
+import { type VariantProps, tv } from "tailwind-variants"
-import { Dialog } from './dialog';
+import { Dialog } from "./dialog"
const overlayStyles = tv({
base: [
- 'fixed top-0 left-0 isolate z-50 flex h-(--visual-viewport-height) w-full items-center justify-center bg-fg/15 p-4 dark:bg-bg/40'
+ "fixed top-0 left-0 isolate z-50 flex h-(--visual-viewport-height) w-full items-center justify-center bg-fg/15 p-4 dark:bg-bg/40",
],
variants: {
isBlurred: {
- true: 'bg-bg/15 backdrop-blur dark:bg-bg/40'
+ true: "bg-bg/15 backdrop-blur dark:bg-bg/40",
},
isEntering: {
- true: 'fade-in animate-in duration-300 ease-out'
+ true: "fade-in animate-in duration-300 ease-out",
},
isExiting: {
- true: 'fade-out animate-out duration-200 ease-in'
- }
- }
-});
+ true: "fade-out animate-out duration-200 ease-in",
+ },
+ },
+})
-type Sides = 'top' | 'bottom' | 'left' | 'right';
+type Sides = "top" | "bottom" | "left" | "right"
const generateCompoundVariants = (sides: Array) => {
return sides.map((side) => ({
side,
isFloat: true,
className:
- side === 'top'
- ? 'top-2 inset-x-2 rounded-xl ring-1 border-b-0'
- : side === 'bottom'
- ? 'bottom-2 inset-x-2 rounded-xl ring-1 border-t-0'
- : side === 'left'
- ? 'left-2 inset-y-2 rounded-xl ring-1 border-r-0'
- : 'right-2 inset-y-2 rounded-xl ring-1 border-l-0'
- }));
-};
+ side === "top"
+ ? "top-2 inset-x-2 rounded-xl ring-1 border-b-0"
+ : side === "bottom"
+ ? "bottom-2 inset-x-2 rounded-xl ring-1 border-t-0"
+ : side === "left"
+ ? "left-2 inset-y-2 rounded-xl ring-1 border-r-0"
+ : "right-2 inset-y-2 rounded-xl ring-1 border-l-0",
+ }))
+}
const contentStyles = tv({
- base: 'fixed z-50 grid gap-4 border-fg/5 bg-overlay text-overlay-fg shadow-lg transition ease-in-out dark:border-border',
+ base: "fixed z-50 grid gap-4 border-fg/5 bg-overlay text-overlay-fg shadow-lg transition ease-in-out dark:border-border",
variants: {
isEntering: {
- true: 'animate-in duration-300 '
+ true: "animate-in duration-300 ",
},
isExiting: {
- true: 'animate-out duration-200'
+ true: "animate-out duration-200",
},
side: {
- top: 'data-entering:slide-in-from-top data-exiting:slide-out-to-top inset-x-0 top-0 rounded-b-2xl border-b',
+ top: "data-entering:slide-in-from-top data-exiting:slide-out-to-top inset-x-0 top-0 rounded-b-2xl border-b",
bottom:
- 'data-entering:slide-in-from-bottom data-exiting:slide-out-to-bottom inset-x-0 bottom-0 rounded-t-2xl border-t',
- left: 'data-entering:slide-in-from-left data-exiting:slide-out-to-left inset-y-0 left-0 h-auto w-full max-w-xs overflow-y-auto border-r',
+ "data-entering:slide-in-from-bottom data-exiting:slide-out-to-bottom inset-x-0 bottom-0 rounded-t-2xl border-t",
+ left: "data-entering:slide-in-from-left data-exiting:slide-out-to-left inset-y-0 left-0 h-auto w-full max-w-xs overflow-y-auto border-r",
right:
- 'data-entering:slide-in-from-right data-exiting:slide-out-to-right inset-y-0 right-0 h-auto w-full max-w-xs overflow-y-auto border-l'
+ "data-entering:slide-in-from-right data-exiting:slide-out-to-right inset-y-0 right-0 h-auto w-full max-w-xs overflow-y-auto border-l",
},
isFloat: {
- false: 'border-fg/20 dark:border-border',
- true: 'ring-fg/5 dark:ring-border'
- }
+ false: "border-fg/20 dark:border-border",
+ true: "ring-fg/5 dark:ring-border",
+ },
},
- compoundVariants: generateCompoundVariants(['top', 'bottom', 'left', 'right'])
-});
+ compoundVariants: generateCompoundVariants(["top", "bottom", "left", "right"]),
+})
-type SheetProps = DialogTriggerProps;
+type SheetProps = DialogTriggerProps
const Sheet = (props: SheetProps) => {
- return ;
-};
+ return
+}
interface SheetContentProps
- extends Omit, 'children' | 'className'>,
- Omit,
+ extends Omit, "children" | "className">,
+ Omit,
VariantProps {
- 'aria-label'?: DialogProps['aria-label'];
- 'aria-labelledby'?: DialogProps['aria-labelledby'];
- role?: DialogProps['role'];
- closeButton?: boolean;
- isBlurred?: boolean;
- isFloat?: boolean;
- side?: Sides;
+ "aria-label"?: DialogProps["aria-label"]
+ "aria-labelledby"?: DialogProps["aria-labelledby"]
+ role?: DialogProps["role"]
+ closeButton?: boolean
+ isBlurred?: boolean
+ isFloat?: boolean
+ side?: Sides
classNames?: {
- overlay?: ModalOverlayProps['className'];
- content?: ModalOverlayProps['className'];
- };
+ overlay?: ModalOverlayProps["className"]
+ content?: ModalOverlayProps["className"]
+ }
}
const SheetContent = ({
classNames,
isBlurred = false,
isDismissable = true,
- side = 'right',
- role = 'dialog',
+ side = "right",
+ role = "dialog",
closeButton = true,
isFloat = true,
children,
...props
}: SheetContentProps) => {
- const _isDismissable = role === 'alertdialog' ? false : isDismissable;
+ const _isDismissable = role === "alertdialog" ? false : isDismissable
return (
@@ -114,32 +114,45 @@ const SheetContent = ({
...renderProps,
side,
isFloat,
- className
- })
+ className,
+ }),
)}
{...props}
>
{(values) => (
-
+
<>
- {typeof children === 'function' ? children(values) : children}
- {closeButton && }
+ {typeof children === "function" ? children(values) : children}
+ {closeButton && (
+
+ )}
>
)}
- );
-};
+ )
+}
+
+const SheetTrigger = Dialog.Trigger
+const SheetFooter = Dialog.Footer
+const SheetHeader = Dialog.Header
+const SheetTitle = Dialog.Title
+const SheetDescription = Dialog.Description
+const SheetBody = Dialog.Body
+const SheetClose = Dialog.Close
-Sheet.Trigger = Dialog.Trigger;
-Sheet.Footer = Dialog.Footer;
-Sheet.Content = SheetContent;
-Sheet.Header = Dialog.Header;
-Sheet.Title = Dialog.Title;
-Sheet.Description = Dialog.Description;
-Sheet.Body = Dialog.Body;
-Sheet.Close = Dialog.Close;
+Sheet.Trigger = SheetTrigger
+Sheet.Footer = SheetFooter
+Sheet.Header = SheetHeader
+Sheet.Title = SheetTitle
+Sheet.Description = SheetDescription
+Sheet.Body = SheetBody
+Sheet.Close = SheetClose
+Sheet.Content = SheetContent
-export { Sheet };
-export type { SheetContentProps, SheetProps, Sides };
+export { Sheet }
+export type { SheetContentProps, SheetProps, Sides }
diff --git a/resources/js/components/ui/table.tsx b/resources/js/components/ui/table.tsx
index b3a9393..fc25780 100644
--- a/resources/js/components/ui/table.tsx
+++ b/resources/js/components/ui/table.tsx
@@ -1,6 +1,6 @@
-import React from 'react';
+import React from "react"
-import { IconChevronLgDown, IconHamburger } from 'justd-icons';
+import { IconChevronLgDown, IconHamburger } from "justd-icons"
import type {
CellProps,
ColumnProps,
@@ -8,53 +8,53 @@ import type {
TableHeaderProps as HeaderProps,
RowProps,
TableBodyProps,
- TableProps as TablePrimitiveProps
-} from 'react-aria-components';
+ TableProps as TablePrimitiveProps,
+} from "react-aria-components"
import {
Button,
Cell,
Collection,
Column,
ColumnResizer as ColumnResizerPrimitive,
- composeRenderProps,
ResizableTableContainer,
Row,
- TableBody,
- TableHeader,
+ TableBody as TableBodyPrimitive,
+ TableHeader as TableHeaderPrimitive,
Table as TablePrimitive,
- useTableOptions
-} from 'react-aria-components';
-import { tv } from 'tailwind-variants';
+ composeRenderProps,
+ useTableOptions,
+} from "react-aria-components"
+import { tv } from "tailwind-variants"
-import { cn } from '@/utils/classes';
-import { Checkbox } from './checkbox';
+import { cn } from "@/utils/classes"
+import { Checkbox } from "./checkbox"
const table = tv({
slots: {
- root: 'table w-full min-w-full caption-bottom border-spacing-0 text-sm outline-hidden [--table-selected-bg:color-mix(in_oklab,var(--color-primary)_5%,white_90%)] **:data-drop-target:border **:data-drop-target:border-primary dark:[--table-selected-bg:color-mix(in_oklab,var(--color-primary)_25%,black_70%)]',
- header: 'x32 border-b',
- row: 'tr group relative cursor-default border-b bg-bg text-fg/70 outline-hidden ring-primary data-selected:data-hovered:bg-(--table-selected-bg)/70 data-selected:bg-(--table-selected-bg) data-focus-visible:ring-1 data-focused:ring-0 dark:data-selected:data-hovered:bg-[color-mix(in_oklab,var(--color-primary)_40%,black_60%)] dark:data-selected:data-hovered:bg-subtle/60',
+ root: "table w-full min-w-full caption-bottom border-spacing-0 text-sm outline-hidden [--table-selected-bg:color-mix(in_oklab,var(--color-primary)_5%,white_90%)] **:data-drop-target:border **:data-drop-target:border-primary dark:[--table-selected-bg:color-mix(in_oklab,var(--color-primary)_25%,black_70%)]",
+ header: "x32 border-b",
+ row: "tr group relative cursor-default border-b bg-bg text-muted-fg outline-hidden ring-primary data-selected:data-hovered:bg-(--table-selected-bg)/70 data-selected:bg-(--table-selected-bg) data-focus-visible:ring-1 data-focused:ring-0 dark:data-selected:data-hovered:bg-[color-mix(in_oklab,var(--color-primary)_30%,black_70%)]",
cellIcon:
- 'grid size-[1.15rem] flex-none shrink-0 place-content-center rounded bg-secondary text-fg *:data-[slot=icon]:size-3.5 *:data-[slot=icon]:shrink-0 *:data-[slot=icon]:transition-transform *:data-[slot=icon]:duration-200',
+ "grid size-[1.15rem] flex-none shrink-0 place-content-center rounded bg-secondary text-fg *:data-[slot=icon]:size-3.5 *:data-[slot=icon]:shrink-0 *:data-[slot=icon]:transition-transform *:data-[slot=icon]:duration-200",
columnResizer: [
- 'absolute top-0 right-0 bottom-0 grid w-px touch-none place-content-center px-1 [&[data-resizing]>div]:bg-primary',
- '&[data-resizable-direction=left]:cursor-e-resize &[data-resizable-direction=right]:cursor-w-resize data-[resizable-direction=both]:cursor-ew-resize'
- ]
- }
-});
+ "absolute top-0 right-0 bottom-0 grid w-px touch-none place-content-center px-1 [&[data-resizing]>div]:bg-primary",
+ "&[data-resizable-direction=left]:cursor-e-resize &[data-resizable-direction=right]:cursor-w-resize data-[resizable-direction=both]:cursor-ew-resize",
+ ],
+ },
+})
-const { root, header, row, cellIcon, columnResizer } = table();
+const { root, header, row, cellIcon, columnResizer } = table()
interface TableProps extends TablePrimitiveProps {
- className?: string;
- allowResize?: boolean;
+ className?: string
+ allowResize?: boolean
}
const TableContext = React.createContext({
- allowResize: false
-});
+ allowResize: false,
+})
-const useTableContext = () => React.useContext(TableContext);
+const useTableContext = () => React.useContext(TableContext)
const Table = ({ children, className, ...props }: TableProps) => (
@@ -72,7 +72,7 @@ const Table = ({ children, className, ...props }: TableProps) => (
)}
-);
+)
const ColumnResizer = ({ className, ...props }: ColumnResizerProps) => (
(
className={composeRenderProps(className, (className, renderProps) =>
columnResizer({
...renderProps,
- className
- })
+ className,
+ }),
)}
>
-);
+)
-const Body = (props: TableBodyProps) => (
-
-);
+const TableBody = (props: TableBodyProps) => (
+
+)
interface TableCellProps extends CellProps {
- className?: string;
+ className?: string
}
const cellStyles = tv({
- base: 'group whitespace-nowrap px-3 py-3 outline-hidden',
+ base: "group whitespace-nowrap px-3 py-3 outline-hidden",
variants: {
allowResize: {
- true: 'overflow-hidden truncate'
- }
- }
-});
+ true: "overflow-hidden truncate",
+ },
+ },
+})
const TableCell = ({ children, className, ...props }: TableCellProps) => {
- const { allowResize } = useTableContext();
+ const { allowResize } = useTableContext()
return (
{children}
|
- );
-};
+ )
+}
const columnStyles = tv({
- base: 'relative allows-sorting:cursor-pointer whitespace-nowrap px-3 py-3 text-left font-medium outline-hidden data-dragging:cursor-grabbing [&:has([slot=selection])]:pr-0',
+ base: "relative allows-sorting:cursor-pointer whitespace-nowrap px-3 py-3 text-left font-medium outline-hidden data-dragging:cursor-grabbing [&:has([slot=selection])]:pr-0",
variants: {
isResizable: {
- true: 'overflow-hidden truncate'
- }
- }
-});
+ true: "overflow-hidden truncate",
+ },
+ },
+})
interface TableColumnProps extends ColumnProps {
- className?: string;
- isResizable?: boolean;
+ className?: string
+ isResizable?: boolean
}
const TableColumn = ({ isResizable = false, className, ...props }: TableColumnProps) => {
@@ -134,7 +138,7 @@ const TableColumn = ({ isResizable = false, className, ...props }: TableColumnPr
{...props}
className={columnStyles({
isResizable,
- className
+ className,
})}
>
{({ allowsSorting, sortDirection, isHovered }) => (
@@ -142,8 +146,8 @@ const TableColumn = ({ isResizable = false, className, ...props }: TableColumnPr
<>
{props.children as React.ReactNode}
{allowsSorting && (
-
-
+
+
)}
{isResizable && }
@@ -151,34 +155,54 @@ const TableColumn = ({ isResizable = false, className, ...props }: TableColumnPr
)}
- );
-};
+ )
+}
interface TableHeaderProps extends HeaderProps {
- className?: string;
- ref?: React.Ref;
+ className?: string
+ ref?: React.Ref
}
-const Header = ({ children, ref, className, columns, ...props }: TableHeaderProps) => {
- const { selectionBehavior, selectionMode, allowsDragging } = useTableOptions();
+const TableHeader = ({
+ children,
+ ref,
+ className,
+ columns,
+ ...props
+}: TableHeaderProps) => {
+ const { selectionBehavior, selectionMode, allowsDragging } = useTableOptions()
return (
-
+
{allowsDragging && }
- {selectionBehavior === 'toggle' && (
- {selectionMode === 'multiple' && }
+ {selectionBehavior === "toggle" && (
+
+ {selectionMode === "multiple" && }
+
)}
{children}
-
- );
-};
+
+ )
+}
interface TableRowProps extends RowProps {
- className?: string;
- ref?: React.Ref;
+ className?: string
+ ref?: React.Ref
}
-const TableRow = ({ children, className, columns, id, ref, ...props }: TableRowProps) => {
- const { selectionBehavior, allowsDragging } = useTableOptions();
+const TableRow = ({
+ children,
+ className,
+ columns,
+ id,
+ ref,
+ ...props
+}: TableRowProps) => {
+ const { selectionBehavior, allowsDragging } = useTableOptions()
return (
({ children, className, columns, id, ref, ...
{...props}
className={row({
className:
- 'href' in props
- ? cn('cursor-pointer data-hovered:bg-secondary/50 data-hovered:text-secondary-fg', className)
- : ''
+ "href" in props
+ ? cn(
+ "cursor-pointer data-hovered:bg-secondary/50 data-hovered:text-secondary-fg",
+ className,
+ )
+ : "",
})}
>
{allowsDragging && (
-
+
|
)}
- {selectionBehavior === 'toggle' && (
+ {selectionBehavior === "toggle" && (
({ children, className, columns, id, ref, ...
)}
{children}
|
- );
-};
+ )
+}
-Table.Body = Body;
-Table.Cell = TableCell;
-Table.Column = TableColumn;
-Table.Header = Header;
-Table.Row = TableRow;
+Table.Body = TableBody
+Table.Cell = TableCell
+Table.Column = TableColumn
+Table.Header = TableHeader
+Table.Row = TableRow
-export { Table };
-export type { TableBodyProps, TableCellProps, TableColumnProps, TableProps, TableRowProps };
+export { Table }
+export type { TableBodyProps, TableCellProps, TableColumnProps, TableProps, TableRowProps }
diff --git a/resources/js/components/ui/text-field.tsx b/resources/js/components/ui/text-field.tsx
index ea1fc3c..6d6eb7d 100644
--- a/resources/js/components/ui/text-field.tsx
+++ b/resources/js/components/ui/text-field.tsx
@@ -1,39 +1,38 @@
-import { useState } from 'react';
+import { useState } from "react"
-import type { TextInputDOMProps } from '@react-types/shared';
-import { IconEye, IconEyeClosed } from 'justd-icons';
+import type { TextInputDOMProps } from "@react-types/shared"
+import { IconEye, IconEyeClosed } from "justd-icons"
import {
Button as ButtonPrimitive,
TextField as TextFieldPrimitive,
- type TextFieldProps as TextFieldPrimitiveProps
-} from 'react-aria-components';
-import { twJoin } from 'tailwind-merge';
+ type TextFieldProps as TextFieldPrimitiveProps,
+} from "react-aria-components"
-import type { FieldProps } from './field';
-import { Description, FieldError, FieldGroup, Input, Label } from './field';
-import { Loader } from './loader';
-import { composeTailwindRenderProps } from './primitive';
+import type { FieldProps } from "./field"
+import { Description, FieldError, FieldGroup, Input, Label } from "./field"
+import { Loader } from "./loader"
+import { composeTailwindRenderProps } from "./primitive"
-type InputType = Exclude;
+type InputType = Exclude
interface BaseTextFieldProps extends TextFieldPrimitiveProps, FieldProps {
- prefix?: React.ReactNode;
- suffix?: React.ReactNode;
- isPending?: boolean;
- className?: string;
+ prefix?: React.ReactNode
+ suffix?: React.ReactNode
+ isPending?: boolean
+ className?: string
}
interface RevealableTextFieldProps extends BaseTextFieldProps {
- isRevealable: true;
- type: 'password';
+ isRevealable: true
+ type: "password"
}
interface NonRevealableTextFieldProps extends BaseTextFieldProps {
- isRevealable?: never;
- type?: InputType;
+ isRevealable?: never
+ type?: InputType
}
-type TextFieldProps = RevealableTextFieldProps | NonRevealableTextFieldProps;
+type TextFieldProps = RevealableTextFieldProps | NonRevealableTextFieldProps
const TextField = ({
placeholder,
@@ -48,35 +47,30 @@ const TextField = ({
type,
...props
}: TextFieldProps) => {
- const [isPasswordVisible, setIsPasswordVisible] = useState(false);
- const inputType = isRevealable ? (isPasswordVisible ? 'text' : 'password') : type;
+ const [isPasswordVisible, setIsPasswordVisible] = useState(false)
+ const inputType = isRevealable ? (isPasswordVisible ? "text" : "password") : type
const handleTogglePasswordVisibility = () => {
- setIsPasswordVisible((prev) => !prev);
- };
+ setIsPasswordVisible((prev) => !prev)
+ }
return (
{!props.children ? (
<>
{label && {label} }
[data-slot=suffix]>button]:mr-[calc(var(--spacing)*-1.7)] [&>[data-slot=suffix]>button]:data-focus-visible:outline-1 [&>[data-slot=suffix]>button]:data-focus-visible:outline-offset-1',
- '[&>[data-slot=prefix]>button]:ml-[calc(var(--spacing)*-1.7)] [&>[data-slot=prefix]>button]:data-focus-visible:outline-1 [&>[data-slot=prefix]>button]:data-focus-visible:outline-offset-1'
- )}
- data-loading={isPending ? 'true' : undefined}
+ isInvalid={!!errorMessage}
+ data-loading={isPending ? "true" : undefined}
>
- {prefix ? (
-
- {prefix}
-
- ) : null}
+ {prefix && typeof prefix === "string" ? (
+ {prefix}
+ ) : (
+ prefix
+ )}
{isRevealable ? (
: }
) : isPending ? (
-
+
) : suffix ? (
- {suffix}
+ typeof suffix === "string" ? (
+ {suffix}
+ ) : (
+ suffix
+ )
) : null}
{description && {description} }
@@ -100,8 +98,8 @@ const TextField = ({
props.children
)}
- );
-};
+ )
+}
-export { TextField };
-export type { TextFieldProps };
+export { TextField }
+export type { TextFieldProps }
diff --git a/resources/js/components/ui/toast.tsx b/resources/js/components/ui/toast.tsx
index ea0958c..d96910c 100644
--- a/resources/js/components/ui/toast.tsx
+++ b/resources/js/components/ui/toast.tsx
@@ -1,21 +1,21 @@
-import { useTheme } from '@/components/theme-provider';
-import { cn } from '@/utils/classes';
+import { useTheme } from "@/components/theme-provider"
+import { cn } from "@/utils/classes"
import {
IconCircleCheckFill,
IconCircleExclamationFill,
IconCircleInfoFill,
- IconTriangleExclamationFill
-} from 'justd-icons';
-import { Toaster as ToasterPrimitive, type ToasterProps } from 'sonner';
+ IconTriangleExclamationFill,
+} from "justd-icons"
+import { Toaster as ToasterPrimitive, type ToasterProps } from "sonner"
-import { buttonStyles } from './button';
-import { Loader } from './loader';
+import { buttonStyles } from "./button"
+import { Loader } from "./loader"
const Toast = ({ ...props }: ToasterProps) => {
- const { theme = 'system' } = useTheme();
+ const { theme = "system" } = useTheme()
return (
{
error: ,
warning: ,
success: ,
- loading:
+ loading: ,
}}
toastOptions={{
unstyled: true,
closeButton: true,
classNames: {
toast: cn(
- 'text-[0.925rem] not-has-data-description:**:data-title:font-normal!',
- 'has-data-description:**:data-title:font-medium [&:has([data-description])_[data-title]]:text-base!',
- 'has-data-[slot=icon]:**:data-content:pl-0',
- 'has-data-button:*:data-content:mb-10',
- 'has-data-button:**:data-close-button:hidden! flex w-full rounded-xl p-4',
- 'inset-ring-1 inset-ring-current/10 backdrop-blur-3xl'
+ "text-[0.925rem] not-has-data-description:**:data-title:font-normal!",
+ "has-data-description:**:data-title:font-medium [&:has([data-description])_[data-title]]:text-base!",
+ "has-data-[slot=icon]:**:data-content:pl-0",
+ "has-data-button:*:data-content:mb-10",
+ "has-data-button:hover:**:data-close-button:hidden! flex w-full rounded-xl p-4",
+ "inset-ring-1 inset-ring-current/10 border-transparent backdrop-blur-3xl",
),
- icon: 'absolute top-[0.2rem] [--toast-icon-margin-end:7px] *:data-[slot=icon]:text-fg *:data-[slot=icon]:size-4.5 **:data-[slot=icon]:text-current',
- title: '',
- description: '',
- default: 'bg-bg text-fg [--gray2:theme(--color-fg/10%)]',
- content: 'pr-6 *:data-description:text-current/65! *:data-description:text-sm!',
+ icon: "absolute top-[0.2rem] [--toast-icon-margin-end:7px] *:data-[slot=icon]:text-fg *:data-[slot=icon]:size-4.5 **:data-[slot=icon]:text-current",
+ title: "",
+ description: "",
+ default: "bg-bg text-fg [--gray2:theme(--color-fg/10%)]",
+ content: "pr-6 *:data-description:text-current/65! *:data-description:text-sm!",
error:
- 'inset-ring-danger/15 dark:inset-ring-danger/25 [--error-bg:theme(--color-danger/10%)] [--error-border:transparent] [--error-text:var(--color-danger)]',
- info: 'inset-ring-sky-600/15 dark:inset-ring-sky-500/20 [--info-border:transparent] [--info-bg:theme(--color-sky-500/10%)] [--info-text:var(--color-sky-700)] dark:[--info-bg:theme(--color-sky-500/15%)] dark:[--info-text:var(--color-sky-400)]',
+ "inset-ring-danger/15 dark:inset-ring-danger/20 [--error-bg:theme(--color-danger/5%)] [--error-text:var(--color-danger)]",
+ info: "inset-ring-sky-600/15 dark:inset-ring-sky-500/20 [--info-bg:theme(--color-sky-500/5%)] [--info-text:var(--color-sky-700)] dark:[--info-text:var(--color-sky-400)]",
warning:
- 'inset-ring-warning/30 dark:inset-ring-warning/15 [--warning-bg:theme(--color-warning/20%)] dark:[--warning-bg:theme(--color-warning/10%)] [--warning-border:transparent] [--warning-text:var(--color-warning-fg)] dark:[--warning-text:var(--color-warning)]',
+ "inset-ring-warning/15 dark:inset-ring-warning/20 [--warning-bg:theme(--color-warning/7%)] [--warning-text:var(--color-warning-fg)] dark:[--warning-text:var(--color-warning)]",
success:
- 'inset-ring-success/20 [--success-bg:theme(--color-success/80%)] dark:[--success-bg:theme(--color-success/20%)] [--success-border:transparent] [--success-text:#fff] dark:[--success-text:var(--color-success)]',
+ "inset-ring-success/15 [--success-bg:theme(--color-success/5%)] [--success-text:var(--color-success)]",
cancelButton: buttonStyles({
className:
- 'hover:border-secondary-fg/10 hover:bg-secondary/90 self-start absolute bottom-4 left-4 justify-self-start',
- size: 'extra-small',
- appearance: 'outline'
+ "hover:border-secondary-fg/10 hover:bg-secondary/90 self-start absolute bottom-4 left-4 justify-self-start",
+ size: "extra-small",
+ appearance: "outline",
}),
actionButton: buttonStyles({
- className: 'absolute bottom-4 right-4 self-end justify-self-end',
- size: 'extra-small'
+ className: "absolute bottom-4 right-4 self-end justify-self-end",
+ size: "extra-small",
}),
closeButton:
- '*:[svg]:size-12 size-6! rounded-md! [--gray1:transparent] [--gray4:transparent] [--gray5:transparent] [--gray12:current] [--toast-close-button-start:full] [--toast-close-button-end:-6px] [--toast-close-button-transform:translate(-75%,60%)] absolute'
- }
+ "*:[svg]:size-5 group-hover:block! hidden! size-6! rounded-md! [--gray1:transparent] [--gray4:transparent] [--gray5:transparent] [--gray12:current] [--toast-close-button-start:full] [--toast-close-button-end:-6px] [--toast-close-button-transform:translate(-75%,60%)] absolute",
+ },
}}
{...props}
/>
- );
-};
+ )
+}
-export { Toast };
-export type { ToasterProps };
+export { Toast }
+export type { ToasterProps }
diff --git a/resources/js/components/ui/touch-target.tsx b/resources/js/components/ui/touch-target.tsx
index e9297db..e914d38 100644
--- a/resources/js/components/ui/touch-target.tsx
+++ b/resources/js/components/ui/touch-target.tsx
@@ -1,15 +1,15 @@
-import * as React from 'react';
+import type * as React from "react"
const TouchTarget = ({ children }: { children: React.ReactNode }) => {
return (
<>
{children}
>
- );
-};
+ )
+}
-export { TouchTarget };
+export { TouchTarget }
diff --git a/resources/js/components/ui/visually-hidden.tsx b/resources/js/components/ui/visually-hidden.tsx
index d0cd4a0..333a9c2 100644
--- a/resources/js/components/ui/visually-hidden.tsx
+++ b/resources/js/components/ui/visually-hidden.tsx
@@ -1,13 +1,13 @@
-import { useVisuallyHidden } from 'react-aria';
+import { useVisuallyHidden } from "react-aria"
type VisuallyHiddenSpanProps = {
- children: React.ReactNode;
-};
+ children: React.ReactNode
+}
const VisuallyHidden = ({ children }: VisuallyHiddenSpanProps) => {
- const { visuallyHiddenProps } = useVisuallyHidden();
+ const { visuallyHiddenProps } = useVisuallyHidden()
- return {children} ;
-};
+ return {children}
+}
-export { VisuallyHidden };
+export { VisuallyHidden }
diff --git a/resources/js/layouts/app-layout.tsx b/resources/js/layouts/app-layout.tsx
index eb2e94d..c2639ef 100644
--- a/resources/js/layouts/app-layout.tsx
+++ b/resources/js/layouts/app-layout.tsx
@@ -1,7 +1,7 @@
-import { FlashMessage } from '@/components/flash-message';
-import { Footer } from '@/components/footer';
-import { AppNavbar } from '@/layouts/app-navbar';
-import { PropsWithChildren } from 'react';
+import { FlashMessage } from "@/components/flash-message"
+import { Footer } from "@/components/footer"
+import { AppNavbar } from "@/layouts/app-navbar"
+import type { PropsWithChildren } from "react"
export default function AppLayout({ children }: PropsWithChildren) {
return (
@@ -10,5 +10,5 @@ export default function AppLayout({ children }: PropsWithChildren) {
{children}
- );
+ )
}
diff --git a/resources/js/layouts/app-navbar.tsx b/resources/js/layouts/app-navbar.tsx
index c672518..236a20b 100644
--- a/resources/js/layouts/app-navbar.tsx
+++ b/resources/js/layouts/app-navbar.tsx
@@ -1,7 +1,7 @@
-import { useTheme } from '@/components/theme-provider';
-import { ThemeSwitcher } from '@/components/theme-switcher';
-import { PagePropsData } from '@/types';
-import { usePage } from '@inertiajs/react';
+import { useTheme } from "@/components/theme-provider"
+import { ThemeSwitcher } from "@/components/theme-switcher"
+import type { PagePropsData } from "@/types"
+import { usePage } from "@inertiajs/react"
import {
IconArrowUpRight,
IconBrandJustd,
@@ -10,30 +10,31 @@ import {
IconColorPalette,
IconColorSwatch,
IconLogout,
- IconSettings
-} from 'justd-icons';
-import React from 'react';
-import { Selection } from 'react-aria-components';
-import { Avatar, buttonStyles, Link, Menu, Navbar, Separator } from 'ui';
+ IconPackage,
+ IconSettings,
+} from "justd-icons"
+import { useState, useEffect } from "react"
+import type { Selection } from "react-aria-components"
+import { Avatar, buttonStyles, Link, Menu, Navbar, Separator } from "ui"
const navigations = [
{
- name: 'Home',
- textValue: 'Home',
- href: '/'
+ name: "Home",
+ textValue: "Home",
+ href: "/",
},
{
- name: 'About',
- textValue: 'About',
- href: '/about'
- }
-];
+ name: "About",
+ textValue: "About",
+ href: "/about",
+ },
+]
export function AppNavbar({ children, ...props }: React.ComponentProps) {
- const page = usePage();
- const { auth } = usePage().props;
- const [isOpen, setIsOpen] = React.useState(false);
- React.useEffect(() => setIsOpen(false), [page.url]);
+ const page = usePage()
+ const { auth } = usePage().props
+ const [isOpen, setIsOpen] = useState(false)
+ useEffect(() => setIsOpen(false), [page.url])
return (
@@ -49,35 +50,52 @@ export function AppNavbar({ children, ...props }: React.ComponentProps
Resources...
-
+
+
Blocks
-
+
Premium Blocks
-
+
Basic Blocks
-
+
Components
-
+
Colors
-
+
Themes
@@ -91,17 +109,20 @@ export function AppNavbar({ children, ...props }: React.ComponentProps
-
+
{!auth.user && }
{auth.user ? (
) : (
<>
-
-
+
+
Login
- Register
+ Register
>
)}
@@ -122,8 +143,8 @@ export function AppNavbar({ children, ...props }: React.ComponentProps
Login
@@ -134,18 +155,18 @@ export function AppNavbar({ children, ...props }: React.ComponentProps
- );
+ )
}
function UserMenu() {
- const { auth } = usePage().props;
- const { theme, setTheme } = useTheme();
- const currentTheme = theme || 'system';
- const [selectedTheme, setSelectedTheme] = React.useState(new Set([currentTheme]));
+ const { auth } = usePage().props
+ const { theme, setTheme } = useTheme()
+ const currentTheme = theme || "system"
+ const [selectedTheme, setSelectedTheme] = useState(new Set([currentTheme]))
return (
@@ -153,19 +174,21 @@ function UserMenu() {
{auth.user.name}
{auth.user.email}
-
+
{auth.user.name}
- {auth.user.email}
+
+ {auth.user.email}
+
-
+
Dashboard
-
+
Settings
@@ -177,14 +200,14 @@ function UserMenu() {
selectionMode="single"
selectedKeys={selectedTheme}
onSelectionChange={(keys) => {
- setSelectedTheme(keys);
+ setSelectedTheme(keys)
// @ts-ignore
- setTheme(keys.has('system') ? 'system' : keys.has('dark') ? 'dark' : 'light');
+ setTheme(keys.has("system") ? "system" : keys.has("dark") ? "dark" : "light")
}}
items={[
- { name: 'Light', value: 'light' },
- { name: 'Dark', value: 'dark' },
- { name: 'System', value: 'system' }
+ { name: "Light", value: "light" },
+ { name: "Dark", value: "dark" },
+ { name: "System", value: "system" },
]}
>
{(item) => (
@@ -196,18 +219,24 @@ function UserMenu() {
-
+
Logout
- );
+ )
}
export function IconBrandJustdBlocks() {
return (
-
+
@@ -232,7 +261,11 @@ export function IconBrandJustdBlocks() {
filterUnits="userSpaceOnUse"
>
-
+
@@ -242,5 +275,5 @@ export function IconBrandJustdBlocks() {
- );
+ )
}
diff --git a/resources/js/layouts/guest-layout.tsx b/resources/js/layouts/guest-layout.tsx
index 569c57c..9dfd568 100644
--- a/resources/js/layouts/guest-layout.tsx
+++ b/resources/js/layouts/guest-layout.tsx
@@ -1,28 +1,28 @@
-import { FlashMessage } from '@/components/flash-message';
-import { Logo } from '@/components/logo';
-import { Card } from '@/components/ui/card';
-import { PropsWithChildren, ReactNode } from 'react';
-import { Link } from 'ui';
+import { FlashMessage } from "@/components/flash-message"
+import { Logo } from "@/components/logo"
+import { Card } from "@/components/ui/card"
+import type { PropsWithChildren, ReactNode } from "react"
+import { Link } from "ui"
interface GuestLayoutProps {
- header?: string | null;
- description?: string | ReactNode | null;
+ header?: string | null
+ description?: string | ReactNode | null
}
export default function GuestLayout({
description = null,
header = null,
- children
+ children,
}: PropsWithChildren) {
return (
-
+
-
+
{header}
{description}
@@ -31,5 +31,5 @@ export default function GuestLayout({
- );
+ )
}
diff --git a/resources/js/pages/about.tsx b/resources/js/pages/about.tsx
index 7af1231..21e8fe0 100644
--- a/resources/js/pages/about.tsx
+++ b/resources/js/pages/about.tsx
@@ -1,8 +1,8 @@
-import { Header } from '@/components/header';
-import AppLayout from '@/layouts/app-layout';
-import { Head } from '@inertiajs/react';
-import React from 'react';
-import { Card, Container } from 'ui';
+import { Header } from "@/components/header"
+import AppLayout from "@/layouts/app-layout"
+import { Head } from "@inertiajs/react"
+import type React from "react"
+import { Card, Container } from "ui"
export default function About() {
return (
@@ -13,7 +13,7 @@ export default function About() {
Your about page content goes here.
>
- );
+ )
}
-About.layout = (page: React.ReactNode) => ;
+About.layout = (page: React.ReactNode) =>
diff --git a/resources/js/pages/auth/confirm-password.tsx b/resources/js/pages/auth/confirm-password.tsx
index 4a7aec7..62cadd3 100644
--- a/resources/js/pages/auth/confirm-password.tsx
+++ b/resources/js/pages/auth/confirm-password.tsx
@@ -1,30 +1,30 @@
-import GuestLayout from '@/layouts/guest-layout';
-import { Head, useForm } from '@inertiajs/react';
-import { useEffect } from 'react';
-import { Button, Form, TextField } from 'ui';
+import GuestLayout from "@/layouts/guest-layout"
+import { Head, useForm } from "@inertiajs/react"
+import { useEffect } from "react"
+import { Button, Form, TextField } from "ui"
export default function ConfirmPassword() {
const { data, setData, post, processing, errors, reset } = useForm({
- password: ''
- });
+ password: "",
+ })
useEffect(() => {
return () => {
- reset('password');
- };
- }, []);
+ reset("password")
+ }
+ }, [])
const submit = (e: { preventDefault: () => void }) => {
- e.preventDefault();
+ e.preventDefault()
- post(route('password.confirm'));
- };
+ post(route("password.confirm"))
+ }
return (
<>
-
+
This is a secure area of the application. Please confirm your password before continuing.
@@ -37,7 +37,7 @@ export default function ConfirmPassword() {
value={data.password}
className="mt-1 block w-full"
autoFocus
- onChange={(v) => setData('password', v)}
+ onChange={(v) => setData("password", v)}
/>
@@ -45,7 +45,7 @@ export default function ConfirmPassword() {
>
- );
+ )
}
-ConfirmPassword.layout = (page: any) =>
;
+ConfirmPassword.layout = (page: any) =>
diff --git a/resources/js/pages/auth/forgot-password.tsx b/resources/js/pages/auth/forgot-password.tsx
index 48a7a09..cb10043 100644
--- a/resources/js/pages/auth/forgot-password.tsx
+++ b/resources/js/pages/auth/forgot-password.tsx
@@ -1,25 +1,25 @@
-import GuestLayout from '@/layouts/guest-layout';
-import { Head, useForm } from '@inertiajs/react';
-import { Button, Form, TextField } from 'ui';
+import GuestLayout from "@/layouts/guest-layout"
+import { Head, useForm } from "@inertiajs/react"
+import { Button, Form, TextField } from "ui"
interface ForgotPasswordProps {
- status: string;
+ status: string
}
export default function ForgotPassword({ status }: ForgotPasswordProps) {
const { data, setData, post, processing, errors } = useForm({
- email: ''
- });
+ email: "",
+ })
const submit = (e: { preventDefault: () => void }) => {
- e.preventDefault();
- post('/forgot-password');
- };
+ e.preventDefault()
+ post("/forgot-password")
+ }
return (
<>
- {status && {status}
}
+ {status && {status}
}
>
- );
+ )
}
ForgotPassword.layout = (page: any) => (
@@ -50,4 +50,4 @@ ForgotPassword.layout = (page: any) => (
reset link that will allow you to choose a new one."
children={page}
/>
-);
+)
diff --git a/resources/js/pages/auth/login.tsx b/resources/js/pages/auth/login.tsx
index e8b4389..faef491 100644
--- a/resources/js/pages/auth/login.tsx
+++ b/resources/js/pages/auth/login.tsx
@@ -1,38 +1,41 @@
-import GuestLayout from '@/layouts/guest-layout';
-import { Head, useForm } from '@inertiajs/react';
-import React, { useEffect } from 'react';
-import { Button, Checkbox, Form, Link, TextField } from 'ui';
+import GuestLayout from "@/layouts/guest-layout"
+import { Head, useForm } from "@inertiajs/react"
+import type React from "react"
+import { useEffect } from "react"
+import { Button, Checkbox, Form, Link, TextField } from "ui"
interface LoginProps {
- status: string;
- canResetPassword: boolean;
+ status: string
+ canResetPassword: boolean
}
export default function Login(args: LoginProps) {
- const { status, canResetPassword } = args;
+ const { status, canResetPassword } = args
const { data, setData, post, processing, errors, reset } = useForm({
- email: '',
- password: '',
- remember: ''
- });
+ email: "",
+ password: "",
+ remember: "",
+ })
useEffect(() => {
return () => {
- reset('password');
- };
- }, []);
+ reset("password")
+ }
+ }, [])
const submit = (e: { preventDefault: () => void }) => {
- e.preventDefault();
+ e.preventDefault()
- post(route('login'));
- };
+ post(route("login"))
+ }
return (
<>
- {status &&
{status}
}
+ {status && (
+
{status}
+ )}
>
- );
+ )
}
Register.layout = (page: React.ReactNode) => {
- return
;
-};
+ return (
+
+ )
+}
diff --git a/resources/js/pages/auth/reset-password.tsx b/resources/js/pages/auth/reset-password.tsx
index f0d16fa..8657de9 100644
--- a/resources/js/pages/auth/reset-password.tsx
+++ b/resources/js/pages/auth/reset-password.tsx
@@ -1,34 +1,32 @@
-import GuestLayout from '@/layouts/guest-layout';
-import { Head, useForm } from '@inertiajs/react';
-import { useEffect } from 'react';
-import { Button, Form, TextField } from 'ui';
+import GuestLayout from "@/layouts/guest-layout"
+import { Head, useForm } from "@inertiajs/react"
+import { useEffect } from "react"
+import { Button, Form, TextField } from "ui"
interface ResetPasswordProps {
- token: string;
- email: string;
+ token: string
+ email: string
}
-type InputTargetProps = { name: any; value: any };
-
export default function ResetPassword(args: ResetPasswordProps) {
- const { token, email } = args;
+ const { token, email } = args
const { data, setData, post, processing, errors, reset } = useForm({
token: token,
email: email,
- password: '',
- password_confirmation: ''
- });
+ password: "",
+ password_confirmation: "",
+ })
useEffect(() => {
return () => {
- reset('password', 'password_confirmation');
- };
- }, []);
+ reset("password", "password_confirmation")
+ }
+ }, [])
const submit = (e: { preventDefault: () => void }) => {
- e.preventDefault();
- post('/reset-password');
- };
+ e.preventDefault()
+ post("/reset-password")
+ }
return (
<>
@@ -43,7 +41,7 @@ export default function ResetPassword(args: ResetPasswordProps) {
name="email"
value={data.email}
autoComplete="username"
- onChange={(v) => setData('email', v)}
+ onChange={(v) => setData("email", v)}
/>
setData('password', v)}
+ onChange={(v) => setData("password", v)}
/>
setData('password_confirmation', v)}
+ onChange={(v) => setData("password_confirmation", v)}
errorMessage={errors.password_confirmation}
isRequired
/>
@@ -76,7 +74,7 @@ export default function ResetPassword(args: ResetPasswordProps) {
>
- );
+ )
}
-ResetPassword.layout = (page: any) =>