@salesforce/webapp-template-app-react-sample-b2e-experimental 1.49.0 → 1.50.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/CHANGELOG.md +8 -0
- package/dist/force-app/main/default/data/Property__c.json +2 -2
- package/dist/force-app/main/default/webapplications/appreactsampleb2e/src/api/dashboard.ts +170 -0
- package/dist/force-app/main/default/webapplications/appreactsampleb2e/src/api/maintenance.ts +221 -0
- package/dist/force-app/main/default/webapplications/appreactsampleb2e/src/api/properties.ts +157 -0
- package/dist/force-app/main/default/webapplications/appreactsampleb2e/src/api/utils.ts +4 -0
- package/dist/force-app/main/default/webapplications/appreactsampleb2e/src/appLayout.tsx +20 -8
- package/dist/force-app/main/default/webapplications/appreactsampleb2e/src/assets/icons/appliances.svg +13 -0
- package/dist/force-app/main/default/webapplications/appreactsampleb2e/src/assets/icons/dashboard.svg +4 -0
- package/dist/force-app/main/default/webapplications/appreactsampleb2e/src/assets/icons/downgraph.svg +3 -0
- package/dist/force-app/main/default/webapplications/appreactsampleb2e/src/assets/icons/electrical.svg +41 -0
- package/dist/force-app/main/default/webapplications/appreactsampleb2e/src/assets/icons/files.svg +7 -0
- package/dist/force-app/main/default/webapplications/appreactsampleb2e/src/assets/icons/hvac.svg +79 -0
- package/dist/force-app/main/default/webapplications/appreactsampleb2e/src/assets/icons/maintenance.svg +4 -0
- package/dist/force-app/main/default/webapplications/appreactsampleb2e/src/assets/icons/pest.svg +5 -0
- package/dist/force-app/main/default/webapplications/appreactsampleb2e/src/assets/icons/plumbing.svg +7 -0
- package/dist/force-app/main/default/webapplications/appreactsampleb2e/src/assets/icons/properties.svg +14 -0
- package/dist/force-app/main/default/webapplications/appreactsampleb2e/src/assets/icons/support.svg +6 -0
- package/dist/force-app/main/default/webapplications/appreactsampleb2e/src/assets/icons/upgraph.svg +3 -0
- package/dist/force-app/main/default/webapplications/appreactsampleb2e/src/assets/icons/users.svg +8 -0
- package/dist/force-app/main/default/webapplications/appreactsampleb2e/src/assets/icons/zen-logo.svg +5 -0
- package/dist/force-app/main/default/webapplications/appreactsampleb2e/src/components/AnalyticsTile.tsx +29 -0
- package/dist/force-app/main/default/webapplications/appreactsampleb2e/src/components/ApplicationCard.tsx +43 -0
- package/dist/force-app/main/default/webapplications/appreactsampleb2e/src/components/IssuesDonutChart.tsx +66 -0
- package/dist/force-app/main/default/webapplications/appreactsampleb2e/src/components/MaintenanceRequestCard.tsx +71 -0
- package/dist/force-app/main/default/webapplications/appreactsampleb2e/src/components/MaintenanceTable.tsx +110 -0
- package/dist/force-app/main/default/webapplications/appreactsampleb2e/src/components/PriorityBadge.tsx +29 -0
- package/dist/force-app/main/default/webapplications/appreactsampleb2e/src/components/PropertyCard.tsx +61 -0
- package/dist/force-app/main/default/webapplications/appreactsampleb2e/src/components/StatCard.tsx +52 -0
- package/dist/force-app/main/default/webapplications/appreactsampleb2e/src/components/StatusBadge.tsx +37 -0
- package/dist/force-app/main/default/webapplications/appreactsampleb2e/src/components/TopBar.tsx +72 -0
- package/dist/force-app/main/default/webapplications/appreactsampleb2e/src/components/UserAvatar.tsx +35 -0
- package/dist/force-app/main/default/webapplications/appreactsampleb2e/src/components/VerticalNav.tsx +54 -0
- package/dist/force-app/main/default/webapplications/appreactsampleb2e/src/components/ui/alert.tsx +69 -0
- package/dist/force-app/main/default/webapplications/appreactsampleb2e/src/components/ui/button.tsx +67 -0
- package/dist/force-app/main/default/webapplications/appreactsampleb2e/src/components/ui/card.tsx +92 -0
- package/dist/force-app/main/default/webapplications/appreactsampleb2e/src/components/ui/dialog.tsx +143 -0
- package/dist/force-app/main/default/webapplications/appreactsampleb2e/src/components/ui/field.tsx +222 -0
- package/dist/force-app/main/default/webapplications/appreactsampleb2e/src/components/ui/index.ts +72 -0
- package/dist/force-app/main/default/webapplications/appreactsampleb2e/src/components/ui/input.tsx +19 -0
- package/dist/force-app/main/default/webapplications/appreactsampleb2e/src/components/ui/label.tsx +19 -0
- package/dist/force-app/main/default/webapplications/appreactsampleb2e/src/components/ui/pagination.tsx +112 -0
- package/dist/force-app/main/default/webapplications/appreactsampleb2e/src/components/ui/select.tsx +183 -0
- package/dist/force-app/main/default/webapplications/appreactsampleb2e/src/components/ui/separator.tsx +26 -0
- package/dist/force-app/main/default/webapplications/appreactsampleb2e/src/components/ui/skeleton.tsx +14 -0
- package/dist/force-app/main/default/webapplications/appreactsampleb2e/src/components/ui/spinner.tsx +15 -0
- package/dist/force-app/main/default/webapplications/appreactsampleb2e/src/components/ui/table.tsx +87 -0
- package/dist/force-app/main/default/webapplications/appreactsampleb2e/src/components/ui/tabs.tsx +78 -0
- package/dist/force-app/main/default/webapplications/appreactsampleb2e/src/components.json +18 -0
- package/dist/force-app/main/default/webapplications/appreactsampleb2e/src/lib/types.ts +57 -0
- package/dist/force-app/main/default/webapplications/appreactsampleb2e/src/lib/utils.ts +6 -0
- package/dist/force-app/main/default/webapplications/appreactsampleb2e/src/pages/Home.tsx +163 -10
- package/dist/force-app/main/default/webapplications/appreactsampleb2e/src/pages/Maintenance.tsx +176 -0
- package/dist/force-app/main/default/webapplications/appreactsampleb2e/src/pages/Properties.tsx +94 -0
- package/dist/force-app/main/default/webapplications/appreactsampleb2e/src/routes.tsx +19 -7
- package/dist/force-app/main/default/webapplications/appreactsampleb2e/src/styles/global.css +160 -0
- package/dist/package.json +1 -1
- package/package.json +2 -2
package/dist/force-app/main/default/webapplications/appreactsampleb2e/src/components/StatusBadge.tsx
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import { Check } from "lucide-react";
|
|
3
|
+
|
|
4
|
+
interface StatusBadgeProps {
|
|
5
|
+
status: "new" | "assigned" | "scheduled" | "in_progress" | "completed";
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
export const StatusBadge: React.FC<StatusBadgeProps> = ({ status }) => {
|
|
9
|
+
const styles = {
|
|
10
|
+
new: "bg-pink-100 text-pink-700",
|
|
11
|
+
assigned: "bg-purple-100 text-purple-700",
|
|
12
|
+
scheduled: "bg-blue-100 text-blue-700",
|
|
13
|
+
in_progress: "bg-yellow-100 text-yellow-700",
|
|
14
|
+
completed: "bg-green-100 text-green-700",
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
const labels = {
|
|
18
|
+
new: "Needs Action",
|
|
19
|
+
assigned: "Assigned",
|
|
20
|
+
scheduled: "Scheduled",
|
|
21
|
+
in_progress: "In Progress",
|
|
22
|
+
completed: "Completed",
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
const showCheckmark = status === "completed";
|
|
26
|
+
const showDot = status === "new" || status === "in_progress";
|
|
27
|
+
|
|
28
|
+
return (
|
|
29
|
+
<span
|
|
30
|
+
className={`inline-flex items-center gap-1.5 px-3 py-1 rounded-full text-sm font-medium ${styles[status]}`}
|
|
31
|
+
>
|
|
32
|
+
{showCheckmark && <Check className="w-4 h-4" />}
|
|
33
|
+
{showDot && <span className="w-2 h-2 rounded-full bg-current" />}
|
|
34
|
+
{labels[status]}
|
|
35
|
+
</span>
|
|
36
|
+
);
|
|
37
|
+
};
|
package/dist/force-app/main/default/webapplications/appreactsampleb2e/src/components/TopBar.tsx
ADDED
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import React, { useEffect, useState } from "react";
|
|
2
|
+
import { Search, Bell, ChevronDown, Menu } from "lucide-react";
|
|
3
|
+
import zenLogo from "../assets/icons/zen-logo.svg";
|
|
4
|
+
import { getUserInfo } from "../api/dashboard.js";
|
|
5
|
+
|
|
6
|
+
interface TopBarProps {
|
|
7
|
+
onMenuClick?: () => void;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export const TopBar: React.FC<TopBarProps> = ({ onMenuClick }) => {
|
|
11
|
+
const [userName, setUserName] = useState<string>("User");
|
|
12
|
+
|
|
13
|
+
useEffect(() => {
|
|
14
|
+
const loadUserInfo = async () => {
|
|
15
|
+
const userInfo = await getUserInfo();
|
|
16
|
+
if (userInfo) {
|
|
17
|
+
setUserName(userInfo.name);
|
|
18
|
+
}
|
|
19
|
+
};
|
|
20
|
+
loadUserInfo();
|
|
21
|
+
}, []);
|
|
22
|
+
return (
|
|
23
|
+
<div className="bg-[#372949] text-white h-16 flex items-center justify-between px-6">
|
|
24
|
+
{/* Left section - Logo and Menu */}
|
|
25
|
+
<div className="flex items-center gap-4">
|
|
26
|
+
<button
|
|
27
|
+
onClick={onMenuClick}
|
|
28
|
+
className="p-2 hover:bg-purple-700 rounded-md transition-colors md:hidden"
|
|
29
|
+
aria-label="Toggle menu"
|
|
30
|
+
>
|
|
31
|
+
<Menu className="w-6 h-6" />
|
|
32
|
+
</button>
|
|
33
|
+
<div className="flex items-center gap-2">
|
|
34
|
+
<img src={zenLogo} alt="Zenlease Logo" className="w-8 h-8" />
|
|
35
|
+
<span className="text-xl tracking-wide">
|
|
36
|
+
<span className="font-light">ZEN</span>
|
|
37
|
+
<span className="font-semibold">LEASE</span>
|
|
38
|
+
</span>
|
|
39
|
+
</div>
|
|
40
|
+
</div>
|
|
41
|
+
|
|
42
|
+
{/* Right section - Search, Notifications, Profile */}
|
|
43
|
+
<div className="flex items-center gap-4">
|
|
44
|
+
{/* Search Icon (Mobile) */}
|
|
45
|
+
<button
|
|
46
|
+
className="p-2 hover:bg-purple-700 rounded-md transition-colors md:hidden"
|
|
47
|
+
aria-label="Search"
|
|
48
|
+
>
|
|
49
|
+
<Search className="w-5 h-5" />
|
|
50
|
+
</button>
|
|
51
|
+
|
|
52
|
+
{/* Notifications */}
|
|
53
|
+
<button
|
|
54
|
+
className="p-2 hover:bg-purple-700 rounded-md transition-colors relative"
|
|
55
|
+
aria-label="Notifications"
|
|
56
|
+
>
|
|
57
|
+
<Bell className="w-5 h-5" />
|
|
58
|
+
<span className="absolute top-1 right-1 w-2 h-2 bg-pink-500 rounded-full"></span>
|
|
59
|
+
</button>
|
|
60
|
+
|
|
61
|
+
{/* User Profile */}
|
|
62
|
+
<button className="flex items-center gap-2 px-3 py-2 hover:bg-purple-700 rounded-md transition-colors">
|
|
63
|
+
<div className="w-8 h-8 bg-purple-300 rounded-full flex items-center justify-center text-purple-900 font-semibold">
|
|
64
|
+
{userName.charAt(0).toUpperCase()}
|
|
65
|
+
</div>
|
|
66
|
+
<span className="hidden md:inline font-medium">{userName.toUpperCase()}</span>
|
|
67
|
+
<ChevronDown className="w-4 h-4 hidden md:inline" />
|
|
68
|
+
</button>
|
|
69
|
+
</div>
|
|
70
|
+
</div>
|
|
71
|
+
);
|
|
72
|
+
};
|
package/dist/force-app/main/default/webapplications/appreactsampleb2e/src/components/UserAvatar.tsx
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
|
|
3
|
+
interface UserAvatarProps {
|
|
4
|
+
name: string;
|
|
5
|
+
imageUrl?: string;
|
|
6
|
+
size?: "sm" | "md" | "lg";
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export const UserAvatar: React.FC<UserAvatarProps> = ({ name, imageUrl, size = "md" }) => {
|
|
10
|
+
const sizeClasses = {
|
|
11
|
+
sm: "w-8 h-8 text-xs",
|
|
12
|
+
md: "w-10 h-10 text-sm",
|
|
13
|
+
lg: "w-12 h-12 text-base",
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
const getInitials = (name: string) => {
|
|
17
|
+
const parts = name.trim().split(" ");
|
|
18
|
+
if (parts.length >= 2) {
|
|
19
|
+
return `${parts[0][0]}${parts[1][0]}`.toUpperCase();
|
|
20
|
+
}
|
|
21
|
+
return name.substring(0, 2).toUpperCase();
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
return (
|
|
25
|
+
<div
|
|
26
|
+
className={`${sizeClasses[size]} rounded-full bg-gray-200 flex items-center justify-center flex-shrink-0 overflow-hidden`}
|
|
27
|
+
>
|
|
28
|
+
{imageUrl ? (
|
|
29
|
+
<img src={imageUrl} alt={name} className="w-full h-full object-cover" />
|
|
30
|
+
) : (
|
|
31
|
+
<span className="font-medium text-gray-700">{getInitials(name)}</span>
|
|
32
|
+
)}
|
|
33
|
+
</div>
|
|
34
|
+
);
|
|
35
|
+
};
|
package/dist/force-app/main/default/webapplications/appreactsampleb2e/src/components/VerticalNav.tsx
ADDED
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import { Link, useLocation } from "react-router";
|
|
3
|
+
import dashboardIcon from "../assets/icons/dashboard.svg";
|
|
4
|
+
import filesIcon from "../assets/icons/files.svg";
|
|
5
|
+
import propertiesIcon from "../assets/icons/properties.svg";
|
|
6
|
+
import maintenanceIcon from "../assets/icons/maintenance.svg";
|
|
7
|
+
import usersIcon from "../assets/icons/users.svg";
|
|
8
|
+
import supportIcon from "../assets/icons/support.svg";
|
|
9
|
+
|
|
10
|
+
interface NavItem {
|
|
11
|
+
path: string;
|
|
12
|
+
icon: string;
|
|
13
|
+
label: string;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
const navItems: NavItem[] = [
|
|
17
|
+
{ path: "/", icon: dashboardIcon, label: "Dashboard" },
|
|
18
|
+
{ path: "/files", icon: filesIcon, label: "Files" },
|
|
19
|
+
{ path: "/properties", icon: propertiesIcon, label: "Properties" },
|
|
20
|
+
{ path: "/maintenance", icon: maintenanceIcon, label: "Maintenance" },
|
|
21
|
+
{ path: "/users", icon: usersIcon, label: "Users" },
|
|
22
|
+
{ path: "/support", icon: supportIcon, label: "Support" },
|
|
23
|
+
];
|
|
24
|
+
|
|
25
|
+
export const VerticalNav: React.FC = () => {
|
|
26
|
+
const location = useLocation();
|
|
27
|
+
|
|
28
|
+
const isActive = (path: string) => {
|
|
29
|
+
if (path === "/") {
|
|
30
|
+
return location.pathname === "/";
|
|
31
|
+
}
|
|
32
|
+
return location.pathname.startsWith(path);
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
return (
|
|
36
|
+
<div className="flex flex-col w-24 bg-white border-r border-gray-200 py-8 space-y-4">
|
|
37
|
+
{navItems.map((item) => (
|
|
38
|
+
<Link
|
|
39
|
+
key={item.path}
|
|
40
|
+
to={item.path}
|
|
41
|
+
className={`flex flex-col items-center justify-center gap-2 py-4 px-2 transition-colors ${
|
|
42
|
+
isActive(item.path)
|
|
43
|
+
? "bg-purple-100 text-purple-700 border-l-4 border-purple-700"
|
|
44
|
+
: "text-gray-600 hover:bg-gray-100 hover:text-gray-900"
|
|
45
|
+
}`}
|
|
46
|
+
title={item.label}
|
|
47
|
+
>
|
|
48
|
+
<img src={item.icon} alt={item.label} className="w-6 h-6" />
|
|
49
|
+
<span className="text-xs font-medium">{item.label}</span>
|
|
50
|
+
</Link>
|
|
51
|
+
))}
|
|
52
|
+
</div>
|
|
53
|
+
);
|
|
54
|
+
};
|
package/dist/force-app/main/default/webapplications/appreactsampleb2e/src/components/ui/alert.tsx
ADDED
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
import { cva, type VariantProps } from "class-variance-authority";
|
|
3
|
+
|
|
4
|
+
import { cn } from "../../lib/utils";
|
|
5
|
+
|
|
6
|
+
const alertVariants = cva(
|
|
7
|
+
"grid gap-0.5 rounded-lg border px-2.5 py-2 text-left text-sm has-data-[slot=alert-action]:relative has-data-[slot=alert-action]:pr-18 has-[>svg]:grid-cols-[auto_1fr] has-[>svg]:gap-x-2 *:[svg]:row-span-2 *:[svg]:translate-y-0.5 *:[svg]:text-current *:[svg:not([class*='size-'])]:size-4 w-full relative group/alert",
|
|
8
|
+
{
|
|
9
|
+
variants: {
|
|
10
|
+
variant: {
|
|
11
|
+
default: "bg-card text-card-foreground",
|
|
12
|
+
destructive:
|
|
13
|
+
"text-destructive bg-card *:data-[slot=alert-description]:text-destructive/90 *:[svg]:text-current",
|
|
14
|
+
},
|
|
15
|
+
},
|
|
16
|
+
defaultVariants: {
|
|
17
|
+
variant: "default",
|
|
18
|
+
},
|
|
19
|
+
},
|
|
20
|
+
);
|
|
21
|
+
|
|
22
|
+
function Alert({
|
|
23
|
+
className,
|
|
24
|
+
variant,
|
|
25
|
+
...props
|
|
26
|
+
}: React.ComponentProps<"div"> & VariantProps<typeof alertVariants>) {
|
|
27
|
+
return (
|
|
28
|
+
<div
|
|
29
|
+
data-slot="alert"
|
|
30
|
+
role="alert"
|
|
31
|
+
className={cn(alertVariants({ variant }), className)}
|
|
32
|
+
{...props}
|
|
33
|
+
/>
|
|
34
|
+
);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
function AlertTitle({ className, ...props }: React.ComponentProps<"div">) {
|
|
38
|
+
return (
|
|
39
|
+
<div
|
|
40
|
+
data-slot="alert-title"
|
|
41
|
+
className={cn(
|
|
42
|
+
"font-medium group-has-[>svg]/alert:col-start-2 [&_a]:hover:text-foreground [&_a]:underline [&_a]:underline-offset-3",
|
|
43
|
+
className,
|
|
44
|
+
)}
|
|
45
|
+
{...props}
|
|
46
|
+
/>
|
|
47
|
+
);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
function AlertDescription({ className, ...props }: React.ComponentProps<"div">) {
|
|
51
|
+
return (
|
|
52
|
+
<div
|
|
53
|
+
data-slot="alert-description"
|
|
54
|
+
className={cn(
|
|
55
|
+
"text-muted-foreground text-sm text-balance md:text-pretty [&_p:not(:last-child)]:mb-4 [&_a]:hover:text-foreground [&_a]:underline [&_a]:underline-offset-3",
|
|
56
|
+
className,
|
|
57
|
+
)}
|
|
58
|
+
{...props}
|
|
59
|
+
/>
|
|
60
|
+
);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
function AlertAction({ className, ...props }: React.ComponentProps<"div">) {
|
|
64
|
+
return (
|
|
65
|
+
<div data-slot="alert-action" className={cn("absolute top-2 right-2", className)} {...props} />
|
|
66
|
+
);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
export { Alert, AlertTitle, AlertDescription, AlertAction };
|
package/dist/force-app/main/default/webapplications/appreactsampleb2e/src/components/ui/button.tsx
ADDED
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
import { cva, type VariantProps } from "class-variance-authority";
|
|
3
|
+
import { Slot } from "radix-ui";
|
|
4
|
+
|
|
5
|
+
import { cn } from "../../lib/utils";
|
|
6
|
+
|
|
7
|
+
const buttonVariants = cva(
|
|
8
|
+
"focus-visible:border-ring focus-visible:ring-ring/50 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive dark:aria-invalid:border-destructive/50 rounded-lg border border-transparent bg-clip-padding text-sm font-medium focus-visible:ring-3 aria-invalid:ring-3 [&_svg:not([class*='size-'])]:size-4 inline-flex items-center justify-center whitespace-nowrap transition-all disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none shrink-0 [&_svg]:shrink-0 outline-none group/button select-none",
|
|
9
|
+
{
|
|
10
|
+
variants: {
|
|
11
|
+
variant: {
|
|
12
|
+
default: "bg-primary text-primary-foreground [a]:hover:bg-primary/80",
|
|
13
|
+
outline:
|
|
14
|
+
"border-border bg-background hover:bg-muted hover:text-foreground dark:bg-input/30 dark:border-input dark:hover:bg-input/50 aria-expanded:bg-muted aria-expanded:text-foreground",
|
|
15
|
+
secondary:
|
|
16
|
+
"bg-secondary text-secondary-foreground hover:bg-secondary/80 aria-expanded:bg-secondary aria-expanded:text-secondary-foreground",
|
|
17
|
+
ghost:
|
|
18
|
+
"hover:bg-muted hover:text-foreground dark:hover:bg-muted/50 aria-expanded:bg-muted aria-expanded:text-foreground",
|
|
19
|
+
destructive:
|
|
20
|
+
"bg-destructive/10 hover:bg-destructive/20 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40 dark:bg-destructive/20 text-destructive focus-visible:border-destructive/40 dark:hover:bg-destructive/30",
|
|
21
|
+
link: "text-primary underline-offset-4 hover:underline",
|
|
22
|
+
},
|
|
23
|
+
size: {
|
|
24
|
+
default:
|
|
25
|
+
"h-8 gap-1.5 px-2.5 has-data-[icon=inline-end]:pr-2 has-data-[icon=inline-start]:pl-2",
|
|
26
|
+
xs: "h-6 gap-1 rounded-[min(var(--radius-md),10px)] px-2 text-xs in-data-[slot=button-group]:rounded-lg has-data-[icon=inline-end]:pr-1.5 has-data-[icon=inline-start]:pl-1.5 [&_svg:not([class*='size-'])]:size-3",
|
|
27
|
+
sm: "h-7 gap-1 rounded-[min(var(--radius-md),12px)] px-2.5 text-[0.8rem] in-data-[slot=button-group]:rounded-lg has-data-[icon=inline-end]:pr-1.5 has-data-[icon=inline-start]:pl-1.5 [&_svg:not([class*='size-'])]:size-3.5",
|
|
28
|
+
lg: "h-9 gap-1.5 px-2.5 has-data-[icon=inline-end]:pr-3 has-data-[icon=inline-start]:pl-3",
|
|
29
|
+
icon: "size-8",
|
|
30
|
+
"icon-xs":
|
|
31
|
+
"size-6 rounded-[min(var(--radius-md),10px)] in-data-[slot=button-group]:rounded-lg [&_svg:not([class*='size-'])]:size-3",
|
|
32
|
+
"icon-sm":
|
|
33
|
+
"size-7 rounded-[min(var(--radius-md),12px)] in-data-[slot=button-group]:rounded-lg",
|
|
34
|
+
"icon-lg": "size-9",
|
|
35
|
+
},
|
|
36
|
+
},
|
|
37
|
+
defaultVariants: {
|
|
38
|
+
variant: "default",
|
|
39
|
+
size: "default",
|
|
40
|
+
},
|
|
41
|
+
},
|
|
42
|
+
);
|
|
43
|
+
|
|
44
|
+
function Button({
|
|
45
|
+
className,
|
|
46
|
+
variant = "default",
|
|
47
|
+
size = "default",
|
|
48
|
+
asChild = false,
|
|
49
|
+
...props
|
|
50
|
+
}: React.ComponentProps<"button"> &
|
|
51
|
+
VariantProps<typeof buttonVariants> & {
|
|
52
|
+
asChild?: boolean;
|
|
53
|
+
}) {
|
|
54
|
+
const Comp = asChild ? Slot.Root : "button";
|
|
55
|
+
|
|
56
|
+
return (
|
|
57
|
+
<Comp
|
|
58
|
+
data-slot="button"
|
|
59
|
+
data-variant={variant}
|
|
60
|
+
data-size={size}
|
|
61
|
+
className={cn(buttonVariants({ variant, size, className }))}
|
|
62
|
+
{...(props as any)}
|
|
63
|
+
/>
|
|
64
|
+
);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
export { Button, buttonVariants };
|
package/dist/force-app/main/default/webapplications/appreactsampleb2e/src/components/ui/card.tsx
ADDED
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
|
|
3
|
+
import { cn } from "../../lib/utils";
|
|
4
|
+
|
|
5
|
+
function Card({
|
|
6
|
+
className,
|
|
7
|
+
size = "default",
|
|
8
|
+
...props
|
|
9
|
+
}: React.ComponentProps<"div"> & { size?: "default" | "sm" }) {
|
|
10
|
+
return (
|
|
11
|
+
<div
|
|
12
|
+
data-slot="card"
|
|
13
|
+
data-size={size}
|
|
14
|
+
className={cn(
|
|
15
|
+
"ring-foreground/10 bg-card text-card-foreground gap-4 overflow-hidden rounded-xl py-4 text-sm ring-1 has-data-[slot=card-footer]:pb-0 has-[>img:first-child]:pt-0 data-[size=sm]:gap-3 data-[size=sm]:py-3 data-[size=sm]:has-data-[slot=card-footer]:pb-0 *:[img:first-child]:rounded-t-xl *:[img:last-child]:rounded-b-xl group/card flex flex-col",
|
|
16
|
+
className,
|
|
17
|
+
)}
|
|
18
|
+
{...props}
|
|
19
|
+
/>
|
|
20
|
+
);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
function CardHeader({ className, ...props }: React.ComponentProps<"div">) {
|
|
24
|
+
return (
|
|
25
|
+
<div
|
|
26
|
+
data-slot="card-header"
|
|
27
|
+
className={cn(
|
|
28
|
+
"gap-1 rounded-t-xl px-4 group-data-[size=sm]/card:px-3 [.border-b]:pb-4 group-data-[size=sm]/card:[.border-b]:pb-3 group/card-header @container/card-header grid auto-rows-min items-start has-data-[slot=card-action]:grid-cols-[1fr_auto] has-data-[slot=card-description]:grid-rows-[auto_auto]",
|
|
29
|
+
className,
|
|
30
|
+
)}
|
|
31
|
+
{...props}
|
|
32
|
+
/>
|
|
33
|
+
);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
function CardTitle({ className, ...props }: React.ComponentProps<"div">) {
|
|
37
|
+
return (
|
|
38
|
+
<div
|
|
39
|
+
data-slot="card-title"
|
|
40
|
+
className={cn(
|
|
41
|
+
"text-base leading-snug font-medium group-data-[size=sm]/card:text-sm",
|
|
42
|
+
className,
|
|
43
|
+
)}
|
|
44
|
+
{...props}
|
|
45
|
+
/>
|
|
46
|
+
);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
function CardDescription({ className, ...props }: React.ComponentProps<"div">) {
|
|
50
|
+
return (
|
|
51
|
+
<div
|
|
52
|
+
data-slot="card-description"
|
|
53
|
+
className={cn("text-muted-foreground text-sm", className)}
|
|
54
|
+
{...props}
|
|
55
|
+
/>
|
|
56
|
+
);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
function CardAction({ className, ...props }: React.ComponentProps<"div">) {
|
|
60
|
+
return (
|
|
61
|
+
<div
|
|
62
|
+
data-slot="card-action"
|
|
63
|
+
className={cn("col-start-2 row-span-2 row-start-1 self-start justify-self-end", className)}
|
|
64
|
+
{...props}
|
|
65
|
+
/>
|
|
66
|
+
);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
function CardContent({ className, ...props }: React.ComponentProps<"div">) {
|
|
70
|
+
return (
|
|
71
|
+
<div
|
|
72
|
+
data-slot="card-content"
|
|
73
|
+
className={cn("px-4 group-data-[size=sm]/card:px-3", className)}
|
|
74
|
+
{...props}
|
|
75
|
+
/>
|
|
76
|
+
);
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
function CardFooter({ className, ...props }: React.ComponentProps<"div">) {
|
|
80
|
+
return (
|
|
81
|
+
<div
|
|
82
|
+
data-slot="card-footer"
|
|
83
|
+
className={cn(
|
|
84
|
+
"bg-muted/50 rounded-b-xl border-t p-4 group-data-[size=sm]/card:p-3 flex items-center",
|
|
85
|
+
className,
|
|
86
|
+
)}
|
|
87
|
+
{...props}
|
|
88
|
+
/>
|
|
89
|
+
);
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
export { Card, CardHeader, CardFooter, CardTitle, CardAction, CardDescription, CardContent };
|
package/dist/force-app/main/default/webapplications/appreactsampleb2e/src/components/ui/dialog.tsx
ADDED
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
import { Dialog as DialogPrimitive } from "radix-ui";
|
|
3
|
+
|
|
4
|
+
import { cn } from "../../lib/utils";
|
|
5
|
+
import { Button } from "./button";
|
|
6
|
+
import { XIcon } from "lucide-react";
|
|
7
|
+
|
|
8
|
+
function Dialog({ ...props }: React.ComponentProps<typeof DialogPrimitive.Root>) {
|
|
9
|
+
return <DialogPrimitive.Root data-slot="dialog" {...props} />;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
function DialogTrigger({ ...props }: React.ComponentProps<typeof DialogPrimitive.Trigger>) {
|
|
13
|
+
return <DialogPrimitive.Trigger data-slot="dialog-trigger" {...props} />;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
function DialogPortal({ ...props }: React.ComponentProps<typeof DialogPrimitive.Portal>) {
|
|
17
|
+
return <DialogPrimitive.Portal data-slot="dialog-portal" {...props} />;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
function DialogClose({ ...props }: React.ComponentProps<typeof DialogPrimitive.Close>) {
|
|
21
|
+
return <DialogPrimitive.Close data-slot="dialog-close" {...props} />;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
function DialogOverlay({
|
|
25
|
+
className,
|
|
26
|
+
...props
|
|
27
|
+
}: React.ComponentProps<typeof DialogPrimitive.Overlay>) {
|
|
28
|
+
return (
|
|
29
|
+
<DialogPrimitive.Overlay
|
|
30
|
+
data-slot="dialog-overlay"
|
|
31
|
+
className={cn(
|
|
32
|
+
"data-open:animate-in data-closed:animate-out data-closed:fade-out-0 data-open:fade-in-0 bg-black/10 duration-100 supports-backdrop-filter:backdrop-blur-xs fixed inset-0 isolate z-50",
|
|
33
|
+
className,
|
|
34
|
+
)}
|
|
35
|
+
{...props}
|
|
36
|
+
/>
|
|
37
|
+
);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
function DialogContent({
|
|
41
|
+
className,
|
|
42
|
+
children,
|
|
43
|
+
showCloseButton = true,
|
|
44
|
+
...props
|
|
45
|
+
}: React.ComponentProps<typeof DialogPrimitive.Content> & {
|
|
46
|
+
showCloseButton?: boolean;
|
|
47
|
+
}) {
|
|
48
|
+
return (
|
|
49
|
+
<DialogPortal>
|
|
50
|
+
<DialogOverlay />
|
|
51
|
+
<DialogPrimitive.Content
|
|
52
|
+
data-slot="dialog-content"
|
|
53
|
+
className={cn(
|
|
54
|
+
"bg-background data-open:animate-in data-closed:animate-out data-closed:fade-out-0 data-open:fade-in-0 data-closed:zoom-out-95 data-open:zoom-in-95 ring-foreground/10 grid max-w-[calc(100%-2rem)] gap-4 rounded-xl p-4 text-sm ring-1 duration-100 sm:max-w-sm fixed top-1/2 left-1/2 z-50 w-full -translate-x-1/2 -translate-y-1/2 outline-none",
|
|
55
|
+
className,
|
|
56
|
+
)}
|
|
57
|
+
{...props}
|
|
58
|
+
>
|
|
59
|
+
{children}
|
|
60
|
+
{showCloseButton && (
|
|
61
|
+
<DialogPrimitive.Close data-slot="dialog-close" asChild>
|
|
62
|
+
<Button variant="ghost" className="absolute top-2 right-2" size="icon-sm">
|
|
63
|
+
<XIcon />
|
|
64
|
+
<span className="sr-only">Close</span>
|
|
65
|
+
</Button>
|
|
66
|
+
</DialogPrimitive.Close>
|
|
67
|
+
)}
|
|
68
|
+
</DialogPrimitive.Content>
|
|
69
|
+
</DialogPortal>
|
|
70
|
+
);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
function DialogHeader({ className, ...props }: React.ComponentProps<"div">) {
|
|
74
|
+
return (
|
|
75
|
+
<div data-slot="dialog-header" className={cn("gap-2 flex flex-col", className)} {...props} />
|
|
76
|
+
);
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
function DialogFooter({
|
|
80
|
+
className,
|
|
81
|
+
showCloseButton = false,
|
|
82
|
+
children,
|
|
83
|
+
...props
|
|
84
|
+
}: React.ComponentProps<"div"> & {
|
|
85
|
+
showCloseButton?: boolean;
|
|
86
|
+
}) {
|
|
87
|
+
return (
|
|
88
|
+
<div
|
|
89
|
+
data-slot="dialog-footer"
|
|
90
|
+
className={cn(
|
|
91
|
+
"bg-muted/50 -mx-4 -mb-4 rounded-b-xl border-t p-4 flex flex-col-reverse gap-2 sm:flex-row sm:justify-end",
|
|
92
|
+
className,
|
|
93
|
+
)}
|
|
94
|
+
{...props}
|
|
95
|
+
>
|
|
96
|
+
{children}
|
|
97
|
+
{showCloseButton && (
|
|
98
|
+
<DialogPrimitive.Close asChild>
|
|
99
|
+
<Button variant="outline">Close</Button>
|
|
100
|
+
</DialogPrimitive.Close>
|
|
101
|
+
)}
|
|
102
|
+
</div>
|
|
103
|
+
);
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
function DialogTitle({ className, ...props }: React.ComponentProps<typeof DialogPrimitive.Title>) {
|
|
107
|
+
return (
|
|
108
|
+
<DialogPrimitive.Title
|
|
109
|
+
data-slot="dialog-title"
|
|
110
|
+
className={cn("text-base leading-none font-medium", className)}
|
|
111
|
+
{...props}
|
|
112
|
+
/>
|
|
113
|
+
);
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
function DialogDescription({
|
|
117
|
+
className,
|
|
118
|
+
...props
|
|
119
|
+
}: React.ComponentProps<typeof DialogPrimitive.Description>) {
|
|
120
|
+
return (
|
|
121
|
+
<DialogPrimitive.Description
|
|
122
|
+
data-slot="dialog-description"
|
|
123
|
+
className={cn(
|
|
124
|
+
"text-muted-foreground *:[a]:hover:text-foreground text-sm *:[a]:underline *:[a]:underline-offset-3",
|
|
125
|
+
className,
|
|
126
|
+
)}
|
|
127
|
+
{...props}
|
|
128
|
+
/>
|
|
129
|
+
);
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
export {
|
|
133
|
+
Dialog,
|
|
134
|
+
DialogClose,
|
|
135
|
+
DialogContent,
|
|
136
|
+
DialogDescription,
|
|
137
|
+
DialogFooter,
|
|
138
|
+
DialogHeader,
|
|
139
|
+
DialogOverlay,
|
|
140
|
+
DialogPortal,
|
|
141
|
+
DialogTitle,
|
|
142
|
+
DialogTrigger,
|
|
143
|
+
};
|