react-edge-dock 1.0.3 → 1.0.5

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/README.md CHANGED
@@ -65,7 +65,7 @@ export default function MyComponent() {
65
65
  - `dockMode`: `"free"` | `"auto"` | `"manual"` - Docking behavior
66
66
  - `dockEdge`: `"left"` | `"right"` | `"top"` | `"bottom"` - Fixed edge (manual mode)
67
67
  - `allowedEdges`: `DockEdge[]` - Restrict docking to specific edges (e.g., `['left', 'right']` for horizontal only)
68
- - `edgeOffset`: `number` - Gap from screen edge in pixels (default: 0)
68
+ - `edgeOffset`: `number | { left?: number; right?: number; top?: number; bottom?: number }` - Gap from edges in pixels
69
69
  - `animation`: `boolean` - Enable snap animations
70
70
  - `popupGap`: `number` - Gap between button and popup
71
71
  - `position`: `{ x: number; y: number }` - Initial/controlled position
@@ -75,13 +75,33 @@ export default function MyComponent() {
75
75
 
76
76
  ## Examples
77
77
 
78
+ ### Same offset for all edges
79
+
80
+ ```tsx
81
+ <EdgeDock
82
+ dockMode="auto"
83
+ edgeOffset={16}
84
+ button={<button>🚀</button>}
85
+ />
86
+ ```
87
+
88
+ ### Different offset for each edge
89
+
90
+ ```tsx
91
+ <EdgeDock
92
+ dockMode="auto"
93
+ edgeOffset={{ left: 10, right: 20, top: 15, bottom: 25 }}
94
+ button={<button>🎯</button>}
95
+ />
96
+ ```
97
+
78
98
  ### Restrict to horizontal edges only (left/right)
79
99
 
80
100
  ```tsx
81
101
  <EdgeDock
82
102
  dockMode="auto"
83
103
  allowedEdges={['left', 'right']}
84
- edgeOffset={16}
104
+ edgeOffset={{ left: 16, right: 24 }}
85
105
  button={<button>📱</button>}
86
106
  />
87
107
  ```
@@ -102,7 +122,7 @@ export default function MyComponent() {
102
122
  <EdgeDock
103
123
  dockMode="manual"
104
124
  dockEdge="right"
105
- edgeOffset={20}
125
+ edgeOffset={{ right: 20 }}
106
126
  button={<button>➡️</button>}
107
127
  />
108
128
  ```
package/dist/types.d.ts CHANGED
@@ -27,6 +27,15 @@ export interface DockState {
27
27
  /** Whether the popup is currently open */
28
28
  isPopupOpen: boolean;
29
29
  }
30
+ /**
31
+ * Edge offset configuration - can be a single number for all edges or individual values
32
+ */
33
+ export type EdgeOffset = number | {
34
+ left?: number;
35
+ right?: number;
36
+ top?: number;
37
+ bottom?: number;
38
+ };
30
39
  /**
31
40
  * Configuration for EdgeDock component
32
41
  */
@@ -43,8 +52,8 @@ export interface EdgeDockConfig {
43
52
  animation?: boolean;
44
53
  /** Gap between button and popup in pixels */
45
54
  popupGap?: number;
46
- /** Offset from edge when docked (in pixels) */
47
- edgeOffset?: number;
55
+ /** Offset from edge when docked - number for all edges or object for individual edges */
56
+ edgeOffset?: EdgeOffset;
48
57
  /** z-index for the dock container */
49
58
  zIndex?: number;
50
59
  /** Callback when dock state changes */
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"useEdgeDock.d.ts","sourceRoot":"","sources":["../src/useEdgeDock.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,cAAc,EAId,iBAAiB,EAGlB,MAAM,SAAS,CAAC;AAwKjB;;GAEG;AACH,wBAAgB,WAAW,CAAC,MAAM,GAAE,cAAmB,GAAG,iBAAiB,CAgV1E"}
1
+ {"version":3,"file":"useEdgeDock.d.ts","sourceRoot":"","sources":["../src/useEdgeDock.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,cAAc,EAId,iBAAiB,EAIlB,MAAM,SAAS,CAAC;AAwLjB;;GAEG;AACH,wBAAgB,WAAW,CAAC,MAAM,GAAE,cAAmB,GAAG,iBAAiB,CAgV1E"}
@@ -12,6 +12,16 @@ function getViewport() {
12
12
  }
13
13
  return { width: window.innerWidth, height: window.innerHeight };
14
14
  }
15
+ /**
16
+ * Get offset value for a specific edge
17
+ */
18
+ function getOffsetForEdge(edgeOffset, edge) {
19
+ if (!edgeOffset)
20
+ return 0;
21
+ if (typeof edgeOffset === 'number')
22
+ return edgeOffset;
23
+ return edgeOffset[edge] ?? 0;
24
+ }
15
25
  /**
16
26
  * Calculate which edge is closest to the given position
17
27
  */
@@ -38,9 +48,10 @@ function getClosestEdge(pos, viewport, allowedEdges) {
38
48
  /**
39
49
  * Snap position to edge based on dock mode
40
50
  */
41
- function snapToEdge(pos, edge, viewport, buttonDimensions, offset = 0) {
51
+ function snapToEdge(pos, edge, viewport, buttonDimensions, edgeOffset) {
42
52
  const halfWidth = buttonDimensions.width / 2;
43
53
  const halfHeight = buttonDimensions.height / 2;
54
+ const offset = getOffsetForEdge(edgeOffset, edge);
44
55
  switch (edge) {
45
56
  case 'left':
46
57
  return {
@@ -65,14 +76,18 @@ function snapToEdge(pos, edge, viewport, buttonDimensions, offset = 0) {
65
76
  }
66
77
  }
67
78
  /**
68
- * Constrain position within viewport bounds
79
+ * Constrain position within viewport bounds, respecting edge offsets
69
80
  */
70
- function constrainToViewport(pos, viewport, buttonDimensions) {
81
+ function constrainToViewport(pos, viewport, buttonDimensions, edgeOffset) {
71
82
  const halfWidth = buttonDimensions.width / 2;
72
83
  const halfHeight = buttonDimensions.height / 2;
84
+ const leftOffset = getOffsetForEdge(edgeOffset, 'left');
85
+ const rightOffset = getOffsetForEdge(edgeOffset, 'right');
86
+ const topOffset = getOffsetForEdge(edgeOffset, 'top');
87
+ const bottomOffset = getOffsetForEdge(edgeOffset, 'bottom');
73
88
  return {
74
- x: Math.max(halfWidth, Math.min(viewport.width - halfWidth, pos.x)),
75
- y: Math.max(halfHeight, Math.min(viewport.height - halfHeight, pos.y)),
89
+ x: Math.max(halfWidth + leftOffset, Math.min(viewport.width - halfWidth - rightOffset, pos.x)),
90
+ y: Math.max(halfHeight + topOffset, Math.min(viewport.height - halfHeight - bottomOffset, pos.y)),
76
91
  };
77
92
  }
78
93
  /**
@@ -128,7 +143,7 @@ function calculatePopupPosition(buttonPos, buttonDimensions, popupDimensions, vi
128
143
  * Main hook for edge dock functionality
129
144
  */
130
145
  export function useEdgeDock(config = {}) {
131
- const { dockMode = 'auto', dockEdge, allowedEdges, position: controlledPosition, animation = true, popupGap = 12, edgeOffset = 0, zIndex = 9999, onDockChange, isPopupOpen: controlledPopupOpen, onPopupChange, } = config;
146
+ const { dockMode = 'auto', dockEdge, allowedEdges, position: controlledPosition, animation = true, popupGap = 12, edgeOffset, zIndex = 9999, onDockChange, isPopupOpen: controlledPopupOpen, onPopupChange, } = config;
132
147
  const buttonRef = useRef(null);
133
148
  const popupRef = useRef(null);
134
149
  const isMountedRef = useRef(false);
@@ -167,7 +182,7 @@ export function useEdgeDock(config = {}) {
167
182
  const buttonDimensions = { width: buttonRect.width, height: buttonRect.height };
168
183
  // Set initial position on client after mount
169
184
  let initialPos = { x: viewport.width - 60, y: viewport.height - 60 };
170
- initialPos = constrainToViewport(initialPos, viewport, buttonDimensions);
185
+ initialPos = constrainToViewport(initialPos, viewport, buttonDimensions, edgeOffset);
171
186
  if (dockMode === 'auto') {
172
187
  const edge = getClosestEdge(initialPos, viewport, allowedEdges);
173
188
  initialPos = snapToEdge(initialPos, edge, viewport, buttonDimensions, edgeOffset);
@@ -209,7 +224,7 @@ export function useEdgeDock(config = {}) {
209
224
  const buttonRect = buttonRef.current.getBoundingClientRect();
210
225
  const viewport = getViewport();
211
226
  const buttonDimensions = { width: buttonRect.width, height: buttonRect.height };
212
- let finalPos = constrainToViewport(newPos, viewport, buttonDimensions);
227
+ let finalPos = constrainToViewport(newPos, viewport, buttonDimensions, edgeOffset);
213
228
  if (dockMode === 'auto') {
214
229
  const edge = getClosestEdge(finalPos, viewport, allowedEdges);
215
230
  finalPos = snapToEdge(finalPos, edge, viewport, buttonDimensions, edgeOffset);
@@ -286,7 +301,7 @@ export function useEdgeDock(config = {}) {
286
301
  const viewport = { width: window.innerWidth, height: window.innerHeight };
287
302
  const buttonDimensions = { width: buttonRect.width, height: buttonRect.height };
288
303
  // During drag, only constrain to viewport (no snapping)
289
- const constrainedPos = constrainToViewport(newPos, viewport, buttonDimensions);
304
+ const constrainedPos = constrainToViewport(newPos, viewport, buttonDimensions, edgeOffset);
290
305
  setPositionInternal(constrainedPos);
291
306
  };
292
307
  const handlePointerUp = () => {
@@ -341,7 +356,7 @@ export function useEdgeDock(config = {}) {
341
356
  const buttonRect = buttonRef.current.getBoundingClientRect();
342
357
  const viewport = getViewport();
343
358
  const buttonDimensions = { width: buttonRect.width, height: buttonRect.height };
344
- let newPos = constrainToViewport(position, viewport, buttonDimensions);
359
+ let newPos = constrainToViewport(position, viewport, buttonDimensions, edgeOffset);
345
360
  if (dockMode === 'auto') {
346
361
  const edge = getClosestEdge(newPos, viewport, allowedEdges);
347
362
  newPos = snapToEdge(newPos, edge, viewport, buttonDimensions, edgeOffset);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "react-edge-dock",
3
- "version": "1.0.3",
3
+ "version": "1.0.5",
4
4
  "description": "A zero-dependency React TypeScript library for customizable draggable edge-docked floating buttons with popup support",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.esm.js",