From aeb2c7d5190537f0990adbb9a67c1a76da22204a Mon Sep 17 00:00:00 2001 From: wil Date: Fri, 13 Sep 2024 00:32:09 -0400 Subject: [PATCH] contextual button for retry done (#12) Co-authored-by: wil --- .../ContextualButtonRetry.tsx | 35 +++++++++ src/KonvaRootComponent/KonvaRootComponent.tsx | 4 +- .../sandbox/ContextualButtonRetryForm.tsx | 73 +++++++++++++++++++ src/app/pages/sandbox/index.tsx | 5 +- src/signals/uiAccess/buttonRetry.ts | 50 +++++++++++++ src/signals/uiAccess/index.ts | 3 +- src/signals/uiAccess/type.ts | 4 + src/signals/uiEvents/buttonRetry.ts | 29 ++++++++ src/signals/uiEvents/index.ts | 6 ++ 9 files changed, 205 insertions(+), 4 deletions(-) create mode 100644 src/KonvaRootComponent/ContextualButtonRetry.tsx create mode 100644 src/app/pages/sandbox/ContextualButtonRetryForm.tsx create mode 100644 src/signals/uiAccess/buttonRetry.ts create mode 100644 src/signals/uiEvents/buttonRetry.ts diff --git a/src/KonvaRootComponent/ContextualButtonRetry.tsx b/src/KonvaRootComponent/ContextualButtonRetry.tsx new file mode 100644 index 0000000000..ba0ac71db5 --- /dev/null +++ b/src/KonvaRootComponent/ContextualButtonRetry.tsx @@ -0,0 +1,35 @@ +import { Transition } from "@headlessui/react"; +import { twMerge } from "tailwind-merge"; +import { faRotateRight } from "@fortawesome/pro-solid-svg-icons"; + +import { Button } from "~/components/ui"; +import { uiAccess } from "~/signals/uiAccess"; +import { dispatchUiEvents } from "~/signals"; +import { transitionTimingStyles } from "~/components/styles"; + +export const ContextualButtonRetry = () => { + const { isShowing, position, ...rest } = uiAccess.buttonRetry.signal.value; + const handleOnClick = ( + e: React.MouseEvent, + ) => { + dispatchUiEvents.buttonRetry.onClick(e); + }; + return ( + +
+ +
+
+ ); +}; diff --git a/src/KonvaRootComponent/KonvaRootComponent.tsx b/src/KonvaRootComponent/KonvaRootComponent.tsx index f3445d7ff9..77155e6baf 100644 --- a/src/KonvaRootComponent/KonvaRootComponent.tsx +++ b/src/KonvaRootComponent/KonvaRootComponent.tsx @@ -2,6 +2,7 @@ import { useCallback, useRef } from "react"; import { useRenderCounter } from "~/hooks/useRenderCounter"; import { KonvaCanvasContainer } from "./KonvaCanvasContainer"; +import { ContextualButtonRetry } from "./ContextualButtonRetry"; import { ContextualToolbarImage } from "./ContextualToolbarImage"; import { ContextualLoadingBar } from "./ContextualLoadingBar"; import { SignaledToolbarMain } from "./SignaledToolbarMain"; @@ -41,15 +42,14 @@ export const KonvaRootComponent = ({ className }: { className: string }) => { > Error Dialogue Test - - + diff --git a/src/app/pages/sandbox/ContextualButtonRetryForm.tsx b/src/app/pages/sandbox/ContextualButtonRetryForm.tsx new file mode 100644 index 0000000000..f56d87e4d5 --- /dev/null +++ b/src/app/pages/sandbox/ContextualButtonRetryForm.tsx @@ -0,0 +1,73 @@ +import { useState } from "react"; +import { uiAccess } from "~/signals/uiAccess"; +import { uiEvents } from "~/signals/uiEvents"; + +import { Input, Button } from "~/components/ui"; + +export const ContextualButtonRetryForm = () => { + uiEvents.buttonRetry.onClick(() => { + console.log( + "uiEvents.buttonRetry.onClick calls uiAccess.buttonRetry.disable", + ); + uiAccess.buttonRetry.disable(); + }); + const buttonRetry = uiAccess.buttonRetry; + + const [state, setState] = useState({ + position: { + x: 0, + y: 0, + }, + isShowing: false, + disabled: false, + }); + + return ( +
+ +
+ + { + setState((curr) => ({ + ...curr, + position: { + ...curr.position, + x: parseInt(e.target.value) || 0, + }, + })); + }} + /> + + { + setState((curr) => ({ + ...curr, + position: { + ...curr.position, + y: parseInt(e.target.value) || 0, + }, + })); + }} + /> +
+ +
+ + + + +
+
+ ); +}; diff --git a/src/app/pages/sandbox/index.tsx b/src/app/pages/sandbox/index.tsx index a62e90ab57..6abf0397de 100644 --- a/src/app/pages/sandbox/index.tsx +++ b/src/app/pages/sandbox/index.tsx @@ -1,12 +1,13 @@ import { ContextualToolbarImage } from "~/KonvaRootComponent/ContextualToolbarImage"; import { ContextualLoadingBar } from "~/KonvaRootComponent/ContextualLoadingBar"; - +import { ContextualButtonRetry } from "~/KonvaRootComponent/ContextualButtonRetry"; import { SignaledDialogError } from "~/KonvaRootComponent/SignaledComponents"; import { useRenderCounter } from "~/hooks/useRenderCounter"; import { ContextualToolbarForm } from "./ContextualToolbarForm"; import { ContextualLoadingBarForm } from "./ContextualLoadingBarForm"; +import { ContextualButtonRetryForm } from "./ContextualButtonRetryForm"; import { DialogErrorForm } from "./DialogErrorForm"; import { ButtonTestTester } from "./ButtonTestTester"; @@ -21,11 +22,13 @@ export const Sandbox = () => { + + ); diff --git a/src/signals/uiAccess/buttonRetry.ts b/src/signals/uiAccess/buttonRetry.ts new file mode 100644 index 0000000000..d9d4620248 --- /dev/null +++ b/src/signals/uiAccess/buttonRetry.ts @@ -0,0 +1,50 @@ +import { signal } from "@preact/signals-react"; +import { ContextualButtonRetryProps } from "./type"; +const buttonRetrySignal = signal({ + position: { + x: 0, + y: 0, + }, + isShowing: false, + disabled: false, +}); + +export const buttonRetry = { + signal: buttonRetrySignal, + disable: () => { + buttonRetrySignal.value = { ...buttonRetrySignal.value, disabled: true }; + }, + updatePosition(position: { x: number; y: number }) { + buttonRetrySignal.value = { + ...buttonRetrySignal.value, + position, + }; + }, + enable: () => { + buttonRetrySignal.value = { + ...buttonRetrySignal.value, + disabled: false, + }; + }, + show(props: Omit) { + if (buttonRetrySignal.value.isShowing) { + if (import.meta.env.DEV) { + console.warn( + "Loading bar is already showing", + "use the `updatePosition` methods instead", + ); + } + return; + } + buttonRetrySignal.value = { + ...props, + isShowing: true, + }; + }, + hide() { + buttonRetrySignal.value = { + ...buttonRetrySignal.value, + isShowing: false, + }; + }, +}; diff --git a/src/signals/uiAccess/index.ts b/src/signals/uiAccess/index.ts index 4a40bdbddb..bf4e4ed8e3 100644 --- a/src/signals/uiAccess/index.ts +++ b/src/signals/uiAccess/index.ts @@ -6,8 +6,8 @@ type uiAccessType = { export type { uiAccessType }; +import { buttonRetry } from "./buttonRetry"; import { buttonTest } from "./buttonTest"; - import { dialogueError } from "./dialogueError"; import { loadingBar } from "./loadingBar"; import { toolbarImage } from "./toolbarImage"; @@ -15,6 +15,7 @@ import { toolbarVideo } from "./toolbarVideo"; import { toolbarMain } from "./toolbarMain"; export const uiAccess = { + buttonRetry, buttonTest, dialogueError, toolbarImage, diff --git a/src/signals/uiAccess/type.ts b/src/signals/uiAccess/type.ts index 30e8dcbb5e..040bdd23af 100644 --- a/src/signals/uiAccess/type.ts +++ b/src/signals/uiAccess/type.ts @@ -11,3 +11,7 @@ export interface ContextualUi { export interface ContextualLoadingBarProps extends ContextualUi, Omit {} + +export interface ContextualButtonRetryProps extends ContextualUi { + disabled: boolean; +} diff --git a/src/signals/uiEvents/buttonRetry.ts b/src/signals/uiEvents/buttonRetry.ts new file mode 100644 index 0000000000..d4e346e9fa --- /dev/null +++ b/src/signals/uiEvents/buttonRetry.ts @@ -0,0 +1,29 @@ +import { MouseEventHandler } from "react"; +import { signal, effect } from "@preact/signals-react"; + +const event = signal< + React.MouseEvent | undefined +>(undefined); + +let effectCleanup: (() => void) | undefined = undefined; + +export const eventsHandler = { + onClick: (callback: MouseEventHandler) => { + if (effectCleanup) { + effectCleanup(); + } + effectCleanup = effect(() => { + if (event.value) { + callback(event.value); + event.value = undefined; + } + }); + }, +}; + +export const dispatcher = { + onClick: (e: React.MouseEvent) => { + console.log("Button Retry dispatcher"); + event.value = e; + }, +}; diff --git a/src/signals/uiEvents/index.ts b/src/signals/uiEvents/index.ts index 147bb167ba..dbe1ccc10b 100644 --- a/src/signals/uiEvents/index.ts +++ b/src/signals/uiEvents/index.ts @@ -18,11 +18,16 @@ import { dispatcher as buttonTestDispatcher, eventsHandler as buttonTestEvent, } from "./buttonTest"; +import { + dispatcher as buttonRetryDispatcher, + eventsHandler as buttonRetryEvent, +} from "./buttonRetry"; import { requestAiStylize, onRequestAiStylize } from "./aiStylize"; export const uiEvents = { ...addMediaEvents, onRequestAiStylize, + buttonRetry: buttonRetryEvent, buttonTest: buttonTestEvent, toolbarImage: toolbarImageEvents, toolbarMain: toolbarMainEvents, @@ -31,6 +36,7 @@ export const uiEvents = { export const dispatchUiEvents = { ...addMediaDispatchers, requestAiStylize, + buttonRetry: buttonRetryDispatcher, buttonTest: buttonTestDispatcher, toolbarImage: toolbarImageDispatchers, toolbarMain: toolbarMainDispatchers,