Skip to content

Commit 7be37ac

Browse files
initial commit
0 parents  commit 7be37ac

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

53 files changed

+4277
-0
lines changed

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
node_modules
2+
.DS_Store

clsx/index.ts

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
import { twMerge } from "tailwind-merge"
2+
3+
type ClassValue = ClassArray | ClassDictionary | string | number | null | boolean | undefined
4+
type ClassDictionary = Record<string, any>
5+
type ClassArray = ClassValue[]
6+
7+
function toVal(mix: any) {
8+
let k,
9+
y,
10+
str = ""
11+
12+
if (typeof mix === "string" || typeof mix === "number") {
13+
str += mix
14+
} else if (typeof mix === "object") {
15+
if (Array.isArray(mix)) {
16+
const len = mix.length
17+
for (k = 0; k < len; k++) {
18+
if (mix[k]) {
19+
if ((y = toVal(mix[k]))) {
20+
str && (str += " ")
21+
str += y
22+
}
23+
}
24+
}
25+
} else {
26+
for (y in mix) {
27+
if (mix[y]) {
28+
str && (str += " ")
29+
str += y
30+
}
31+
}
32+
}
33+
}
34+
35+
return str
36+
}
37+
38+
export function cx(...inputs: ClassValue[]): string
39+
export function cx() {
40+
let i = 0,
41+
tmp,
42+
x,
43+
str = "",
44+
// eslint-disable-next-line prefer-const
45+
len = arguments.length
46+
for (; i < len; i++) {
47+
// eslint-disable-next-line prefer-rest-params
48+
if ((tmp = arguments[i])) {
49+
if ((x = toVal(tmp))) {
50+
str && (str += " ")
51+
str += x
52+
}
53+
}
54+
}
55+
56+
return str
57+
}
58+
59+
export function cn(...inputs: ClassValue[]) {
60+
return twMerge(cx(inputs))
61+
}
62+
63+
export default cn

index.ts

Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
export * from "./src"
2+
export * from "./clsx"
3+
export { Accordion, AccordionItem, AccordionTrigger, AccordionContent } from "./src/Accordion"
4+
export {
5+
AlertDialog,
6+
AlertDialogPortal,
7+
AlertDialogOverlay,
8+
AlertDialogTrigger,
9+
AlertDialogContent,
10+
AlertDialogHeader,
11+
AlertDialogFooter,
12+
AlertDialogTitle,
13+
AlertDialogDescription,
14+
AlertDialogAction,
15+
AlertDialogCancel,
16+
} from "./src/AlertDialog"
17+
export { Avatar, AvatarImage, AvatarFallback } from "./src/Avatar"
18+
export { Button } from "./src/Button"
19+
export type { ButtonProps } from "./src/Button"
20+
export { Checkbox } from "./src/Checkbox"
21+
export { Chip } from "./src/Chip"
22+
export { Collapsible, CollapsibleTrigger, CollapsibleContent } from "./src/Collapsible"
23+
24+
export {
25+
Dialog,
26+
DialogPortal,
27+
DialogOverlay,
28+
DialogClose,
29+
DialogTrigger,
30+
DialogContent,
31+
DialogHeader,
32+
DialogFooter,
33+
DialogTitle,
34+
DialogDescription,
35+
} from "./src/Dialog"
36+
export {
37+
DropdownMenu,
38+
DropdownMenuTrigger,
39+
DropdownMenuContent,
40+
DropdownMenuItem,
41+
DropdownMenuCheckboxItem,
42+
DropdownMenuRadioItem,
43+
DropdownMenuLabel,
44+
DropdownMenuSeparator,
45+
DropdownMenuShortcut,
46+
DropdownMenuGroup,
47+
DropdownMenuPortal,
48+
DropdownMenuSub,
49+
DropdownMenuSubContent,
50+
DropdownMenuSubTrigger,
51+
DropdownMenuRadioGroup,
52+
} from "./src/DropdownMenu"
53+
export { HoverCard, HoverCardTrigger, HoverCardContent } from "./src/HoverCard"
54+
export { IconButton } from "./src/IconButton"
55+
export { Input } from "./src/Input"
56+
export { Label } from "./src/Label"
57+
export { Popover, PopoverContent, PopoverRoot, PopoverTrigger, PopoverPortal } from "./src/Popover"
58+
export { Progress } from "./src/Progress"
59+
export { RadioGroup, RadioGroupItem } from "./src/RadioGroup"
60+
export { ScrollArea, ScrollBar } from "./src/ScrollArea"
61+
export {
62+
Select,
63+
SelectGroup,
64+
SelectValue,
65+
SelectTrigger,
66+
SelectContent,
67+
SelectLabel,
68+
SelectItem,
69+
SelectSeparator,
70+
} from "./src/Select"
71+
export { Separator } from "./src/Separator"
72+
export { Slider } from "./src/Slider"
73+
export { Switch } from "./src/Switch"
74+
export {
75+
Table,
76+
TableHeader,
77+
TableBody,
78+
TableFooter,
79+
TableHead,
80+
TableRow,
81+
TableCell,
82+
TableCaption,
83+
} from "./src/Table"
84+
export { Tabs, TabsList, TabsTrigger, TabsContent } from "./src/Tabs"
85+
export { Toggle } from "./src/Toggle"
86+
export { ToggleGroup, ToggleGroupItem } from "./src/ToggleGroup"
87+
88+
export { DropdownButton } from "./src/DropdownButton"
89+
export {
90+
Tooltip,
91+
TooltipProvider,
92+
TooltipContent,
93+
TooltipTrigger,
94+
TooltipRoot,
95+
TooltipPortal,
96+
} from "./src/Tooltip"
97+
export { DataTable, DataTableRowContext } from "./src/DataTable"
98+
export { FixedText } from "./src/FixedText"
99+
export { Slot } from "@radix-ui/react-slot"
100+
export * from "./src/index"
101+
export { Select as EnchangedSelect, SelectVariant } from "./src/Select/Select"
102+
export { CodeExample } from "./src/CodeExample"

