add modal to show code

This commit is contained in:
MapleLeaf
2022-01-12 20:10:09 -06:00
parent 8ce3834cf4
commit fdd6a3a3cc
8 changed files with 496 additions and 221 deletions

View File

@@ -0,0 +1,20 @@
import type { ReactNode } from "react"
import { useEffect, useRef } from "react"
import { createPortal } from "react-dom"
export function Portal({ children }: { children: ReactNode }) {
const containerRef = useRef<Element>()
if (!containerRef.current && typeof document !== "undefined") {
containerRef.current = document.createElement("react-portal")
document.body.append(containerRef.current)
}
useEffect(() => () => containerRef.current!.remove(), [])
return containerRef.current ? (
createPortal(children, containerRef.current)
) : (
<>{children}</>
)
}

View File

@@ -0,0 +1,197 @@
import clsx from "clsx"
import { useEffect, useRef, useState } from "react"
import blobComfyUrl from "~/assets/blob-comfy.png"
import cursorIbeamUrl from "~/assets/cursor-ibeam.png"
import cursorUrl from "~/assets/cursor.png"
const defaultState = {
chatInputText: "",
chatInputCursorVisible: true,
messageVisible: false,
count: 0,
cursorLeft: "25%",
cursorBottom: "-15px",
}
const delay = (ms: number) => new Promise((resolve) => setTimeout(resolve, ms))
const animationFrame = () =>
new Promise((resolve) => requestAnimationFrame(resolve))
export function LandingAnimation() {
const [state, setState] = useState(defaultState)
const chatInputRef = useRef<HTMLDivElement>(null)
const addRef = useRef<HTMLDivElement>(null)
const deleteRef = useRef<HTMLDivElement>(null)
const cursorRef = useRef<HTMLImageElement>(null)
useEffect(() => {
const animateClick = (element: HTMLElement) =>
element.animate(
[{ transform: `translateY(2px)` }, { transform: `translateY(0px)` }],
300,
)
let running = true
void (async () => {
await delay(1000)
while (running) {
setState(defaultState)
await delay(1000)
for (const letter of "/counter") {
setState((state) => ({
...state,
chatInputText: state.chatInputText + letter,
}))
await delay(100)
}
await delay(1000)
setState((state) => ({
...state,
messageVisible: true,
chatInputText: "",
}))
await delay(1000)
setState((state) => ({
...state,
cursorLeft: "70px",
cursorBottom: "40px",
}))
await delay(1500)
for (let i = 0; i < 3; i++) {
setState((state) => ({
...state,
count: state.count + 1,
chatInputCursorVisible: false,
}))
animateClick(addRef.current!)
await delay(700)
}
await delay(500)
setState((state) => ({
...state,
cursorLeft: "140px",
}))
await delay(1000)
animateClick(deleteRef.current!)
setState((state) => ({ ...state, messageVisible: false }))
await delay(1000)
setState(() => ({
...defaultState,
chatInputCursorVisible: false,
}))
await delay(500)
}
})()
return () => {
running = false
}
}, [])
useEffect(() => {
let running = true
void (async () => {
while (running) {
// check if the cursor is in the input
const cursorRect = cursorRef.current!.getBoundingClientRect()
const chatInputRect = chatInputRef.current!.getBoundingClientRect()
const isOverInput =
cursorRef.current &&
chatInputRef.current &&
cursorRect.top + cursorRect.height / 2 > chatInputRect.top
cursorRef.current!.src = isOverInput ? cursorIbeamUrl : cursorUrl
await animationFrame()
}
})()
return () => {
running = false
}
})
return (
<div
className="grid gap-2 relative pointer-events-none select-none"
role="presentation"
>
<div
className={clsx(
"bg-slate-800 p-4 rounded-lg shadow transition",
state.messageVisible ? "opacity-100" : "opacity-0 -translate-y-2",
)}
>
<div className="flex items-start gap-4">
<div className="w-12 h-12 p-2 rounded-full bg-no-repeat bg-contain bg-black/25">
<img
src={blobComfyUrl}
alt=""
className="object-contain scale-90 w-full h-full"
/>
</div>
<div>
<p className="font-bold">comfybot</p>
<p>this button was clicked {state.count} times</p>
<div className="mt-2 flex flex-row gap-3">
<div
ref={addRef}
className="bg-emerald-700 text-white py-1.5 px-3 text-sm rounded"
>
+1
</div>
<div
ref={deleteRef}
className="bg-red-700 text-white py-1.5 px-3 text-sm rounded"
>
🗑 delete
</div>
</div>
</div>
</div>
</div>
<div
className="bg-slate-700 pb-2 pt-1.5 px-4 rounded-lg shadow"
ref={chatInputRef}
>
<span
className={clsx(
"text-sm after:content-[attr(data-after)] after:relative after:-top-px after:-left-[2px]",
state.chatInputCursorVisible
? "after:opacity-100"
: "after:opacity-0",
)}
data-after="|"
>
{state.chatInputText || (
<span className="opacity-50 block absolute translate-y-1">
Message #showing-off-reacord
</span>
)}
</span>
</div>
<img
src={cursorUrl}
alt=""
className="transition-all duration-500 absolute scale-75"
style={{ left: state.cursorLeft, bottom: state.cursorBottom }}
ref={cursorRef}
/>
</div>
)
}

