@plone/components
Version:
ReactJS components for Plone
1,751 lines (1,727 loc) • 63.8 kB
JavaScript
"use client"
import {
AlignWidget,
CustomRadio,
Description,
Field,
FieldError,
FieldGroup,
FieldWrapper,
Input,
Label,
Radio,
RadioGroup,
SizeWidget,
WidthWidget,
composeTailwindRenderProps,
fieldBorderStyles,
fieldGroupStyles,
focusRing,
getMenuTriggerChildren,
inputStyles
} from "../chunk-YWREOUAG.js";
import {
CalendarIcon,
CheckboxIcon,
ChevrondownIcon,
ChevronleftIcon,
ChevronrightIcon,
CloseIcon,
DashIcon
} from "../chunk-V3F5PCGN.js";
// src/components/Button/Button.quanta.tsx
import "react";
import {
composeRenderProps,
Button as RACButton
} from "react-aria-components";
import { tv } from "tailwind-variants";
import { jsx } from "react/jsx-runtime";
var button = tv({
extend: focusRing,
base: `
cursor-default rounded-md px-3 py-1.5 text-center text-base font-medium transition
hover:shadow-sm
focus:shadow-sm
active:shadow-md
has-[svg]:rounded-full has-[svg]:p-1.5 has-[svg]:text-xs
`,
variants: {
variant: {
neutral: `
bg-quanta-air text-quanta-iron
hover:bg-quanta-snow
focus:bg-quanta-snow
active:bg-quanta-silver
has-[svg]:text-quanta-iron
pressed:bg-quanta-silver
`,
primary: `
focus:bg-quanta-artic focus:text-quanta-royal
bg-quanta-air text-quanta-sapphire
hover:bg-quanta-arctic hover:text-quanta-royal
active:bg-quanta-sky active:text-quanta-royal
pressed:bg-quanta-cobalt
`,
destructive: `
bg-quanta-air text-quanta-candy
hover:bg-quanta-ballet hover:text-quanta-wine
focus:bg-quanta-ballet focus:text-quanta-wine
active:bg-quanta-flamingo active:text-quanta-wine
pressed:bg-quanta-rose
`,
icon: `
focus:bg-quanta-artic
flex items-center justify-center border-0 bg-quanta-air p-1 text-quanta-iron
hover:bg-quanta-snow
active:bg-quanta-silver
has-[svg]:text-quanta-iron
pressed:bg-quanta-cobalt pressed:[&_svg]:text-white
`
},
accent: {
true: ""
},
size: {
S: `
text-xs
has-[svg]:p-1.5
[&_svg]:size-5
`,
L: `
px-4.5 py-3 text-xl/6
has-[svg]:p-3 has-[svg]:text-xs
`
},
isDisabled: {
true: `
cursor-not-allowed bg-quanta-air text-quanta-smoke
hover:bg-quanta-air hover:text-quanta-silver
has-[svg]:text-quanta-smoke has-[svg]:hover:text-quanta-silver
`
}
},
compoundVariants: [
{
variant: "neutral",
accent: true,
class: `
bg-quanta-snow text-quanta-iron
hover:bg-quanta-smoke
focus:bg-quanta-smoke
active:bg-quanta-silver
pressed:bg-quanta-smoke
`
},
{
variant: "primary",
accent: true,
class: `
bg-quanta-sapphire text-quanta-air
hover:bg-quanta-royal hover:text-quanta-air
focus:bg-quanta-royal focus:text-quanta-air
active:bg-quanta-cobalt active:text-quanta-air
pressed:bg-quanta-cobalt
`
},
{
variant: "icon",
accent: true,
class: `
focus:bg-quanta-artic
flex items-center justify-center border-0 bg-quanta-air p-1 text-quanta-iron
hover:bg-quanta-snow
active:bg-quanta-silver
has-[svg]:text-quanta-iron
pressed:bg-quanta-cobalt pressed:[&_svg]:text-white
`
},
{
variant: "destructive",
accent: true,
class: `
bg-quanta-candy text-quanta-air
hover:bg-quanta-wine hover:text-quanta-air
focus:bg-quanta-wine focus:text-quanta-air
active:bg-quanta-rose active:text-quanta-air
pressed:bg-quanta-rose
`
},
{
isDisabled: true,
accent: true,
class: `
bg-quanta-snow text-quanta-silver
hover:bg-quanta-smoke
`
}
],
defaultVariants: {
variant: "neutral"
}
});
function Button(props) {
return /* @__PURE__ */ jsx(
RACButton,
{
...props,
className: composeRenderProps(
props.className,
(className, renderProps) => button({
...renderProps,
variant: props.variant,
size: props.size,
accent: props.accent,
className
})
)
}
);
}
// src/components/Breadcrumbs/Breadcrumbs.quanta.tsx
import "react";
import {
Breadcrumbs as RACBreadcrumbs,
Breadcrumb as RACBreadcrumb
} from "react-aria-components";
import { twMerge } from "tailwind-merge";
// src/components/Link/Link.quanta.tsx
import "react";
import {
Link as AriaLink,
composeRenderProps as composeRenderProps2
} from "react-aria-components";
import { tv as tv2 } from "tailwind-variants";
import { jsx as jsx2 } from "react/jsx-runtime";
var styles = tv2({
extend: focusRing,
base: `
rounded-xs underline transition
disabled:cursor-default disabled:no-underline
forced-colors:disabled:text-[GrayText]
`,
variants: {
variant: {
primary: `
text-quanta-sapphire underline decoration-quanta-sapphire/40
hover:text-quanta-royal hover:decoration-quanta-royal
focus:text-quanta-royal focus:decoration-quanta-royal
active:text-quanta-cobalt active:decoration-quanta-cobalt
`,
secondary: `
text-gray-700 underline decoration-gray-700/50
hover:decoration-gray-700
`
}
},
defaultVariants: {
variant: "primary"
}
});
function Link(props) {
return /* @__PURE__ */ jsx2(
AriaLink,
{
...props,
className: composeRenderProps2(
props.className,
(className, renderProps) => styles({ ...renderProps, className, variant: props.variant })
)
}
);
}
// src/components/Breadcrumbs/Breadcrumbs.quanta.tsx
import { Fragment, jsx as jsx3, jsxs } from "react/jsx-runtime";
function Breadcrumb(props) {
return /* @__PURE__ */ jsx3(
RACBreadcrumb,
{
...props,
className: composeTailwindRenderProps(
props.className,
`
flex items-center gap-1
[&_a>svg]:mx-1 [&_a>svg]:inline [&_a>svg]:align-text-top
`
),
children: ({ isCurrent }) => /* @__PURE__ */ jsxs(Fragment, { children: [
props.value?.icon && props.value?.icon,
/* @__PURE__ */ jsx3(Link, { variant: "secondary", ...props }),
!isCurrent && (props.separator ?? /* @__PURE__ */ jsx3(ChevronrightIcon, { className: "h-3 w-3 text-gray-600" }))
] })
}
);
}
function Breadcrumbs(props) {
const { root, items, homeIcon } = props;
let itemsWithRoot;
if (root && items) {
const icon = null;
const rootItem = {
"@id": root["@id"] || "/",
title: "Home",
icon
};
itemsWithRoot = [rootItem, ...items];
}
return /* @__PURE__ */ jsx3(
RACBreadcrumbs,
{
...props,
items: itemsWithRoot || items,
className: twMerge("flex gap-1", props.className)
}
);
}
// src/components/Accordion/Accordion.quanta.tsx
import "react";
import {
DisclosureGroup,
Button as Button2,
Disclosure,
DisclosurePanel,
Heading
} from "react-aria-components";
import { Fragment as Fragment2, jsx as jsx4, jsxs as jsxs2 } from "react/jsx-runtime";
var Accordion = ({ children, ref, className, ...props }) => {
return /* @__PURE__ */ jsx4(
DisclosureGroup,
{
ref,
"data-slot": "disclosure-group",
...props,
className: composeTailwindRenderProps(
className,
`
peer cursor-pointer
disabled:cursor-not-allowed disabled:opacity-75
`
),
children: (values) => /* @__PURE__ */ jsx4("div", { "data-slot": "disclosure-content", children: typeof children === "function" ? children(values) : children })
}
);
};
var AccordionItem = ({ className, ref, ...props }) => {
return /* @__PURE__ */ jsx4(
Disclosure,
{
ref,
"data-slot": "disclosure",
...props,
className: composeTailwindRenderProps(
className,
`
peer group/disclosure w-full min-w-60 border-b border-border
disabled:opacity-60
`
),
children: props.children
}
);
};
var AccordionItemTrigger = ({
className,
ref,
...props
}) => {
return /* @__PURE__ */ jsx4(Heading, { children: /* @__PURE__ */ jsx4(
Button2,
{
ref,
slot: "trigger",
className: composeTailwindRenderProps(
className,
`
group/trigger flex w-full items-center justify-between gap-x-2 py-3 text-left
font-medium
open:text-fg
focus:text-fg focus:outline-hidden
**:data-[slot=icon]:text-muted-fg **:data-[slot=icon]:-mx-0.5
**:data-[slot=icon]:shrink-0
disabled:cursor-default disabled:opacity-50
**:data-[slot=disclosure-chevron]:size-5
sm:text-sm
forced-colors:disabled:text-[GrayText]
**:[span]:flex **:[span]:items-center **:[span]:gap-x-1
**:[span]:*:data-[slot=icon]:mr-1
[&[aria-expanded=true]_[data-slot=disclosure-chevron]]:-rotate-90
`
),
...props,
children: (values) => /* @__PURE__ */ jsxs2(Fragment2, { children: [
typeof props.children === "function" ? props.children(values) : props.children,
/* @__PURE__ */ jsx4(
ChevronleftIcon,
{
"data-slot": "disclosure-chevron",
className: "internal-chevron ml-auto size-4 shrink-0 transition duration-300"
}
)
] })
}
) });
};
var AccordionPanel = ({ className, ref, ...props }) => {
return /* @__PURE__ */ jsx4(
DisclosurePanel,
{
ref,
"data-slot": "disclosure-panel",
className: composeTailwindRenderProps(
className,
`
text-muted-fg overflow-hidden text-sm transition-all
**:data-[slot=disclosure-group]:border-t
**:data-[slot=disclosure-group]:**:[.internal-chevron]:hidden
has-data-[slot=disclosure-group]:**:[button]:px-4
`
),
...props,
children: /* @__PURE__ */ jsx4(
"div",
{
"data-slot": "disclosure-panel-content",
className: `
pt-0
not-has-data-[slot=disclosure-group]:group-data-expanded/disclosure:pb-3
[&:has([data-slot=disclosure-group])_&]:px-11
`,
children: props.children
}
)
}
);
};
// src/components/Calendar/Calendar.quanta.tsx
import "react";
import {
Calendar as AriaCalendar,
CalendarGridHeader as AriaCalendarGridHeader,
CalendarCell,
CalendarGrid,
CalendarGridBody,
CalendarHeaderCell,
Heading as Heading2,
Text,
useLocale
} from "react-aria-components";
import { tv as tv3 } from "tailwind-variants";
import { jsx as jsx5, jsxs as jsxs3 } from "react/jsx-runtime";
var cellStyles = tv3({
extend: focusRing,
base: `
m-px flex h-9 w-9 cursor-default items-center justify-center rounded-full text-sm
forced-color-adjust-none
`,
variants: {
isSelected: {
false: `
text-zinc-900
hover:bg-gray-100
dark:text-zinc-200 dark:hover:bg-zinc-700
pressed:bg-gray-200
dark:pressed:bg-zinc-600
`,
true: `
bg-blue-600 text-white
invalid:bg-red-600
forced-colors:bg-[Highlight] forced-colors:text-[HighlightText]
forced-colors:invalid:bg-[Mark]
`
},
isDisabled: {
true: `
text-gray-300
dark:text-zinc-600
forced-colors:text-[GrayText]
`
}
}
});
function Calendar({
errorMessage,
...props
}) {
return /* @__PURE__ */ jsxs3(AriaCalendar, { ...props, children: [
/* @__PURE__ */ jsx5(CalendarHeader, {}),
/* @__PURE__ */ jsxs3(CalendarGrid, { children: [
/* @__PURE__ */ jsx5(CalendarGridHeader, {}),
/* @__PURE__ */ jsx5(CalendarGridBody, { children: (date) => /* @__PURE__ */ jsx5(CalendarCell, { date, className: cellStyles }) })
] }),
errorMessage && /* @__PURE__ */ jsx5(Text, { slot: "errorMessage", className: "text-sm text-red-600", children: errorMessage })
] });
}
function CalendarHeader() {
const { direction } = useLocale();
return /* @__PURE__ */ jsxs3("header", { className: "flex w-full items-center gap-1 px-1 pb-4", children: [
/* @__PURE__ */ jsx5(Button, { slot: "previous", children: direction === "rtl" ? /* @__PURE__ */ jsx5(ChevronrightIcon, { "aria-hidden": true }) : /* @__PURE__ */ jsx5(ChevronleftIcon, { "aria-hidden": true }) }),
/* @__PURE__ */ jsx5(
Heading2,
{
className: `
mx-2 flex-1 text-center text-xl font-semibold text-zinc-900
dark:text-zinc-200
`
}
),
/* @__PURE__ */ jsx5(Button, { slot: "next", children: direction === "rtl" ? /* @__PURE__ */ jsx5(ChevronleftIcon, { "aria-hidden": true }) : /* @__PURE__ */ jsx5(ChevronrightIcon, { "aria-hidden": true }) })
] });
}
function CalendarGridHeader() {
return /* @__PURE__ */ jsx5(AriaCalendarGridHeader, { children: (day) => /* @__PURE__ */ jsx5(CalendarHeaderCell, { className: "text-xs font-semibold text-gray-500", children: day }) });
}
// src/components/Checkbox/Checkbox.quanta.tsx
import "react";
import {
Checkbox as AriaCheckbox,
CheckboxGroup as AriaCheckboxGroup,
composeRenderProps as composeRenderProps3
} from "react-aria-components";
import { tv as tv4 } from "tailwind-variants";
import { Fragment as Fragment3, jsx as jsx6, jsxs as jsxs4 } from "react/jsx-runtime";
function CheckboxGroup(props) {
return /* @__PURE__ */ jsxs4(
AriaCheckboxGroup,
{
...props,
className: composeTailwindRenderProps(
props.className,
"flex flex-col gap-2"
),
children: [
/* @__PURE__ */ jsx6(Label, { children: props.label }),
props.children,
props.description && /* @__PURE__ */ jsx6(Description, { children: props.description }),
/* @__PURE__ */ jsx6(FieldError, { children: props.errorMessage })
]
}
);
}
var checkboxStyles = tv4({
base: "group flex items-center gap-2 text-sm transition",
variants: {
isDisabled: {
false: "text-quanta-cobalt",
true: `
text-quanta-iron
forced-colors:text-[GrayText]
`
}
}
});
var boxStyles = tv4({
extend: focusRing,
base: "flex h-5 w-5 flex-shrink-0 items-center justify-center rounded border-2 transition",
variants: {
isSelected: {
false: `
border-quanta-pigeon bg-quanta-snow
group-pressed:border-quanta-silver
`,
true: `
border-quanta-sapphire bg-quanta-sapphire
group-pressed:border-quanta-sapphire
forced-colors:![--color:Highlight]
`
},
isInvalid: {
true: `
group-pressed:border-quanta-ruby
border-quanta-ruby
forced-colors:![--color:Mark]
`
},
isDisabled: {
true: `
border-quanta-silver bg-quanta-smoke
forced-colors:![--color:GrayText]
`
}
}
});
var iconStyles = "w-4 h-4 text-white group-disabled:text-quanta-iron forced-colors:text-[HighlightText]";
function Checkbox(props) {
return /* @__PURE__ */ jsx6(
AriaCheckbox,
{
...props,
className: composeRenderProps3(
props.className,
(className, renderProps) => checkboxStyles({ ...renderProps, className })
),
children: ({ isSelected, isIndeterminate, ...renderProps }) => /* @__PURE__ */ jsxs4(Fragment3, { children: [
/* @__PURE__ */ jsx6(
"div",
{
className: boxStyles({
isSelected: isSelected || isIndeterminate,
...renderProps
}),
children: isIndeterminate ? /* @__PURE__ */ jsx6(DashIcon, { "aria-hidden": true, className: iconStyles }) : isSelected ? /* @__PURE__ */ jsx6(CheckboxIcon, { "aria-hidden": true, className: iconStyles }) : null
}
),
props.children
] })
}
);
}
// src/components/Container/Container.quanta.tsx
import "react";
import { tv as tv5 } from "tailwind-variants";
import { twMerge as twMerge2 } from "tailwind-merge";
import { jsx as jsx7 } from "react/jsx-runtime";
var Container = (props) => {
const { as: Component = "div", children, width, ...rest } = props;
const container = tv5({
base: "@container mx-auto",
variants: {
width: {
layout: "max-w-(--layout-container-width)",
default: "max-w-(--default-container-width)",
narrow: "max-w-(--narrow-container-width)",
full: "w-full"
}
},
defaultVariants: {
width: "full"
}
});
return /* @__PURE__ */ jsx7(
Component,
{
...rest,
className: twMerge2(props.className, container({ width })),
children
}
);
};
// src/components/Menu/Menu.quanta.tsx
import "react";
import {
Header,
Menu as AriaMenu,
MenuItem as AriaMenuItem,
MenuSection as AriaMenuSection,
MenuTrigger as AriaMenuTrigger,
Separator as AriaSeparator,
SubmenuTrigger as AriaSubmenuTrigger,
composeRenderProps as composeRenderProps5
} from "react-aria-components";
import { tv as tv7 } from "tailwind-variants";
import { twMerge as twMerge3 } from "tailwind-merge";
// src/components/Popover/Popover.quanta.tsx
import "react";
import {
Popover as AriaPopover,
composeRenderProps as composeRenderProps4,
OverlayArrow,
PopoverContext,
useSlottedContext
} from "react-aria-components";
import { tv as tv6 } from "tailwind-variants";
import { jsx as jsx8, jsxs as jsxs5 } from "react/jsx-runtime";
var styles2 = tv6({
base: `
rounded-xl border border-black/10 bg-white bg-clip-padding text-slate-700 shadow-2xl
dark:border-white/[15%] dark:bg-zinc-900/70 dark:text-zinc-300 dark:backdrop-blur-2xl
dark:backdrop-saturate-200
forced-colors:bg-[Canvas]
`,
variants: {
isEntering: {
true: `
duration-200 ease-out animate-in fade-in
placement-left:slide-in-from-right-1
placement-right:slide-in-from-left-1
placement-top:slide-in-from-bottom-1
placement-bottom:slide-in-from-top-1
`
},
isExiting: {
true: `
duration-150 ease-in animate-out fade-out
placement-left:slide-out-to-right-1
placement-right:slide-out-to-left-1
placement-top:slide-out-to-bottom-1
placement-bottom:slide-out-to-top-1
`
}
}
});
function Popover({
children,
showArrow,
className,
...props
}) {
const popoverContext = useSlottedContext(PopoverContext);
const isSubmenu = popoverContext?.trigger === "SubmenuTrigger";
let offset = showArrow ? 12 : 8;
offset = isSubmenu ? offset - 6 : offset;
return /* @__PURE__ */ jsxs5(
AriaPopover,
{
offset,
...props,
className: composeRenderProps4(
className,
(className2, renderProps) => styles2({ ...renderProps, className: className2 })
),
children: [
showArrow && /* @__PURE__ */ jsx8(OverlayArrow, { className: "group", children: /* @__PURE__ */ jsx8(
"svg",
{
width: 12,
height: 12,
viewBox: "0 0 12 12",
className: `
block fill-white stroke-black/10 stroke-1
group-placement-left:-rotate-90
group-placement-right:rotate-90
group-placement-bottom:rotate-180
dark:fill-[#1f1f21] dark:stroke-zinc-600
forced-colors:fill-[Canvas] forced-colors:stroke-[ButtonBorder]
`,
children: /* @__PURE__ */ jsx8("path", { d: "M0 0 L6 6 L12 0" })
}
) }),
children
]
}
);
}
// src/components/Menu/Menu.quanta.tsx
import { Fragment as Fragment4, jsx as jsx9, jsxs as jsxs6 } from "react/jsx-runtime";
function Menu(props) {
return /* @__PURE__ */ jsx9(
AriaMenu,
{
...props,
className: composeTailwindRenderProps(
props.className,
`
max-h-[inherit] overflow-auto p-1 font-sans
[clip-path:inset(0_0_0_0_round_.75rem)]
empty:pb-2 empty:text-center
`
)
}
);
}
var menuItemStyles = tv7({
extend: focusRing,
base: `
group relative flex cursor-default items-center gap-4 rounded-lg py-2 pr-3 pl-3 text-sm
no-underline forced-color-adjust-none select-none
[-webkit-tap-highlight-color:transparent]
selected:pr-1
[&[href]]:cursor-pointer
`,
variants: {
isDisabled: {
false: `
text-neutral-900
dark:text-neutral-100
`,
true: `
text-neutral-300
dark:text-neutral-600
forced-colors:text-[GrayText]
`
},
isPressed: {
true: `
bg-neutral-100
dark:bg-neutral-800
`
},
isFocused: {
true: `
bg-blue-600 text-white
forced-colors:bg-[Highlight] forced-colors:text-[HighlightText]
`
}
},
compoundVariants: [
{
isFocused: false,
isOpen: true,
className: `
bg-neutral-100
dark:bg-neutral-700/60
`
}
]
});
function MenuItem(props) {
const textValue = props.textValue || (typeof props.children === "string" ? props.children : void 0);
return /* @__PURE__ */ jsx9(
AriaMenuItem,
{
...props,
textValue,
className: composeRenderProps5(
props.className,
(className, renderProps) => menuItemStyles({ ...renderProps, className })
),
children: composeRenderProps5(
props.children,
(children, { selectionMode, isSelected, hasSubmenu }) => /* @__PURE__ */ jsxs6(Fragment4, { children: [
selectionMode !== "none" && /* @__PURE__ */ jsx9("span", { className: "flex w-4 items-center", children: isSelected && /* @__PURE__ */ jsx9(CheckboxIcon, { "aria-hidden": true, className: "h-4 w-4" }) }),
children,
hasSubmenu && /* @__PURE__ */ jsx9(
ChevronrightIcon,
{
"aria-hidden": true,
className: "absolute right-2 h-4 w-4"
}
)
] })
)
}
);
}
function MenuSeparator(props) {
return /* @__PURE__ */ jsx9(
AriaSeparator,
{
...props,
className: twMerge3(
`
mx-3 my-1 border-b border-neutral-300
dark:border-neutral-700
`,
props.className
)
}
);
}
function MenuSection(props) {
return /* @__PURE__ */ jsx9(
AriaMenuSection,
{
...props,
className: twMerge3(
`
after:block after:h-[5px] after:content-['']
first:-mt-[5px]
last:after:hidden
`,
props.className
),
children: props.children
}
);
}
function MenuSectionHeader(props) {
return /* @__PURE__ */ jsx9(
Header,
{
...props,
className: twMerge3(
`
sticky -top-[5px] z-10 -mx-1 -mt-px truncate border-y border-y-neutral-200
bg-neutral-100/60 px-4 py-1 text-sm font-semibold text-neutral-500 backdrop-blur-md
supports-[-moz-appearance:none]:bg-neutral-100
dark:border-y-neutral-700 dark:bg-neutral-700/60 dark:text-neutral-300
[&+*]:mt-1
`,
props.className
)
}
);
}
function MenuTrigger(props) {
const [trigger, menu] = getMenuTriggerChildren(props.children, "MenuTrigger");
return /* @__PURE__ */ jsxs6(AriaMenuTrigger, { ...props, children: [
trigger,
/* @__PURE__ */ jsx9(Popover, { placement: props.placement, className: "min-w-[150px]", children: menu })
] });
}
function SubmenuTrigger(props) {
const [trigger, menu] = getMenuTriggerChildren(
props.children,
"SubmenuTrigger"
);
return /* @__PURE__ */ jsxs6(AriaSubmenuTrigger, { ...props, children: [
trigger,
/* @__PURE__ */ jsx9(Popover, { offset: -2, crossOffset: -4, children: menu })
] });
}
// src/components/Select/Select.quanta.tsx
import "react";
import {
Button as Button3,
Header as Header3,
ListBoxSection as ListBoxSection2,
Select as RACSelect,
SelectValue
} from "react-aria-components";
import { twMerge as twMerge4 } from "tailwind-merge";
import { tv as tv9 } from "tailwind-variants";
// src/components/ListBox/ListBox.quanta.tsx
import "react";
import {
ListBox as AriaListBox,
ListBoxItem as AriaListBoxItem,
Collection,
Header as Header2,
ListBoxSection,
composeRenderProps as composeRenderProps6
} from "react-aria-components";
import { tv as tv8 } from "tailwind-variants";
import { Fragment as Fragment5, jsx as jsx10, jsxs as jsxs7 } from "react/jsx-runtime";
function ListBox({
children,
...props
}) {
return /* @__PURE__ */ jsx10(
AriaListBox,
{
...props,
className: composeTailwindRenderProps(
props.className,
"flex-1 overflow-auto outline-0"
),
children
}
);
}
var itemStyles = tv8({
extend: focusRing,
base: `
group relative flex cursor-default items-center gap-8 rounded-md px-2.5 py-1.5 text-sm
will-change-transform forced-color-adjust-none select-none
`,
variants: {
isSelected: {
false: `
text-slate-700 -outline-offset-2
hover:bg-slate-200
dark:text-zinc-300 dark:hover:bg-zinc-700
`,
true: `
bg-blue-600 text-white -outline-offset-4 outline-white
dark:outline-white
forced-colors:bg-[Highlight] forced-colors:text-[HighlightText]
forced-colors:outline-[HighlightText]
[&+[data-selected]]:rounded-t-none
[&:has(+[data-selected])]:rounded-b-none
`
},
isDisabled: {
true: `
text-slate-300
dark:text-zinc-600
forced-colors:text-[GrayText]
`
}
}
});
var dropdownItemStyles = tv8({
base: `
group flex cursor-default items-center gap-4 rounded-lg py-2 pr-1 pl-3 text-sm outline-0
forced-color-adjust-none select-none
`,
variants: {
isDisabled: {
false: `
text-gray-900
dark:text-zinc-100
`,
true: `
text-gray-300
dark:text-zinc-600
forced-colors:text-[GrayText]
`
},
isFocused: {
true: `
bg-blue-600 text-white
forced-colors:bg-[Highlight] forced-colors:text-[HighlightText]
`
}
},
compoundVariants: [
{
isFocused: false,
isOpen: true,
className: `
bg-gray-100
dark:bg-zinc-700/60
`
}
]
});
function DropdownItem(props) {
const textValue = props.textValue || (typeof props.children === "string" ? props.children : void 0);
return /* @__PURE__ */ jsx10(
AriaListBoxItem,
{
...props,
textValue,
className: dropdownItemStyles,
children: composeRenderProps6(props.children, (children, { isSelected }) => /* @__PURE__ */ jsxs7(Fragment5, { children: [
/* @__PURE__ */ jsx10(
"span",
{
className: `
flex flex-1 items-center gap-2 truncate font-normal
group-selected:font-semibold
`,
children
}
),
/* @__PURE__ */ jsx10("span", { className: "flex w-5 items-center", children: isSelected && /* @__PURE__ */ jsx10(CheckboxIcon, { className: "h-4 w-4" }) })
] }))
}
);
}
// src/components/Select/Select.quanta.tsx
import { Fragment as Fragment6, jsx as jsx11, jsxs as jsxs8 } from "react/jsx-runtime";
var triggerStyles = tv9({
extend: focusRing,
base: `
flex min-h-11 min-w-[180px] items-center gap-3 rounded-lg bg-quanta-snow px-3 py-2 text-left
text-sm text-quanta-space transition
hover:bg-quanta-smoke
focus:bg-quanta-air
active:bg-quanta-air
forced-colors:bg-[Field]
`,
variants: {
isDisabled: {
true: `
cursor-not-allowed bg-quanta-air text-quanta-silver
hover:bg-quanta-air
forced-colors:text-[GrayText]
`
},
isInvalid: {
true: `
bg-quanta-ballet
hover:bg-quanta-flamingo
`
}
}
});
function DefaultSelectItem(item) {
return /* @__PURE__ */ jsx11(SelectItem, { id: item.label, children: item.value });
}
function Select({
label,
description,
errorMessage,
children,
items,
...props
}) {
return /* @__PURE__ */ jsx11(
RACSelect,
{
...props,
className: composeTailwindRenderProps(
props.className,
"group flex flex-col gap-1"
),
children: ({ isOpen }) => /* @__PURE__ */ jsxs8(Fragment6, { children: [
label && /* @__PURE__ */ jsx11(Label, { children: label }),
/* @__PURE__ */ jsxs8(Button3, { className: triggerStyles, children: [
/* @__PURE__ */ jsx11(
SelectValue,
{
className: `
min-w-0 flex-1 truncate
data-[placeholder]:text-quanta-pigeon
`
}
),
/* @__PURE__ */ jsx11(SelectChevron, { isOpen })
] }),
description && /* @__PURE__ */ jsx11(Description, { children: description }),
/* @__PURE__ */ jsx11(FieldError, { children: errorMessage }),
/* @__PURE__ */ jsx11(Popover, { className: "min-w-(--trigger-width) p-1", children: children ? /* @__PURE__ */ jsx11(SelectListBox, { items, children }) : /* @__PURE__ */ jsx11(
SelectListBox,
{
items,
children: DefaultSelectItem
}
) })
] })
}
);
}
function SelectChevron({ isOpen }) {
return /* @__PURE__ */ jsx11(
ChevrondownIcon,
{
"aria-hidden": true,
size: "base",
className: isOpen ? "shrink-0 rotate-180 transition-transform" : "shrink-0 transition-transform"
}
);
}
function SelectListBox(props) {
return /* @__PURE__ */ jsx11(
ListBox,
{
...props,
className: composeTailwindRenderProps(
props.className,
"max-h-72 min-w-(--trigger-width) p-1"
)
}
);
}
function SelectItem(props) {
return /* @__PURE__ */ jsx11(DropdownItem, { ...props });
}
function SelectSection(props) {
return /* @__PURE__ */ jsx11(
ListBoxSection2,
{
...props,
className: twMerge4(
`
after:block after:h-1 after:content-['']
first:after:h-0
`,
props.className
)
}
);
}
function SelectSectionHeader(props) {
return /* @__PURE__ */ jsx11(
Header3,
{
...props,
className: twMerge4(
"px-3 py-1 text-xs font-semibold tracking-wide text-quanta-pigeon uppercase",
props.className
)
}
);
}
// src/components/TextField/TextField.quanta.tsx
import "react";
import {
TextField as AriaTextField
} from "react-aria-components";
import { jsx as jsx12, jsxs as jsxs9 } from "react/jsx-runtime";
function TextField({
label,
description,
errorMessage,
...props
}) {
return /* @__PURE__ */ jsxs9(
AriaTextField,
{
...props,
className: composeTailwindRenderProps(
props.className,
"group flex flex-col gap-1"
),
children: [
label && /* @__PURE__ */ jsx12(Label, { children: label }),
/* @__PURE__ */ jsx12(Input, { className: inputStyles }),
description && /* @__PURE__ */ jsx12(Description, { children: description }),
/* @__PURE__ */ jsx12(FieldError, { children: errorMessage })
]
}
);
}
// src/components/DateTimePicker/DateTimePicker.quanta.tsx
import { useCallback, useState, useEffect } from "react";
import {
DatePicker as AriaDatePicker
} from "react-aria-components";
import {
now,
getLocalTimeZone,
parseDate,
toZoned,
parseAbsolute,
ZonedDateTime
} from "@internationalized/date";
// src/components/Dialog/Dialog.quanta.tsx
import "react";
import { Dialog as RACDialog } from "react-aria-components";
import { twMerge as twMerge5 } from "tailwind-merge";
import { DialogTrigger } from "react-aria-components";
import { jsx as jsx13 } from "react/jsx-runtime";
function Dialog(props) {
return /* @__PURE__ */ jsx13(
RACDialog,
{
...props,
className: twMerge5(
`
relative max-h-[inherit] overflow-auto p-6 outline-0
[[data-placement]>&]:p-4
`,
props.className
)
}
);
}
// src/components/DateInput/DateInput.quanta.tsx
import "react";
import {
DateInput as AriaDateInput,
DateSegment
} from "react-aria-components";
import { tv as tv10 } from "tailwind-variants";
import { jsx as jsx14 } from "react/jsx-runtime";
var segmentStyles = tv10({
base: `
inline rounded-xs p-1 text-gray-800 caret-transparent outline-0 forced-color-adjust-none
dark:text-zinc-200
forced-colors:text-[ButtonText]
type-literal:px-0
`,
variants: {
isPlaceholder: {
true: `
text-gray-600 italic
dark:text-zinc-400
`
},
isDisabled: {
true: `
text-gray-200
dark:text-zinc-600
forced-colors:text-[GrayText]
`
},
isFocused: {
true: `
bg-blue-600 text-white
dark:text-white
forced-colors:bg-[Highlight] forced-colors:text-[HighlightText]
`
}
}
});
function DateInput(props) {
return /* @__PURE__ */ jsx14(
AriaDateInput,
{
...props,
className: composeTailwindRenderProps(
props.className,
"ml-1 flex h-10 min-w-[150px] flex-1 items-center pl-2"
),
children: (segment) => /* @__PURE__ */ jsx14(DateSegment, { segment, className: segmentStyles })
}
);
}
// src/components/DateTimePicker/DateTimePicker.quanta.tsx
import { jsx as jsx15, jsxs as jsxs10 } from "react/jsx-runtime";
function isDateOnly(granularity) {
return granularity === "day";
}
function utcStringToLocalDateValue(utcString, isDateOnly2) {
if (!utcString) return null;
if (isDateOnly2) {
return parseDate(utcString);
}
try {
const localTimeZone = getLocalTimeZone();
return parseAbsolute(utcString, localTimeZone);
} catch (error) {
console.warn("Failed to parse UTC string:", utcString, error);
return null;
}
}
function DateTimePicker({
label,
description,
errorMessage,
resettable = true,
value,
defaultValue,
onChange,
isDisabled,
granularity = "minute",
...props
}) {
const [internalValue, setInternalValue] = useState(() => {
const initialValue = value ?? defaultValue ?? null;
return utcStringToLocalDateValue(initialValue, isDateOnly(granularity));
});
useEffect(() => {
if (value !== void 0) {
setInternalValue(
utcStringToLocalDateValue(value, isDateOnly(granularity))
);
}
}, [value, granularity]);
const handleReset = useCallback(() => {
setInternalValue(null);
if (onChange) {
onChange(null);
}
}, [onChange]);
const handleDateChange = useCallback(
(newValue) => {
if (!isDateOnly(granularity) && !internalValue && newValue) {
const currentTime = now(getLocalTimeZone());
const localZoned = toZoned(
newValue,
getLocalTimeZone()
);
const dateTimeValue = localZoned.set({
hour: currentTime.hour,
minute: currentTime.minute,
second: currentTime.second
});
setInternalValue(dateTimeValue);
if (onChange) {
onChange(dateTimeValue.toAbsoluteString());
}
return;
}
setInternalValue(newValue);
if (onChange && newValue) {
if (newValue instanceof ZonedDateTime) {
onChange(newValue.toAbsoluteString());
} else {
onChange(newValue.toString());
}
}
},
[onChange, internalValue, granularity]
);
return /* @__PURE__ */ jsx15("div", { className: "flex items-center", children: /* @__PURE__ */ jsxs10(
AriaDatePicker,
{
...props,
value: value !== void 0 ? internalValue : internalValue,
defaultValue: value === void 0 ? utcStringToLocalDateValue(
defaultValue ?? null,
isDateOnly(granularity)
) : void 0,
onChange: handleDateChange,
granularity,
isDisabled,
className: composeTailwindRenderProps(
props.className,
"group flex flex-col gap-1"
),
children: [
label && /* @__PURE__ */ jsx15(Label, { children: label }),
/* @__PURE__ */ jsxs10("div", { className: "flex items-center gap-2", children: [
/* @__PURE__ */ jsxs10(FieldGroup, { className: "w-auto min-w-[208px]", children: [
/* @__PURE__ */ jsx15(DateInput, { className: "flex h-10 min-w-[150px] flex-1 items-center text-sm" }),
/* @__PURE__ */ jsx15(
Button,
{
variant: "icon",
className: "mr-1 w-7 rounded-xs outline-offset-0",
children: /* @__PURE__ */ jsx15(CalendarIcon, { "aria-hidden": true, className: "h-4 w-4" })
}
)
] }),
resettable && /* @__PURE__ */ jsx15(
Button,
{
variant: "icon",
className: "h-7 w-7 flex-shrink-0 p-1",
onPress: handleReset,
isDisabled: isDisabled || !internalValue || props.isReadOnly,
"aria-label": "Clear date and time",
slot: null,
children: /* @__PURE__ */ jsx15(CloseIcon, { className: "h-4 w-4" })
}
)
] }),
description && /* @__PURE__ */ jsx15(Description, { children: description }),
/* @__PURE__ */ jsx15(FieldError, { children: errorMessage }),
/* @__PURE__ */ jsx15(Popover, { children: /* @__PURE__ */ jsx15(Dialog, { children: /* @__PURE__ */ jsx15(Calendar, {}) }) })
]
}
) });
}
// src/components/DatePicker/DatePicker.quanta.tsx
import "react";
import "react-aria-components";
import { jsx as jsx16 } from "react/jsx-runtime";
function DatePicker({
label,
description,
errorMessage,
...props
}) {
return /* @__PURE__ */ jsx16(
DateTimePicker,
{
...props,
label,
description,
errorMessage,
granularity: "day"
}
);
}
// src/components/TimeField/TimeField.quanta.tsx
import "react";
import {
TimeField as AriaTimeField
} from "react-aria-components";
import { jsx as jsx17, jsxs as jsxs11 } from "react/jsx-runtime";
function TimeField({
label,
description,
errorMessage,
...props
}) {
return /* @__PURE__ */ jsxs11(AriaTimeField, { ...props, children: [
/* @__PURE__ */ jsx17(Label, { children: label }),
/* @__PURE__ */ jsx17(DateInput, { className: "w-fit px-2" }),
description && /* @__PURE__ */ jsx17(Description, { children: description }),
/* @__PURE__ */ jsx17(FieldError, { children: errorMessage })
] });
}
// src/components/MultiSelect/MultiSelect.quanta.tsx
import { useRef, useState as useState2, useEffect as useEffect2, useCallback as useCallback2, useId } from "react";
import {
Button as Button4,
ComboBox,
Input as Input2,
ListBox as ListBox2,
Popover as Popover2,
ListBoxItem,
TagGroup,
TagList,
Tag
} from "react-aria-components";
import { useListData } from "react-stately";
import { useFilter } from "react-aria";
import { twMerge as twMerge6 } from "tailwind-merge";
import { Fragment as Fragment7, jsx as jsx18, jsxs as jsxs12 } from "react/jsx-runtime";
function MultiSelect({
label,
placeholder = "Select items...",
items,
className = "",
description,
onItemCleared,
onItemInserted,
renderEmptyState,
selectedItems,
creatable = true,
...props
}) {
const triggerRef = useRef(null);
const tagGroupIdentifier = useId();
const selectedKeys = selectedItems?.items.map((i) => i.id);
const [width, setWidth] = useState2(0);
const { contains } = useFilter({ sensitivity: "base" });
const filter = useCallback2(
(item, filterText) => {
return !selectedKeys.includes(item.id) && contains(item.name, filterText);
},
[contains, selectedKeys]
);
const accessibleList = useListData({
initialItems: items,
filter
});
const [fieldState, setFieldState] = useState2({
selectedKey: null,
inputValue: ""
});
const onRemove = useCallback2(
(keys) => {
const key = keys.values().next().value;
if (key) {
selectedItems.remove(key);
setFieldState({
inputValue: "",
selectedKey: null
});
onItemCleared?.(key);
}
},
[selectedItems, onItemCleared]
);
const onSelectionChange = (id) => {
if (!id) {
return;
}
const item = accessibleList.getItem(id);
if (!item) {
return;
}
if (!selectedKeys.includes(id)) {
selectedItems.append(item);
setFieldState({
inputValue: "",
selectedKey: id
});
onItemInserted?.(id);
}
accessibleList.setFilterText("");
};
const onInputChange = (value) => {
setFieldState((prev) => ({
inputValue: value,
selectedKey: value === "" ? null : prev.selectedKey
}));
accessibleList.setFilterText(value);
};
useEffect2(() => {
const trigger = triggerRef.current;
if (!trigger) return;
const observer = new ResizeObserver((entries) => {
for (const entry of entries) {
setWidth(entry.target.clientWidth);
}
});
observer.observe(trigger);
return () => {
observer.unobserve(trigger);
};
}, []);
const onCreateTag = useCallback2(() => {
const inputValue = fieldState.inputValue.trim();
const id = inputValue.toLocaleLowerCase();
let item = accessibleList.getItem(id);
if (!item) {
item = {
id,
name: inputValue
};
setFieldState((prev) => ({
...prev,
inputValue: "",
selectedKey: id
}));
accessibleList.append(item);
selectedItems.append(item);
}
}, [fieldState.inputValue, accessibleList, selectedItems, setFieldState]);
const popLast = useCallback2(() => {
if (selectedItems.items.length === 0) {
return;
}
const endKey = selectedItems.items[selectedItems.items.length - 1];
if (endKey) {
selectedItems.remove(endKey.id);
onItemCleared?.(endKey.id);
}
setFieldState({
inputValue: "",
selectedKey: null
});
}, [selectedItems, onItemCleared]);
const onKeyDownCapture = useCallback2(
(e) => {
if (e.key === "Backspace" && fieldState.inputValue === "") {
popLast();
}
if (e.key === "Enter" && fieldState.inputValue && creatable && accessibleList.items.length === 0) {
onCreateTag();
}
},
[popLast, fieldState.inputValue, onCreateTag, creatable, accessibleList]
);
return /* @__PURE__ */ jsxs12("div", { className: twMerge6("w-full", className), children: [
label && /* @__PURE__ */ jsx18(Label, { children: label }),
/* @__PURE__ */ jsx18("div", { ref: triggerRef, className: "relative", children: /* @__PURE__ */ jsxs12(
"div",
{
className: `
relative flex min-h-10 w-full flex-wrap items-center gap-1 rounded-md border
border-gray-300 bg-white px-3 py-1.5 shadow-sm
focus-within:border-gray-500 focus-within:ring-2 focus-within:ring-gray-400
`,
children: [
/* @__PURE__ */ jsx18(
TagGroup,
{
id: tagGroupIdentifier,
"aria-label": "Selected items",
onRemove,
children: /* @__PURE__ */ jsx18(
TagList,
{
items: selectedItems.items,
className: "flex flex-wrap items-center gap-1",
children: (item) => /* @__PURE__ */ jsxs12(
Tag,
{
className: `
inline-flex items-center gap-x-1.5 rounded-md bg-gray-200 px-2 py-0.5 text-sm
text-gray-800
`,
textValue: item.name,
id: item.id,
children: [
item.name,
/* @__PURE__ */ jsx18(
Button4,
{
slot: "remove",
className: `
grid cursor-pointer place-content-center text-gray-500
hover:bg-gray-600 hover:text-gray-300
focus:bg-gray-600 focus:outline-none
`,
type: "button",
children: /* @__PURE__ */ jsx18(CloseIcon, { size: "xs" })
}
)
]
}
)
}
)
}
),
/* @__PURE__ */ jsxs12(
ComboBox,
{
...props,
allowsEmptyCollection: true,
"aria-label": "Available items",
items: accessibleList.items,
selectedKey: fieldState.selectedKey,
inputValue: fieldState.inputValue,
onSelectionChange,
onInputChange,
className: "relative flex flex-1",
children: [
/* @__PURE__ */ jsx18(
Input2,
{
placeholder,
onBlur: () => {
setFieldState({
inputValue: "",
selectedKey: null
});
accessibleList.setFilterText("");
},
onKeyDownCapture,
className: `
min-w-0 flex-1 bg-white px-2 py-1.5 text-sm text-gray-800 outline-0
disabled:text-gray-200
`
}
),
/* @__PURE__ */ jsx18(
Button4,
{
className: `
absolute top-1/2 right-2 -translate-y-1/2 p-1 text-gray-400
hover:text-gray-600
focus:outline-none
`,
type: "button",
children: /* @__PURE__ */ jsx18(ChevrondownIcon, {})
}
),
/* @__PURE__ */ jsx18(
Popover2,
{
isNonModal: true,
trigger: "ComboBox",
triggerRef,
style: { width: `${width}px` },
className: "max-w-none overflow-hidden",
children: /* @__PURE__ */ jsx18(
ListBox2,
{
selectionMode: "multiple",
className: "rounded-md border border-gray-200 bg-white p-1 shadow-lg",
disallowEmptySelection: false,
renderEmptyState: renderEmptyState ? () => renderEmptyState(fieldState.inputValue) : () => /* @__PURE__ */ jsx18(
"div",
{
className: `
block cursor-pointer rounded-md px-3 py-2 text-gray-700
hover:bg-gray-100
focus:bg-gray-100 focus:outline-none
`,
role: "button",
onMouseDown: (e) => {
e.stopPropagation();
if (fieldState.inputValue && creatable) {
onCreateTag();
}
},
tabIndex: 0,
children: fieldState.inputValue ? /* @__PURE__ */ jsxs12(Fragment7, { children: [
creatable ? "Create:" : "No results found for:",
" ",
/* @__PURE__ */ jsx18("strong", { className: "font-medium text-gray-900", children: fieldState.inputValue })
] }) : "No options"
}
),
children: (item) => /* @__PURE__ */ jsx18(
ListBoxItem,
{
id: item.id,
textValue: item.name,
className: `
cursor-pointer rounded-md px-3 py-2 text-gray-700
hover:bg-gray-100
focus:bg-gray-100 focus:outline-none
data-[focused]:bg-gray-100
`,
children: item.name
},
item.id
)
}
)
}
)
]
}
)
]
}
) }),
description && /* @__PURE__ */ jsx18(Description, { children: description })
] });
}
// src/components/Separator/Separator.quanta.tsx
import "react";
import {
Separator as RACSeparator
} from "react-aria-components";
import { tv as tv11 } from "tailwind-variants";
import { jsx as jsx19 } from "react/jsx-runtime";
var styles3 = tv11({
base: `
bg-gray-300
dark:bg-zinc-600
forced-colors:bg-[ButtonBorder]
`,
variants: {
orientation: {
horizontal: "h-px w-full",
vertical: "w-px"
}
},
defaultVariants: {
orientation: "horizontal"
}
});
function Separator(props) {
return /* @__PURE__ */ jsx19(
RACSeparator,
{
...props,
className: styles3({
orientation: props.orientation,
className: props.className
})
}
);
}
// src/components/Spinner/Spinner.quanta