@djangocfg/ui-core 2.1.18 → 2.1.20
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/package.json +2 -2
- package/src/components/resizable.tsx +127 -69
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@djangocfg/ui-core",
|
|
3
|
-
"version": "2.1.
|
|
3
|
+
"version": "2.1.20",
|
|
4
4
|
"description": "Pure React UI component library without Next.js dependencies - for Electron, Vite, CRA apps",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"ui-components",
|
|
@@ -102,7 +102,7 @@
|
|
|
102
102
|
"vaul": "1.1.2"
|
|
103
103
|
},
|
|
104
104
|
"devDependencies": {
|
|
105
|
-
"@djangocfg/typescript-config": "^2.1.
|
|
105
|
+
"@djangocfg/typescript-config": "^2.1.20",
|
|
106
106
|
"@types/node": "^24.7.2",
|
|
107
107
|
"@types/react": "^19.1.0",
|
|
108
108
|
"@types/react-dom": "^19.1.0",
|
|
@@ -8,97 +8,155 @@ import { DragHandleDots2Icon } from "@radix-ui/react-icons"
|
|
|
8
8
|
const ResizablePanelGroup = ({
|
|
9
9
|
className,
|
|
10
10
|
...props
|
|
11
|
-
}: React.ComponentProps<typeof ResizablePrimitive.PanelGroup>) =>
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
)
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
11
|
+
}: React.ComponentProps<typeof ResizablePrimitive.PanelGroup>) => {
|
|
12
|
+
const [mounted, setMounted] = React.useState(false)
|
|
13
|
+
|
|
14
|
+
React.useEffect(() => {
|
|
15
|
+
setMounted(true)
|
|
16
|
+
}, [])
|
|
17
|
+
|
|
18
|
+
// SSR fallback - render static flex container
|
|
19
|
+
if (!mounted) {
|
|
20
|
+
return (
|
|
21
|
+
<div
|
|
22
|
+
className={cn(
|
|
23
|
+
"flex h-full w-full data-[panel-group-direction=vertical]:flex-col",
|
|
24
|
+
className
|
|
25
|
+
)}
|
|
26
|
+
>
|
|
27
|
+
{props.children}
|
|
28
|
+
</div>
|
|
29
|
+
)
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
return (
|
|
33
|
+
<ResizablePrimitive.PanelGroup
|
|
34
|
+
className={cn(
|
|
35
|
+
"flex h-full w-full data-[panel-group-direction=vertical]:flex-col",
|
|
36
|
+
className
|
|
37
|
+
)}
|
|
38
|
+
{...props}
|
|
39
|
+
/>
|
|
40
|
+
)
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
const ResizablePanel = React.forwardRef<
|
|
44
|
+
React.ElementRef<typeof ResizablePrimitive.Panel>,
|
|
45
|
+
React.ComponentPropsWithoutRef<typeof ResizablePrimitive.Panel>
|
|
46
|
+
>(({ className, defaultSize, minSize, maxSize, children, ...props }, ref) => {
|
|
47
|
+
const [mounted, setMounted] = React.useState(false)
|
|
48
|
+
|
|
49
|
+
React.useEffect(() => {
|
|
50
|
+
setMounted(true)
|
|
51
|
+
}, [])
|
|
52
|
+
|
|
53
|
+
// SSR fallback - render static div with default size
|
|
54
|
+
if (!mounted) {
|
|
55
|
+
const direction = (props as any)['data-panel-group-direction']
|
|
56
|
+
const sizeStyle = defaultSize
|
|
57
|
+
? direction === 'vertical'
|
|
58
|
+
? { height: `${defaultSize}%` }
|
|
59
|
+
: { width: `${defaultSize}%` }
|
|
60
|
+
: { flex: 1 }
|
|
61
|
+
|
|
62
|
+
return (
|
|
63
|
+
<div className={cn("overflow-hidden", className)} style={sizeStyle}>
|
|
64
|
+
{children}
|
|
65
|
+
</div>
|
|
66
|
+
)
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
return (
|
|
70
|
+
<ResizablePrimitive.Panel
|
|
71
|
+
ref={ref}
|
|
72
|
+
className={className}
|
|
73
|
+
defaultSize={defaultSize}
|
|
74
|
+
minSize={minSize}
|
|
75
|
+
maxSize={maxSize}
|
|
76
|
+
{...props}
|
|
77
|
+
>
|
|
78
|
+
{children}
|
|
79
|
+
</ResizablePrimitive.Panel>
|
|
80
|
+
)
|
|
81
|
+
})
|
|
82
|
+
ResizablePanel.displayName = "ResizablePanel"
|
|
83
|
+
|
|
84
|
+
export interface ResizableHandleProps extends React.ComponentProps<typeof ResizablePrimitive.PanelResizeHandle> {
|
|
85
|
+
withHandle?: boolean;
|
|
86
|
+
size?: 'sm' | 'md' | 'lg';
|
|
87
|
+
showIndicator?: boolean;
|
|
88
|
+
indicatorHeight?: number;
|
|
40
89
|
}
|
|
41
90
|
|
|
42
91
|
const ResizableHandle = ({
|
|
43
92
|
withHandle,
|
|
44
|
-
size = "md",
|
|
45
|
-
showIndicator = true,
|
|
46
|
-
indicatorHeight,
|
|
47
93
|
className,
|
|
94
|
+
size = 'md',
|
|
95
|
+
showIndicator = false,
|
|
96
|
+
indicatorHeight = 32,
|
|
48
97
|
...props
|
|
49
98
|
}: ResizableHandleProps) => {
|
|
50
|
-
const
|
|
51
|
-
|
|
52
|
-
|
|
99
|
+
const [mounted, setMounted] = React.useState(false)
|
|
100
|
+
|
|
101
|
+
React.useEffect(() => {
|
|
102
|
+
setMounted(true)
|
|
103
|
+
}, [])
|
|
104
|
+
|
|
105
|
+
// Size variants for hit area
|
|
106
|
+
const sizeClasses = {
|
|
107
|
+
sm: 'after:w-0.5',
|
|
108
|
+
md: 'after:w-1',
|
|
109
|
+
lg: 'after:w-1.5',
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
// SSR fallback - render static border
|
|
113
|
+
if (!mounted) {
|
|
114
|
+
return (
|
|
115
|
+
<div
|
|
116
|
+
className={cn(
|
|
117
|
+
"bg-border w-px",
|
|
118
|
+
"data-[panel-group-direction=vertical]:h-px data-[panel-group-direction=vertical]:w-full",
|
|
119
|
+
className
|
|
120
|
+
)}
|
|
121
|
+
/>
|
|
122
|
+
)
|
|
123
|
+
}
|
|
53
124
|
|
|
54
125
|
return (
|
|
55
126
|
<ResizablePrimitive.PanelResizeHandle
|
|
56
127
|
className={cn(
|
|
57
|
-
"
|
|
58
|
-
"
|
|
59
|
-
"hover:bg-primary/
|
|
60
|
-
"
|
|
61
|
-
//
|
|
62
|
-
"
|
|
63
|
-
|
|
64
|
-
"data-[panel-group-direction=vertical]:
|
|
128
|
+
"relative flex items-center justify-center bg-border",
|
|
129
|
+
"w-px h-full",
|
|
130
|
+
"hover:bg-primary/20 active:bg-primary/30",
|
|
131
|
+
"transition-colors",
|
|
132
|
+
// Invisible hit area for easier dragging
|
|
133
|
+
"after:absolute after:inset-y-0 after:left-1/2 after:-translate-x-1/2",
|
|
134
|
+
sizeClasses[size],
|
|
135
|
+
"data-[panel-group-direction=vertical]:w-full data-[panel-group-direction=vertical]:h-px",
|
|
136
|
+
"data-[panel-group-direction=vertical]:after:left-0 data-[panel-group-direction=vertical]:after:inset-x-0",
|
|
137
|
+
"data-[panel-group-direction=vertical]:after:top-1/2 data-[panel-group-direction=vertical]:after:-translate-y-1/2",
|
|
138
|
+
"data-[panel-group-direction=vertical]:after:h-0.5 data-[panel-group-direction=vertical]:after:w-full",
|
|
139
|
+
"data-[panel-group-direction=vertical]:after:translate-x-0",
|
|
140
|
+
"focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring",
|
|
65
141
|
className
|
|
66
142
|
)}
|
|
67
|
-
style={{
|
|
68
|
-
// Expand hit area without changing visual width
|
|
69
|
-
// Using padding to increase clickable area
|
|
70
|
-
}}
|
|
71
143
|
{...props}
|
|
72
144
|
>
|
|
73
|
-
{/*
|
|
74
|
-
<div
|
|
75
|
-
className={cn(
|
|
76
|
-
"absolute inset-y-0 cursor-ew-resize z-10",
|
|
77
|
-
"data-[panel-group-direction=vertical]:inset-x-0 data-[panel-group-direction=vertical]:inset-y-auto",
|
|
78
|
-
"data-[panel-group-direction=vertical]:cursor-ns-resize"
|
|
79
|
-
)}
|
|
80
|
-
style={{
|
|
81
|
-
left: -hitAreaPx / 2,
|
|
82
|
-
right: -hitAreaPx / 2,
|
|
83
|
-
}}
|
|
84
|
-
/>
|
|
85
|
-
|
|
86
|
-
{/* Visual indicator - appears on hover */}
|
|
145
|
+
{/* Optional pill indicator */}
|
|
87
146
|
{showIndicator && (
|
|
88
147
|
<div
|
|
89
148
|
className={cn(
|
|
90
|
-
"absolute rounded-full bg-border opacity-0 transition-opacity",
|
|
91
|
-
"group-
|
|
92
|
-
// Horizontal
|
|
93
|
-
"left-1/2 top-1/2 -translate-x-1/2 -translate-y-1/2 w-1",
|
|
94
|
-
// Vertical
|
|
95
|
-
"data-[panel-group-direction=vertical]:w-auto data-[panel-group-direction=vertical]:h-1",
|
|
149
|
+
"absolute z-10 rounded-full bg-border opacity-0 hover:opacity-100 transition-opacity",
|
|
150
|
+
"w-1 data-[panel-group-direction=vertical]:w-auto data-[panel-group-direction=vertical]:h-1"
|
|
96
151
|
)}
|
|
97
|
-
style={{
|
|
152
|
+
style={{
|
|
153
|
+
height: `${indicatorHeight}px`,
|
|
154
|
+
width: '4px',
|
|
155
|
+
}}
|
|
98
156
|
/>
|
|
99
157
|
)}
|
|
100
158
|
|
|
101
|
-
{/*
|
|
159
|
+
{/* Optional dots handle */}
|
|
102
160
|
{withHandle && (
|
|
103
161
|
<div className="z-10 flex h-4 w-3 items-center justify-center rounded-sm border bg-border">
|
|
104
162
|
<DragHandleDots2Icon className="h-2.5 w-2.5" />
|