View File

@@ -0,0 +1,26 @@
{/* prettier-ignore */}
```tsx
import * as React from "react"
import { Button, useInstance } from "reacord"
function Counter() {
const [count, setCount] = React.useState(0)
const instance = useInstance()
return (
<>
this button was clicked {count} times
<Button
label="+1"
style="success"
onClick={() => setCount(count + 1)}
/>
<Button
label="delete"
emoji="🗑"
style="danger"
onClick={() => instance.destroy()}
/>
</>
)
}
```

View File

@@ -1,19 +0,0 @@
{/* prettier-ignore */}
```tsx
import * as React from "react"
import { Embed, Button } from "reacord"
function Counter() {
const [count, setCount] = React.useState(0)
return (
<>
<Embed title="Counter">
This button has been clicked {count} times.
</Embed>
<Button onClick={() => setCount(count + 1)}>
+1
</Button>
</>
)
}
```

View File

@@ -0,0 +1,80 @@
import { XIcon } from "@heroicons/react/outline"
import clsx from "clsx"
import type { ReactNode } from "react"
import { useEffect, useRef, useState } from "react"
import { FocusOn } from "react-focus-on"
import { Portal } from "~/modules/dom/portal"
export function Modal({
children,
visible,
onClose,
}: {
children: ReactNode
visible: boolean
onClose: () => void
}) {
const closeButtonRef = useRef<HTMLButtonElement>(null)
useEffect(() => {
if (visible) {
// trying to immediately focus doesn't work for whatever reason
// neither did requestAnimationFrame
setTimeout(() => {
closeButtonRef.current?.focus()
}, 50)
}
}, [visible])
return (
<Portal>
<div
className={clsx(
"bg-black/70 fixed inset-0 transition-all flex flex-col p-4",
visible ? "opacity-100 visible" : "opacity-0 invisible",
)}
>
<FocusOn
className={clsx(
"m-auto flex flex-col gap-2 w-full max-h-full max-w-screen-sm overflow-y-auto transition",
visible ? "translate-y-0" : "translate-y-3",
)}
enabled={visible}
onClickOutside={onClose}
onEscapeKey={onClose}
>
<button
type="button"
className="self-end"
onClick={onClose}
ref={closeButtonRef}
>
<span className="sr-only">Close</span>
<XIcon aria-hidden className="w-6 text-white" />
</button>
<div className={clsx("bg-slate-700 rounded-md shadow p-4")}>
{children}
</div>
</FocusOn>
</div>
</Portal>
)
}
export function ControlledModal({
children,
button,
}: {
children: ReactNode
button: (buttonProps: { onClick: () => void }) => void
}) {
const [visible, setVisible] = useState(false)
return (
<>
{button({ onClick: () => setVisible(true) })}
<Modal visible={visible} onClose={() => setVisible(false)}>
{children}
</Modal>
</>
)
}

