@optilogic/core 1.0.0-beta.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/LICENSE +21 -0
- package/README.md +107 -0
- package/dist/index.cjs +6003 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +2310 -0
- package/dist/index.d.ts +2310 -0
- package/dist/index.js +5828 -0
- package/dist/index.js.map +1 -0
- package/dist/styles.css +96 -0
- package/dist/tailwind-preset.cjs +106 -0
- package/dist/tailwind-preset.cjs.map +1 -0
- package/dist/tailwind-preset.d.cts +23 -0
- package/dist/tailwind-preset.d.ts +23 -0
- package/dist/tailwind-preset.js +101 -0
- package/dist/tailwind-preset.js.map +1 -0
- package/package.json +154 -0
- package/src/components/accordion.tsx +187 -0
- package/src/components/alert-dialog.tsx +143 -0
- package/src/components/autocomplete.tsx +271 -0
- package/src/components/badge.tsx +62 -0
- package/src/components/button.tsx +85 -0
- package/src/components/calendar.tsx +235 -0
- package/src/components/card.tsx +94 -0
- package/src/components/checkbox.tsx +77 -0
- package/src/components/chip.tsx +77 -0
- package/src/components/confirmation-modal.tsx +195 -0
- package/src/components/context-menu.tsx +406 -0
- package/src/components/copy-button.tsx +84 -0
- package/src/components/data-grid/DataGrid.tsx +1027 -0
- package/src/components/data-grid/components/CellEditor.tsx +346 -0
- package/src/components/data-grid/components/FilterPopover.tsx +459 -0
- package/src/components/data-grid/components/HeaderCell.tsx +207 -0
- package/src/components/data-grid/components/index.ts +14 -0
- package/src/components/data-grid/hooks/index.ts +28 -0
- package/src/components/data-grid/hooks/useColumnResize.ts +378 -0
- package/src/components/data-grid/hooks/useDataGridState.ts +346 -0
- package/src/components/data-grid/hooks/useKeyboardNavigation.ts +361 -0
- package/src/components/data-grid/index.ts +71 -0
- package/src/components/data-grid/types.ts +478 -0
- package/src/components/data-grid/utils/dataProcessing.ts +277 -0
- package/src/components/data-grid/utils/index.ts +12 -0
- package/src/components/date-picker.tsx +366 -0
- package/src/components/dropdown-menu.tsx +230 -0
- package/src/components/icon-button.tsx +157 -0
- package/src/components/input.tsx +40 -0
- package/src/components/label.tsx +37 -0
- package/src/components/loading-spinner.tsx +113 -0
- package/src/components/modal.tsx +207 -0
- package/src/components/popover.tsx +62 -0
- package/src/components/progress.tsx +41 -0
- package/src/components/resizable-panel.tsx +434 -0
- package/src/components/resize-handle.tsx +187 -0
- package/src/components/select.tsx +160 -0
- package/src/components/separator.tsx +50 -0
- package/src/components/skeleton.tsx +37 -0
- package/src/components/switch.tsx +59 -0
- package/src/components/table.tsx +136 -0
- package/src/components/tabs.tsx +102 -0
- package/src/components/textarea.tsx +36 -0
- package/src/components/theme-picker.tsx +245 -0
- package/src/components/toaster.tsx +84 -0
- package/src/components/tooltip.tsx +199 -0
- package/src/index.ts +318 -0
- package/src/styles.css +96 -0
- package/src/tailwind-preset.ts +129 -0
- package/src/theme/index.ts +41 -0
- package/src/theme/presets.ts +502 -0
- package/src/theme/types.ts +164 -0
- package/src/theme/utils.ts +309 -0
- package/src/utils/cn.ts +14 -0
|
@@ -0,0 +1,207 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
import { X } from "lucide-react";
|
|
3
|
+
|
|
4
|
+
import { cn } from "../utils/cn";
|
|
5
|
+
import { Button, type ButtonProps } from "./button";
|
|
6
|
+
|
|
7
|
+
export interface ModalProps {
|
|
8
|
+
/**
|
|
9
|
+
* Whether the modal is open
|
|
10
|
+
*/
|
|
11
|
+
isOpen: boolean;
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Callback when modal should close
|
|
15
|
+
*/
|
|
16
|
+
onClose: () => void;
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Modal title
|
|
20
|
+
*/
|
|
21
|
+
title: string;
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Modal content
|
|
25
|
+
*/
|
|
26
|
+
children: React.ReactNode;
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Footer content (buttons, actions, etc.)
|
|
30
|
+
*/
|
|
31
|
+
footer?: React.ReactNode;
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Size variant
|
|
35
|
+
*/
|
|
36
|
+
size?: "sm" | "md" | "lg";
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Z-index for stacking modals (default: 50)
|
|
40
|
+
*/
|
|
41
|
+
zIndex?: number;
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Additional class names for modal content
|
|
45
|
+
*/
|
|
46
|
+
className?: string;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Modal component
|
|
51
|
+
*
|
|
52
|
+
* Extensible modal base for dialogs, confirmations, and forms.
|
|
53
|
+
* Features:
|
|
54
|
+
* - Backdrop overlay
|
|
55
|
+
* - Escape key to close
|
|
56
|
+
* - Click outside to close
|
|
57
|
+
* - Customizable footer with action buttons
|
|
58
|
+
* - Multiple size variants
|
|
59
|
+
*
|
|
60
|
+
* @example
|
|
61
|
+
* <Modal isOpen={open} onClose={() => setOpen(false)} title="Confirm">
|
|
62
|
+
* <p>Are you sure?</p>
|
|
63
|
+
* <footer slot="footer">
|
|
64
|
+
* <Button onClick={() => setOpen(false)}>Cancel</Button>
|
|
65
|
+
* <Button variant="primary" onClick={handleConfirm}>Confirm</Button>
|
|
66
|
+
* </footer>
|
|
67
|
+
* </Modal>
|
|
68
|
+
*/
|
|
69
|
+
export function Modal({
|
|
70
|
+
isOpen,
|
|
71
|
+
onClose,
|
|
72
|
+
title,
|
|
73
|
+
children,
|
|
74
|
+
footer,
|
|
75
|
+
size = "md",
|
|
76
|
+
zIndex = 50,
|
|
77
|
+
className,
|
|
78
|
+
}: ModalProps) {
|
|
79
|
+
React.useEffect(() => {
|
|
80
|
+
if (!isOpen) return;
|
|
81
|
+
|
|
82
|
+
const handleEscape = (e: KeyboardEvent) => {
|
|
83
|
+
if (e.key === "Escape") {
|
|
84
|
+
onClose();
|
|
85
|
+
}
|
|
86
|
+
};
|
|
87
|
+
|
|
88
|
+
window.addEventListener("keydown", handleEscape);
|
|
89
|
+
return () => window.removeEventListener("keydown", handleEscape);
|
|
90
|
+
}, [isOpen, onClose]);
|
|
91
|
+
|
|
92
|
+
React.useEffect(() => {
|
|
93
|
+
if (isOpen) {
|
|
94
|
+
document.body.style.overflow = "hidden";
|
|
95
|
+
} else {
|
|
96
|
+
document.body.style.overflow = "";
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
return () => {
|
|
100
|
+
document.body.style.overflow = "";
|
|
101
|
+
};
|
|
102
|
+
}, [isOpen]);
|
|
103
|
+
|
|
104
|
+
if (!isOpen) return null;
|
|
105
|
+
|
|
106
|
+
const sizeClasses = {
|
|
107
|
+
sm: "max-w-md",
|
|
108
|
+
md: "max-w-lg",
|
|
109
|
+
lg: "max-w-2xl",
|
|
110
|
+
};
|
|
111
|
+
|
|
112
|
+
return (
|
|
113
|
+
<div
|
|
114
|
+
className="fixed inset-0 flex items-center justify-center p-4"
|
|
115
|
+
style={{ zIndex }}
|
|
116
|
+
onClick={onClose}
|
|
117
|
+
>
|
|
118
|
+
<div className="absolute inset-0 bg-background/80 backdrop-blur-sm" />
|
|
119
|
+
|
|
120
|
+
<div
|
|
121
|
+
className={cn(
|
|
122
|
+
"relative w-full",
|
|
123
|
+
"bg-card border border-border rounded-lg shadow-lg",
|
|
124
|
+
"flex flex-col",
|
|
125
|
+
"max-h-[90vh]",
|
|
126
|
+
sizeClasses[size]
|
|
127
|
+
)}
|
|
128
|
+
onClick={(e) => e.stopPropagation()}
|
|
129
|
+
>
|
|
130
|
+
<div className="flex items-center justify-between p-4 border-b border-border flex-shrink-0">
|
|
131
|
+
<h2 className="text-lg font-semibold text-foreground">{title}</h2>
|
|
132
|
+
<Button
|
|
133
|
+
onClick={onClose}
|
|
134
|
+
variant="ghost"
|
|
135
|
+
size="icon"
|
|
136
|
+
className="h-8 w-8"
|
|
137
|
+
aria-label="Close modal"
|
|
138
|
+
>
|
|
139
|
+
<X className="w-4 h-4" />
|
|
140
|
+
</Button>
|
|
141
|
+
</div>
|
|
142
|
+
|
|
143
|
+
<div className={cn("flex-1 overflow-y-auto p-4", className)}>
|
|
144
|
+
{children}
|
|
145
|
+
</div>
|
|
146
|
+
|
|
147
|
+
{footer && (
|
|
148
|
+
<div className="flex items-center justify-end gap-2 p-4 border-t border-border flex-shrink-0">
|
|
149
|
+
{footer}
|
|
150
|
+
</div>
|
|
151
|
+
)}
|
|
152
|
+
</div>
|
|
153
|
+
</div>
|
|
154
|
+
);
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
/**
|
|
158
|
+
* ModalButton component
|
|
159
|
+
* @deprecated Use Button component from @optilogic/core instead
|
|
160
|
+
*
|
|
161
|
+
* Wrapper around Button for backward compatibility
|
|
162
|
+
*/
|
|
163
|
+
export interface ModalButtonProps {
|
|
164
|
+
/**
|
|
165
|
+
* Button label
|
|
166
|
+
*/
|
|
167
|
+
label: string;
|
|
168
|
+
|
|
169
|
+
/**
|
|
170
|
+
* Click handler
|
|
171
|
+
*/
|
|
172
|
+
onClick: () => void;
|
|
173
|
+
|
|
174
|
+
/**
|
|
175
|
+
* Button variant
|
|
176
|
+
*/
|
|
177
|
+
variant?: "default" | "primary" | "destructive";
|
|
178
|
+
|
|
179
|
+
/**
|
|
180
|
+
* Whether the button is disabled
|
|
181
|
+
*/
|
|
182
|
+
disabled?: boolean;
|
|
183
|
+
|
|
184
|
+
/**
|
|
185
|
+
* Additional class names
|
|
186
|
+
*/
|
|
187
|
+
className?: string;
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
export function ModalButton({
|
|
191
|
+
label,
|
|
192
|
+
onClick,
|
|
193
|
+
variant = "default",
|
|
194
|
+
disabled = false,
|
|
195
|
+
className,
|
|
196
|
+
}: ModalButtonProps) {
|
|
197
|
+
return (
|
|
198
|
+
<Button
|
|
199
|
+
onClick={onClick}
|
|
200
|
+
disabled={disabled}
|
|
201
|
+
variant={variant}
|
|
202
|
+
className={className}
|
|
203
|
+
>
|
|
204
|
+
{label}
|
|
205
|
+
</Button>
|
|
206
|
+
);
|
|
207
|
+
}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
import * as PopoverPrimitive from "@radix-ui/react-popover";
|
|
3
|
+
|
|
4
|
+
import { cn } from "../utils/cn";
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Popover - Root component for popover behavior
|
|
8
|
+
*/
|
|
9
|
+
const Popover = PopoverPrimitive.Root;
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* PopoverTrigger - Element that triggers the popover
|
|
13
|
+
*/
|
|
14
|
+
const PopoverTrigger = PopoverPrimitive.Trigger;
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* PopoverAnchor - Custom anchor element for positioning
|
|
18
|
+
*/
|
|
19
|
+
const PopoverAnchor = PopoverPrimitive.Anchor;
|
|
20
|
+
|
|
21
|
+
export interface PopoverContentProps
|
|
22
|
+
extends React.ComponentPropsWithoutRef<typeof PopoverPrimitive.Content> {}
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* PopoverContent - The popover content panel
|
|
26
|
+
*
|
|
27
|
+
* @example
|
|
28
|
+
* <Popover>
|
|
29
|
+
* <PopoverTrigger asChild>
|
|
30
|
+
* <Button>Open</Button>
|
|
31
|
+
* </PopoverTrigger>
|
|
32
|
+
* <PopoverContent>
|
|
33
|
+
* <p>Popover content here</p>
|
|
34
|
+
* </PopoverContent>
|
|
35
|
+
* </Popover>
|
|
36
|
+
*/
|
|
37
|
+
const PopoverContent = React.forwardRef<
|
|
38
|
+
React.ElementRef<typeof PopoverPrimitive.Content>,
|
|
39
|
+
PopoverContentProps
|
|
40
|
+
>(({ className, align = "center", sideOffset = 4, ...props }, ref) => (
|
|
41
|
+
<PopoverPrimitive.Portal>
|
|
42
|
+
<PopoverPrimitive.Content
|
|
43
|
+
ref={ref}
|
|
44
|
+
align={align}
|
|
45
|
+
sideOffset={sideOffset}
|
|
46
|
+
className={cn(
|
|
47
|
+
"z-50 w-72 rounded-md border border-border bg-popover p-4 text-popover-foreground shadow-md outline-none",
|
|
48
|
+
// Animation
|
|
49
|
+
"data-[state=open]:animate-in data-[state=closed]:animate-out",
|
|
50
|
+
"data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0",
|
|
51
|
+
"data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95",
|
|
52
|
+
"data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2",
|
|
53
|
+
"data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2",
|
|
54
|
+
className
|
|
55
|
+
)}
|
|
56
|
+
{...props}
|
|
57
|
+
/>
|
|
58
|
+
</PopoverPrimitive.Portal>
|
|
59
|
+
));
|
|
60
|
+
PopoverContent.displayName = PopoverPrimitive.Content.displayName;
|
|
61
|
+
|
|
62
|
+
export { Popover, PopoverTrigger, PopoverContent, PopoverAnchor };
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
import * as ProgressPrimitive from "@radix-ui/react-progress";
|
|
3
|
+
|
|
4
|
+
import { cn } from "../utils/cn";
|
|
5
|
+
|
|
6
|
+
export interface ProgressProps
|
|
7
|
+
extends React.ComponentPropsWithoutRef<typeof ProgressPrimitive.Root> {}
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Progress Component
|
|
11
|
+
*
|
|
12
|
+
* A progress bar showing completion percentage.
|
|
13
|
+
* Use for loading states, file uploads, or task progress.
|
|
14
|
+
*
|
|
15
|
+
* @example
|
|
16
|
+
* <Progress value={50} />
|
|
17
|
+
*
|
|
18
|
+
* @example
|
|
19
|
+
* <Progress value={progress} className="w-[60%]" />
|
|
20
|
+
*/
|
|
21
|
+
const Progress = React.forwardRef<
|
|
22
|
+
React.ElementRef<typeof ProgressPrimitive.Root>,
|
|
23
|
+
ProgressProps
|
|
24
|
+
>(({ className, value, ...props }, ref) => (
|
|
25
|
+
<ProgressPrimitive.Root
|
|
26
|
+
ref={ref}
|
|
27
|
+
className={cn(
|
|
28
|
+
"relative h-2 w-full overflow-hidden rounded-full bg-primary/20",
|
|
29
|
+
className
|
|
30
|
+
)}
|
|
31
|
+
{...props}
|
|
32
|
+
>
|
|
33
|
+
<ProgressPrimitive.Indicator
|
|
34
|
+
className="h-full w-full flex-1 bg-primary transition-all"
|
|
35
|
+
style={{ transform: `translateX(-${100 - (value || 0)}%)` }}
|
|
36
|
+
/>
|
|
37
|
+
</ProgressPrimitive.Root>
|
|
38
|
+
));
|
|
39
|
+
Progress.displayName = ProgressPrimitive.Root.displayName;
|
|
40
|
+
|
|
41
|
+
export { Progress };
|