@xenide-io/the-old-ui-theme 0.5.4 → 0.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{Chip-C5hRFAhe.d.mts → Chip-DzC5xtK9.d.mts} +8 -3
- package/dist/{Chip-C5hRFAhe.d.ts → Chip-DzC5xtK9.d.ts} +8 -3
- package/dist/chunk-3G43JEI3.mjs +2564 -0
- package/dist/index.d.mts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +7 -2
- package/dist/index.mjs +3 -1
- package/dist/tailwind-preset.js +1 -0
- package/dist/tailwind-preset.mjs +1 -0
- package/dist/ui.d.mts +4 -531
- package/dist/ui.d.ts +4 -531
- package/dist/ui.js +407 -2504
- package/dist/ui.mjs +5 -91
- package/package.json +1 -1
- package/src/app/globals.css +18 -0
- package/src/components/ui/Typography.tsx +12 -4
- package/src/components/ui/index.ts +7 -184
- package/src/components/ui/typography.test.tsx +27 -0
- package/src/styles/suite-skin.css +21 -1
- package/src/styles/typography.css +72 -3
- package/tailwind-preset.ts +1 -0
- package/dist/chunk-SBBKXV35.mjs +0 -4620
- package/src/components/ui/AlertDialog.tsx +0 -62
- package/src/components/ui/AppLayout.tsx +0 -27
- package/src/components/ui/Autocomplete.tsx +0 -106
- package/src/components/ui/Banner.tsx +0 -63
- package/src/components/ui/ButtonGroup.tsx +0 -16
- package/src/components/ui/ChatBubble.tsx +0 -71
- package/src/components/ui/Collapsible.tsx +0 -46
- package/src/components/ui/Combobox.tsx +0 -119
- package/src/components/ui/ContextMenu.tsx +0 -81
- package/src/components/ui/DataTable.tsx +0 -133
- package/src/components/ui/DatePicker.tsx +0 -96
- package/src/components/ui/Dialog.tsx +0 -75
- package/src/components/ui/Divider.tsx +0 -39
- package/src/components/ui/Drawer.tsx +0 -71
- package/src/components/ui/HoverCard.tsx +0 -36
- package/src/components/ui/Indicator.tsx +0 -61
- package/src/components/ui/InputGroup.tsx +0 -16
- package/src/components/ui/Lettermark.tsx +0 -47
- package/src/components/ui/LoadingBar.tsx +0 -25
- package/src/components/ui/Menubar.tsx +0 -66
- package/src/components/ui/Metric.tsx +0 -34
- package/src/components/ui/Navigation.tsx +0 -94
- package/src/components/ui/NumberField.tsx +0 -76
- package/src/components/ui/Popover.tsx +0 -73
- package/src/components/ui/ProgressCircle.tsx +0 -63
- package/src/components/ui/Rating.tsx +0 -65
- package/src/components/ui/Resizable.tsx +0 -71
- package/src/components/ui/Row.tsx +0 -51
- package/src/components/ui/ScrollArea.tsx +0 -54
- package/src/components/ui/Sidebar.tsx +0 -79
- package/src/components/ui/Snack.tsx +0 -48
- package/src/components/ui/Splotch.tsx +0 -33
- package/src/components/ui/Stepper.tsx +0 -74
- package/src/components/ui/Tabs.tsx +0 -53
- package/src/components/ui/Tag.tsx +0 -65
- package/src/components/ui/Terminal.tsx +0 -54
- package/src/components/ui/ThemeManager.tsx +0 -18
- package/src/components/ui/Timeline.tsx +0 -60
- package/src/components/ui/Toast.tsx +0 -70
- package/src/components/ui/Toggle.tsx +0 -62
- package/src/components/ui/Widget.tsx +0 -31
|
@@ -1,48 +0,0 @@
|
|
|
1
|
-
import { forwardRef, type HTMLAttributes, type ReactNode } from "react";
|
|
2
|
-
import { cn } from "@/lib/cn";
|
|
3
|
-
|
|
4
|
-
export interface SnackProps extends HTMLAttributes<HTMLSpanElement> {
|
|
5
|
-
type?: "regular" | "pill";
|
|
6
|
-
onClose?: () => void;
|
|
7
|
-
wrap?: boolean;
|
|
8
|
-
children: ReactNode;
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
export const Snack = forwardRef<HTMLSpanElement, SnackProps>(function Snack({
|
|
12
|
-
type = "regular",
|
|
13
|
-
onClose,
|
|
14
|
-
wrap = false,
|
|
15
|
-
className,
|
|
16
|
-
children,
|
|
17
|
-
...props
|
|
18
|
-
}, ref) {
|
|
19
|
-
return (
|
|
20
|
-
<span
|
|
21
|
-
ref={ref}
|
|
22
|
-
className={cn(
|
|
23
|
-
"ph-snack",
|
|
24
|
-
type === "pill" && "ph-snack--pill",
|
|
25
|
-
!wrap && "truncate",
|
|
26
|
-
className
|
|
27
|
-
)}
|
|
28
|
-
title={typeof children === "string" ? children : undefined}
|
|
29
|
-
{...props}
|
|
30
|
-
>
|
|
31
|
-
<span className="ph-snack__text">{children}</span>
|
|
32
|
-
{onClose && (
|
|
33
|
-
<button
|
|
34
|
-
type="button"
|
|
35
|
-
onClick={(e) => { e.stopPropagation(); onClose(); }}
|
|
36
|
-
className="ph-snack__close"
|
|
37
|
-
aria-label="Remove"
|
|
38
|
-
>
|
|
39
|
-
<svg width="12" height="12" viewBox="0 0 12 12" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round">
|
|
40
|
-
<path d="M3 3l6 6M9 3l-6 6" />
|
|
41
|
-
</svg>
|
|
42
|
-
</button>
|
|
43
|
-
)}
|
|
44
|
-
</span>
|
|
45
|
-
);
|
|
46
|
-
});
|
|
47
|
-
|
|
48
|
-
Snack.displayName = "Snack";
|
|
@@ -1,33 +0,0 @@
|
|
|
1
|
-
import type { HTMLAttributes } from "react";
|
|
2
|
-
import { cn } from "@/lib/cn";
|
|
3
|
-
|
|
4
|
-
export type SplotchColor = "purple" | "blue" | "green" | "black" | "white" | "orange" | "red" | "yellow";
|
|
5
|
-
|
|
6
|
-
export interface SplotchProps extends HTMLAttributes<HTMLDivElement> {
|
|
7
|
-
color: SplotchColor;
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
const colorMap: Record<SplotchColor, string> = {
|
|
11
|
-
purple: "ph-splotch--purple",
|
|
12
|
-
blue: "ph-splotch--blue",
|
|
13
|
-
green: "ph-splotch--green",
|
|
14
|
-
black: "ph-splotch--black",
|
|
15
|
-
white: "ph-splotch--white",
|
|
16
|
-
orange: "ph-splotch--orange",
|
|
17
|
-
red: "ph-splotch--red",
|
|
18
|
-
yellow: "ph-splotch--yellow",
|
|
19
|
-
};
|
|
20
|
-
|
|
21
|
-
export function Splotch({ color, className, ...props }: SplotchProps) {
|
|
22
|
-
return (
|
|
23
|
-
<div
|
|
24
|
-
className={cn("ph-splotch", colorMap[color], className)}
|
|
25
|
-
aria-hidden="true"
|
|
26
|
-
{...props}
|
|
27
|
-
>
|
|
28
|
-
<div className="ph-splotch__paint" />
|
|
29
|
-
</div>
|
|
30
|
-
);
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
Splotch.displayName = "Splotch";
|
|
@@ -1,74 +0,0 @@
|
|
|
1
|
-
"use client";
|
|
2
|
-
|
|
3
|
-
import { cn } from "@/lib/cn";
|
|
4
|
-
import { IconCheck } from "@/components/icons";
|
|
5
|
-
|
|
6
|
-
interface Step {
|
|
7
|
-
id: string;
|
|
8
|
-
label: string;
|
|
9
|
-
description?: string;
|
|
10
|
-
status?: "pending" | "current" | "completed" | "error";
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
interface StepperProps {
|
|
14
|
-
steps: Step[];
|
|
15
|
-
currentStep: number;
|
|
16
|
-
className?: string;
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
export function Stepper({ steps, currentStep, className }: StepperProps) {
|
|
20
|
-
return (
|
|
21
|
-
<div className={cn("flex items-start gap-2", className)}>
|
|
22
|
-
{steps.map((step, index) => {
|
|
23
|
-
const isCompleted = index < currentStep;
|
|
24
|
-
const isCurrent = index === currentStep;
|
|
25
|
-
const isPending = index > currentStep;
|
|
26
|
-
const isError = step.status === "error";
|
|
27
|
-
|
|
28
|
-
return (
|
|
29
|
-
<div key={step.id} className="flex flex-1 items-start gap-2">
|
|
30
|
-
<div className="flex flex-1 flex-col items-center">
|
|
31
|
-
<div
|
|
32
|
-
className={cn(
|
|
33
|
-
"flex h-9 w-9 items-center justify-center rounded-full text-sm font-bold transition-colors",
|
|
34
|
-
isCompleted && "bg-ph-success text-[var(--ph-on-success)]",
|
|
35
|
-
isCurrent && !isError && "bg-ph-brand text-[var(--ph-on-accent)] ring-4 ring-ph-brand/20",
|
|
36
|
-
isCurrent && isError && "bg-ph-danger text-[var(--ph-on-danger)]",
|
|
37
|
-
isPending && "bg-ph-muted text-ph-mutedtext"
|
|
38
|
-
)}
|
|
39
|
-
>
|
|
40
|
-
{isCompleted ? (
|
|
41
|
-
<IconCheck className="h-5 w-5" aria-hidden />
|
|
42
|
-
) : (
|
|
43
|
-
index + 1
|
|
44
|
-
)}
|
|
45
|
-
</div>
|
|
46
|
-
<div className="mt-2 text-center">
|
|
47
|
-
<p
|
|
48
|
-
className={cn(
|
|
49
|
-
"text-sm font-semibold",
|
|
50
|
-
isCurrent && "text-ph-ink",
|
|
51
|
-
!isCurrent && "text-ph-mutedtext"
|
|
52
|
-
)}
|
|
53
|
-
>
|
|
54
|
-
{step.label}
|
|
55
|
-
</p>
|
|
56
|
-
{step.description && (
|
|
57
|
-
<p className="mt-0.5 text-xs text-ph-mutedtext">{step.description}</p>
|
|
58
|
-
)}
|
|
59
|
-
</div>
|
|
60
|
-
</div>
|
|
61
|
-
{index < steps.length - 1 && (
|
|
62
|
-
<div
|
|
63
|
-
className={cn(
|
|
64
|
-
"mt-4 h-0.5 flex-1 rounded-full transition-colors",
|
|
65
|
-
isCompleted ? "bg-ph-success" : "bg-ph-border"
|
|
66
|
-
)}
|
|
67
|
-
/>
|
|
68
|
-
)}
|
|
69
|
-
</div>
|
|
70
|
-
);
|
|
71
|
-
})}
|
|
72
|
-
</div>
|
|
73
|
-
);
|
|
74
|
-
}
|
|
@@ -1,53 +0,0 @@
|
|
|
1
|
-
import { cn } from "@/lib/cn";
|
|
2
|
-
|
|
3
|
-
export interface TabItem {
|
|
4
|
-
value: string;
|
|
5
|
-
label: string;
|
|
6
|
-
}
|
|
7
|
-
|
|
8
|
-
export type TabsVariant = "pill" | "underline";
|
|
9
|
-
|
|
10
|
-
export interface TabsProps {
|
|
11
|
-
items: TabItem[];
|
|
12
|
-
value: string;
|
|
13
|
-
onChange: (value: string) => void;
|
|
14
|
-
variant?: TabsVariant;
|
|
15
|
-
className?: string;
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
export function Tabs({ items, value, onChange, variant = "pill", className }: TabsProps) {
|
|
19
|
-
if (variant === "underline") {
|
|
20
|
-
return (
|
|
21
|
-
<div className={cn("flex gap-6 border-b border-ph-border", className)}>
|
|
22
|
-
{items.map((item) => (
|
|
23
|
-
<button
|
|
24
|
-
key={item.value}
|
|
25
|
-
type="button"
|
|
26
|
-
onClick={() => onChange(item.value)}
|
|
27
|
-
className={cn(
|
|
28
|
-
"-mb-px border-b-2 pb-2 text-sm font-semibold transition",
|
|
29
|
-
value === item.value ? "border-ph-brand text-ph-ink" : "border-transparent text-ph-mutedtext hover:text-ph-ink"
|
|
30
|
-
)}
|
|
31
|
-
>
|
|
32
|
-
{item.label}
|
|
33
|
-
</button>
|
|
34
|
-
))}
|
|
35
|
-
</div>
|
|
36
|
-
);
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
return (
|
|
40
|
-
<div className={cn("ph-tabs-row inline-flex", className)}>
|
|
41
|
-
{items.map((item) => (
|
|
42
|
-
<button
|
|
43
|
-
key={item.value}
|
|
44
|
-
type="button"
|
|
45
|
-
onClick={() => onChange(item.value)}
|
|
46
|
-
className={cn("ph-tab", value === item.value && "ph-tab-active")}
|
|
47
|
-
>
|
|
48
|
-
{item.label}
|
|
49
|
-
</button>
|
|
50
|
-
))}
|
|
51
|
-
</div>
|
|
52
|
-
);
|
|
53
|
-
}
|
|
@@ -1,65 +0,0 @@
|
|
|
1
|
-
import { forwardRef, type HTMLAttributes, type ReactNode } from "react";
|
|
2
|
-
import { cn } from "@/lib/cn";
|
|
3
|
-
|
|
4
|
-
export type TagType = "default" | "primary" | "success" | "warning" | "danger" | "info" | "muted" | "highlight";
|
|
5
|
-
|
|
6
|
-
export interface TagProps extends HTMLAttributes<HTMLDivElement> {
|
|
7
|
-
type?: TagType;
|
|
8
|
-
size?: "sm" | "md";
|
|
9
|
-
icon?: ReactNode;
|
|
10
|
-
closable?: boolean;
|
|
11
|
-
onClose?: () => void;
|
|
12
|
-
children: ReactNode;
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
const typeClass: Record<TagType, string> = {
|
|
16
|
-
default: "ph-tag-default",
|
|
17
|
-
primary: "ph-tag-primary",
|
|
18
|
-
success: "ph-tag-success",
|
|
19
|
-
warning: "ph-tag-warning",
|
|
20
|
-
danger: "ph-tag-danger",
|
|
21
|
-
info: "ph-tag-info",
|
|
22
|
-
muted: "ph-tag-muted",
|
|
23
|
-
highlight: "ph-tag-highlight",
|
|
24
|
-
};
|
|
25
|
-
|
|
26
|
-
export const Tag = forwardRef<HTMLDivElement, TagProps>(function Tag({
|
|
27
|
-
type = "default",
|
|
28
|
-
size = "md",
|
|
29
|
-
icon,
|
|
30
|
-
closable = false,
|
|
31
|
-
onClose,
|
|
32
|
-
className,
|
|
33
|
-
children,
|
|
34
|
-
...props
|
|
35
|
-
}, ref) {
|
|
36
|
-
return (
|
|
37
|
-
<div
|
|
38
|
-
ref={ref}
|
|
39
|
-
className={cn(
|
|
40
|
-
"ph-tag",
|
|
41
|
-
typeClass[type],
|
|
42
|
-
size === "sm" && "ph-tag-sm",
|
|
43
|
-
className
|
|
44
|
-
)}
|
|
45
|
-
{...props}
|
|
46
|
-
>
|
|
47
|
-
{icon && <span className="ph-tag__icon">{icon}</span>}
|
|
48
|
-
<span className="ph-tag__text">{children}</span>
|
|
49
|
-
{closable && (
|
|
50
|
-
<button
|
|
51
|
-
type="button"
|
|
52
|
-
onClick={(e) => { e.stopPropagation(); onClose?.(); }}
|
|
53
|
-
className="ph-tag__close"
|
|
54
|
-
aria-label="Remove"
|
|
55
|
-
>
|
|
56
|
-
<svg width="12" height="12" viewBox="0 0 12 12" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round">
|
|
57
|
-
<path d="M3 3l6 6M9 3l-6 6" />
|
|
58
|
-
</svg>
|
|
59
|
-
</button>
|
|
60
|
-
)}
|
|
61
|
-
</div>
|
|
62
|
-
);
|
|
63
|
-
});
|
|
64
|
-
|
|
65
|
-
Tag.displayName = "Tag";
|
|
@@ -1,54 +0,0 @@
|
|
|
1
|
-
import type { ComponentPropsWithoutRef, ReactNode } from "react";
|
|
2
|
-
import { cn } from "@/lib/cn";
|
|
3
|
-
|
|
4
|
-
export interface TerminalProps extends ComponentPropsWithoutRef<"div"> {
|
|
5
|
-
/** Window title */
|
|
6
|
-
title?: string;
|
|
7
|
-
/** Terminal lines — array of { text, color? } or plain strings */
|
|
8
|
-
lines?: Array<{ text: string; color?: string } | string>;
|
|
9
|
-
/** Custom content instead of lines */
|
|
10
|
-
children?: ReactNode;
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
export function Terminal({
|
|
14
|
-
title = "sandbox",
|
|
15
|
-
lines,
|
|
16
|
-
children,
|
|
17
|
-
className,
|
|
18
|
-
...props
|
|
19
|
-
}: TerminalProps) {
|
|
20
|
-
return (
|
|
21
|
-
<div
|
|
22
|
-
className={cn(
|
|
23
|
-
"overflow-hidden rounded-xl border border-ph-border shadow-ph-md",
|
|
24
|
-
className,
|
|
25
|
-
)}
|
|
26
|
-
{...props}
|
|
27
|
-
>
|
|
28
|
-
<header className="flex items-center gap-2 border-b border-ph-border bg-ph-muted px-4 py-3">
|
|
29
|
-
<div className="h-3 w-3 rounded-full bg-red-400" />
|
|
30
|
-
<div className="h-3 w-3 rounded-full bg-amber-400" />
|
|
31
|
-
<div className="h-3 w-3 rounded-full bg-emerald-400" />
|
|
32
|
-
{title && (
|
|
33
|
-
<span className="text-xs font-medium text-ph-mutedtext">{title}</span>
|
|
34
|
-
)}
|
|
35
|
-
</header>
|
|
36
|
-
<div className="ph-code rounded-none border-x-0 border-b-0 text-[13px] leading-relaxed">
|
|
37
|
-
{children || (
|
|
38
|
-
<>
|
|
39
|
-
{lines?.map((line, i) => {
|
|
40
|
-
const text = typeof line === "string" ? line : line.text;
|
|
41
|
-
const color = typeof line === "string" ? undefined : line.color;
|
|
42
|
-
return (
|
|
43
|
-
<span key={i}>
|
|
44
|
-
<span className={color || "text-neutral-600"}>{text}</span>
|
|
45
|
-
{i < lines.length - 1 && <br />}
|
|
46
|
-
</span>
|
|
47
|
-
);
|
|
48
|
-
})}
|
|
49
|
-
</>
|
|
50
|
-
)}
|
|
51
|
-
</div>
|
|
52
|
-
</div>
|
|
53
|
-
);
|
|
54
|
-
}
|
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
"use client";
|
|
2
|
-
|
|
3
|
-
import type { ReactNode } from "react";
|
|
4
|
-
import { useLayoutEffect } from "react";
|
|
5
|
-
import { persistTheme, readStoredTheme } from "@/themes";
|
|
6
|
-
|
|
7
|
-
export interface ThemeManagerProps {
|
|
8
|
-
children?: ReactNode;
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
/** Client wrapper that keeps html[data-theme] synced with localStorage. */
|
|
12
|
-
export function ThemeManager({ children }: ThemeManagerProps) {
|
|
13
|
-
useLayoutEffect(() => {
|
|
14
|
-
persistTheme(readStoredTheme());
|
|
15
|
-
}, []);
|
|
16
|
-
|
|
17
|
-
return <>{children}</>;
|
|
18
|
-
}
|
|
@@ -1,60 +0,0 @@
|
|
|
1
|
-
import type { ComponentPropsWithoutRef, ReactNode } from "react";
|
|
2
|
-
import { cn } from "@/lib/cn";
|
|
3
|
-
|
|
4
|
-
export interface TimelineEvent {
|
|
5
|
-
id: string;
|
|
6
|
-
title: string;
|
|
7
|
-
description?: string;
|
|
8
|
-
time?: string;
|
|
9
|
-
icon?: ReactNode;
|
|
10
|
-
color?: string;
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
export interface TimelineProps extends ComponentPropsWithoutRef<"ol"> {
|
|
14
|
-
events: TimelineEvent[];
|
|
15
|
-
/** Alternate left/right layout on large screens */
|
|
16
|
-
alternate?: boolean;
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
export function Timeline({
|
|
20
|
-
events,
|
|
21
|
-
alternate = false,
|
|
22
|
-
className,
|
|
23
|
-
...props
|
|
24
|
-
}: TimelineProps) {
|
|
25
|
-
return (
|
|
26
|
-
<ol
|
|
27
|
-
className={cn("relative space-y-8", className)}
|
|
28
|
-
{...props}
|
|
29
|
-
>
|
|
30
|
-
{events.map((event, idx) => {
|
|
31
|
-
const align = alternate && idx % 2 !== 0 ? "lg:flex-row-reverse" : "";
|
|
32
|
-
return (
|
|
33
|
-
<li key={event.id} className={cn("relative flex gap-6", align)}>
|
|
34
|
-
<div
|
|
35
|
-
className={cn(
|
|
36
|
-
"relative z-10 flex h-12 w-12 shrink-0 items-center justify-center rounded-full ring-8 ring-ph-muted shadow-md",
|
|
37
|
-
event.color || "bg-ph-brand text-white",
|
|
38
|
-
)}
|
|
39
|
-
>
|
|
40
|
-
{event.icon}
|
|
41
|
-
</div>
|
|
42
|
-
<article className="flex-1 rounded-xl border border-ph-border bg-ph-surface p-4 shadow-ph">
|
|
43
|
-
<div className="flex flex-wrap items-baseline gap-3">
|
|
44
|
-
<h4 className="text-base font-semibold text-ph-ink">{event.title}</h4>
|
|
45
|
-
{event.time && (
|
|
46
|
-
<time className="text-[11px] font-semibold uppercase tracking-wide text-ph-mutedtext">
|
|
47
|
-
{event.time}
|
|
48
|
-
</time>
|
|
49
|
-
)}
|
|
50
|
-
</div>
|
|
51
|
-
{event.description && (
|
|
52
|
-
<p className="mt-2 text-sm text-ph-subtle">{event.description}</p>
|
|
53
|
-
)}
|
|
54
|
-
</article>
|
|
55
|
-
</li>
|
|
56
|
-
);
|
|
57
|
-
})}
|
|
58
|
-
</ol>
|
|
59
|
-
);
|
|
60
|
-
}
|
|
@@ -1,70 +0,0 @@
|
|
|
1
|
-
import type { ReactNode } from "react";
|
|
2
|
-
import {
|
|
3
|
-
IconCancel,
|
|
4
|
-
IconCheckCircle,
|
|
5
|
-
IconClose,
|
|
6
|
-
IconErrorOutline,
|
|
7
|
-
IconExclamation,
|
|
8
|
-
} from "@/components/icons";
|
|
9
|
-
import { cn } from "@/lib/cn";
|
|
10
|
-
|
|
11
|
-
export type ToastStatus = "info" | "success" | "warning" | "danger";
|
|
12
|
-
|
|
13
|
-
export interface ToastProps {
|
|
14
|
-
status?: ToastStatus;
|
|
15
|
-
title: string;
|
|
16
|
-
description?: string;
|
|
17
|
-
onDismiss?: () => void;
|
|
18
|
-
className?: string;
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
const statusConfig: Record<ToastStatus, { icon: typeof IconErrorOutline; color: string; bg: string } > = {
|
|
22
|
-
info: { icon: IconErrorOutline, color: "text-ph-info", bg: "ph-toast-info" },
|
|
23
|
-
success: { icon: IconCheckCircle, color: "text-ph-success", bg: "ph-toast-success" },
|
|
24
|
-
warning: { icon: IconExclamation, color: "text-ph-warning", bg: "ph-toast-warning" },
|
|
25
|
-
danger: { icon: IconCancel, color: "text-ph-danger", bg: "ph-toast-danger" },
|
|
26
|
-
};
|
|
27
|
-
|
|
28
|
-
export function Toast({
|
|
29
|
-
status = "info",
|
|
30
|
-
title,
|
|
31
|
-
description,
|
|
32
|
-
onDismiss,
|
|
33
|
-
className,
|
|
34
|
-
}: ToastProps) {
|
|
35
|
-
const config = statusConfig[status];
|
|
36
|
-
const Icon = config.icon;
|
|
37
|
-
|
|
38
|
-
return (
|
|
39
|
-
<div className={cn("ph-toast", config.bg, className)}>
|
|
40
|
-
<Icon className={cn("mt-0.5 h-5 w-5 shrink-0", config.color)} aria-hidden />
|
|
41
|
-
<div className="pr-8">
|
|
42
|
-
<div className="font-semibold">{title}</div>
|
|
43
|
-
{description && <p className="mt-1 text-xs text-ph-subtle">{description}</p>}
|
|
44
|
-
</div>
|
|
45
|
-
{onDismiss && (
|
|
46
|
-
<button
|
|
47
|
-
type="button"
|
|
48
|
-
aria-label={`Dismiss ${title}`}
|
|
49
|
-
className="absolute right-2 top-2 ph-btn ph-btn-ghost ph-btn-xs ph-btn-circle"
|
|
50
|
-
onClick={onDismiss}
|
|
51
|
-
>
|
|
52
|
-
<IconClose className="h-4 w-4" />
|
|
53
|
-
</button>
|
|
54
|
-
)}
|
|
55
|
-
</div>
|
|
56
|
-
);
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
export interface ToastStackProps {
|
|
60
|
-
children?: ReactNode;
|
|
61
|
-
className?: string;
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
export function ToastStack({ children, className }: ToastStackProps) {
|
|
65
|
-
return (
|
|
66
|
-
<div className={cn("ph-toast-stack", className)}>
|
|
67
|
-
{children}
|
|
68
|
-
</div>
|
|
69
|
-
);
|
|
70
|
-
}
|
|
@@ -1,62 +0,0 @@
|
|
|
1
|
-
import { forwardRef, type ButtonHTMLAttributes, type ReactNode } from "react";
|
|
2
|
-
import { cn } from "@/lib/cn";
|
|
3
|
-
|
|
4
|
-
export interface ToggleButtonProps extends ButtonHTMLAttributes<HTMLButtonElement> {
|
|
5
|
-
pressed?: boolean;
|
|
6
|
-
onPressedChange?: (pressed: boolean) => void;
|
|
7
|
-
icon?: ReactNode;
|
|
8
|
-
children?: ReactNode;
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
export const ToggleButton = forwardRef<HTMLButtonElement, ToggleButtonProps>(function ToggleButton({
|
|
12
|
-
pressed = false,
|
|
13
|
-
onPressedChange,
|
|
14
|
-
icon,
|
|
15
|
-
children,
|
|
16
|
-
className,
|
|
17
|
-
...props
|
|
18
|
-
}, ref) {
|
|
19
|
-
return (
|
|
20
|
-
<button
|
|
21
|
-
ref={ref}
|
|
22
|
-
type="button"
|
|
23
|
-
aria-pressed={pressed}
|
|
24
|
-
onClick={() => onPressedChange?.(!pressed)}
|
|
25
|
-
className={cn(
|
|
26
|
-
"ph-toggle-btn",
|
|
27
|
-
pressed && "ph-toggle-btn--pressed",
|
|
28
|
-
className
|
|
29
|
-
)}
|
|
30
|
-
{...props}
|
|
31
|
-
>
|
|
32
|
-
{icon && <span className="ph-toggle-btn__icon">{icon}</span>}
|
|
33
|
-
{children}
|
|
34
|
-
</button>
|
|
35
|
-
);
|
|
36
|
-
});
|
|
37
|
-
|
|
38
|
-
ToggleButton.displayName = "ToggleButton";
|
|
39
|
-
|
|
40
|
-
export interface ToggleGroupProps {
|
|
41
|
-
type?: "single" | "multiple";
|
|
42
|
-
value?: string | string[];
|
|
43
|
-
onValueChange?: (value: string | string[]) => void;
|
|
44
|
-
children: ReactNode;
|
|
45
|
-
className?: string;
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
export function ToggleGroup({
|
|
49
|
-
type = "single",
|
|
50
|
-
value,
|
|
51
|
-
onValueChange,
|
|
52
|
-
children,
|
|
53
|
-
className,
|
|
54
|
-
}: ToggleGroupProps) {
|
|
55
|
-
return (
|
|
56
|
-
<div className={cn("ph-toggle-group", className)} role="group">
|
|
57
|
-
{children}
|
|
58
|
-
</div>
|
|
59
|
-
);
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
ToggleGroup.displayName = "ToggleGroup";
|
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
import { type ReactNode } from "react";
|
|
2
|
-
import { cn } from "@/lib/cn";
|
|
3
|
-
|
|
4
|
-
export interface WidgetProps {
|
|
5
|
-
title: ReactNode;
|
|
6
|
-
onClose?: () => void;
|
|
7
|
-
actions?: ReactNode;
|
|
8
|
-
children?: ReactNode;
|
|
9
|
-
className?: string;
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
export function Widget({ title, onClose, actions, children, className }: WidgetProps) {
|
|
13
|
-
return (
|
|
14
|
-
<div className={cn("ph-widget", className)}>
|
|
15
|
-
<div className="ph-widget__header">
|
|
16
|
-
<span className="ph-widget__title">{title}</span>
|
|
17
|
-
{actions}
|
|
18
|
-
{onClose && (
|
|
19
|
-
<button type="button" onClick={onClose} className="ph-widget__close" aria-label="Close">
|
|
20
|
-
<svg width="14" height="14" viewBox="0 0 14 14" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round">
|
|
21
|
-
<path d="M3 3l8 8M11 3l-8 8" />
|
|
22
|
-
</svg>
|
|
23
|
-
</button>
|
|
24
|
-
)}
|
|
25
|
-
</div>
|
|
26
|
-
<div className="ph-widget__content">{children}</div>
|
|
27
|
-
</div>
|
|
28
|
-
);
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
Widget.displayName = "Widget";
|