react-edge-dock 1.0.9 → 1.0.11

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 CHANGED
@@ -1,6 +1,6 @@
1
1
  MIT License
2
2
 
3
- Copyright (c) 2026 [Your Name]
3
+ Copyright (c) 2026 Shivam Patel
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  of this software and associated documentation files (the "Software"), to deal
@@ -1 +1 @@
1
- {"version":3,"file":"EdgeDock.d.ts","sourceRoot":"","sources":["../src/EdgeDock.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAE7C;;;;;;;;;;;;GAYG;AACH,wBAAgB,QAAQ,CAAC,KAAK,EAAE,aAAa,qBAsF5C"}
1
+ {"version":3,"file":"EdgeDock.d.ts","sourceRoot":"","sources":["../src/EdgeDock.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAE7C;;;;;;;;;;;;GAYG;AACH,wBAAgB,QAAQ,CAAC,KAAK,EAAE,aAAa,qBAwF5C"}
package/dist/EdgeDock.js CHANGED
@@ -14,7 +14,7 @@ import { useEdgeDock } from './useEdgeDock';
14
14
  * ```
15
15
  */
16
16
  export function EdgeDock(props) {
17
- const { button, popup, className, style, dockMode, dockEdge, allowedEdges, position, animation, popupGap, edgeOffset, zIndex, onDockChange, isPopupOpen, onPopupChange, } = props;
17
+ const { button, popup, className, style, dockMode, dockEdge, allowedEdges, position, animation, popupGap, edgeOffset, zIndex, onDockChange, isPopupOpen, onPopupChange, draggable, } = props;
18
18
  const { state, buttonRef, popupRef, closePopup, buttonStyles, popupStyles, buttonProps, } = useEdgeDock({
19
19
  dockMode,
20
20
  dockEdge,
@@ -27,6 +27,7 @@ export function EdgeDock(props) {
27
27
  onDockChange,
28
28
  isPopupOpen,
29
29
  onPopupChange,
30
+ draggable,
30
31
  });
31
32
  // Render button content
32
33
  const renderButton = () => {
package/dist/types.d.ts CHANGED
@@ -62,7 +62,34 @@ export interface EdgeDockConfig {
62
62
  isPopupOpen?: boolean;
63
63
  /** Callback when popup state changes */
64
64
  onPopupChange?: (isOpen: boolean) => void;
65
+ /** Whether the button is draggable. Defaults to true. */
66
+ draggable?: boolean;
67
+ /**
68
+ * Sticky position configuration for non-draggable mode.
69
+ * Can be a single position, an array of positions (for responsive),
70
+ * or an object with named breakpoints.
71
+ */
72
+ sticky?: StickyConfig;
65
73
  }
74
+ /**
75
+ * Sticky position coordinates.
76
+ * Values can be numbers (pixels) or strings (percentage/css units).
77
+ */
78
+ export interface StickyPosition {
79
+ top?: number | string;
80
+ bottom?: number | string;
81
+ left?: number | string;
82
+ right?: number | string;
83
+ }
84
+ /**
85
+ * Sticky configuration supporting responsive breakpoints.
86
+ */
87
+ export type StickyConfig = StickyPosition | StickyPosition[] | {
88
+ mobile?: StickyPosition;
89
+ tablet?: StickyPosition;
90
+ desktop?: StickyPosition;
91
+ largeDesktop?: StickyPosition;
92
+ };
66
93
  /**
67
94
  * Props for EdgeDock component
68
95
  */
@@ -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,EAIlB,MAAM,SAAS,CAAC;AAwLjB;;GAEG;AACH,wBAAgB,WAAW,CAAC,MAAM,GAAE,cAAmB,GAAG,iBAAiB,CA8W1E"}
1
+ {"version":3,"file":"useEdgeDock.d.ts","sourceRoot":"","sources":["../src/useEdgeDock.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,cAAc,EAId,iBAAiB,EAMlB,MAAM,SAAS,CAAC;AAuQjB;;GAEG;AACH,wBAAgB,WAAW,CAAC,MAAM,GAAE,cAAmB,GAAG,iBAAiB,CAsa1E"}
@@ -139,11 +139,81 @@ function calculatePopupPosition(buttonPos, buttonDimensions, popupDimensions, vi
139
139
  origin,
140
140
  };
141
141
  }
142
+ /**
143
+ * Resolve sticky position based on viewport width
144
+ */
145
+ function resolveStickyConfig(config, viewportWidth) {
146
+ if (!config)
147
+ return undefined;
148
+ // Single position object
149
+ if ('top' in config || 'bottom' in config || 'left' in config || 'right' in config) {
150
+ return config;
151
+ }
152
+ // Array format: [mobile, tablet, desktop, largeDesktop]
153
+ if (Array.isArray(config)) {
154
+ if (viewportWidth < 768)
155
+ return config[0];
156
+ if (viewportWidth < 1024)
157
+ return config[1] ?? config[0];
158
+ if (viewportWidth < 1440)
159
+ return config[2] ?? config[1] ?? config[0];
160
+ return config[3] ?? config[2] ?? config[1] ?? config[0];
161
+ }
162
+ // Object format with named breakpoints
163
+ const breakpoints = config;
164
+ if (viewportWidth < 768)
165
+ return breakpoints.mobile;
166
+ if (viewportWidth < 1024)
167
+ return breakpoints.tablet ?? breakpoints.mobile;
168
+ if (viewportWidth < 1440)
169
+ return breakpoints.desktop ?? breakpoints.tablet ?? breakpoints.mobile;
170
+ return breakpoints.largeDesktop ?? breakpoints.desktop ?? breakpoints.tablet ?? breakpoints.mobile;
171
+ }
172
+ /**
173
+ * Calculate absolute coordinates from sticky position
174
+ */
175
+ function calculateStickyCoordinates(stickyPos, viewport) {
176
+ let x = 0;
177
+ let y = 0;
178
+ // Helper to resolve value (number or percentage string)
179
+ const resolveVal = (val, dimension) => {
180
+ if (typeof val === 'number')
181
+ return val;
182
+ if (typeof val === 'string' && val.endsWith('%')) {
183
+ return (parseFloat(val) / 100) * dimension;
184
+ }
185
+ return parseFloat(val) || 0;
186
+ };
187
+ // Horizontal
188
+ if (stickyPos.left !== undefined) {
189
+ x = resolveVal(stickyPos.left, viewport.width);
190
+ }
191
+ else if (stickyPos.right !== undefined) {
192
+ x = viewport.width - resolveVal(stickyPos.right, viewport.width);
193
+ }
194
+ else {
195
+ // Default to center if neither specified? Or default to checking dockMode...
196
+ // For sticky, let's assume if omitted, it stays current or 0.
197
+ // But returning 0 might jump. Let's assume left: 0 if nothing.
198
+ x = 0;
199
+ }
200
+ // Vertical
201
+ if (stickyPos.top !== undefined) {
202
+ y = resolveVal(stickyPos.top, viewport.height);
203
+ }
204
+ else if (stickyPos.bottom !== undefined) {
205
+ y = viewport.height - resolveVal(stickyPos.bottom, viewport.height);
206
+ }
207
+ else {
208
+ y = 0;
209
+ }
210
+ return { x, y };
211
+ }
142
212
  /**
143
213
  * Main hook for edge dock functionality
144
214
  */
145
215
  export function useEdgeDock(config = {}) {
146
- const { dockMode = 'auto', dockEdge, allowedEdges, position: controlledPosition, animation = true, popupGap = 12, edgeOffset, zIndex = 9999, onDockChange, isPopupOpen: controlledPopupOpen, onPopupChange, } = config;
216
+ const { dockMode = 'auto', dockEdge, allowedEdges, position: controlledPosition, animation = true, popupGap = 12, edgeOffset, zIndex = 9999, onDockChange, isPopupOpen: controlledPopupOpen, onPopupChange, draggable = true, sticky, } = config;
147
217
  const buttonRef = useRef(null);
148
218
  const popupRef = useRef(null);
149
219
  const isMountedRef = useRef(false);
@@ -183,19 +253,49 @@ export function useEdgeDock(config = {}) {
183
253
  const buttonDimensions = { width: buttonRect.width, height: buttonRect.height };
184
254
  // Set initial position on client after mount
185
255
  let initialPos = { x: viewport.width - 60, y: viewport.height - 60 };
186
- initialPos = constrainToViewport(initialPos, viewport, buttonDimensions, edgeOffset);
187
- if (dockMode === 'auto') {
188
- const edge = getClosestEdge(initialPos, viewport, allowedEdges);
189
- initialPos = snapToEdge(initialPos, edge, viewport, buttonDimensions, edgeOffset);
190
- setDockedEdge(edge);
256
+ // Check for sticky config first if not draggable
257
+ if (!draggable && sticky) {
258
+ const stickyPos = resolveStickyConfig(sticky, viewport.width);
259
+ if (stickyPos) {
260
+ initialPos = calculateStickyCoordinates(stickyPos, viewport);
261
+ // Adjust for center origin point of the button
262
+ // The button is positioned with transform: translate(-50%, -50%)
263
+ // So if sticky says left: 20, right now x=20.
264
+ // However, calculateStickyCoordinates returns the exact point for left/top.
265
+ // If we use that directly with translate(-50%, -50%), the center of button is at that point.
266
+ // Usually sticky means "distance from edge to edge of element".
267
+ // If left: 20, we want left edge of button at 20.
268
+ // So center should be 20 + width/2.
269
+ if (stickyPos.left !== undefined) {
270
+ initialPos.x += buttonDimensions.width / 2;
271
+ }
272
+ else if (stickyPos.right !== undefined) {
273
+ initialPos.x -= buttonDimensions.width / 2;
274
+ }
275
+ if (stickyPos.top !== undefined) {
276
+ initialPos.y += buttonDimensions.height / 2;
277
+ }
278
+ else if (stickyPos.bottom !== undefined) {
279
+ initialPos.y -= buttonDimensions.height / 2;
280
+ }
281
+ }
191
282
  }
192
- else if (dockMode === 'manual' && dockEdge) {
193
- initialPos = snapToEdge(initialPos, dockEdge, viewport, buttonDimensions, edgeOffset);
194
- setDockedEdge(dockEdge);
283
+ else {
284
+ // Normal dock logic
285
+ initialPos = constrainToViewport(initialPos, viewport, buttonDimensions, edgeOffset);
286
+ if (dockMode === 'auto') {
287
+ const edge = getClosestEdge(initialPos, viewport, allowedEdges);
288
+ initialPos = snapToEdge(initialPos, edge, viewport, buttonDimensions, edgeOffset);
289
+ setDockedEdge(edge);
290
+ }
291
+ else if (dockMode === 'manual' && dockEdge) {
292
+ initialPos = snapToEdge(initialPos, dockEdge, viewport, buttonDimensions, edgeOffset);
293
+ setDockedEdge(dockEdge);
294
+ }
195
295
  }
196
296
  setPositionInternal(initialPos);
197
297
  }
198
- }, [controlledPosition, dockMode, dockEdge, allowedEdges, edgeOffset]);
298
+ }, [controlledPosition, dockMode, dockEdge, allowedEdges, edgeOffset, draggable, sticky]);
199
299
  // Update controlled position
200
300
  useEffect(() => {
201
301
  if (controlledPosition) {
@@ -284,7 +384,7 @@ export function useEdgeDock(config = {}) {
284
384
  }, [dockMode, dockEdge, allowedEdges, edgeOffset]);
285
385
  // Pointer down handler
286
386
  const handlePointerDown = useCallback((e) => {
287
- if (!buttonRef.current)
387
+ if (!buttonRef.current || !draggable)
288
388
  return;
289
389
  e.preventDefault();
290
390
  e.stopPropagation();
@@ -301,7 +401,7 @@ export function useEdgeDock(config = {}) {
301
401
  };
302
402
  setIsDragging(true);
303
403
  setIsAnimating(false);
304
- }, [position, isPopupOpen]);
404
+ }, [position, isPopupOpen, draggable]);
305
405
  // Pointer move handler
306
406
  useEffect(() => {
307
407
  const handlePointerMove = (e) => {
@@ -382,7 +482,29 @@ export function useEdgeDock(config = {}) {
382
482
  const buttonRect = buttonRef.current.getBoundingClientRect();
383
483
  const viewport = getViewport();
384
484
  const buttonDimensions = { width: buttonRect.width, height: buttonRect.height };
385
- let newPos = constrainToViewport(position, viewport, buttonDimensions, edgeOffset);
485
+ let newPos = position;
486
+ if (!draggable && sticky) {
487
+ const stickyPos = resolveStickyConfig(sticky, viewport.width);
488
+ if (stickyPos) {
489
+ newPos = calculateStickyCoordinates(stickyPos, viewport);
490
+ // Adjust for center origin
491
+ if (stickyPos.left !== undefined) {
492
+ newPos.x += buttonDimensions.width / 2;
493
+ }
494
+ else if (stickyPos.right !== undefined) {
495
+ newPos.x -= buttonDimensions.width / 2;
496
+ }
497
+ if (stickyPos.top !== undefined) {
498
+ newPos.y += buttonDimensions.height / 2;
499
+ }
500
+ else if (stickyPos.bottom !== undefined) {
501
+ newPos.y -= buttonDimensions.height / 2;
502
+ }
503
+ setPositionInternal(newPos);
504
+ return;
505
+ }
506
+ }
507
+ newPos = constrainToViewport(position, viewport, buttonDimensions, edgeOffset);
386
508
  if (dockMode === 'auto') {
387
509
  const edge = getClosestEdge(newPos, viewport, allowedEdges);
388
510
  newPos = snapToEdge(newPos, edge, viewport, buttonDimensions, edgeOffset);
@@ -396,7 +518,7 @@ export function useEdgeDock(config = {}) {
396
518
  };
397
519
  window.addEventListener('resize', handleResize);
398
520
  return () => window.removeEventListener('resize', handleResize);
399
- }, [position, dockMode, dockEdge, edgeOffset, allowedEdges]);
521
+ }, [position, dockMode, dockEdge, edgeOffset, allowedEdges, draggable, sticky]);
400
522
  // Button styles
401
523
  const buttonStyles = {
402
524
  position: 'fixed',
@@ -404,7 +526,7 @@ export function useEdgeDock(config = {}) {
404
526
  top: 0,
405
527
  transform: `translate3d(${position.x}px, ${position.y}px, 0) translate(-50%, -50%)`,
406
528
  transition: isAnimating && animation ? 'transform 0.3s cubic-bezier(0.34, 1.56, 0.64, 1)' : 'none',
407
- cursor: isDragging ? 'grabbing' : 'grab',
529
+ cursor: draggable ? (isDragging ? 'grabbing' : 'grab') : 'pointer',
408
530
  touchAction: 'none',
409
531
  userSelect: 'none',
410
532
  zIndex,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "react-edge-dock",
3
- "version": "1.0.9",
3
+ "version": "1.0.11",
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",
@@ -22,8 +22,7 @@
22
22
  "dev": "tsc --watch",
23
23
  "clean": "rm -rf dist",
24
24
  "prepublishOnly": "npm run clean && npm run build",
25
- "prepack": "npm run build",
26
- "publish": "npm publish --access public"
25
+ "prepack": "npm run build"
27
26
  },
28
27
  "keywords": [
29
28
  "react",