@orchard9ai/design-system
Version:
DaisyUI-based component library for Orchard9 applications
1,524 lines (1,502 loc) • 239 kB
JavaScript
// src/components/Typography/Heading.tsx
import * as React from "react";
// src/utils/cn.ts
import { clsx } from "clsx";
function cn(...inputs) {
return clsx(inputs);
}
// src/components/Typography/Heading.tsx
import { jsx } from "react/jsx-runtime";
var sizeClasses = {
xs: "text-xs",
sm: "text-sm",
md: "text-base md:text-lg",
lg: "text-lg md:text-xl lg:text-2xl",
xl: "text-xl md:text-2xl lg:text-3xl",
"2xl": "text-2xl md:text-3xl lg:text-4xl",
"3xl": "text-3xl md:text-4xl lg:text-5xl",
"4xl": "text-4xl md:text-5xl lg:text-6xl",
"5xl": "text-5xl md:text-6xl lg:text-7xl"
};
var headingSizeMap = {
h1: { default: "xl", md: "2xl", lg: "2xl" },
h2: { default: "lg", md: "xl", lg: "xl" },
h3: { default: "md", md: "lg", lg: "lg" },
h4: { default: "sm", md: "md", lg: "md" },
h5: { default: "xs", md: "sm", lg: "sm" },
h6: { default: "xs", md: "xs", lg: "xs" }
};
var weightClasses = {
normal: "font-normal",
medium: "font-medium",
semibold: "font-semibold",
bold: "font-bold",
extrabold: "font-extrabold"
};
var colorClasses = {
default: "text-base-content",
primary: "text-primary",
secondary: "text-secondary",
muted: "text-base-content/70",
error: "text-error"
};
var alignClasses = {
left: "text-left",
center: "text-center",
right: "text-right",
justify: "text-justify"
};
var Heading = React.forwardRef(
({
as: Component2 = "h2",
size,
weight = "bold",
color = "default",
align,
truncate = false,
clamp,
gradient = false,
id,
children,
className
}, ref) => {
const autoSize = size || sizeClasses[headingSizeMap[Component2].default];
const sizeClass = size ? sizeClasses[size] : autoSize;
const clampClass = clamp ? `line-clamp-${clamp}` : truncate ? "truncate" : "";
const gradientClass = gradient ? "bg-gradient-to-r from-primary to-secondary bg-clip-text text-transparent" : "";
return /* @__PURE__ */ jsx(
Component2,
{
ref,
id,
className: cn(
sizeClass,
weightClasses[weight],
!gradient && colorClasses[color],
align && alignClasses[align],
clampClass,
gradientClass,
"tracking-tight",
className
),
children
}
);
}
);
Heading.displayName = "Heading";
// src/components/Typography/Text.tsx
import * as React2 from "react";
import { jsx as jsx2 } from "react/jsx-runtime";
var sizeClasses2 = {
xs: "text-xs",
sm: "text-sm",
base: "text-base",
lg: "text-lg",
xl: "text-xl",
"2xl": "text-2xl"
};
var weightClasses2 = {
normal: "font-normal",
medium: "font-medium",
semibold: "font-semibold",
bold: "font-bold"
};
var colorClasses2 = {
default: "text-base-content",
primary: "text-primary",
secondary: "text-secondary",
muted: "text-base-content/70",
error: "text-error",
success: "text-success"
};
var alignClasses2 = {
left: "text-left",
center: "text-center",
right: "text-right",
justify: "text-justify"
};
var variantPresets = {
body: { size: "base", weight: "normal" },
caption: { size: "sm", color: "muted" },
overline: { size: "xs", weight: "semibold", uppercase: true },
helper: { size: "sm", color: "muted", italic: true },
error: { size: "sm", color: "error", weight: "medium" }
};
var Text = React2.forwardRef(
({
as: Component2 = "p",
size,
weight,
color,
align = "left",
italic = false,
underline = false,
strikethrough = false,
uppercase = false,
lowercase = false,
capitalize = false,
truncate = false,
clamp,
nowrap = false,
variant,
children,
className
}, ref) => {
const variantProps = variant ? variantPresets[variant] : {};
const finalSize = size || variantProps.size || "base";
const finalWeight = weight || variantProps.weight || "normal";
const finalColor = color || variantProps.color || "default";
const finalItalic = italic || variantProps.italic || false;
const finalUppercase = uppercase || variantProps.uppercase || false;
const textTransformClass = uppercase || finalUppercase ? "uppercase" : lowercase ? "lowercase" : capitalize ? "capitalize" : "";
const decorationClass = underline ? "underline" : strikethrough ? "line-through" : "";
const clampClass = clamp ? `line-clamp-${clamp}` : truncate ? "truncate" : "";
return /* @__PURE__ */ jsx2(
Component2,
{
ref,
className: cn(
sizeClasses2[finalSize],
weightClasses2[finalWeight],
colorClasses2[finalColor],
alignClasses2[align],
finalItalic && "italic",
decorationClass,
textTransformClass,
clampClass,
nowrap && "whitespace-nowrap",
"leading-relaxed",
className
),
children
}
);
}
);
Text.displayName = "Text";
// src/components/Typography/Prose.tsx
import * as React3 from "react";
import { jsx as jsx3 } from "react/jsx-runtime";
var sizeClasses3 = {
sm: "prose-sm",
base: "prose",
lg: "prose-lg",
xl: "prose-xl"
};
var maxWidthClasses = {
none: "max-w-none",
sm: "max-w-prose-sm",
md: "max-w-prose",
lg: "max-w-prose-lg",
xl: "max-w-prose-xl",
"2xl": "max-w-prose-2xl"
};
var Prose = React3.forwardRef(
({
children,
size = "base",
maxWidth = "lg",
centered = false,
serif = false,
dropCap = false,
balancedText = false,
className
}, ref) => {
return /* @__PURE__ */ jsx3(
"div",
{
ref,
className: cn(
"prose",
sizeClasses3[size],
maxWidthClasses[maxWidth],
centered && "mx-auto",
serif && "font-serif",
balancedText && "[text-wrap:balance]",
// Dark mode support
"prose-headings:text-base-content",
"prose-p:text-base-content",
"prose-strong:text-base-content",
"prose-em:text-base-content",
"prose-blockquote:text-base-content/80",
"prose-lead:text-base-content",
"prose-a:text-primary",
"prose-a:no-underline",
"hover:prose-a:underline",
"prose-code:text-base-content",
"prose-code:bg-base-200",
"prose-code:px-1",
"prose-code:py-0.5",
"prose-code:rounded",
"prose-pre:bg-base-200",
"prose-pre:text-base-content",
"prose-ol:text-base-content",
"prose-ul:text-base-content",
"prose-li:text-base-content",
"prose-table:text-base-content",
"prose-thead:border-base-300",
"prose-tr:border-base-300",
"prose-th:text-base-content",
"prose-td:text-base-content",
"prose-hr:border-base-300",
"prose-figure:text-base-content",
"prose-figcaption:text-base-content/70",
"prose-video:rounded",
"prose-img:rounded",
// First letter drop cap
dropCap && "prose-p:first-of-type:first-letter:text-7xl prose-p:first-of-type:first-letter:font-bold prose-p:first-of-type:first-letter:float-left prose-p:first-of-type:first-letter:mr-3 prose-p:first-of-type:first-letter:mt-1 prose-p:first-of-type:first-letter:text-primary",
className
),
children
}
);
}
);
Prose.displayName = "Prose";
// src/components/Typography/Link.tsx
import * as React4 from "react";
import { jsx as jsx4, jsxs } from "react/jsx-runtime";
var variantClasses = {
default: "text-primary hover:text-primary-focus",
primary: "text-primary hover:text-primary-focus",
muted: "text-base-content/70 hover:text-base-content",
nav: "text-base-content hover:text-primary transition-colors focus:!ring-offset-0"
};
var underlineClasses = {
always: "underline",
hover: "no-underline hover:underline",
none: "no-underline"
};
var weightClasses3 = {
normal: "font-normal",
medium: "font-medium",
semibold: "font-semibold",
bold: "font-bold"
};
var Link = React4.forwardRef(
({
href,
to,
variant = "default",
external = false,
download,
underline = "hover",
weight = "normal",
icon,
iconPosition = "right",
children,
className,
onClick
}, ref) => {
const linkHref = href || to || "#";
const isExternal = external || typeof linkHref === "string" && linkHref.startsWith("http");
const externalProps = isExternal ? {
target: "_blank",
rel: "noopener noreferrer"
} : {};
const downloadProps = download ? {
download: typeof download === "string" ? download : true
} : {};
const iconElement = icon && /* @__PURE__ */ jsx4("span", { className: cn("inline-flex items-center", iconPosition === "left" ? "mr-1" : "ml-1"), children: icon });
return /* @__PURE__ */ jsxs(
"a",
{
ref,
href: linkHref,
className: cn(
variant === "nav" ? "flex items-center focus-ring" : "inline-flex items-center focus-ring",
variantClasses[variant],
underlineClasses[underline],
weightClasses3[weight],
"transition-colors duration-200",
"focus:!outline-none focus:!ring-1 focus:!ring-primary focus:!ring-offset-1",
className
),
onClick,
...externalProps,
...downloadProps,
children: [
iconPosition === "left" && iconElement,
children,
iconPosition === "right" && iconElement
]
}
);
}
);
Link.displayName = "Link";
// src/components/Typography/Code.tsx
import * as React5 from "react";
import { jsx as jsx5, jsxs as jsxs2 } from "react/jsx-runtime";
var Code = React5.forwardRef(
({
children,
language,
inline = false,
showLineNumbers = false,
highlightLines = [],
copyButton = false,
theme = "auto",
className
}, ref) => {
const [copied, setCopied] = React5.useState(false);
const handleCopy = async () => {
try {
await navigator.clipboard.writeText(children);
setCopied(true);
setTimeout(() => setCopied(false), 2e3);
} catch (err) {
console.error("Failed to copy:", err);
}
};
if (inline) {
return /* @__PURE__ */ jsx5(
"code",
{
ref,
className: cn(
"px-1.5 py-0.5 rounded text-sm font-mono",
"bg-base-200 text-base-content",
className
),
children
}
);
}
const lines = children.split("\n");
const lineNumberWidth = lines.length.toString().length;
return /* @__PURE__ */ jsxs2("div", { className: cn("relative group", className), children: [
/* @__PURE__ */ jsxs2(
"pre",
{
ref,
className: cn(
"overflow-x-auto p-4 rounded-lg text-sm",
"bg-base-200 text-base-content",
theme === "dark" && "bg-base-300",
theme === "auto" && "dark:bg-base-300",
showLineNumbers && "pl-12"
),
children: [
showLineNumbers && /* @__PURE__ */ jsx5("div", { className: "absolute left-0 top-0 bottom-0 w-12 flex flex-col py-4 text-right pr-3 select-none", children: lines.map((_, index) => /* @__PURE__ */ jsx5(
"span",
{
className: cn(
"text-base-content/50 text-xs leading-6 font-mono",
highlightLines.includes(index + 1) && "text-primary font-semibold"
),
style: { minWidth: `${lineNumberWidth}ch` },
children: index + 1
},
index
)) }),
/* @__PURE__ */ jsx5("code", { className: cn("font-mono", language && `language-${language}`), children: lines.map((line, index) => /* @__PURE__ */ jsx5(
"div",
{
className: cn(
"leading-6",
highlightLines.includes(index + 1) && "bg-primary/10 -mx-4 px-4"
),
children: line || "\n"
},
index
)) })
]
}
),
copyButton && /* @__PURE__ */ jsx5(
"button",
{
onClick: handleCopy,
className: cn(
"absolute top-2 right-2",
"btn btn-sm btn-ghost",
"opacity-0 group-hover:opacity-100 transition-opacity",
"focus:opacity-100"
),
"aria-label": "Copy code",
children: copied ? /* @__PURE__ */ jsx5("svg", { width: "16", height: "16", viewBox: "0 0 16 16", fill: "none", className: "text-success", children: /* @__PURE__ */ jsx5(
"path",
{
d: "M13.5 4.5L6 12L2.5 8.5",
stroke: "currentColor",
strokeWidth: "1.5",
strokeLinecap: "round",
strokeLinejoin: "round"
}
) }) : /* @__PURE__ */ jsxs2("svg", { width: "16", height: "16", viewBox: "0 0 16 16", fill: "none", children: [
/* @__PURE__ */ jsx5(
"rect",
{
x: "5.5",
y: "5.5",
width: "8",
height: "8",
rx: "1",
stroke: "currentColor",
strokeWidth: "1.5"
}
),
/* @__PURE__ */ jsx5(
"path",
{
d: "M10.5 5.5V3.5C10.5 2.94772 10.0523 2.5 9.5 2.5H3.5C2.94772 2.5 2.5 2.94772 2.5 3.5V9.5C2.5 10.0523 2.94772 10.5 3.5 10.5H5.5",
stroke: "currentColor",
strokeWidth: "1.5"
}
)
] })
}
),
language && /* @__PURE__ */ jsx5("div", { className: "absolute top-2 left-2 text-xs text-base-content/50 font-mono", children: language })
] });
}
);
Code.displayName = "Code";
// src/components/Typography/List.tsx
import * as React6 from "react";
import { jsx as jsx6, jsxs as jsxs3 } from "react/jsx-runtime";
var styleTypeClasses = {
disc: "list-disc",
circle: "list-circle",
square: "list-square",
decimal: "list-decimal",
alpha: "list-alpha",
roman: "list-roman",
none: "list-none"
};
var spacingClasses = {
tight: "space-y-1",
normal: "space-y-2",
loose: "space-y-4"
};
var columnsClasses = {
1: "",
2: "columns-2",
3: "columns-3",
4: "columns-4"
};
var List = React6.forwardRef(
({
as: Component2 = "ul",
children,
styleType = Component2 === "ul" ? "disc" : "decimal",
spacing = "normal",
columns = 1,
horizontal = false,
className
}, ref) => {
return /* @__PURE__ */ jsx6(
Component2,
{
ref,
className: cn(
styleTypeClasses[styleType],
!horizontal && spacingClasses[spacing],
horizontal && "flex flex-wrap gap-4",
columnsClasses[columns],
styleType !== "none" && !horizontal && "pl-5",
"text-base-content",
className
),
children
}
);
}
);
List.displayName = "List";
var ListItem = React6.forwardRef(
({ children, icon, className }, ref) => {
if (icon) {
return /* @__PURE__ */ jsxs3("li", { ref, className: cn("flex items-start gap-2", className), children: [
/* @__PURE__ */ jsx6("span", { className: "flex-shrink-0 mt-0.5", "aria-hidden": "true", children: icon }),
/* @__PURE__ */ jsx6("span", { children })
] });
}
return /* @__PURE__ */ jsx6("li", { ref, className, children });
}
);
ListItem.displayName = "ListItem";
// src/components/Logo/Logo.tsx
import { jsx as jsx7 } from "react/jsx-runtime";
var Logo = ({
withHighlight = false,
size = "md",
withLink = true,
className,
text = "Orchard9",
href = "/"
}) => {
const sizeClasses5 = {
sm: "text-lg",
md: "text-xl",
lg: "text-2xl",
xl: "text-4xl md:text-5xl"
};
const baseClasses = cn(
"font-bold",
sizeClasses5[size],
"bg-gradient-to-r from-emerald-400 to-teal-500 bg-clip-text text-transparent",
withHighlight && "via-emerald-300",
className
);
const content = /* @__PURE__ */ jsx7("span", { className: baseClasses, children: text });
if (withLink) {
return /* @__PURE__ */ jsx7(
Link,
{
href,
className: "hover:opacity-80 transition-opacity inline-flex items-center gap-2",
children: content
}
);
}
return content;
};
// src/components/Error/ErrorBoundary.tsx
import * as React7 from "react";
import { jsx as jsx8, jsxs as jsxs4 } from "react/jsx-runtime";
var DefaultErrorFallback = ({ error, resetErrorBoundary }) => {
const isDevelopment = process.env["NODE_ENV"] === "development";
return /* @__PURE__ */ jsx8("div", { className: "min-h-[200px] flex items-center justify-center p-8", children: /* @__PURE__ */ jsxs4("div", { className: "text-center max-w-md", children: [
/* @__PURE__ */ jsx8("h2", { className: "text-2xl font-bold text-error mb-4", children: "Something went wrong" }),
/* @__PURE__ */ jsx8("p", { className: "text-base-content/70 mb-6", children: "We're sorry, but something unexpected happened. Please try again." }),
isDevelopment && error && /* @__PURE__ */ jsxs4("details", { className: "mb-6 text-left", children: [
/* @__PURE__ */ jsx8("summary", { className: "cursor-pointer text-sm text-base-content/70 hover:text-base-content", children: "Error details" }),
/* @__PURE__ */ jsx8("pre", { className: "mt-2 p-4 bg-base-200 rounded text-xs overflow-auto max-h-64", children: error.stack || error.toString() })
] }),
/* @__PURE__ */ jsx8("button", { onClick: resetErrorBoundary, className: "btn btn-primary", children: "Try Again" })
] }) });
};
var ErrorBoundary = class extends React7.Component {
resetTimeoutId = null;
previousResetKeys = [];
constructor(props) {
super(props);
this.state = {
hasError: false,
error: null,
errorInfo: null
};
}
static getDerivedStateFromError(error) {
return {
hasError: true,
error
};
}
componentDidCatch(error, errorInfo) {
const { onError } = this.props;
this.setState({
errorInfo
});
if (onError) {
onError(error, errorInfo);
}
if (process.env["NODE_ENV"] === "development") {
console.error("ErrorBoundary caught an error:", error, errorInfo);
}
}
componentDidUpdate(prevProps) {
const { resetKeys, resetOnPropsChange } = this.props;
const { hasError } = this.state;
if (hasError && resetKeys) {
const hasResetKeyChanged = resetKeys.some(
(key, index) => key !== this.previousResetKeys[index]
);
if (hasResetKeyChanged) {
this.resetErrorBoundary();
}
}
if (hasError && resetOnPropsChange && prevProps !== this.props) {
this.resetErrorBoundary();
}
this.previousResetKeys = resetKeys || [];
}
componentWillUnmount() {
if (this.resetTimeoutId) {
clearTimeout(this.resetTimeoutId);
}
}
resetErrorBoundary = () => {
this.setState({
hasError: false,
error: null,
errorInfo: null
});
};
render() {
const { hasError, error, errorInfo } = this.state;
const { fallback: Fallback = DefaultErrorFallback, children, isolate, level } = this.props;
if (hasError && error) {
const errorBoundaryClass = isolate ? "error-boundary-isolated" : `error-boundary-${level || "component"}`;
return /* @__PURE__ */ jsx8("div", { className: errorBoundaryClass, children: /* @__PURE__ */ jsx8(
Fallback,
{
error,
...errorInfo ? { errorInfo } : {},
resetErrorBoundary: this.resetErrorBoundary
}
) });
}
return children;
}
};
// src/components/Error/ErrorPage.tsx
import * as React9 from "react";
// src/components/Button/Button.tsx
import React8 from "react";
import { jsx as jsx9, jsxs as jsxs5 } from "react/jsx-runtime";
var Button = React8.forwardRef(
({
variant,
size = "md",
shape = "default",
loading = false,
fullWidth = false,
active = false,
glass = false,
noAnimation = false,
as: Component2 = "button",
startIcon,
endIcon,
children,
className,
disabled,
...props
}, ref) => {
const isLoading = !!loading;
const loadingText = typeof loading === "object" ? loading.text : void 0;
const classes = cn(
"btn",
"focus-interactive",
// Use standardized focus utilities
// Variants
variant === "primary" && "btn-primary",
variant === "secondary" && "btn-secondary",
variant === "accent" && "btn-accent",
variant === "info" && "btn-info",
variant === "success" && "btn-success",
variant === "warning" && "btn-warning",
variant === "error" && "btn-error",
variant === "ghost" && "btn-ghost",
variant === "link" && "btn-link",
variant === "outline" && "btn-outline",
variant === "neutral" && "btn-neutral",
// Sizes
size === "xs" && "btn-xs",
size === "sm" && "btn-sm",
size === "lg" && "btn-lg",
// Shapes
shape === "square" && "btn-square",
shape === "circle" && "btn-circle",
// States
active && "btn-active",
glass && "glass",
noAnimation && "no-animation",
fullWidth && "btn-block",
className
);
return /* @__PURE__ */ jsxs5(Component2, { ref, className: classes, disabled: disabled || isLoading, ...props, children: [
isLoading && /* @__PURE__ */ jsx9("span", { className: "loading loading-spinner loading-xs" }),
startIcon && !isLoading && /* @__PURE__ */ jsx9("span", { className: "btn-start-icon", children: startIcon }),
loadingText && isLoading ? loadingText : children,
endIcon && !isLoading && /* @__PURE__ */ jsx9("span", { className: "btn-end-icon", children: endIcon })
] });
}
);
Button.displayName = "Button";
// src/components/Error/ErrorPage.tsx
import { jsx as jsx10, jsxs as jsxs6 } from "react/jsx-runtime";
var NotFoundIllustration = () => /* @__PURE__ */ jsxs6("svg", { className: "w-64 h-64", viewBox: "0 0 256 256", fill: "none", children: [
/* @__PURE__ */ jsx10("circle", { cx: "128", cy: "128", r: "96", stroke: "currentColor", strokeWidth: "8", opacity: "0.2" }),
/* @__PURE__ */ jsx10(
"path",
{
d: "M88 104C88 95.1634 95.1634 88 104 88H152C160.837 88 168 95.1634 168 104V104C168 112.837 160.837 120 152 120H104C95.1634 120 88 112.837 88 104V104Z",
fill: "currentColor",
opacity: "0.3"
}
),
/* @__PURE__ */ jsx10("rect", { x: "88", y: "136", width: "80", height: "16", rx: "8", fill: "currentColor", opacity: "0.3" }),
/* @__PURE__ */ jsx10("rect", { x: "104", y: "168", width: "48", height: "16", rx: "8", fill: "currentColor", opacity: "0.3" })
] });
var ServerErrorIllustration = () => /* @__PURE__ */ jsxs6("svg", { className: "w-64 h-64", viewBox: "0 0 256 256", fill: "none", children: [
/* @__PURE__ */ jsx10(
"rect",
{
x: "64",
y: "80",
width: "128",
height: "96",
rx: "8",
stroke: "currentColor",
strokeWidth: "8",
opacity: "0.2"
}
),
/* @__PURE__ */ jsx10("circle", { cx: "88", cy: "104", r: "8", fill: "currentColor", opacity: "0.5" }),
/* @__PURE__ */ jsx10("circle", { cx: "112", cy: "104", r: "8", fill: "currentColor", opacity: "0.5" }),
/* @__PURE__ */ jsx10("circle", { cx: "136", cy: "104", r: "8", fill: "currentColor", opacity: "0.5" }),
/* @__PURE__ */ jsx10(
"path",
{
d: "M88 128H168M88 144H168M88 160H168",
stroke: "currentColor",
strokeWidth: "8",
strokeLinecap: "round",
opacity: "0.3"
}
)
] });
var ForbiddenIllustration = () => /* @__PURE__ */ jsxs6("svg", { className: "w-64 h-64", viewBox: "0 0 256 256", fill: "none", children: [
/* @__PURE__ */ jsx10("circle", { cx: "128", cy: "128", r: "96", stroke: "currentColor", strokeWidth: "8", opacity: "0.2" }),
/* @__PURE__ */ jsx10(
"path",
{
d: "M128 88V144M128 168V176",
stroke: "currentColor",
strokeWidth: "16",
strokeLinecap: "round",
opacity: "0.5"
}
)
] });
var UnauthorizedIllustration = () => /* @__PURE__ */ jsxs6("svg", { className: "w-64 h-64", viewBox: "0 0 256 256", fill: "none", children: [
/* @__PURE__ */ jsx10(
"rect",
{
x: "88",
y: "96",
width: "80",
height: "96",
rx: "8",
stroke: "currentColor",
strokeWidth: "8",
opacity: "0.2"
}
),
/* @__PURE__ */ jsx10("circle", { cx: "128", cy: "120", r: "16", fill: "currentColor", opacity: "0.3" }),
/* @__PURE__ */ jsx10(
"path",
{
d: "M112 144C112 135.163 119.163 128 128 128V128C136.837 128 144 135.163 144 144V168",
stroke: "currentColor",
strokeWidth: "8",
strokeLinecap: "round",
opacity: "0.3"
}
)
] });
var errorTemplates = {
404: {
title: "Page Not Found",
description: "The page you're looking for doesn't exist or has been moved.",
illustration: /* @__PURE__ */ jsx10(NotFoundIllustration, {}),
actions: [
{ label: "Go Home", href: "/", variant: "primary" },
{ label: "Go Back", onClick: () => window.history.back(), variant: "secondary" }
]
},
500: {
title: "Something Went Wrong",
description: "We're having technical difficulties. Please try again later.",
illustration: /* @__PURE__ */ jsx10(ServerErrorIllustration, {}),
actions: [
{ label: "Retry", onClick: () => window.location.reload(), variant: "primary" },
{ label: "Go Home", href: "/", variant: "secondary" }
]
},
403: {
title: "Access Denied",
description: "You don't have permission to view this page.",
illustration: /* @__PURE__ */ jsx10(ForbiddenIllustration, {}),
actions: [
{ label: "Go Home", href: "/", variant: "primary" },
{ label: "Contact Support", href: "/support", variant: "secondary" }
]
},
401: {
title: "Authentication Required",
description: "Please log in to access this page.",
illustration: /* @__PURE__ */ jsx10(UnauthorizedIllustration, {}),
actions: [
{ label: "Log In", href: "/login", variant: "primary" },
{ label: "Go Home", href: "/", variant: "secondary" }
]
}
};
var ErrorPage = React9.forwardRef(
({
code = 404,
title,
description,
illustration,
actions,
showDetails = false,
error,
className
}, ref) => {
const template = errorTemplates[code] || errorTemplates[404];
const finalTitle = title || template.title;
const finalDescription = description || template.description;
const finalIllustration = illustration || template.illustration;
const finalActions = actions || template.actions;
const isDevelopment = typeof process !== "undefined" && process.env && process.env["NODE_ENV"] === "development";
return /* @__PURE__ */ jsx10(
"div",
{
ref,
className: cn(
"min-h-screen flex items-center justify-center p-4",
"bg-base-100",
className
),
children: /* @__PURE__ */ jsxs6("div", { className: "max-w-md w-full text-center relative", children: [
/* @__PURE__ */ jsx10("div", { className: "absolute inset-0 flex items-center justify-center pointer-events-none", children: /* @__PURE__ */ jsx10("div", { className: "text-base-content", children: finalIllustration }) }),
/* @__PURE__ */ jsxs6("div", { className: "relative z-10", children: [
/* @__PURE__ */ jsx10("div", { className: "text-6xl font-bold text-base-content/80 mb-4", children: code }),
/* @__PURE__ */ jsx10("h1", { className: "text-2xl font-bold mb-2 text-base-content", children: finalTitle }),
/* @__PURE__ */ jsx10("p", { className: "text-base-content/70 mb-8", children: finalDescription }),
/* @__PURE__ */ jsx10("div", { className: "flex flex-col sm:flex-row gap-4 justify-center", children: finalActions.map((action, index) => {
if ("href" in action && action.href) {
return /* @__PURE__ */ jsxs6(
"a",
{
href: action.href,
className: cn(
"btn",
action.variant && `btn-${action.variant}`,
"inline-flex items-center justify-center gap-2"
),
children: [
"icon" in action && action.icon && action.icon,
action.label
]
},
index
);
}
return /* @__PURE__ */ jsxs6(
Button,
{
variant: action.variant || "primary",
onClick: "onClick" in action ? action.onClick : void 0,
className: "inline-flex items-center justify-center gap-2",
children: [
"icon" in action && action.icon && action.icon,
action.label
]
},
index
);
}) }),
showDetails && error && isDevelopment && /* @__PURE__ */ jsxs6("details", { className: "mt-8 text-left", children: [
/* @__PURE__ */ jsx10("summary", { className: "cursor-pointer text-sm text-base-content/70 hover:text-base-content", children: "Technical Details" }),
/* @__PURE__ */ jsx10("pre", { className: "mt-2 p-4 bg-base-200 rounded text-xs overflow-auto max-h-64", children: error.stack || error.toString() })
] })
] })
] })
}
);
}
);
ErrorPage.displayName = "ErrorPage";
// src/components/Error/ErrorMessage.tsx
import * as React10 from "react";
import { jsx as jsx11, jsxs as jsxs7 } from "react/jsx-runtime";
var defaultIcons = {
error: /* @__PURE__ */ jsxs7("svg", { width: "16", height: "16", viewBox: "0 0 16 16", fill: "none", className: "flex-shrink-0", children: [
/* @__PURE__ */ jsx11("circle", { cx: "8", cy: "8", r: "7", stroke: "currentColor", strokeWidth: "2" }),
/* @__PURE__ */ jsx11("path", { d: "M8 5V9M8 11V11.5", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round" })
] }),
warning: /* @__PURE__ */ jsxs7("svg", { width: "16", height: "16", viewBox: "0 0 16 16", fill: "none", className: "flex-shrink-0", children: [
/* @__PURE__ */ jsx11(
"path",
{
d: "M7.2 3.5C7.6 2.8 8.4 2.8 8.8 3.5L14.4 13C14.8 13.7 14.4 14.5 13.6 14.5H2.4C1.6 14.5 1.2 13.7 1.6 13L7.2 3.5Z",
stroke: "currentColor",
strokeWidth: "2",
strokeLinejoin: "round"
}
),
/* @__PURE__ */ jsx11("path", { d: "M8 6V9M8 11.5V12", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round" })
] }),
info: /* @__PURE__ */ jsxs7("svg", { width: "16", height: "16", viewBox: "0 0 16 16", fill: "none", className: "flex-shrink-0", children: [
/* @__PURE__ */ jsx11("circle", { cx: "8", cy: "8", r: "7", stroke: "currentColor", strokeWidth: "2" }),
/* @__PURE__ */ jsx11("path", { d: "M8 7V11M8 5V5.5", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round" })
] })
};
var variantClasses2 = {
error: "text-error border-error/20 bg-error/10",
warning: "text-warning border-warning/20 bg-warning/10",
info: "text-info border-info/20 bg-info/10"
};
var ErrorMessage = React10.forwardRef(
({ error, errors, icon, dismissible = false, onDismiss, className, variant = "error" }, ref) => {
const [isVisible, setIsVisible] = React10.useState(true);
const errorList = React10.useMemo(() => {
if (errors) {
return errors.map((e) => e instanceof Error ? e.message : e);
}
if (error) {
return [error instanceof Error ? error.message : error];
}
return [];
}, [error, errors]);
const handleDismiss = () => {
setIsVisible(false);
onDismiss?.();
};
if (!isVisible || errorList.length === 0) {
return null;
}
const finalIcon = icon || defaultIcons[variant];
return /* @__PURE__ */ jsxs7(
"div",
{
ref,
role: "alert",
className: cn(
"relative flex gap-3 p-3 rounded-lg border",
variantClasses2[variant],
"animate-in fade-in slide-in-from-top-1 duration-200",
className
),
children: [
finalIcon && /* @__PURE__ */ jsx11("div", { className: "mt-0.5", children: finalIcon }),
/* @__PURE__ */ jsx11("div", { className: "flex-1 space-y-1", children: errorList.map((msg, index) => /* @__PURE__ */ jsx11("div", { className: "text-sm", children: msg }, index)) }),
dismissible && /* @__PURE__ */ jsx11(
"button",
{
onClick: handleDismiss,
className: "flex-shrink-0 p-0.5 hover:bg-base-content/10 rounded transition-colors",
"aria-label": "Dismiss error",
children: /* @__PURE__ */ jsx11("svg", { width: "16", height: "16", viewBox: "0 0 16 16", fill: "none", children: /* @__PURE__ */ jsx11(
"path",
{
d: "M12 4L4 12M4 4L12 12",
stroke: "currentColor",
strokeWidth: "2",
strokeLinecap: "round"
}
) })
}
)
]
}
);
}
);
ErrorMessage.displayName = "ErrorMessage";
// src/components/Button/ButtonGroup.tsx
import { jsx as jsx12 } from "react/jsx-runtime";
var ButtonGroup = ({
children,
vertical = false,
className
}) => {
return /* @__PURE__ */ jsx12("div", { className: cn("btn-group", vertical && "btn-group-vertical", className), children });
};
// src/theme/ThemeProvider.tsx
import { createContext, useContext, useEffect, useState as useState3, useCallback, useMemo as useMemo2 } from "react";
import { jsx as jsx13 } from "react/jsx-runtime";
var ThemeContext = createContext(void 0);
var BUILT_IN_THEMES = [
"light",
"dark",
"cupcake",
"business",
"grove-light",
"grove-dark",
"dawn",
"dusk",
"twilight-light",
"twilight-dark",
"squad-light",
"squad-dark",
"lounge-light",
"lounge-dark",
"meadow-light",
"meadow-dark",
"focus-light",
"focus-dark",
"peach-light",
"peach-dark"
];
var themeInitScript = (defaultTheme2) => `
(function() {
const theme = localStorage.getItem('theme');
const systemTheme = window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light';
const fallbackTheme = ${defaultTheme2 ? `'${defaultTheme2}'` : "systemTheme"};
document.documentElement.setAttribute('data-theme', theme || fallbackTheme);
})();
`;
var ThemeProvider = ({
children,
defaultTheme: defaultTheme2 = "light",
initialTheme,
onThemeChange,
disableInitialTransition = true,
customThemes = []
}) => {
if (typeof process !== "undefined" && process.env && process.env["NODE_ENV"] === "development") {
const propsToValidate = {
children,
defaultTheme: defaultTheme2,
initialTheme,
onThemeChange,
disableInitialTransition,
customThemes
};
const invalidProps = Object.keys(propsToValidate).filter(
(key) => ![
"children",
"defaultTheme",
"initialTheme",
"onThemeChange",
"disableInitialTransition",
"customThemes"
].includes(key)
);
if (invalidProps.length > 0) {
console.warn(
`ThemeProvider: Invalid props detected: ${invalidProps.join(", ")}.
Valid props are: children, defaultTheme, initialTheme, onThemeChange, disableInitialTransition, customThemes.
See docs: https://design-system.orchard9.ai/theme`
);
}
const allThemes = [...BUILT_IN_THEMES, ...customThemes];
if (defaultTheme2 && !allThemes.includes(defaultTheme2)) {
console.warn(
`ThemeProvider: Unknown theme "${defaultTheme2}".
Built-in themes: ${BUILT_IN_THEMES.join(", ")}.
` + (customThemes.length > 0 ? `Custom themes: ${customThemes.join(", ")}.
` : `No custom themes provided. Use customThemes prop to add your own themes.
`) + `Make sure to import the theme CSS file if using a custom theme.`
);
}
}
const [theme, setThemeState] = useState3(initialTheme || defaultTheme2);
const [systemTheme, setSystemTheme] = useState3("light");
const [colors, setColors] = useState3({});
const [isInitialized, setIsInitialized] = useState3(false);
const themes3 = useMemo2(() => [...BUILT_IN_THEMES, ...customThemes], [customThemes]);
const updateColors = useCallback(() => {
const computed = getComputedStyle(document.documentElement);
const newColors = {};
const colorVars = [
"primary",
"primary-focus",
"primary-content",
"secondary",
"secondary-focus",
"secondary-content",
"accent",
"accent-focus",
"accent-content",
"neutral",
"neutral-focus",
"neutral-content",
"base-100",
"base-200",
"base-300",
"base-content",
"info",
"success",
"warning",
"error"
];
colorVars.forEach((color) => {
const hsl = computed.getPropertyValue(`--${color}`).trim();
if (hsl) {
newColors[color] = `hsl(${hsl})`;
}
});
setColors(newColors);
}, []);
useEffect(() => {
if (initialTheme) {
return;
}
const stored = localStorage.getItem("theme");
const mediaQuery = window.matchMedia("(prefers-color-scheme: dark)");
setSystemTheme(mediaQuery.matches ? "dark" : "light");
if (stored && themes3.includes(stored)) {
setThemeState(stored);
} else if (defaultTheme2 && themes3.includes(defaultTheme2)) {
setThemeState(defaultTheme2);
} else if (mediaQuery.matches) {
setThemeState("dark");
} else {
setThemeState("light");
}
const handleChange = (e) => {
setSystemTheme(e.matches ? "dark" : "light");
if (!localStorage.getItem("theme")) {
setThemeState(e.matches ? "dark" : "light");
}
};
mediaQuery.addEventListener("change", handleChange);
return () => mediaQuery.removeEventListener("change", handleChange);
}, [themes3, initialTheme, defaultTheme2]);
useEffect(() => {
document.documentElement.setAttribute("data-theme", theme);
if (disableInitialTransition && !isInitialized) {
} else {
document.documentElement.style.setProperty(
"transition",
"background-color 0.3s ease, color 0.3s ease"
);
}
localStorage.setItem("theme", theme);
requestAnimationFrame(updateColors);
window.dispatchEvent(new CustomEvent("themechange", { detail: { theme } }));
onThemeChange?.(theme);
}, [theme, updateColors, onThemeChange, disableInitialTransition, isInitialized]);
useEffect(() => {
setIsInitialized(true);
}, []);
const setTheme = useCallback((newTheme) => {
setThemeState(newTheme);
}, []);
const value = {
theme,
setTheme,
themes: themes3,
systemTheme,
colors
};
return /* @__PURE__ */ jsx13(ThemeContext.Provider, { value, children });
};
var useTheme = () => {
const context = useContext(ThemeContext);
if (!context) {
throw new Error("useTheme must be used within ThemeProvider");
}
return context;
};
// src/components/Loading/LoadingButton.tsx
import React12 from "react";
import { jsx as jsx14, jsxs as jsxs8 } from "react/jsx-runtime";
var LoadingButton = React12.forwardRef(
({
loading = false,
loadingText = "Loading...",
loadingIcon = /* @__PURE__ */ jsx14("span", { className: "loading loading-spinner loading-sm" }),
children,
disabled,
className,
...props
}, ref) => {
return /* @__PURE__ */ jsx14(
Button,
{
ref,
disabled: disabled || loading,
className: cn("focus-interactive", loading && "opacity-80", className),
"aria-busy": loading,
...props,
children: loading ? /* @__PURE__ */ jsxs8("span", { className: "inline-flex items-center gap-2", children: [
loadingIcon,
/* @__PURE__ */ jsx14("span", { children: loadingText })
] }) : children
}
);
}
);
LoadingButton.displayName = "LoadingButton";
// src/components/Loading/LoadingContainer.tsx
import { jsx as jsx15, jsxs as jsxs9 } from "react/jsx-runtime";
var LoadingContainer = ({
loading = false,
skeleton,
children,
overlay = false,
className,
minHeight = "200px",
spinner = /* @__PURE__ */ jsx15("span", { className: "loading loading-spinner loading-lg" })
}) => {
if (loading && skeleton && !overlay) {
return /* @__PURE__ */ jsx15("div", { className: cn("animate-pulse", className), children: skeleton });
}
return /* @__PURE__ */ jsxs9(
"div",
{
className: cn("relative", className),
style: loading && overlay ? { minHeight } : void 0,
"aria-busy": loading,
children: [
children,
loading && overlay && /* @__PURE__ */ jsx15("div", { className: "absolute inset-0 bg-base-100/80 backdrop-blur-sm flex items-center justify-center z-10 focus-container rounded-inherit", children: /* @__PURE__ */ jsxs9("div", { className: "flex flex-col items-center gap-4", children: [
spinner,
/* @__PURE__ */ jsx15("span", { className: "text-sm text-base-content/70", children: "Loading..." })
] }) })
]
}
);
};
// src/components/Loading/LoadingSkeleton.tsx
import { jsx as jsx16, jsxs as jsxs10 } from "react/jsx-runtime";
var LoadingSkeleton = ({
variant = "text",
width,
height,
className,
lines = 1,
animate = true
}) => {
const baseClasses = cn("bg-base-300", animate && "animate-pulse", className);
const style = {
width: typeof width === "number" ? `${width}px` : width,
height: typeof height === "number" ? `${height}px` : height
};
if (variant === "text" && lines > 1) {
return /* @__PURE__ */ jsx16("div", { className: "space-y-2", children: Array.from({ length: lines }).map((_, index) => /* @__PURE__ */ jsx16(
"div",
{
className: cn(
baseClasses,
"h-4 rounded",
// Make last line shorter for natural text appearance
index === lines - 1 && "w-3/4"
),
style: { width: index === lines - 1 ? "75%" : width }
},
index
)) });
}
const variantClasses3 = {
text: "h-4 rounded",
circular: "rounded-full",
rectangular: "rounded",
card: "rounded-lg"
};
if (variant === "card") {
return /* @__PURE__ */ jsxs10("div", { className: cn(baseClasses, "p-4 space-y-3", variantClasses3[variant]), style, children: [
/* @__PURE__ */ jsxs10("div", { className: "flex items-center space-x-3", children: [
/* @__PURE__ */ jsx16("div", { className: "w-10 h-10 bg-base-200 rounded-full animate-pulse" }),
/* @__PURE__ */ jsxs10("div", { className: "flex-1 space-y-2", children: [
/* @__PURE__ */ jsx16("div", { className: "h-4 bg-base-200 rounded w-3/4 animate-pulse" }),
/* @__PURE__ */ jsx16("div", { className: "h-3 bg-base-200 rounded w-1/2 animate-pulse" })
] })
] }),
/* @__PURE__ */ jsxs10("div", { className: "space-y-2", children: [
/* @__PURE__ */ jsx16("div", { className: "h-3 bg-base-200 rounded animate-pulse" }),
/* @__PURE__ */ jsx16("div", { className: "h-3 bg-base-200 rounded animate-pulse" }),
/* @__PURE__ */ jsx16("div", { className: "h-3 bg-base-200 rounded w-5/6 animate-pulse" })
] })
] });
}
return /* @__PURE__ */ jsx16(
"div",
{
className: cn(baseClasses, variantClasses3[variant]),
style,
role: "status",
"aria-label": "Loading",
children: /* @__PURE__ */ jsx16("span", { className: "sr-only", children: "Loading..." })
}
);
};
// src/hooks/useAsyncOperation.ts
import { useState as useState4, useCallback as useCallback2, useEffect as useEffect2, useRef } from "react";
function useAsyncOperation(asyncFn, options = {}) {
const { onSuccess, onError, immediate = false, resetOnDepsChange = true } = options;
const [state, setState] = useState4({
loading: false,
data: null,
error: null,
called: false
});
const isMountedRef = useRef(true);
const operationIdRef = useRef(0);
useEffect2(() => {
isMountedRef.current = true;
return () => {
isMountedRef.current = false;
};
}, []);
const execute = useCallback2(async () => {
const currentOperationId = ++operationIdRef.current;
if (!isMountedRef.current) return;
setState((prev) => ({
...prev,
loading: true,
error: null,
called: true
}));
try {
const data = await asyncFn();
if (currentOperationId === operationIdRef.current && isMountedRef.current) {
setState({
loading: false,
data,
error: null,
called: true
});
onSuccess?.(data);
}
return data;
} catch (error) {
const err = error instanceof Error ? error : new Error(String(error));
if (currentOperationId === operationIdRef.current && isMountedRef.current) {
setState({
loading: false,
data: null,
error: err,
called: true
});
onError?.(err);
}
throw error;
}
}, [asyncFn, onSuccess, onError]);
const reset = useCallback2(() => {
setState({
loading: false,
data: null,
error: null,
called: false
});
operationIdRef.current = 0;
}, []);
useEffect2(() => {
if (immediate && !state.called) {
execute();
}
}, [immediate, execute, state.called]);
useEffect2(() => {
if (resetOnDepsChange && state.called) {
reset();
}
}, [asyncFn]);
return {
...state,
execute,
reset
};
}
// src/utils/verify-imports.ts
function verifyDesignSystemImports() {
const exports = {
// Core utilities
cn: typeof cn !== "undefined" ? cn : void 0,
// Theme system
ThemeProvider: typeof ThemeProvider !== "undefined" ? ThemeProvider : void 0,
useTheme: typeof useTheme !== "undefined" ? useTheme : void 0,
Theme: true,
// Type exports always available
// Components
Button: typeof Button !== "undefined" ? Button : void 0,
LoadingButton: typeof LoadingButton !== "undefined" ? LoadingButton : void 0,
LoadingContainer: typeof LoadingContainer !== "undefined" ? LoadingContainer : void 0,
LoadingSkeleton: typeof LoadingSkeleton !== "undefined" ? LoadingSkeleton : void 0,
// Hooks
useAsyncOperation: typeof useAsyncOperation !== "undefined" ? useAsyncOperation : void 0
};
const missing = Object.entries(exports).filter(([_, value]) => !value).map(([key]) => key);
return {
exports,
missing,
allPresent: missing.length === 0
};
}
function validateThemeConfiguration(config) {
const errors = [];
const validThemes = ["light", "dark", "cupcake", "business", "grove-light", "grove-dark"];
if (config.defaultTheme && !validThemes.includes(config.defaultTheme)) {
errors.push(
`Invalid defaultTheme "${config.defaultTheme}". Valid themes: ${validThemes.join(", ")}`
);
}
if (config.supportedThemes) {
const invalidThemes = config.supportedThemes.filter((theme) => !validThemes.includes(theme));
if (invalidThemes.length > 0) {
errors.push(
`Invalid themes: ${invalidThemes.join(", ")}. Valid themes: ${validThemes.join(", ")}`
);
}
}
return {
valid: errors.length === 0,
errors
};
}
function generateTemplateMetadata(options) {
return {
name: options.templateName,
designSystem: {
version: options.designSystemVersion || "0.1.2",
defaultTheme: options.defaultTheme || "light",
requiredImports: options.requiredImports || ["ThemeProvider", "cn"],
optionalImports: options.optionalImports || ["useTheme"],
configuration: {
cssImport: "@orchard9ai/design-system/dist/styles.css",
tailwindPreset: "@orchard9ai/design-system/tailwind.config.js"
}
},
generated: (/* @__PURE__ */ new Date()).toISOString()
};
}
// src/components/FormControl.tsx
import { jsx as jsx17, jsxs as jsxs11 } from "react/jsx-runtime";
var FormControl = ({
label,
labelAlt,
helperText,
error,
warning,
success,
required,
children,
className
}) => {
return /* @__PURE__ */ jsxs11("div", { className: cn("form-control", className), children: [
label && /* @__PURE__ */ jsxs11("label", { className: "label pb-2", children: [
/* @__PURE__ */ jsxs11("span", { className: "label-text", children: [
label,
required && /* @__PURE__ */ jsx17("span", { className: "text-error ml-1", children: "*" })
] }),
labelAlt && /* @__PURE__ */ jsx17("span", { className: "label-text-alt", children: labelAlt })
] }),
children,
(helperText || error || warning || success) && /* @__PURE__ */ jsx17("label", { className: "label", children: /* @__PURE__ */ jsx17(
"span",
{
className: cn(
"label-text-alt",
error && "text-error",
warning && "text-warning",
success && "text-success"
),
children: error || warning || success || helperText
}
) })
] });
};
// src/components/Input.tsx
import React13 from "react";
import { jsx as jsx18, jsxs as jsxs12 } from "react/jsx-runtime";
var Input = React13.forwardRef(
({
variant = "bordered",
inputSize = "md",
state = "default",
fullWidth = true,
leftIcon,
rightIcon,
leftAddon,
rightAddon,
label,
error,
helperText,
className,
required,
...props
}, ref) => {
const effectiveState = error ? "error" : state;
const finalInputClasses = cn(
"input",
varia