package.json

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
{
2+
"name": "@loft-enterprise/primitives",
3+
"private": true,
4+
"version": "1.0.0",
5+
"main": "index.ts",
6+
"peerDependencies": {
7+
"@loft-enterprise/client": "0.1.0",
8+
"@loft-enterprise/icons": "*",
9+
"framer-motion": "9.0.1",
10+
"tailwindcss": "3.4.0"
11+
},
12+
"dependencies": {
13+
"@radix-ui/react-accordion": "1.1.2",
14+
"@radix-ui/react-alert-dialog": "1.0.5",
15+
"@radix-ui/react-avatar": "1.0.4",
16+
"@radix-ui/react-checkbox": "1.0.4",
17+
"@radix-ui/react-collapsible": "1.0.3",
18+
"@radix-ui/react-context-menu": "2.1.5",
19+
"@radix-ui/react-dialog": "1.0.5",
20+
"@radix-ui/react-dropdown-menu": "2.0.6",
21+
"@radix-ui/react-form": "0.0.3",
22+
"@radix-ui/react-hover-card": "1.0.7",
23+
"@radix-ui/react-label": "2.0.2",
24+
"@radix-ui/react-menubar": "1.0.4",
25+
"@radix-ui/react-navigation-menu": "1.1.4",
26+
"@radix-ui/react-popover": "1.0.7",
27+
"@radix-ui/react-progress": "1.0.3",
28+
"@radix-ui/react-radio-group": "1.1.3",
29+
"@radix-ui/react-scroll-area": "1.0.5",
30+
"@radix-ui/react-select": "2.0.0",
31+
"@radix-ui/react-separator": "1.0.3",
32+
"@radix-ui/react-slider": "1.1.2",
33+
"@radix-ui/react-switch": "1.0.3",
34+
"@radix-ui/react-tabs": "1.0.4",
35+
"@radix-ui/react-toast": "1.1.5",
36+
"@radix-ui/react-toggle": "1.0.3",
37+
"@radix-ui/react-toggle-group": "1.0.4",
38+
"@radix-ui/react-toolbar": "1.0.4",
39+
"@radix-ui/react-tooltip": "1.0.7",
40+
"react-select": "^5.8.0"
41+
}
42+
}

