atproto explorer pdsls.dev
atproto tool

unlock modal button

juli.ee 6e4e65ec 00e9a156

verified
Changed files
+63 -19
src
+26 -4
src/components/create.tsx
···
const [notice, setNotice] = createSignal("");
const [openUpload, setOpenUpload] = createSignal(false);
const [validate, setValidate] = createSignal<boolean | undefined>(undefined);
+
const [nonBlocking, setNonBlocking] = createSignal(false);
let blobInput!: HTMLInputElement;
let formRef!: HTMLFormElement;
···
return (
<>
-
<Modal open={openDialog()} onClose={() => setOpenDialog(false)} closeOnClick={false}>
+
<Modal
+
open={openDialog()}
+
onClose={() => setOpenDialog(false)}
+
closeOnClick={false}
+
nonBlocking={nonBlocking()}
+
>
<div
data-draggable
-
class="dark:bg-dark-300 dark:shadow-dark-700 absolute top-16 left-[50%] w-screen -translate-x-1/2 cursor-grab rounded-lg border-[0.5px] border-neutral-300 bg-neutral-50 p-4 shadow-md transition-opacity duration-200 sm:w-xl lg:w-[48rem] dark:border-neutral-700 starting:opacity-0"
+
classList={{
+
"dark:bg-dark-300 dark:shadow-dark-700 pointer-events-auto absolute top-16 left-[50%] w-screen -translate-x-1/2 cursor-grab rounded-lg border-[0.5px] border-neutral-300 bg-neutral-50 p-4 shadow-md transition-opacity duration-200 sm:w-xl lg:w-[48rem] dark:border-neutral-700 starting:opacity-0": true,
+
"opacity-60 hover:opacity-100": nonBlocking(),
+
}}
ref={dragBox}
>
<div class="mb-2 flex w-full justify-between text-base">
-
<div class="font-semibold">
-
<span class="select-none">{props.create ? "Creating" : "Editing"} record</span>
+
<div class="flex items-center gap-2">
+
<span class="font-semibold select-none">
+
{props.create ? "Creating" : "Editing"} record
+
</span>
+
<Tooltip text={nonBlocking() ? "Lock" : "Unlock"}>
+
<button
+
type="button"
+
onclick={() => setNonBlocking(!nonBlocking())}
+
class="flex items-center rounded-lg p-1 hover:bg-neutral-200 active:bg-neutral-300 dark:hover:bg-neutral-700 dark:active:bg-neutral-600"
+
>
+
<span
+
class={`iconify ${nonBlocking() ? "lucide--lock-open" : "lucide--lock"}`}
+
></span>
+
</button>
+
</Tooltip>
</div>
<button
id="close"
+36 -14
src/components/modal.tsx
···
-
import { ComponentProps, onCleanup, onMount, Show } from "solid-js";
+
import { ComponentProps, createEffect, onCleanup, Show } from "solid-js";
export interface ModalProps extends Pick<ComponentProps<"svg">, "children"> {
open?: boolean;
onClose?: () => void;
closeOnClick?: boolean;
+
nonBlocking?: boolean;
}
export const Modal = (props: ModalProps) => {
return (
<Show when={props.open}>
-
<dialog
+
<div
+
data-modal
+
class="fixed inset-0 z-50 h-full max-h-none w-full max-w-none bg-transparent text-neutral-900 dark:text-neutral-200"
+
classList={{
+
"pointer-events-none": props.nonBlocking,
+
}}
ref={(node) => {
-
onMount(() => {
-
document.body.style.overflow = "hidden";
-
node.showModal();
-
(document.activeElement as any).blur();
+
const handleEscape = (e: KeyboardEvent) => {
+
if (e.key === "Escape") {
+
const modals = document.querySelectorAll("[data-modal]");
+
const lastModal = modals[modals.length - 1];
+
if (lastModal === node) {
+
e.preventDefault();
+
e.stopPropagation();
+
if (props.onClose) props.onClose();
+
}
+
}
+
};
+
+
createEffect(() => {
+
if (!props.nonBlocking) document.body.style.overflow = "hidden";
+
else document.body.style.overflow = "auto";
});
-
onCleanup(() => node.close());
+
+
document.addEventListener("keydown", handleEscape);
+
+
onCleanup(() => {
+
document.body.style.overflow = "auto";
+
document.removeEventListener("keydown", handleEscape);
+
});
}}
onClick={(ev) => {
-
if ((props.closeOnClick ?? true) && ev.target === ev.currentTarget) {
+
if (
+
(props.closeOnClick ?? true) &&
+
ev.target === ev.currentTarget &&
+
!props.nonBlocking
+
) {
if (props.onClose) props.onClose();
}
}}
-
onClose={() => {
-
document.body.style.overflow = "auto";
-
if (props.onClose) props.onClose();
-
}}
-
class="h-full max-h-none w-full max-w-none bg-transparent text-neutral-900 backdrop:bg-transparent dark:text-neutral-200"
>
{props.children}
-
</dialog>
+
</div>
</Show>
);
};
+1 -1
src/components/search.tsx
···
onCleanup(() => window.removeEventListener("keydown", keyEvent));
const keyEvent = (ev: KeyboardEvent) => {
-
if (document.querySelector("dialog")) return;
+
if (document.querySelector("[data-modal]")) return;
if ((ev.ctrlKey || ev.metaKey) && ev.key == "k") {
ev.preventDefault();