import type { ReactNode } from 'react'
import { Link, NavLink } from 'react-router-dom'
import type { AcAppKey } from '../lib/acAssets'
import { AcIcon } from './AcIcon'
const fieldClass =
'ac-field w-full px-4 py-3 text-[15px] text-ink outline-none transition placeholder:text-subtle focus:border-brand focus:ring-4 focus:ring-brand-soft'
export function PageTitle({ title, subtitle }: { title: string; subtitle?: string }) {
return (
{title}
{subtitle ? (
{subtitle}
) : null}
)
}
export function Card({ children, className = '' }: { children: ReactNode; className?: string }) {
return (
{children}
)
}
export function Field({
label,
children,
}: {
label: string
children: ReactNode
}) {
return (
)
}
export function Input(props: React.InputHTMLAttributes) {
return
}
export function Textarea(
props: React.TextareaHTMLAttributes & { mono?: boolean },
) {
const { mono, className, ...rest } = props
return (
)
}
export function Select(props: React.SelectHTMLAttributes) {
return
}
export function SectionTitle({ children }: { children: ReactNode }) {
return {children}
}
export function AcLink({
to,
children,
className = '',
}: {
to: string
children: ReactNode
className?: string
}) {
return (
{children}
)
}
export function TabLink({ to, children }: { to: string; children: ReactNode }) {
return (
`ac-tab ${isActive ? 'ac-tab--active' : ''}`}
>
{children}
)
}
export function ChoiceCard({
active,
title,
hint,
disabled,
onClick,
}: {
active?: boolean
title: string
hint?: string
disabled?: boolean
onClick: () => void
}) {
return (
)
}
export function SuccessText({ message }: { message?: string }) {
if (!message) return null
return {message}
}
export function Button({
children,
variant = 'primary',
...props
}: React.ButtonHTMLAttributes & { variant?: 'primary' | 'ghost' | 'danger' | 'soft' }) {
const styles =
variant === 'primary'
? 'ac-btn-primary'
: variant === 'danger'
? 'ac-btn-danger'
: variant === 'soft'
? 'ac-btn-secondary bg-brand-soft text-brand'
: 'ac-btn-secondary'
const { className, ...rest } = props
return (
)
}
export function Badge({
children,
tone = 'neutral',
}: {
children: ReactNode
tone?: 'neutral' | 'brand' | 'sky' | 'success' | 'warning' | 'danger'
}) {
const tones = {
neutral: 'border-wood-dark bg-accent-soft text-ink',
brand: 'border-brand bg-brand-soft text-brand',
sky: 'border-accent bg-accent-soft text-accent',
success: 'border-success bg-success-soft text-success',
warning: 'border-warning bg-warning-soft text-warning',
danger: 'border-danger bg-danger-soft text-danger',
}
return (
{children}
)
}
export function ErrorText({ message }: { message?: string }) {
if (!message) return null
return {message}
}
export function Notice({
tone = 'info',
title,
message,
}: {
tone?: 'info' | 'success' | 'warning'
title: string
message?: string
}) {
const tones = {
info: 'border-accent bg-accent-soft text-ink',
success: 'border-success/40 bg-success-soft text-ink',
warning: 'border-warning/40 bg-warning-soft text-ink',
}
return (
{title}
{message ?
{message}
: null}
)
}
export function CopyableId({ label, value }: { label: string; value: string }) {
const copy = async () => {
if (!value) return
await navigator.clipboard.writeText(value)
}
return (
{label}
{value || '—'}
{value ? (
) : null}
)
}
export function QuickLinkCard({
to,
title,
desc,
icon,
className = '',
guideBadge = false,
}: {
to: string
title: string
desc: string
icon: AcAppKey
tag?: string
className?: string
guideBadge?: boolean
}) {
return (
{guideBadge ? (
完成連線
) : null}
{title}
{desc}
打開 →
)
}
export function StatCard({
label,
value,
hint,
tone = 'default',
}: {
label: string
value: ReactNode
hint?: string
tone?: 'default' | 'brand' | 'sky'
}) {
const slot =
tone === 'brand' ? 'ac-slot ac-slot--brand' : tone === 'sky' ? 'ac-slot ac-slot--sky' : 'ac-slot'
return (
{label}
{value}
{hint ?
{hint}
: null}
)
}
export function TablePanel({
title,
count,
children,
className = '',
}: {
title: string
count?: number | string
children: ReactNode
className?: string
}) {
return (
{title}
{count !== undefined ? (
{typeof count === 'number' ? `共 ${count} 筆` : count}
) : null}
{children}
)
}
export function TableShell({ children, className = '' }: { children: ReactNode; className?: string }) {
return {children}
}
export function Table({
children,
className = '',
minWidth,
}: {
children: ReactNode
className?: string
minWidth?: string
}) {
return (
)
}
export function TableEmpty({ children }: { children: ReactNode }) {
return {children}
}
export function TableAction({
children,
variant = 'default',
className,
...props
}: React.ButtonHTMLAttributes & {
variant?: 'default' | 'danger' | 'link'
}) {
const variantClass =
variant === 'danger'
? 'ac-table-action--danger'
: variant === 'link'
? 'ac-table-action--link'
: ''
return (
)
}
export function StatusBadge({
children,
className = '',
}: {
children: ReactNode
className?: string
}) {
return {children}
}
export function ProgressBar({ value, className = '' }: { value: number; className?: string }) {
const pct = Math.min(100, Math.max(0, value))
return (
)
}