IDE redesign, initial implementation #362

Merged
Irev-Dev merged 17 commits from kurt/update-ide-panel-toolbar-360 into main 2021-06-15 10:05:03 +02:00
11 changed files with 242 additions and 127 deletions
Showing only changes of commit 3c18a24cb6 - Show all commits

View File

@@ -42,6 +42,7 @@
"react-helmet": "^6.1.0", "react-helmet": "^6.1.0",
"react-image-crop": "^8.6.6", "react-image-crop": "^8.6.6",
"react-mosaic-component": "^4.1.1", "react-mosaic-component": "^4.1.1",
"react-tabs": "^3.2.2",
"react-three-fiber": "^5.3.19", "react-three-fiber": "^5.3.19",
"rich-markdown-editor": "^11.0.2", "rich-markdown-editor": "^11.0.2",
"styled-components": "^5.2.0", "styled-components": "^5.2.0",

View File

@@ -1,6 +1,20 @@
import { useContext } from 'react'
import { Menu } from '@headlessui/react'
import { IdeContext } from 'src/components/IdeToolbarNew/IdeToolbarNew'
import Svg from 'src/components/Svg/Svg' import Svg from 'src/components/Svg/Svg'
import { useRender } from 'src/components/IdeToolbarNew/useRender'
import {makeStlDownloadHandler, PullTitleFromFirstLine} from './helpers'
Irev-Dev commented 2021-06-14 02:21:24 +02:00 (Migrated from github.com)
Review

image

![image](https://user-images.githubusercontent.com/29681384/121826268-436c6680-ccfa-11eb-9b06-ba4d61270ab5.png)
franknoirot commented 2021-06-14 15:18:09 +02:00 (Migrated from github.com)
Review

Did you do all these snippet images manually? They're very helpful!

Did you do all these snippet images manually? They're very helpful!
Irev-Dev commented 2021-06-15 10:02:26 +02:00 (Migrated from github.com)
Review

:)
Yeah I did.
CContext is super important when trying to look at other's code. You could have figured this out yourself but 20x quicker for me to add a few screen shots.