View File

@@ -1,13 +1,11 @@
import clsx from "clsx"
import { useEffect, useRef, useState } from "react"
import blobComfyUrl from "~/assets/blob-comfy.png"
import cursorIbeamUrl from "~/assets/cursor-ibeam.png"
import cursorUrl from "~/assets/cursor.png"
import dotsBackgroundUrl from "~/assets/dots-background.svg" import dotsBackgroundUrl from "~/assets/dots-background.svg"
import { AppFooter } from "~/modules/app/app-footer" import { AppFooter } from "~/modules/app/app-footer"
import { AppLogo } from "~/modules/app/app-logo" import { AppLogo } from "~/modules/app/app-logo"
import LandingCode from "~/modules/landing/landing-code.mdx"
import { MainNavigation } from "~/modules/navigation/main-navigation" import { MainNavigation } from "~/modules/navigation/main-navigation"
import { maxWidthContainer } from "~/modules/ui/components" import { maxWidthContainer } from "~/modules/ui/components"
import { LandingAnimation } from "../modules/landing/landing-animation"
import { ControlledModal } from "../modules/ui/modal"
export default function Landing() { export default function Landing() {
return ( return (
@@ -28,9 +26,21 @@ export default function Landing() {
<p className="text-center text-lg font-light -mb-1"> <p className="text-center text-lg font-light -mb-1">
Create interactive Discord messages with React. Create interactive Discord messages with React.
</p> </p>
{/* <button className="px-3 py-1.5 font-medium bg-black/25 text-sm rounded-full self-center hover:bg-black/40 transition active:transition-none active:translate-y-[2px]">
Show Code <ControlledModal
</button> */} button={(button) => (
<button
{...button}
className="px-3 py-1.5 font-medium bg-black/25 text-sm rounded-full self-center hover:bg-black/40 transition active:transition-none active:translate-y-[2px]"
>
Show Code
</button>
)}
>
<div className="text-sm sm:text-base">
<LandingCode />
</div>
</ControlledModal>
</div> </div>
<div className="text-center"> <div className="text-center">
<AppFooter /> <AppFooter />
@@ -39,195 +49,3 @@ export default function Landing() {
</> </>
) )
} }
const defaultState = {
chatInputText: "",
chatInputCursorVisible: true,
messageVisible: false,
count: 0,
cursorLeft: "25%",
cursorBottom: "-15px",
}
const delay = (ms: number) => new Promise((resolve) => setTimeout(resolve, ms))
const animationFrame = () =>
new Promise((resolve) => requestAnimationFrame(resolve))
function LandingAnimation() {
const [state, setState] = useState(defaultState)
const chatInputRef = useRef<HTMLDivElement>(null)
const addRef = useRef<HTMLButtonElement>(null)
const deleteRef = useRef<HTMLButtonElement>(null)
const cursorRef = useRef<HTMLImageElement>(null)
useEffect(() => {
const animateClick = (element: HTMLElement) =>
element.animate(
[{ transform: `translateY(2px)` }, { transform: `translateY(0px)` }],
300,
)
let running = true
void (async () => {
await delay(1000)
while (running) {
setState(defaultState)
await delay(1000)
for (const letter of "/counter") {
setState((state) => ({
...state,
chatInputText: state.chatInputText + letter,
}))
await delay(100)
}
await delay(1000)
setState((state) => ({
...state,
messageVisible: true,
chatInputText: "",
}))
await delay(1000)
setState((state) => ({
...state,
cursorLeft: "70px",
cursorBottom: "40px",
}))
await delay(1500)
for (let i = 0; i < 3; i++) {
setState((state) => ({
...state,
count: state.count + 1,
chatInputCursorVisible: false,
}))
animateClick(addRef.current!)
await delay(700)
}
await delay(500)
setState((state) => ({
...state,
cursorLeft: "140px",
}))
await delay(1000)
animateClick(deleteRef.current!)
setState((state) => ({ ...state, messageVisible: false }))
await delay(1000)
setState(() => ({
...defaultState,
chatInputCursorVisible: false,
}))
await delay(500)
}
})()
return () => {
running = false
}
}, [])
useEffect(() => {
let running = true
void (async () => {
while (running) {
// check if the cursor is in the input
const cursorRect = cursorRef.current!.getBoundingClientRect()
const chatInputRect = chatInputRef.current!.getBoundingClientRect()
const isOverInput =
cursorRef.current &&
chatInputRef.current &&
cursorRect.top + cursorRect.height / 2 > chatInputRect.top
cursorRef.current!.src = isOverInput ? cursorIbeamUrl : cursorUrl
await animationFrame()
}
})()
return () => {
running = false
}
})
return (
<div
className="grid gap-2 relative pointer-events-none"
role="presentation"
>
<div
className={clsx(
"bg-slate-800 p-4 rounded-lg shadow transition",
state.messageVisible ? "opacity-100" : "opacity-0 -translate-y-2",
)}
>
<div className="flex items-start gap-4">
<div className="w-12 h-12 p-2 rounded-full bg-no-repeat bg-contain bg-black/25">
<img
src={blobComfyUrl}
alt=""
className="object-contain scale-90 w-full h-full"
/>
</div>
<div>
<p className="font-bold">comfybot</p>
<p>this button was clicked {state.count} times</p>
<div className="mt-2 flex flex-row gap-3">
<button
ref={addRef}
className="bg-emerald-700 text-white py-1.5 px-3 text-sm rounded"
>
+1
</button>
<button
ref={deleteRef}
className="bg-red-700 text-white py-1.5 px-3 text-sm rounded"
>
🗑 delete
</button>
</div>
</div>
</div>
</div>
<div
className="bg-slate-700 pb-2 pt-1.5 px-4 rounded-lg shadow"
ref={chatInputRef}
>
<span
className={clsx(
"text-sm after:content-[attr(data-after)] after:relative after:-top-px after:-left-[2px]",
state.chatInputCursorVisible
? "after:opacity-100"
: "after:opacity-0",
)}
data-after="|"
>
{state.chatInputText || (
<span className="opacity-50 block absolute translate-y-1">
Message #showing-off-reacord
</span>
)}
</span>
</div>
<img
src={cursorUrl}
alt=""
className="transition-all duration-500 absolute scale-75"
style={{ left: state.cursorLeft, bottom: state.cursorBottom }}
ref={cursorRef}
/>
</div>
)
}

View File

@@ -22,6 +22,7 @@
"reacord": "workspace:*", "reacord": "workspace:*",
"react": "^17.0.2", "react": "^17.0.2",
"react-dom": "^17.0.2", "react-dom": "^17.0.2",
"react-focus-on": "^3.5.4",
"remix": "^1.1.1" "remix": "^1.1.1"
}, },
"devDependencies": { "devDependencies": {

156
pnpm-lock.yaml generated
View File

@@ -114,6 +114,7 @@ importers:
reacord: workspace:* reacord: workspace:*
react: ^17.0.2 react: ^17.0.2
react-dom: ^17.0.2 react-dom: ^17.0.2
react-focus-on: ^3.5.4
rehype-prism-plus: ^1.3.1 rehype-prism-plus: ^1.3.1
remix: ^1.1.1 remix: ^1.1.1
tailwindcss: ^3.0.13 tailwindcss: ^3.0.13
@@ -131,6 +132,7 @@ importers:
reacord: link:../reacord reacord: link:../reacord
react: 17.0.2 react: 17.0.2
react-dom: 17.0.2_react@17.0.2 react-dom: 17.0.2_react@17.0.2
react-focus-on: 3.5.4_b08e3c15324cbe90a6ff8fcd416c932c
remix: 1.1.1 remix: 1.1.1
devDependencies: devDependencies:
'@remix-run/dev': 1.1.1 '@remix-run/dev': 1.1.1
@@ -1593,6 +1595,13 @@ packages:
resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==} resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==}
dev: true dev: true
/aria-hidden/1.1.3:
resolution: {integrity: sha512-RhVWFtKH5BiGMycI72q2RAFMLQi8JP9bLuQXgR5a8Znp7P5KOIADSJeyfI8PCVxLEp067B2HbP5JIiI/PXIZeA==}
engines: {node: '>=8.5.0'}
dependencies:
tslib: 1.14.1
dev: false
/aria-query/4.2.2: /aria-query/4.2.2:
resolution: {integrity: sha512-o/HelwhuKpTj/frsOsbNLNgnNGVIFsVP/SW2BSF14gVl7kAfMOJ6/8wUAUvG1R1NHKrfG+2sHZTu0yauT1qBrA==} resolution: {integrity: sha512-o/HelwhuKpTj/frsOsbNLNgnNGVIFsVP/SW2BSF14gVl7kAfMOJ6/8wUAUvG1R1NHKrfG+2sHZTu0yauT1qBrA==}
engines: {node: '>=6.0'} engines: {node: '>=6.0'}
@@ -2875,6 +2884,10 @@ packages:
resolution: {integrity: sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=} resolution: {integrity: sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=}
dev: false dev: false
/detect-node-es/1.1.0:
resolution: {integrity: sha512-ypdmJU/TbBby2Dxibuv7ZLW3Bs1QEmM7nHjEANfohJLvE0XVujisn1qPJcZxg+qDucsr+bP6fLD1rPS3AhJ7EQ==}
dev: false
/detective/5.2.0: /detective/5.2.0:
resolution: {integrity: sha512-6SsIx+nUUbuK0EthKjv0zrdnajCCXVYGmbYYiYjFVpzcjwEs/JMDZ8tPRG29J/HhN56t3GJp2cGSWDRjjot8Pg==} resolution: {integrity: sha512-6SsIx+nUUbuK0EthKjv0zrdnajCCXVYGmbYYiYjFVpzcjwEs/JMDZ8tPRG29J/HhN56t3GJp2cGSWDRjjot8Pg==}
engines: {node: '>=0.8.0'} engines: {node: '>=0.8.0'}
@@ -3943,6 +3956,13 @@ packages:
resolution: {integrity: sha512-8/sOawo8tJ4QOBX8YlQBMxL8+RLZfxMQOif9o0KUKTNTjMYElWPE0r/m5VNFxTRd0NSw8qSy8dajrwX4RYI1Hw==} resolution: {integrity: sha512-8/sOawo8tJ4QOBX8YlQBMxL8+RLZfxMQOif9o0KUKTNTjMYElWPE0r/m5VNFxTRd0NSw8qSy8dajrwX4RYI1Hw==}
dev: true dev: true
/focus-lock/0.10.1:
resolution: {integrity: sha512-b9yUklCi4fTu2GXn7dnaVf4hiLVVBp7xTiZarAHMODV2To6Bitf6F/UI67RmKbdgJQeVwI1UO0d9HYNbXt3GkA==}
engines: {node: '>=10'}
dependencies:
tslib: 2.3.1
dev: false
/follow-redirects/1.14.7: /follow-redirects/1.14.7:
resolution: {integrity: sha512-+hbxoLbFMbRKDwohX8GkTataGqO6Jb7jGwpAlwgy2bIz25XtRm7KEzJM76R1WiNT5SwZkX4Y75SwBolkpmE7iQ==} resolution: {integrity: sha512-+hbxoLbFMbRKDwohX8GkTataGqO6Jb7jGwpAlwgy2bIz25XtRm7KEzJM76R1WiNT5SwZkX4Y75SwBolkpmE7iQ==}
engines: {node: '>=4.0'} engines: {node: '>=4.0'}
@@ -4086,6 +4106,11 @@ packages:
has: 1.0.3 has: 1.0.3
has-symbols: 1.0.2 has-symbols: 1.0.2
/get-nonce/1.0.1:
resolution: {integrity: sha512-FJhYRoDaiatfEkUK8HKlicmu/3SGFD51q3itKDGoSTysQJBnfOcxU5GxnhE1E6soB76MbT0MBtnKJuXyAx+96Q==}
engines: {node: '>=6'}
dev: false
/get-package-type/0.1.0: /get-package-type/0.1.0:
resolution: {integrity: sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==} resolution: {integrity: sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==}
engines: {node: '>=8.0.0'} engines: {node: '>=8.0.0'}
@@ -4607,6 +4632,12 @@ packages:
engines: {node: '>= 0.10'} engines: {node: '>= 0.10'}
dev: true dev: true
/invariant/2.2.4:
resolution: {integrity: sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==}
dependencies:
loose-envify: 1.4.0
dev: false
/ipaddr.js/1.9.1: /ipaddr.js/1.9.1:
resolution: {integrity: sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==} resolution: {integrity: sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==}
engines: {node: '>= 0.10'} engines: {node: '>= 0.10'}
@@ -6781,7 +6812,6 @@ packages:
loose-envify: 1.4.0 loose-envify: 1.4.0
object-assign: 4.1.1 object-assign: 4.1.1
react-is: 16.13.1 react-is: 16.13.1
dev: true
/property-information/6.1.1: /property-information/6.1.1:
resolution: {integrity: sha512-hrzC564QIl0r0vy4l6MvRLhafmUowhO/O3KgVSoXIbbA2Sz4j8HGpJc6T2cubRVwMwpdiG/vKGfhT4IixmKN9w==} resolution: {integrity: sha512-hrzC564QIl0r0vy4l6MvRLhafmUowhO/O3KgVSoXIbbA2Sz4j8HGpJc6T2cubRVwMwpdiG/vKGfhT4IixmKN9w==}
@@ -6905,6 +6935,15 @@ packages:
strip-json-comments: 2.0.1 strip-json-comments: 2.0.1
dev: true dev: true
/react-clientside-effect/1.2.5_react@17.0.2:
resolution: {integrity: sha512-2bL8qFW1TGBHozGGbVeyvnggRpMjibeZM2536AKNENLECutp2yfs44IL8Hmpn8qjFQ2K7A9PnYf3vc7aQq/cPA==}
peerDependencies:
react: ^15.3.0 || ^16.0.0 || ^17.0.0
dependencies:
'@babel/runtime': 7.16.7
react: 17.0.2
dev: false
/react-dom/17.0.2_react@17.0.2: /react-dom/17.0.2_react@17.0.2:
resolution: {integrity: sha512-s4h96KtLDUQlsENhMn1ar8t2bEa+q/YAtj8pPPdIjPDGBDIVNsrD9aXNWqspUe6AzKCIG0C1HZZLqLV7qpOBGA==} resolution: {integrity: sha512-s4h96KtLDUQlsENhMn1ar8t2bEa+q/YAtj8pPPdIjPDGBDIVNsrD9aXNWqspUe6AzKCIG0C1HZZLqLV7qpOBGA==}
peerDependencies: peerDependencies:
@@ -6916,9 +6955,45 @@ packages:
scheduler: 0.20.2 scheduler: 0.20.2
dev: false dev: false
/react-focus-lock/2.7.1_b08e3c15324cbe90a6ff8fcd416c932c:
resolution: {integrity: sha512-ImSeVmcrLKNMqzUsIdqOkXwTVltj79OPu43oT8tVun7eIckA4VdM7UmYUFo3H/UC2nRVgagMZGFnAOQEDiDYcA==}
peerDependencies:
react: ^16.8.0 || ^17.0.0 || ^18.0.0
dependencies:
'@babel/runtime': 7.16.7
focus-lock: 0.10.1
prop-types: 15.8.1
react: 17.0.2
react-clientside-effect: 1.2.5_react@17.0.2
use-callback-ref: 1.2.5_b08e3c15324cbe90a6ff8fcd416c932c
use-sidecar: 1.0.5_react@17.0.2
transitivePeerDependencies:
- '@types/react'
dev: false
/react-focus-on/3.5.4_b08e3c15324cbe90a6ff8fcd416c932c:
resolution: {integrity: sha512-HnU0YGKhNSUsC4k6K8L+2wk8mC/qdg+CsS7A1bWLMgK7UuBphdECs2esnS6cLmBoVNjsFnCm/vMypeezKOdK3A==}
engines: {node: '>=8.5.0'}
peerDependencies:
'@types/react': ^16.8.0 || ^17.0.0 || ^18.0.0
react: ^16.8.0 || ^17.0.0 || ^18.0.0
peerDependenciesMeta:
'@types/react':
optional: true
dependencies:
'@types/react': 17.0.38
aria-hidden: 1.1.3
react: 17.0.2
react-focus-lock: 2.7.1_b08e3c15324cbe90a6ff8fcd416c932c
react-remove-scroll: 2.4.3_b08e3c15324cbe90a6ff8fcd416c932c
react-style-singleton: 2.1.1_b08e3c15324cbe90a6ff8fcd416c932c
tslib: 2.3.1
use-callback-ref: 1.2.5_b08e3c15324cbe90a6ff8fcd416c932c
use-sidecar: 1.0.5_react@17.0.2
dev: false
/react-is/16.13.1: /react-is/16.13.1:
resolution: {integrity: sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==} resolution: {integrity: sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==}
dev: true
/react-is/17.0.2: /react-is/17.0.2:
resolution: {integrity: sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==} resolution: {integrity: sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==}
@@ -6936,6 +7011,41 @@ packages:
scheduler: 0.20.2 scheduler: 0.20.2
dev: false dev: false
/react-remove-scroll-bar/2.2.0_b08e3c15324cbe90a6ff8fcd416c932c:
resolution: {integrity: sha512-UU9ZBP1wdMR8qoUs7owiVcpaPwsQxUDC2lypP6mmixaGlARZa7ZIBx1jcuObLdhMOvCsnZcvetOho0wzPa9PYg==}
engines: {node: '>=8.5.0'}
peerDependencies:
'@types/react': ^16.8.0 || ^17.0.0
react: ^16.8.0 || ^17.0.0
peerDependenciesMeta:
'@types/react':
optional: true
dependencies:
'@types/react': 17.0.38
react: 17.0.2
react-style-singleton: 2.1.1_b08e3c15324cbe90a6ff8fcd416c932c
tslib: 1.14.1
dev: false
/react-remove-scroll/2.4.3_b08e3c15324cbe90a6ff8fcd416c932c:
resolution: {integrity: sha512-lGWYXfV6jykJwbFpsuPdexKKzp96f3RbvGapDSIdcyGvHb7/eqyn46C7/6h+rUzYar1j5mdU+XECITHXCKBk9Q==}
engines: {node: '>=8.5.0'}
peerDependencies:
'@types/react': ^16.8.0 || ^17.0.0
react: ^16.8.0 || ^17.0.0
peerDependenciesMeta:
'@types/react':
optional: true
dependencies:
'@types/react': 17.0.38
react: 17.0.2
react-remove-scroll-bar: 2.2.0_b08e3c15324cbe90a6ff8fcd416c932c
react-style-singleton: 2.1.1_b08e3c15324cbe90a6ff8fcd416c932c
tslib: 1.14.1
use-callback-ref: 1.2.5_b08e3c15324cbe90a6ff8fcd416c932c
use-sidecar: 1.0.5_react@17.0.2
dev: false
/react-router-dom/6.2.1_react-dom@17.0.2+react@17.0.2: /react-router-dom/6.2.1_react-dom@17.0.2+react@17.0.2:
resolution: {integrity: sha512-I6Zax+/TH/cZMDpj3/4Fl2eaNdcvoxxHoH1tYOREsQ22OKDYofGebrNm6CTPUcvLvZm63NL/vzCYdjf9CUhqmA==} resolution: {integrity: sha512-I6Zax+/TH/cZMDpj3/4Fl2eaNdcvoxxHoH1tYOREsQ22OKDYofGebrNm6CTPUcvLvZm63NL/vzCYdjf9CUhqmA==}
peerDependencies: peerDependencies:
@@ -6955,6 +7065,23 @@ packages:
history: 5.2.0 history: 5.2.0
react: 17.0.2 react: 17.0.2
/react-style-singleton/2.1.1_b08e3c15324cbe90a6ff8fcd416c932c:
resolution: {integrity: sha512-jNRp07Jza6CBqdRKNgGhT3u9umWvils1xsuMOjZlghBDH2MU0PL2WZor4PGYjXpnRCa9DQSlHMs/xnABWOwYbA==}
engines: {node: '>=8.5.0'}
peerDependencies:
'@types/react': ^16.8.0 || ^17.0.0
react: ^16.8.0 || ^17.0.0
peerDependenciesMeta:
'@types/react':
optional: true
dependencies:
'@types/react': 17.0.38
get-nonce: 1.0.1
invariant: 2.2.4
react: 17.0.2
tslib: 1.14.1
dev: false
/react/17.0.2: /react/17.0.2:
resolution: {integrity: sha512-gnhPt75i/dq/z3/6q/0asP78D0u592D5L1pd7M8P+dck6Fu/jJeL6iVVK23fptSUZj8Vjf++7wXA8UNclGQcbA==} resolution: {integrity: sha512-gnhPt75i/dq/z3/6q/0asP78D0u592D5L1pd7M8P+dck6Fu/jJeL6iVVK23fptSUZj8Vjf++7wXA8UNclGQcbA==}
engines: {node: '>=0.10.0'} engines: {node: '>=0.10.0'}
@@ -8347,6 +8474,31 @@ packages:
querystring: 0.2.0 querystring: 0.2.0
dev: true dev: true
/use-callback-ref/1.2.5_b08e3c15324cbe90a6ff8fcd416c932c:
resolution: {integrity: sha512-gN3vgMISAgacF7sqsLPByqoePooY3n2emTH59Ur5d/M8eg4WTWu1xp8i8DHjohftIyEx0S08RiYxbffr4j8Peg==}
engines: {node: '>=8.5.0'}
peerDependencies:
'@types/react': ^16.8.0 || ^17.0.0
react: ^16.8.0 || ^17.0.0
peerDependenciesMeta:
'@types/react':
optional: true
dependencies:
'@types/react': 17.0.38
react: 17.0.2
dev: false
/use-sidecar/1.0.5_react@17.0.2:
resolution: {integrity: sha512-k9jnrjYNwN6xYLj1iaGhonDghfvmeTmYjAiGvOr7clwKfPjMXJf4/HOr7oT5tJwYafgp2tG2l3eZEOfoELiMcA==}
engines: {node: '>=8.5.0'}
peerDependencies:
react: ^16.8.0 || ^17.0.0
dependencies:
detect-node-es: 1.1.0
react: 17.0.2
tslib: 1.14.1
dev: false
/use/3.1.1: /use/3.1.1:
resolution: {integrity: sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ==} resolution: {integrity: sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ==}
engines: {node: '>=0.10.0'} engines: {node: '>=0.10.0'}