src/Accordion.tsx

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
import * as AccordionPrimitive from "@radix-ui/react-accordion"
2+
import * as React from "react"
3+
4+
import cn from "../clsx"
5+
import { DownOutlined } from "@loft-enterprise/icons"
6+
7+
const Accordion = AccordionPrimitive.Root
8+
9+
const AccordionItem = React.forwardRef<
10+
React.ElementRef<typeof AccordionPrimitive.Item>,
11+
React.ComponentPropsWithoutRef<typeof AccordionPrimitive.Item>
12+
>(({ className, ...props }, ref) => (
13+
<AccordionPrimitive.Item ref={ref} className={className} {...props} />
14+
))
15+
AccordionItem.displayName = "AccordionItem"
16+
17+
const AccordionTrigger = React.forwardRef<
18+
React.ElementRef<typeof AccordionPrimitive.Trigger>,
19+
React.ComponentPropsWithoutRef<typeof AccordionPrimitive.Trigger>
20+
>(({ className, children, ...props }, ref) => (
21+
<AccordionPrimitive.Header>
22+
<AccordionPrimitive.Trigger
23+
ref={ref}
24+
className={cn(
25+
"group/accordion flex cursor-pointer items-center justify-between bg-transparent p-2 transition-all [&[aria-expanded=true]>svg]:rotate-180",
26+
className
27+
)}
28+
{...props}>
29+
{children}
30+
<DownOutlined
31+
className="transition-transform
32+
duration-200 ease-in-out *:size-3 group-aria-[expanded=true]/accordion:rotate-180"
33+
/>
34+
</AccordionPrimitive.Trigger>
35+
</AccordionPrimitive.Header>
36+
))
37+
AccordionTrigger.displayName = AccordionPrimitive.Trigger.displayName
38+
39+
const AccordionContent = React.forwardRef<
40+
React.ElementRef<typeof AccordionPrimitive.Content>,
41+
React.ComponentPropsWithoutRef<typeof AccordionPrimitive.Content>
42+
>(({ className, children, ...props }, ref) => (
43+
<AccordionPrimitive.Content
44+
ref={ref}
45+
className="overflow-hidden transition-all data-[state=closed]:animate-accordion-up data-[state=open]:animate-accordion-down"
46+
{...props}>
47+
<div className={cn("", className)}>{children}</div>
48+
</AccordionPrimitive.Content>
49+
))
50+
AccordionContent.displayName = AccordionPrimitive.Content.displayName
51+
52+
export { Accordion, AccordionItem, AccordionTrigger, AccordionContent }

src/Alert.tsx

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
import React from "react"
2+
3+
import cn from "../clsx"
4+
import { Button, ButtonProps } from "./Button"
5+
import {
6+
BulbOutlined,
7+
ExclamationCircleFilled,
8+
InfoCircleOutlined,
9+
WarningOutlined,
10+
} from "@loft-enterprise/icons"
11+
12+
type Props = {
13+
title?: string
14+
text: string
15+
buttonText?: string
16+
onButtonClick?: () => Promise<void>
17+
linkText?: string
18+
linkUrl?: string
19+
variant?: "info" | "warning" | "error" | "blank"
20+
className?: string
21+
children?: React.ReactNode
22+
icon?: React.ReactNode
23+
}
24+
25+
function Alert({
26+
title,
27+
text,
28+
buttonText,
29+
onButtonClick,
30+
linkText,
31+
linkUrl,
32+
variant = "info",
33+
className,
34+
children,
35+
icon: Icon,
36+
}: Props) {
37+
const icon = {
38+
info: <InfoCircleOutlined />,
39+
warning: <WarningOutlined />,
40+
error: <ExclamationCircleFilled />,
41+
blank: <BulbOutlined />,
42+
}
43+
44+
const buttonChild = React.Children.toArray(children).find(
45+
(child) => React.isValidElement(child) && (child.type as any)?.name === "AlertButton"
46+
) as React.ReactElement | undefined
47+
48+
return (
49+
<div
50+
className={cn("rounded-md border px-3 py-3", className, {
51+
"border-primary-light bg-primary-extra-light": variant === "info",
52+
"border-warning-light bg-warning-extra-light": variant === "warning",
53+
"border-error-light bg-error-extra-light": variant === "error",
54+
"border-neutral-light": variant === "blank",
55+
"flex flex-col gap-2": title,
56+
})}>
57+
<span className="flex flex-row items-center gap-2 [&_svg]:size-4">
58+
{Icon ? Icon : icon[variant]}
59+
{title ? <span className="font-bold">{title}</span> : <span>{text}</span>}
60+
</span>
61+
{title && <span className="text-primary-main text-sm">{text}</span>}
62+
<div className="flex flex-row items-center gap-2">
63+
{buttonText && !buttonChild && (
64+
<Button className="self-start" size="small" onClickAsync={onButtonClick}>
65+
{buttonText}
66+
</Button>
67+
)}
68+
{buttonChild}
69+
{linkText && linkUrl && (
70+
<a href={linkUrl} rel="noreferrer" target="_blank" className="text-xs underline">
71+
<span className="text-primary-main">{linkText}</span>
72+
</a>
73+
)}
74+
</div>
75+
</div>
76+
)
77+
}
78+
79+
function AlertButton({ children, ...props }: ButtonProps) {
80+
return <Button {...props}>{children}</Button>
81+
}
82+
83+
AlertButton.displayName = "AlertButton"
84+
85+
Alert.Button = AlertButton
86+
87+
export { Alert }

0 commit comments

Comments
 (0)