@djangocfg/ui-core 2.1.17 → 2.1.19

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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@djangocfg/ui-core",
3
- "version": "2.1.17",
3
+ "version": "2.1.19",
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.17",
105
+ "@djangocfg/typescript-config": "^2.1.19",
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
- <ResizablePrimitive.PanelGroup
13
- className={cn(
14
- "flex h-full w-full data-[panel-group-direction=vertical]:flex-col",
15
- className
16
- )}
17
- {...props}
18
- />
19
- )
20
-
21
- const ResizablePanel = ResizablePrimitive.Panel
22
-
23
- // Size variants for the handle hit area
24
- const sizeVariants = {
25
- sm: { hitArea: 4, indicator: 4 }, // 4px hit area, 4px indicator height
26
- md: { hitArea: 8, indicator: 8 }, // 8px hit area, 8px indicator height
27
- lg: { hitArea: 12, indicator: 12 }, // 12px hit area, 12px indicator height
28
- } as const
29
-
30
- export interface ResizableHandleProps
31
- extends React.ComponentProps<typeof ResizablePrimitive.PanelResizeHandle> {
32
- /** Show classic dots handle icon */
33
- withHandle?: boolean
34
- /** Size variant - controls hit area and indicator size */
35
- size?: keyof typeof sizeVariants
36
- /** Show visual indicator on hover */
37
- showIndicator?: boolean
38
- /** Custom indicator height in pixels (overrides size variant) */
39
- indicatorHeight?: number
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 variant = sizeVariants[size]
51
- const hitAreaPx = variant.hitArea
52
- const indicatorPx = indicatorHeight ?? variant.indicator * 4 // 32px default for md
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
- "group/resize relative flex items-center justify-center",
58
- "bg-border transition-colors",
59
- "hover:bg-primary/30 active:bg-primary/50",
60
- "focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring focus-visible:ring-offset-1",
61
- // Horizontal (default)
62
- "w-px",
63
- // Vertical
64
- "data-[panel-group-direction=vertical]:h-px data-[panel-group-direction=vertical]:w-full",
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
- {/* Expanded hit area - invisible but clickable */}
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-hover/resize:opacity-100 group-active/resize:bg-primary/50",
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={{ height: indicatorPx }}
152
+ style={{
153
+ height: `${indicatorHeight}px`,
154
+ width: '4px',
155
+ }}
98
156
  />
99
157
  )}
100
158
 
101
- {/* Classic dots handle */}
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" />