From cc4f2ad4eef8b0ef6999458ac0b14f6973946b15 Mon Sep 17 00:00:00 2001 From: MarconLP <13001502+MarconLP@users.noreply.github.com> Date: Fri, 14 Apr 2023 16:44:09 +0200 Subject: [PATCH] add ExpireDateSelectMenu --- package-lock.json | 55 +++++++++++++++++++ package.json | 2 + src/components/ExpireDateSelectMenu.tsx | 72 +++++++++++++++++++++++++ src/components/ShareModal.tsx | 9 ++-- src/utils/use-popper.ts | 41 ++++++++++++++ 5 files changed, 175 insertions(+), 4 deletions(-) create mode 100644 src/components/ExpireDateSelectMenu.tsx create mode 100644 src/utils/use-popper.ts diff --git a/package-lock.json b/package-lock.json index 91f046e..445d2e7 100644 --- a/package-lock.json +++ b/package-lock.json @@ -13,6 +13,7 @@ "@aws-sdk/s3-request-presigner": "^3.310.0", "@headlessui/react": "^1.7.13", "@next-auth/prisma-adapter": "^1.0.5", + "@popperjs/core": "^2.11.7", "@prisma/client": "^4.11.0", "@tanstack/react-query": "^4.28.0", "@trpc/client": "^10.18.0", @@ -25,6 +26,7 @@ "react": "18.2.0", "react-dom": "18.2.0", "react-player": "^2.12.0", + "react-popper": "^2.3.0", "superjson": "1.12.2", "zod": "^3.21.4" }, @@ -1754,6 +1756,15 @@ "url": "https://opencollective.com/unts" } }, + "node_modules/@popperjs/core": { + "version": "2.11.7", + "resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.11.7.tgz", + "integrity": "sha512-Cr4OjIkipTtcXKjAsm8agyleBuDHvxzeBoa1v543lbv1YaIwQjESsVcmjiWiPEbC1FIeHOG/Op9kdCmAmiS3Kw==", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/popperjs" + } + }, "node_modules/@prisma/client": { "version": "4.12.0", "resolved": "https://registry.npmjs.org/@prisma/client/-/client-4.12.0.tgz", @@ -5427,6 +5438,20 @@ "react": ">=16.6.0" } }, + "node_modules/react-popper": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/react-popper/-/react-popper-2.3.0.tgz", + "integrity": "sha512-e1hj8lL3uM+sgSR4Lxzn5h1GxBlpa4CQz0XLF8kx4MDrDRWY0Ena4c97PUeSX9i5W3UAfDP0z0FXCTQkoXUl3Q==", + "dependencies": { + "react-fast-compare": "^3.0.1", + "warning": "^4.0.2" + }, + "peerDependencies": { + "@popperjs/core": "^2.0.0", + "react": "^16.8.0 || ^17 || ^18", + "react-dom": "^16.8.0 || ^17 || ^18" + } + }, "node_modules/react-ssr-prepass": { "version": "1.5.0", "resolved": "https://registry.npmjs.org/react-ssr-prepass/-/react-ssr-prepass-1.5.0.tgz", @@ -6183,6 +6208,14 @@ "uuid": "dist/bin/uuid" } }, + "node_modules/warning": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/warning/-/warning-4.0.3.tgz", + "integrity": "sha512-rpJyN222KWIvHJ/F53XSZv0Zl/accqHR8et1kpaMTD/fLCRxtV8iX8czMzY7sVZupTI3zcUTg8eycS2kNF9l6w==", + "dependencies": { + "loose-envify": "^1.0.0" + } + }, "node_modules/which": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", @@ -7650,6 +7683,11 @@ "tslib": "^2.4.0" } }, + "@popperjs/core": { + "version": "2.11.7", + "resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.11.7.tgz", + "integrity": "sha512-Cr4OjIkipTtcXKjAsm8agyleBuDHvxzeBoa1v543lbv1YaIwQjESsVcmjiWiPEbC1FIeHOG/Op9kdCmAmiS3Kw==" + }, "@prisma/client": { "version": "4.12.0", "resolved": "https://registry.npmjs.org/@prisma/client/-/client-4.12.0.tgz", @@ -10181,6 +10219,15 @@ "react-fast-compare": "^3.0.1" } }, + "react-popper": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/react-popper/-/react-popper-2.3.0.tgz", + "integrity": "sha512-e1hj8lL3uM+sgSR4Lxzn5h1GxBlpa4CQz0XLF8kx4MDrDRWY0Ena4c97PUeSX9i5W3UAfDP0z0FXCTQkoXUl3Q==", + "requires": { + "react-fast-compare": "^3.0.1", + "warning": "^4.0.2" + } + }, "react-ssr-prepass": { "version": "1.5.0", "resolved": "https://registry.npmjs.org/react-ssr-prepass/-/react-ssr-prepass-1.5.0.tgz", @@ -10707,6 +10754,14 @@ "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==" }, + "warning": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/warning/-/warning-4.0.3.tgz", + "integrity": "sha512-rpJyN222KWIvHJ/F53XSZv0Zl/accqHR8et1kpaMTD/fLCRxtV8iX8czMzY7sVZupTI3zcUTg8eycS2kNF9l6w==", + "requires": { + "loose-envify": "^1.0.0" + } + }, "which": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", diff --git a/package.json b/package.json index 9829f7c..daa2253 100644 --- a/package.json +++ b/package.json @@ -14,6 +14,7 @@ "@aws-sdk/s3-request-presigner": "^3.310.0", "@headlessui/react": "^1.7.13", "@next-auth/prisma-adapter": "^1.0.5", + "@popperjs/core": "^2.11.7", "@prisma/client": "^4.11.0", "@tanstack/react-query": "^4.28.0", "@trpc/client": "^10.18.0", @@ -26,6 +27,7 @@ "react": "18.2.0", "react-dom": "18.2.0", "react-player": "^2.12.0", + "react-popper": "^2.3.0", "superjson": "1.12.2", "zod": "^3.21.4" }, diff --git a/src/components/ExpireDateSelectMenu.tsx b/src/components/ExpireDateSelectMenu.tsx new file mode 100644 index 0000000..cff0ea2 --- /dev/null +++ b/src/components/ExpireDateSelectMenu.tsx @@ -0,0 +1,72 @@ +import { Listbox, Transition } from "@headlessui/react"; +import { Fragment, useState } from "react"; +import { getTime } from "~/utils/getTime"; + +interface Props { + shareExpiryAt: Date | null; +} + +export default function ExpireDateSelectMenu({ shareExpiryAt }: Props) { + const handleChange = (value) => { + console.log("selecting value", value); + }; + + const availableExpireDates = [ + "Never expire", + "In 1 hour", + "In 24 hours", + "In 7 days", + "In 30 days", + ]; + + return ( +
+ +
+ + + {typeof shareExpiryAt === null + ? getTime(shareExpiryAt) + : "Never expire"} + + + + + {availableExpireDates.map((person, personIdx) => ( + + `relative mx-2 flex h-8 cursor-pointer select-none items-center rounded px-2 ${ + active ? "bg-[#f3f4f6]" : "text-gray-900" + }` + } + value={person} + > + {({ selected }) => ( + <> + + {person} + + + )} + + ))} + + +
+
+
+ ); +} diff --git a/src/components/ShareModal.tsx b/src/components/ShareModal.tsx index 064a164..130ac9f 100644 --- a/src/components/ShareModal.tsx +++ b/src/components/ShareModal.tsx @@ -2,6 +2,7 @@ import { Dialog, Transition } from "@headlessui/react"; import { Fragment, useState } from "react"; import { ModernSwitch } from "~/components/ModernSwitch"; import { api, type RouterOutputs } from "~/utils/api"; +import ExpireDateSelectMenu from "~/components/ExpireDateSelectMenu"; interface Props { video: RouterOutputs["video"]["get"]; @@ -97,7 +98,7 @@ export function ShareModal({ video }: Props) { leaveFrom="opacity-100 scale-100" leaveTo="opacity-0 scale-95" > - +
Share this recording @@ -127,9 +128,9 @@ export function ShareModal({ video }: Props) {
Expire link - +
Delete video after link expires diff --git a/src/utils/use-popper.ts b/src/utils/use-popper.ts new file mode 100644 index 0000000..262ea69 --- /dev/null +++ b/src/utils/use-popper.ts @@ -0,0 +1,41 @@ +import { type RefCallback, useRef, useCallback, useMemo } from "react"; +import { createPopper, type Options } from "@popperjs/core"; + +/** + * Example implementation to use Popper: https://popper.js.org/ + */ +export function usePopper( + options?: Partial +): [RefCallback, RefCallback] { + let reference = useRef(null); + let popper = useRef(null); + + let cleanupCallback = useRef(() => {}); + + let instantiatePopper = useCallback(() => { + if (!reference.current) return; + if (!popper.current) return; + + if (cleanupCallback.current) cleanupCallback.current(); + + cleanupCallback.current = createPopper( + reference.current, + popper.current, + options + ).destroy; + }, [reference, popper, cleanupCallback, options]); + + return useMemo( + () => [ + (referenceDomNode) => { + reference.current = referenceDomNode; + instantiatePopper(); + }, + (popperDomNode) => { + popper.current = popperDomNode; + instantiatePopper(); + }, + ], + [reference, popper, instantiatePopper] + ); +}