:) Yeah I did. CContext is super important when trying to look at other's code. You could have figured this out yourself but 20x quicker for me to add a few screen shots.
const EditorMenu = () => { const EditorMenu = () => {
const handleRender = useRender()
const { state, thunkDispatch } = useContext(IdeContext)
const handleStlDownload = makeStlDownloadHandler({
type: state.objectData?.type,
geometry: state.objectData?.data,
fileName: PullTitleFromFirstLine(state.code || ''),
thunkDispatch,
})
return ( return (
<div className="bg-gray-500 flex items-center h-9 w-full cursor-grab"> <div className="bg-gray-500 flex items-center h-9 w-full cursor-grab">
<div className=" text-gray-500 bg-gray-300 cursor-grab px-2 h-full flex items-center"> <div className=" text-gray-500 bg-gray-300 cursor-grab px-2 h-full flex items-center">
@@ -14,9 +28,10 @@ const EditorMenu = () => {
</button> </button>
<div className="w-px h-full bg-gray-300"/> <div className="w-px h-full bg-gray-300"/>
<div className="flex gap-6 px-6"> <div className="flex gap-6 px-6">
<button className="text-gray-100"> <FileDropdown
File handleRender={handleRender}
</button> handleStlDownload={handleStlDownload}
/>
<button className="text-gray-100"> <button className="text-gray-100">
Edit Edit
</button> </button>
@@ -29,3 +44,37 @@ const EditorMenu = () => {
} }
export default EditorMenu export default EditorMenu
franknoirot commented 2021-06-14 15:23:05 +02:00 (Migrated from github.com)
Review

With the additional background I added in the latest Figma designs we may want to start aliasing the CAD packages to class names in the next round so several elements can inherit styles.

With the additional background I added in the latest Figma designs we may want to start aliasing the CAD packages to class names in the next round so several elements can inherit styles.
Irev-Dev commented 2021-06-15 10:02:44 +02:00 (Migrated from github.com)
Review

Oh right, yeah that's a good idea.

Oh right, yeah that's a good idea.
function FileDropdown({handleRender, handleStlDownload}) {
return (
<Menu>
<Menu.Button className="text-gray-100">File</Menu.Button>
<Menu.Items className="absolute flex flex-col mt-10 bg-gray-500 rounded shadow-md text-gray-100">
<Menu.Item>
{({ active }) => (
<button
className={`${active && 'bg-gray-600'} px-2 py-1`}
onClick={handleRender}
>
Irev-Dev commented 2021-06-14 02:21:45 +02:00 (Migrated from github.com)
Review

image

![image](https://user-images.githubusercontent.com/29681384/121826279-4ff0bf00-ccfa-11eb-8315-bd8a4cfc0ef7.png)
Save &amp; Render <span className="text-gray-400 pl-4">{
/(Mac|iPhone|iPod|iPad)/i.test(navigator.platform) ?
<><Svg name="mac-cmd-key" className="h-3 w-3 inline-block text-left" />S</> :
'Ctrl S'
}</span>
</button>
)}
</Menu.Item>
<Menu.Item>
{({ active }) => (
<button
className={`${active && 'bg-gray-600'} px-2 py-1 text-left`}
onClick={handleStlDownload}
>
Download STL
</button>
)}
</Menu.Item>
</Menu.Items>
</Menu>
)
}

View File

@@ -0,0 +1,59 @@
import { flow, identity } from 'lodash/fp'
import { fileSave } from 'browser-fs-access'
import { MeshBasicMaterial, Mesh, Scene } from 'three'
import { STLExporter } from 'three/examples/jsm/exporters/STLExporter'
import { requestRender } from 'src/helpers/hooks/useIdeState'
export const PullTitleFromFirstLine = (code: string = '') => {
const firstLine = code.split('\n').filter(identity)[0] || ''
if (!(firstLine.startsWith('//') || firstLine.startsWith('#'))) {
return 'object.stl'
}
return (
(firstLine.replace(/^(\/\/|#)\s*(.+)/, (_, __, titleWithSpaces) =>
titleWithSpaces.replaceAll(/\s/g, '-')
) || 'object') + '.stl'
)
}
export const makeStlDownloadHandler = (({ geometry, fileName, type, thunkDispatch}) => () => {
const makeStlBlobFromGeo = flow(
(geo) => new Mesh(geo, new MeshBasicMaterial()),
(mesh) => new Scene().add(mesh),
(scene) => new STLExporter().parse(scene),
(stl) =>
new Blob([stl], {
type: 'text/plain',
})
)
const saveFile = (geometry) => {
const blob = makeStlBlobFromGeo(geometry)
fileSave(blob, {
fileName,
extensions: ['.stl'],
})
}
if (geometry) {
if (type === 'geometry') {
saveFile(geometry)
} else {
thunkDispatch((dispatch, getState) => {
const state = getState()
if (state.ideType === 'openScad') {
thunkDispatch((dispatch, getState) => {
const state = getState()
dispatch({ type: 'setLoading' })
requestRender({
state,
dispatch,
code: state.code,
viewerSize: state.viewerSize,
camera: state.camera,
specialCadProcess: 'stl',
}).then((result) => result && saveFile(result.data))
})
}
})
}
}
})

View File

@@ -1,23 +1,57 @@
import Svg from 'src/components/Svg/Svg' import { Popover } from '@headlessui/react'
import { Tab, Tabs, TabList, TabPanel } from 'react-tabs';
import { copyTextToClipboard } from 'src/helpers/clipboard'
import { encode } from 'src/helpers/compress'
const TopButton = ({children}) => ( const TopButton = ({children, onClick}: {onClick?: () => void, children: React.ReactNode}) => (
<button className="flex bg-gray-500 h-10 justify-center items-center px-4 rounded"> <button onClick={onClick} className="flex bg-gray-500 h-10 justify-center items-center px-4 rounded">
<div className="rounded-full bg-gray-200 h-6 w-6 mr-4"/> <div className="rounded-full bg-gray-200 h-6 w-6 mr-4"/>
{children} {children}
</button> </button>
) )
const IdeHeader = () => { const IdeHeader = ({handleRender}: {handleRender: () => void}) => {
return ( return (
<div className="h-16 bg-gray-900 flex justify-between items-center"> <div className="h-16 w-full bg-gray-900 flex justify-between items-center">
<div className="bg-gray-700 pr-48 h-full"> <div className="bg-gray-700 pr-48 h-full">
<div className="w-16 h-full flex items-center justify-center bg-gray-900">
<Svg className="w-12" name="favicon" />
</div>
</div> </div>
<div className="text-gray-200 flex gap-4 mr-4"> <div className="text-gray-200 flex gap-4 mr-4">
<TopButton>Render</TopButton> <TopButton onClick={handleRender}>Render</TopButton>
<TopButton>Share</TopButton>
<Popover className="relative outline-none w-full h-full">
{({open}) => {
const encodedLink = makeEncodedLink('bing bong')
return (
<>
Irev-Dev commented 2021-06-14 02:34:39 +02:00 (Migrated from github.com)
Review

image

![image](https://user-images.githubusercontent.com/29681384/121826642-1d47c600-ccfc-11eb-89d1-a0ac63141405.png)
<Popover.Button className="h-full w-full outline-none">
<TopButton>Share</TopButton>
</Popover.Button>
{open && <Popover.Panel className="absolute z-10 mt-4 right-0">
<Tabs
className="bg-gray-300 rounded-md shadow-md overflow-hidden text-gray-700"
selectedTabClassName="bg-gray-200"
>
<TabPanel className="p-4">
<p className="text-sm pb-4 border-b border-gray-700">Encodes your CodeCad script into a URL so that you can share your work</p>
<input value={encodedLink.replace(/^.+:\/\//g, '')} readOnly className="p-1 mt-4 text-xs rounded-t border border-gray-700 w-full" />
<button className="w-full bg-gray-700 py-1 rounded-b text-gray-300" onClick={() => copyTextToClipboard(encodedLink)} >Copy URL</button>
</TabPanel>
<TabPanel>
<h2 className="h-32">Any content 2</h2>
</TabPanel>
<TabList className="flex whitespace-nowrap text-gray-700 border-t border-gray-700">
<Tab className="p-3 px-5">encoded script</Tab>
<Tab className="p-3 px-5">external script</Tab>
</TabList>
</Tabs>
</Popover.Panel>}
</>
)
}}
</Popover>
<TopButton>Fork</TopButton> <TopButton>Fork</TopButton>
</div> </div>
</div> </div>
@@ -25,3 +59,10 @@ const IdeHeader = () => {
} }
export default IdeHeader export default IdeHeader
const scriptKeyV2 = 'encoded_script_v2' // todo don't leave here
function makeEncodedLink(code: string): string {
const encodedScript = encode(code)
return `${location.href}#${scriptKeyV2}=${encodedScript}`
}

View File

@@ -2,7 +2,10 @@ import Svg from 'src/components/Svg/Svg'
const IdeSideBar = () => { const IdeSideBar = () => {
return ( return (
Irev-Dev commented 2021-06-14 02:35:11 +02:00 (Migrated from github.com)
Review

image

![image](https://user-images.githubusercontent.com/29681384/121826656-2fc1ff80-ccfc-11eb-998b-55c254eeaae6.png)
<div className="h-full flex flex-col justify-end"> <div className="h-full flex flex-col justify-between">
<div className="w-16 h-16 flex items-center justify-center bg-gray-900">
<Svg className="w-12" name="favicon" />
</div>
<button className=" text-gray-300 p-2 pb-4 flex justify-center" aria-label="IDE settings"> <button className=" text-gray-300 p-2 pb-4 flex justify-center" aria-label="IDE settings">
<Svg name="big-gear" /> <Svg name="big-gear" />
</button> </button>

View File

@@ -1,16 +1,13 @@
import { createContext, useEffect } from 'react' import { createContext, useEffect } from 'react'
import IdeContainer from 'src/components/IdeContainer' import IdeContainer from 'src/components/IdeContainer'
import { isBrowser } from '@redwoodjs/prerender/browserUtils' import { isBrowser } from '@redwoodjs/prerender/browserUtils'
import { useIdeState, makeCodeStoreKey } from 'src/helpers/hooks/useIdeState' import { useIdeState } from 'src/helpers/hooks/useIdeState'
import { copyTextToClipboard } from 'src/helpers/clipboard' import { handleRenderVerbose } from './useRender'
import { requestRender } from 'src/helpers/hooks/useIdeState' import { decode } from 'src/helpers/compress'
import { encode, decode } from 'src/helpers/compress' import { flow } from 'lodash/fp'
import { flow, identity } from 'lodash/fp'
import { fileSave } from 'browser-fs-access'
import { MeshBasicMaterial, Mesh, Scene } from 'three'
import { STLExporter } from 'three/examples/jsm/exporters/STLExporter'
import OutBound from 'src/components/OutBound' import OutBound from 'src/components/OutBound'
import IdeSideBar from 'src/components/IdeSideBar' import IdeSideBar from 'src/components/IdeSideBar'
import IdeHeader from 'src/components/IdeHeader'
export const githubSafe = (url) => export const githubSafe = (url) =>
url.includes('github.com') url.includes('github.com')
@@ -65,83 +62,8 @@ const IdeToolbarNew = ({ cadPackage }) => {
window.location.hash = '' window.location.hash = ''
}, [cadPackage]) }, [cadPackage])
function handleRender() { function handleRender() {
thunkDispatch((dispatch, getState) => { return handleRenderVerbose({thunkDispatch, state})
const state = getState()
dispatch({ type: 'setLoading' })
requestRender({
state,
dispatch,
code: state.code,
viewerSize: state.viewerSize,
camera: state.camera,
})
})
localStorage.setItem(makeCodeStoreKey(state.ideType), state.code)
} }
function handleMakeLink() {
if (isBrowser) {
const encodedScript = encode(state.code)
window.location.hash = `${scriptKeyV2}=${encodedScript}`
copyTextToClipboard(window.location.href)
}
}
const PullTitleFromFirstLine = (code = '') => {
const firstLine = code.split('\n').filter(identity)[0] || ''
if (!(firstLine.startsWith('//') || firstLine.startsWith('#'))) {
return 'object.stl'
}
return (
(firstLine.replace(/^(\/\/|#)\s*(.+)/, (_, __, titleWithSpaces) =>
titleWithSpaces.replaceAll(/\s/g, '-')
) || 'object') + '.stl'
)
}
const handleStlDownload = (({ geometry, fileName, type }) => () => {
const makeStlBlobFromGeo = flow(
(geo) => new Mesh(geo, new MeshBasicMaterial()),
(mesh) => new Scene().add(mesh),
(scene) => new STLExporter().parse(scene),
(stl) =>
new Blob([stl], {
type: 'text/plain',
})
)
const saveFile = (geometry) => {
const blob = makeStlBlobFromGeo(geometry)
fileSave(blob, {
fileName,
extensions: ['.stl'],
})
}
if (geometry) {
if (type === 'geometry') {
saveFile(geometry)
} else {
thunkDispatch((dispatch, getState) => {
const state = getState()
if (state.ideType === 'openScad') {
thunkDispatch((dispatch, getState) => {
const state = getState()
dispatch({ type: 'setLoading' })
requestRender({
state,
dispatch,
code: state.code,
viewerSize: state.viewerSize,
camera: state.camera,
specialCadProcess: 'stl',
}).then((result) => result && saveFile(result.data))
})
}
})
}
}
})({
type: state.objectData?.type,
geometry: state.objectData?.data,
fileName: PullTitleFromFirstLine(state.code),
})
return ( return (
<IdeContext.Provider value={{ state, thunkDispatch }}> <IdeContext.Provider value={{ state, thunkDispatch }}>
@@ -150,6 +72,9 @@ const IdeToolbarNew = ({ cadPackage }) => {
<IdeSideBar /> <IdeSideBar />
</div> </div>
<div className="h-full flex flex-grow flex-col"> <div className="h-full flex flex-grow flex-col">
<nav className="flex">
<IdeHeader handleRender={handleRender} />
</nav>
<div className="py-2 bg-pink-200"> <div className="py-2 bg-pink-200">
<div className="mx-auto max-w-3xl"> <div className="mx-auto max-w-3xl">
We're still working on this. Since you're here, have a look what{' '} We're still working on this. Since you're here, have a look what{' '}
@@ -162,26 +87,6 @@ const IdeToolbarNew = ({ cadPackage }) => {
. .
</div> </div>
</div> </div>
<nav className="flex">
<button
onClick={handleRender}
className="border-2 px-2 text-gray-700 text-sm m-1"
>
Render
</button>
<button
onClick={handleMakeLink}
className="border-2 text-gray-700 px-2 text-sm m-1 ml-2"
>
Copy link
</button>
<button
onClick={handleStlDownload}
className="border-2 text-gray-700 px-2 text-sm m-1 ml-2"
>
Download STL
</button>
</nav>
<IdeContainer /> <IdeContainer />
</div> </div>
</div> </div>

View File

@@ -0,0 +1,25 @@
import { makeCodeStoreKey } from 'src/helpers/hooks/useIdeState'
import { requestRender } from 'src/helpers/hooks/useIdeState'
import { useContext } from 'react'
import { IdeContext } from 'src/components/IdeToolbarNew/IdeToolbarNew'
export const handleRenderVerbose = ({thunkDispatch, state}) => {
thunkDispatch((dispatch, getState) => {
const state = getState()
dispatch({ type: 'setLoading' })
requestRender({
state,
dispatch,
code: state.code,
viewerSize: state.viewerSize,
camera: state.camera,
})
})
localStorage.setItem(makeCodeStoreKey(state.ideType), state.code)
}
export const useRender = () => {
const { state, thunkDispatch } = useContext(IdeContext)
return () => handleRenderVerbose({thunkDispatch, state})
}

View File

@@ -14,6 +14,7 @@ type SvgNames = 'arrow-down' |
'gear' | 'gear' |
'lightbulb' | 'lightbulb' |
'logout' | 'logout' |
'mac-cmd-key' |
'pencil' | 'pencil' |
'plus' | 'plus' |
'plus-circle' | 'plus-circle' |
@@ -323,6 +324,18 @@ const Svg = ({ name, className: className2 = '', strokeWidth = 2 }: {
/> />
</svg> </svg>
), ),
'mac-cmd-key': (
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 220 220"
>
<
path
fill="currentColor"
d="M57.254,121.064c-17.735,0-31.45,4.723-40.765,14.035c-19.39,19.391-19.39,50.943,0,70.334 C25.884,214.828,38.375,220,51.66,220c0,0,0,0,0,0c13.284,0,25.774-5.172,35.168-14.566c11.069-11.07,14.037-27.061,14.041-41.016 c0.001-3.531,0.017-10.09,0.017-10.09h18.227c0,0,0.016,6.559,0.018,10.09c0.004,13.955,2.971,29.945,14.041,41.016 C142.565,214.828,155.056,220,168.34,220c13.285,0,25.775-5.172,35.17-14.566c19.391-19.391,19.391-50.943,0-70.334 c-9.314-9.312-23.029-14.035-40.764-14.035c-3.602,0-10.346,0.02-10.346,0.02c0-0.932,0-22.178,0-22.178s6.744,0.029,10.346,0.029 c17.734,0,31.449-4.721,40.762-14.033c19.391-19.392,19.391-50.943,0.002-70.334C194.113,5.174,181.624,0,168.34,0 c-13.285,0-25.773,5.174-35.168,14.566c-10.67,10.672-13.812,25.914-14.029,39.498l-0.193,11.609H101.05l-0.192-11.609 c-0.217-13.584-3.359-28.826-14.03-39.498C77.434,5.174,64.944,0,51.66,0C38.376,0,25.886,5.174,16.49,14.568 C-2.899,33.959-2.899,65.51,16.491,84.902c9.314,9.313,23.028,14.033,40.762,14.033c3.601,0,10.346-0.029,10.346-0.029 s0,21.246,0,22.178C67.6,121.084,60.855,121.064,57.254,121.064z M154.328,35.587c3.727-3.726,8.683-5.779,13.954-5.779 s10.229,2.053,13.957,5.781c7.692,7.693,7.692,20.213-0.002,27.906c-3.384,3.385-10.327,5.248-19.549,5.248 c-4.6,0-14.107,0-14.107,0v-8.688C148.581,60.056,147.566,41.495,154.328,35.587z M148.581,159.945v-8.688c0,0,9.508,0,14.107,0 c9.222,0,16.165,1.863,19.549,5.248c7.694,7.693,7.694,20.213,0.002,27.906c-3.729,3.729-8.686,5.781-13.957,5.781 s-10.228-2.053-13.954-5.779C147.566,178.506,148.581,159.945,148.581,159.945z M93.75,93.75h32.5v32.5h-32.5V93.75z M57.312,68.743 c-9.222,0-16.165-1.863-19.549-5.248c-7.694-7.693-7.694-20.213-0.002-27.906c3.729-3.729,8.686-5.781,13.957-5.781 s10.228,2.053,13.954,5.779c6.762,5.908,5.747,24.469,5.747,24.469v8.688C71.419,68.743,61.911,68.743,57.312,68.743z M71.419,151.258v8.688c0,0,1.015,18.561-5.747,24.469c-3.727,3.727-8.683,5.779-13.954,5.779s-10.229-2.053-13.957-5.781 c-7.692-7.693-7.692-20.213,0.002-27.906c3.384-3.385,10.327-5.248,19.549-5.248C61.911,151.258,71.419,151.258,71.419,151.258z"
/>
</svg>
),
pencil: ( pencil: (
<svg <svg
xmlns="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg"

View File

@@ -1,4 +1,6 @@
function fallbackCopyTextToClipboard(text) { import { toast } from '@redwoodjs/web/toast'
function fallbackCopyTextToClipboard(text: string) {
var textArea = document.createElement('textarea') var textArea = document.createElement('textarea')
textArea.value = text textArea.value = text
@@ -21,17 +23,28 @@ function fallbackCopyTextToClipboard(text) {
document.body.removeChild(textArea) document.body.removeChild(textArea)
} }
export function copyTextToClipboard(text) {
const clipboardSuccessToast = (text: string) => toast.success(() => (
<div className="overflow-hidden">
<p>link added to clipboard.</p>
</div>
))
const makeClipboardCopier = (success: Function) => (text: string) => {
if (!navigator.clipboard) { if (!navigator.clipboard) {
fallbackCopyTextToClipboard(text) fallbackCopyTextToClipboard(text)
success(text)
return return
} }
navigator.clipboard.writeText(text).then( navigator.clipboard.writeText(text).then(
function () { function () {
console.log('Async: Copying to clipboard was successful!') console.log('Async: Copying to clipboard was successful!')
success(text)
}, },
function (err) { function (err) {
console.error('Async: Could not copy text: ', err) console.error('Async: Could not copy text: ', err)
} }
) )
} }
export const copyTextToClipboard = makeClipboardCopier(clipboardSuccessToast)

View File

@@ -1,6 +1,6 @@
import Seo from 'src/components/Seo/Seo' import Seo from 'src/components/Seo/Seo'
import IdeToolbar from 'src/components/IdeToolbarNew' import IdeToolbar from 'src/components/IdeToolbarNew'
import IdeHeader from 'src/components/IdeHeader' import { Toaster } from '@redwoodjs/web/toast'
const DevIdePage = ({ cadPackage }) => { const DevIdePage = ({ cadPackage }) => {
return ( return (
@@ -10,10 +10,8 @@ const DevIdePage = ({ cadPackage }) => {
description="new ide in development" description="new ide in development"
lang="en-US" lang="en-US"
/> />
<IdeHeader /> <Toaster timeout={9000} />
<div className="flex-auto"> <IdeToolbar cadPackage={cadPackage} />
<IdeToolbar cadPackage={cadPackage} />
</div>
</div> </div>
) )
} }

View File

@@ -6827,7 +6827,7 @@ cloudinary@^1.23.0:
lodash "^4.17.11" lodash "^4.17.11"
q "^1.5.1" q "^1.5.1"
clsx@^1.0.4, clsx@^1.1.1: clsx@^1.0.4, clsx@^1.1.0, clsx@^1.1.1:
version "1.1.1" version "1.1.1"
resolved "https://registry.yarnpkg.com/clsx/-/clsx-1.1.1.tgz#98b3134f9abbdf23b2663491ace13c5c03a73188" resolved "https://registry.yarnpkg.com/clsx/-/clsx-1.1.1.tgz#98b3134f9abbdf23b2663491ace13c5c03a73188"
integrity sha512-6/bPho624p3S2pMyvP5kKBPXnI3ufHLObBFCfgx+LkeR5lg2XYy2hqZqUf45ypD8COn2bhgGJSUE+l5dhNBieA== integrity sha512-6/bPho624p3S2pMyvP5kKBPXnI3ufHLObBFCfgx+LkeR5lg2XYy2hqZqUf45ypD8COn2bhgGJSUE+l5dhNBieA==
@@ -14898,7 +14898,7 @@ prompts@2.4.1, prompts@^2.0.1:
kleur "^3.0.3" kleur "^3.0.3"
sisteransi "^1.0.5" sisteransi "^1.0.5"
prop-types@^15.5.10, prop-types@^15.5.8, prop-types@^15.6.0, prop-types@^15.6.1, prop-types@^15.6.2, prop-types@^15.7.2: prop-types@^15.5.0, prop-types@^15.5.10, prop-types@^15.5.8, prop-types@^15.6.0, prop-types@^15.6.1, prop-types@^15.6.2, prop-types@^15.7.2:
version "15.7.2" version "15.7.2"
resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.7.2.tgz#52c41e75b8c87e72b9d9360e0206b99dcbffa6c5" resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.7.2.tgz#52c41e75b8c87e72b9d9360e0206b99dcbffa6c5"
integrity sha512-8QQikdH7//R2vurIJSutZ1smHYTcLpRWEOlHnzcWHmBYrOGUysKwSsrC89BCiFj3CbrfJ/nXFdJepOVrY1GCHQ== integrity sha512-8QQikdH7//R2vurIJSutZ1smHYTcLpRWEOlHnzcWHmBYrOGUysKwSsrC89BCiFj3CbrfJ/nXFdJepOVrY1GCHQ==
@@ -15610,6 +15610,14 @@ react-syntax-highlighter@^13.5.0, react-syntax-highlighter@^13.5.3:
prismjs "^1.21.0" prismjs "^1.21.0"
refractor "^3.1.0" refractor "^3.1.0"
react-tabs@^3.2.2:
version "3.2.2"
resolved "https://registry.yarnpkg.com/react-tabs/-/react-tabs-3.2.2.tgz#07bdc3cdb17bdffedd02627f32a93cd4b3d6e4d0"
integrity sha512-/o52eGKxFHRa+ssuTEgSM8qORnV4+k7ibW+aNQzKe+5gifeVz8nLxCrsI9xdRhfb0wCLdgIambIpb1qCxaMN+A==
dependencies:
clsx "^1.1.0"
prop-types "^15.5.0"
react-textarea-autosize@^8.1.1: react-textarea-autosize@^8.1.1:
version "8.3.3" version "8.3.3"
resolved "https://registry.yarnpkg.com/react-textarea-autosize/-/react-textarea-autosize-8.3.3.tgz#f70913945369da453fd554c168f6baacd1fa04d8" resolved "https://registry.yarnpkg.com/react-textarea-autosize/-/react-textarea-autosize-8.3.3.tgz#f70913945369da453fd554c168f6baacd1fa04d8"