react-edge-dock 1.0.6 → 1.0.8

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.
@@ -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,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,CA8W1E"}
@@ -164,6 +164,7 @@ export function useEdgeDock(config = {}) {
164
164
  startPosX: 0,
165
165
  startPosY: 0,
166
166
  hasMoved: false,
167
+ popupWasOpen: false,
167
168
  });
168
169
  const isPopupOpen = controlledPopupOpen ?? isPopupOpenInternal;
169
170
  // Get current state
@@ -201,6 +202,26 @@ export function useEdgeDock(config = {}) {
201
202
  setPositionInternal(controlledPosition);
202
203
  }
203
204
  }, [controlledPosition]);
205
+ // Toggle popup
206
+ const togglePopup = useCallback(() => {
207
+ const newState = !isPopupOpen;
208
+ if (controlledPopupOpen === undefined) {
209
+ setIsPopupOpenInternal(newState);
210
+ }
211
+ onPopupChange?.(newState);
212
+ }, [isPopupOpen, controlledPopupOpen, onPopupChange]);
213
+ const closePopup = useCallback(() => {
214
+ if (controlledPopupOpen === undefined) {
215
+ setIsPopupOpenInternal(false);
216
+ }
217
+ onPopupChange?.(false);
218
+ }, [controlledPopupOpen, onPopupChange]);
219
+ const openPopup = useCallback(() => {
220
+ if (controlledPopupOpen === undefined) {
221
+ setIsPopupOpenInternal(true);
222
+ }
223
+ onPopupChange?.(true);
224
+ }, [controlledPopupOpen, onPopupChange]);
204
225
  // Calculate popup position when it opens or button moves
205
226
  useEffect(() => {
206
227
  if (isPopupOpen && buttonRef.current && popupRef.current) {
@@ -211,6 +232,28 @@ export function useEdgeDock(config = {}) {
211
232
  setPopupOrigin(result.origin);
212
233
  }
213
234
  }, [isPopupOpen, position, popupGap]);
235
+ // Close popup when clicking outside
236
+ useEffect(() => {
237
+ if (!isPopupOpen || !isBrowser)
238
+ return;
239
+ const handleClickOutside = (e) => {
240
+ const target = e.target;
241
+ // Check if click is outside both button and popup
242
+ const isOutsideButton = buttonRef.current && !buttonRef.current.contains(target);
243
+ const isOutsidePopup = popupRef.current && !popupRef.current.contains(target);
244
+ if (isOutsideButton && isOutsidePopup) {
245
+ closePopup();
246
+ }
247
+ };
248
+ // Use setTimeout to avoid closing immediately on the same click that opened it
249
+ const timeoutId = setTimeout(() => {
250
+ document.addEventListener('mousedown', handleClickOutside);
251
+ }, 0);
252
+ return () => {
253
+ clearTimeout(timeoutId);
254
+ document.removeEventListener('mousedown', handleClickOutside);
255
+ };
256
+ }, [isPopupOpen, closePopup]);
214
257
  // Notify state changes
215
258
  useEffect(() => {
216
259
  if (onDockChange) {
@@ -239,26 +282,6 @@ export function useEdgeDock(config = {}) {
239
282
  }
240
283
  setPositionInternal(finalPos);
241
284
  }, [dockMode, dockEdge, allowedEdges, edgeOffset]);
242
- // Toggle popup
243
- const togglePopup = useCallback(() => {
244
- const newState = !isPopupOpen;
245
- if (controlledPopupOpen === undefined) {
246
- setIsPopupOpenInternal(newState);
247
- }
248
- onPopupChange?.(newState);
249
- }, [isPopupOpen, controlledPopupOpen, onPopupChange]);
250
- const closePopup = useCallback(() => {
251
- if (controlledPopupOpen === undefined) {
252
- setIsPopupOpenInternal(false);
253
- }
254
- onPopupChange?.(false);
255
- }, [controlledPopupOpen, onPopupChange]);
256
- const openPopup = useCallback(() => {
257
- if (controlledPopupOpen === undefined) {
258
- setIsPopupOpenInternal(true);
259
- }
260
- onPopupChange?.(true);
261
- }, [controlledPopupOpen, onPopupChange]);
262
285
  // Pointer down handler
263
286
  const handlePointerDown = useCallback((e) => {
264
287
  if (!buttonRef.current)
@@ -274,14 +297,11 @@ export function useEdgeDock(config = {}) {
274
297
  startPosX: position.x,
275
298
  startPosY: position.y,
276
299
  hasMoved: false,
300
+ popupWasOpen: isPopupOpen,
277
301
  };
278
302
  setIsDragging(true);
279
303
  setIsAnimating(false);
280
- // Close popup when starting to drag
281
- if (isPopupOpen) {
282
- closePopup();
283
- }
284
- }, [position, isPopupOpen, closePopup]);
304
+ }, [position, isPopupOpen]);
285
305
  // Pointer move handler
286
306
  useEffect(() => {
287
307
  const handlePointerMove = (e) => {
@@ -291,6 +311,12 @@ export function useEdgeDock(config = {}) {
291
311
  const deltaY = e.clientY - dragStateRef.current.startY;
292
312
  // Mark as moved if dragged more than 5px
293
313
  if (Math.abs(deltaX) > 5 || Math.abs(deltaY) > 5) {
314
+ if (!dragStateRef.current.hasMoved) {
315
+ // First time detecting movement - close popup if it was open
316
+ if (dragStateRef.current.popupWasOpen) {
317
+ closePopup();
318
+ }
319
+ }
294
320
  dragStateRef.current.hasMoved = true;
295
321
  }
296
322
  const newPos = {
@@ -337,7 +363,7 @@ export function useEdgeDock(config = {}) {
337
363
  document.removeEventListener('pointermove', handlePointerMove);
338
364
  document.removeEventListener('pointerup', handlePointerUp);
339
365
  };
340
- }, [position, dockMode, dockEdge, animation, edgeOffset, allowedEdges]);
366
+ }, [position, dockMode, dockEdge, animation, edgeOffset, allowedEdges, closePopup]);
341
367
  // Click handler (only trigger if not dragged)
342
368
  const handleClick = useCallback((e) => {
343
369
  if (dragStateRef.current.hasMoved) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "react-edge-dock",
3
- "version": "1.0.6",
3
+ "version": "1.0.8",
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",