-
Notifications
You must be signed in to change notification settings - Fork 22
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
ntp: handle drag + drop outside of favorites (#1256)
* ntp: handle drag + drop outside of favorites * don't prevent drop in playwright tests * linting * fixed format --------- Co-authored-by: Shane Osbourne <[email protected]>
- Loading branch information
1 parent
c9f7798
commit ae441a9
Showing
10 changed files
with
274 additions
and
58 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,14 @@ | ||
import { h } from 'preact'; | ||
|
||
export function Centered({ children }) { | ||
return <div class="layout-centered">{children}</div>; | ||
/** | ||
* @param {object} props | ||
* @param {import("preact").ComponentChild} props.children | ||
* @param {import("preact").ComponentProps<"div">} [props.rest] | ||
*/ | ||
export function Centered({ children, ...rest }) { | ||
return ( | ||
<div {...rest} class="layout-centered"> | ||
{children} | ||
</div> | ||
); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,106 @@ | ||
import { useEffect, useRef } from 'preact/hooks'; | ||
|
||
const REGISTER_EVENT = 'register-dropzone'; | ||
const CLEAR_EVENT = 'clear-dropzone'; | ||
|
||
/** | ||
* Setup the global listeners for the page. This prevents a new tab | ||
* being launched when an unsupported link is dropped in (like from another app) | ||
*/ | ||
export function useGlobalDropzone() { | ||
useEffect(() => { | ||
/** @type {HTMLElement[]} */ | ||
let safezones = []; | ||
const controller = new AbortController(); | ||
|
||
/** | ||
* Allow HTML elements to be part of a 'safe zone' where dropping is allowed | ||
*/ | ||
window.addEventListener( | ||
REGISTER_EVENT, | ||
(/** @type {CustomEvent} */ e) => { | ||
if (isValidEvent(e)) { | ||
safezones.push(e.detail.dropzone); | ||
} | ||
}, | ||
{ signal: controller.signal }, | ||
); | ||
|
||
/** | ||
* Allow registered HTML elements to be removed from the list of safe-zones | ||
*/ | ||
window.addEventListener( | ||
CLEAR_EVENT, | ||
(/** @type {CustomEvent} */ e) => { | ||
if (isValidEvent(e)) { | ||
const match = safezones.findIndex((x) => x === e.detail.dropzone); | ||
safezones.splice(match, 1); | ||
} | ||
}, | ||
{ signal: controller.signal }, | ||
); | ||
|
||
/** | ||
* Use drag over to ensure | ||
*/ | ||
document.addEventListener( | ||
'dragover', | ||
(event) => { | ||
if (!event.target) return; | ||
const target = /** @type {HTMLElement} */ (event.target); | ||
if (safezones.length > 0) { | ||
for (const safezone of safezones) { | ||
if (safezone.contains(target)) return; | ||
} | ||
} | ||
|
||
// At the moment, this is not supported in the Playwright tests :( | ||
// So we allow the integration build to check first | ||
let preventDrop = true; | ||
// eslint-disable-next-line no-labels,no-unused-labels | ||
$INTEGRATION: (() => { | ||
if (window.__playwright_01) { | ||
preventDrop = false; | ||
} | ||
})(); | ||
|
||
if (preventDrop) { | ||
// if we get here, we're stopping a drag/drop from being allowed | ||
event.preventDefault(); | ||
if (event.dataTransfer) { | ||
event.dataTransfer.dropEffect = 'none'; | ||
} | ||
} | ||
}, | ||
{ signal: controller.signal }, | ||
); | ||
return () => { | ||
controller.abort(); | ||
safezones = []; | ||
}; | ||
}, []); | ||
} | ||
|
||
/** | ||
* Register an area allowed to receive drop events | ||
*/ | ||
export function useDropzoneSafeArea() { | ||
const ref = useRef(null); | ||
useEffect(() => { | ||
if (!ref.current) return; | ||
const evt = new CustomEvent(REGISTER_EVENT, { detail: { dropzone: ref.current } }); | ||
window.dispatchEvent(evt); | ||
return () => { | ||
window.dispatchEvent(new CustomEvent(CLEAR_EVENT, { detail: { dropzone: ref.current } })); | ||
}; | ||
}, []); | ||
return ref; | ||
} | ||
|
||
/** | ||
* @param {Record<string, any>} input | ||
* @return {input is {dropzone: HTMLElement}} | ||
*/ | ||
function isValidEvent(input) { | ||
return 'detail' in input && input.detail.dropzone instanceof HTMLElement; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.