Export (#213)
* initial Signed-off-by: Jess Frazelle <github@jessfraz.com> update Signed-off-by: Jess Frazelle <github@jessfraz.com> * updates Signed-off-by: Jess Frazelle <github@jessfraz.com> * start of tauri Signed-off-by: Jess Frazelle <github@jessfraz.com> * updates Signed-off-by: Jess Frazelle <github@jessfraz.com> * better Signed-off-by: Jess Frazelle <github@jessfraz.com> * set the default type Signed-off-by: Jess Frazelle <github@jessfraz.com> * updates Signed-off-by: Jess Frazelle <github@jessfraz.com> * add comments Signed-off-by: Jess Frazelle <github@jessfraz.com> * fix Signed-off-by: Jess Frazelle <github@jessfraz.com> * updates Signed-off-by: Jess Frazelle <github@jessfraz.com> * dialog for save tauri Signed-off-by: Jess Frazelle <github@jessfraz.com> * partial tsc fix * bump kittycad lib * Update src/lib/exportSave.ts Co-authored-by: Kurt Hutten <k.hutten@protonmail.ch> * updates; Signed-off-by: Jess Frazelle <github@jessfraz.com> * default coords Signed-off-by: Jess Frazelle <github@jessfraz.com> --------- Signed-off-by: Jess Frazelle <github@jessfraz.com> Co-authored-by: Kurt Hutten Irev-Dev <k.hutten@protonmail.ch>
This commit is contained in:
@ -8,7 +8,7 @@
|
||||
"@fortawesome/free-solid-svg-icons": "^6.4.0",
|
||||
"@fortawesome/react-fontawesome": "^0.2.0",
|
||||
"@headlessui/react": "^1.7.13",
|
||||
"@kittycad/lib": "^0.0.22",
|
||||
"@kittycad/lib": "^0.0.24",
|
||||
"@react-hook/resize-observer": "^1.2.6",
|
||||
"@tauri-apps/api": "^1.3.0",
|
||||
"@testing-library/jest-dom": "^5.14.1",
|
||||
@ -21,12 +21,14 @@
|
||||
"@uiw/react-codemirror": "^4.15.1",
|
||||
"allotment": "^1.17.0",
|
||||
"crypto-js": "^4.1.1",
|
||||
"formik": "^2.4.3",
|
||||
"http-server": "^14.1.1",
|
||||
"react": "^18.2.0",
|
||||
"react-dom": "^18.2.0",
|
||||
"react-hot-toast": "^2.4.1",
|
||||
"react-hotkeys-hook": "^4.4.1",
|
||||
"react-json-view": "^1.21.3",
|
||||
"react-modal": "^3.16.1",
|
||||
"react-modal-promise": "^1.0.2",
|
||||
"react-router-dom": "^6.14.2",
|
||||
"sketch-helpers": "^0.0.4",
|
||||
@ -82,7 +84,9 @@
|
||||
"@tauri-apps/cli": "^1.3.1",
|
||||
"@types/crypto-js": "^4.1.1",
|
||||
"@types/isomorphic-fetch": "^0.0.36",
|
||||
"@types/react-modal": "^3.16.0",
|
||||
"@types/uuid": "^9.0.1",
|
||||
"@types/wicg-file-system-access": "^2020.9.6",
|
||||
"@types/ws": "^8.5.5",
|
||||
"@vitejs/plugin-react": "^4.0.3",
|
||||
"autoprefixer": "^10.4.13",
|
||||
|
@ -11,6 +11,7 @@ import { SetAngleLength } from './components/Toolbar/setAngleLength'
|
||||
import { ConvertToVariable } from './components/Toolbar/ConvertVariable'
|
||||
import { SetAbsDistance } from './components/Toolbar/SetAbsDistance'
|
||||
import { SetAngleBetween } from './components/Toolbar/SetAngleBetween'
|
||||
import { ExportButton } from './components/ExportButton'
|
||||
|
||||
export const Toolbar = () => {
|
||||
const {
|
||||
@ -31,6 +32,7 @@ export const Toolbar = () => {
|
||||
|
||||
return (
|
||||
<div>
|
||||
<ExportButton />
|
||||
{guiMode.mode === 'default' && (
|
||||
<button
|
||||
onClick={() => {
|
||||
|
185
src/components/ExportButton.tsx
Normal file
185
src/components/ExportButton.tsx
Normal file
@ -0,0 +1,185 @@
|
||||
import { v4 as uuidv4 } from 'uuid'
|
||||
import { useStore } from '../useStore'
|
||||
import { faXmark } from '@fortawesome/free-solid-svg-icons'
|
||||
import { ActionButton } from './ActionButton'
|
||||
import Modal from 'react-modal'
|
||||
import React from 'react'
|
||||
import { useFormik } from 'formik'
|
||||
import { Models } from '@kittycad/lib'
|
||||
|
||||
type OutputFormat = Models['OutputFormat_type']
|
||||
|
||||
export const ExportButton = () => {
|
||||
const { engineCommandManager } = useStore((s) => ({
|
||||
engineCommandManager: s.engineCommandManager,
|
||||
}))
|
||||
|
||||
const [modalIsOpen, setIsOpen] = React.useState(false)
|
||||
|
||||
const defaultType = 'gltf'
|
||||
const [type, setType] = React.useState(defaultType)
|
||||
|
||||
const customModalStyles = {
|
||||
content: {
|
||||
top: '50%',
|
||||
left: '50%',
|
||||
right: 'auto',
|
||||
bottom: 'auto',
|
||||
marginRight: '-50%',
|
||||
transform: 'translate(-50%, -50%)',
|
||||
},
|
||||
}
|
||||
|
||||
function openModal() {
|
||||
setIsOpen(true)
|
||||
}
|
||||
|
||||
function closeModal() {
|
||||
setIsOpen(false)
|
||||
}
|
||||
|
||||
// Default to gltf and embedded.
|
||||
const initialValues: OutputFormat = {
|
||||
type: defaultType,
|
||||
storage: 'embedded',
|
||||
}
|
||||
const formik = useFormik({
|
||||
initialValues,
|
||||
onSubmit: (values: OutputFormat) => {
|
||||
// Set the default coords.
|
||||
if (
|
||||
values.type === 'obj' ||
|
||||
values.type === 'ply' ||
|
||||
values.type === 'step' ||
|
||||
values.type === 'stl'
|
||||
) {
|
||||
// Set the default coords.
|
||||
// In the future we can make this configurable.
|
||||
// But for now, its probably best to keep it consistent with the
|
||||
// UI.
|
||||
values.coords = {
|
||||
forward: {
|
||||
axis: 'y',
|
||||
direction: 'negative',
|
||||
},
|
||||
up: {
|
||||
axis: 'z',
|
||||
direction: 'positive',
|
||||
},
|
||||
}
|
||||
}
|
||||
engineCommandManager?.sendSceneCommand({
|
||||
type: 'modeling_cmd_req',
|
||||
cmd: {
|
||||
type: 'export',
|
||||
// By default let's leave this blank to export the whole scene.
|
||||
// In the future we might want to let the user choose which entities
|
||||
// in the scene to export. In that case, you'd pass the IDs thru here.
|
||||
entity_ids: [],
|
||||
format: values,
|
||||
},
|
||||
cmd_id: uuidv4(),
|
||||
file_id: uuidv4(),
|
||||
})
|
||||
|
||||
closeModal()
|
||||
},
|
||||
})
|
||||
|
||||
return (
|
||||
<>
|
||||
<button onClick={openModal}>Export</button>
|
||||
<Modal
|
||||
isOpen={modalIsOpen}
|
||||
onRequestClose={closeModal}
|
||||
contentLabel="Export"
|
||||
style={customModalStyles}
|
||||
>
|
||||
<div className="text-black">
|
||||
<h1 className="text-2xl font-bold">Export your design</h1>
|
||||
<form onSubmit={formik.handleSubmit}>
|
||||
<p>
|
||||
<label htmlFor="type">Type</label>
|
||||
</p>
|
||||
<p>
|
||||
<select
|
||||
id="type"
|
||||
name="type"
|
||||
onChange={(e) => {
|
||||
setType(e.target.value)
|
||||
formik.handleChange(e)
|
||||
}}
|
||||
>
|
||||
<option value="gltf">gltf</option>
|
||||
<option value="obj">obj</option>
|
||||
<option value="ply">ply</option>
|
||||
<option value="step">step</option>
|
||||
<option value="stl">stl</option>
|
||||
</select>
|
||||
</p>
|
||||
|
||||
{(type === 'gltf' || type === 'ply' || type === 'stl') && (
|
||||
<>
|
||||
<p>
|
||||
{' '}
|
||||
<label htmlFor="storage">Storage</label>
|
||||
</p>
|
||||
<p>
|
||||
<select
|
||||
id="storage"
|
||||
name="storage"
|
||||
onChange={formik.handleChange}
|
||||
value={formik.values.storage}
|
||||
>
|
||||
{type === 'gltf' && (
|
||||
<>
|
||||
<option value="embedded">embedded</option>
|
||||
<option value="binary">binary</option>
|
||||
<option value="standard">standard</option>
|
||||
</>
|
||||
)}
|
||||
{type === 'ply' && (
|
||||
<>
|
||||
<option value="ascii">ascii</option>
|
||||
<option value="binary">binary</option>
|
||||
</>
|
||||
)}
|
||||
{type === 'stl' && (
|
||||
<>
|
||||
<option value="ascii">ascii</option>
|
||||
<option value="binary_little_endian">
|
||||
binary_little_endian
|
||||
</option>
|
||||
<option value="binary_big_endian">
|
||||
binary_big_endian
|
||||
</option>
|
||||
</>
|
||||
)}
|
||||
</select>
|
||||
</p>
|
||||
</>
|
||||
)}
|
||||
|
||||
<div className="flex justify-between mt-6">
|
||||
<button type="submit">Submit</button>
|
||||
</div>
|
||||
</form>
|
||||
<div className="flex justify-between mt-6">
|
||||
<ActionButton
|
||||
onClick={closeModal}
|
||||
icon={{
|
||||
icon: faXmark,
|
||||
bgClassName: 'bg-destroy-80',
|
||||
iconClassName:
|
||||
'text-destroy-20 group-hover:text-destroy-10 hover:text-destroy-10',
|
||||
}}
|
||||
className="hover:border-destroy-40"
|
||||
>
|
||||
Close
|
||||
</ActionButton>
|
||||
</div>
|
||||
</div>
|
||||
</Modal>
|
||||
</>
|
||||
)
|
||||
}
|
@ -2,6 +2,7 @@ import { SourceRange } from '../executor'
|
||||
import { Selections } from '../../useStore'
|
||||
import { VITE_KC_API_WS_MODELING_URL } from '../../env'
|
||||
import { Models } from '@kittycad/lib'
|
||||
import { exportSave } from '../../lib/exportSave'
|
||||
|
||||
interface ResultCommand {
|
||||
type: 'result'
|
||||
@ -65,6 +66,10 @@ export class EngineCommandManager {
|
||||
})
|
||||
|
||||
this.socket = new WebSocket(VITE_KC_API_WS_MODELING_URL, [])
|
||||
|
||||
// Change binary type from "blob" to "arraybuffer"
|
||||
this.socket.binaryType = 'arraybuffer'
|
||||
|
||||
this.pc = new RTCPeerConnection()
|
||||
this.pc.createDataChannel('unreliable_modeling_cmds')
|
||||
this.socket.addEventListener('open', (event) => {
|
||||
@ -87,15 +92,13 @@ export class EngineCommandManager {
|
||||
this?.socket?.addEventListener('message', (event) => {
|
||||
if (!this.socket || !this.pc) return
|
||||
|
||||
//console.log('Message from server ', event.data);
|
||||
if (event.data instanceof Blob) {
|
||||
const reader = new FileReader()
|
||||
|
||||
reader.onload = () => {
|
||||
//console.log("Result: " + reader.result);
|
||||
}
|
||||
|
||||
reader.readAsText(event.data)
|
||||
// console.log('Message from server ', event.data);
|
||||
if (event.data instanceof ArrayBuffer) {
|
||||
// If the data is an ArrayBuffer, it's the result of an export command,
|
||||
// because in all other cases we send JSON strings. But in the case of
|
||||
// export we send a binary blob.
|
||||
// Pass this to our export function.
|
||||
exportSave(event.data)
|
||||
} else if (
|
||||
typeof event.data === 'string' &&
|
||||
event.data.toLocaleLowerCase().startsWith('error')
|
||||
@ -211,6 +214,7 @@ export class EngineCommandManager {
|
||||
} else if (message.type === 'click') {
|
||||
this.onClickCallback(message)
|
||||
} else {
|
||||
console.log('received message', message)
|
||||
}
|
||||
}
|
||||
})
|
||||
@ -272,6 +276,7 @@ export class EngineCommandManager {
|
||||
this.lossyDataChannel.send(JSON.stringify(command))
|
||||
return
|
||||
}
|
||||
console.log('sending command', command)
|
||||
this.socket?.send(JSON.stringify(command))
|
||||
}
|
||||
sendModellingCommand({
|
||||
|
53
src/lib/browserSaveFile.ts
Normal file
53
src/lib/browserSaveFile.ts
Normal file
@ -0,0 +1,53 @@
|
||||
/// The method below uses the File System Access API when it's supported and
|
||||
// else falls back to the classic approach. In both cases the function saves
|
||||
// the file, but in case of where the File System Access API is supported, the
|
||||
// user will get a file save dialog where they can choose where the file should be saved.
|
||||
export const browserSaveFile = async (blob: Blob, suggestedName: string) => {
|
||||
// Feature detection. The API needs to be supported
|
||||
// and the app not run in an iframe.
|
||||
const supportsFileSystemAccess =
|
||||
'showSaveFilePicker' in window &&
|
||||
(() => {
|
||||
try {
|
||||
return window.self === window.top
|
||||
} catch {
|
||||
return false
|
||||
}
|
||||
})()
|
||||
// If the File System Access API is supported…
|
||||
if (supportsFileSystemAccess && window.showSaveFilePicker) {
|
||||
try {
|
||||
// Show the file save dialog.
|
||||
const handle = await window.showSaveFilePicker({
|
||||
suggestedName,
|
||||
})
|
||||
// Write the blob to the file.
|
||||
const writable = await handle.createWritable()
|
||||
await writable.write(blob)
|
||||
await writable.close()
|
||||
return
|
||||
} catch (err: any) {
|
||||
// Fail silently if the user has simply canceled the dialog.
|
||||
if (err.name !== 'AbortError') {
|
||||
console.error(err.name, err.message)
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
// Fallback if the File System Access API is not supported…
|
||||
// Create the blob URL.
|
||||
const blobURL = URL.createObjectURL(blob)
|
||||
// Create the `<a download>` element and append it invisibly.
|
||||
const a = document.createElement('a')
|
||||
a.href = blobURL
|
||||
a.download = suggestedName
|
||||
a.style.display = 'none'
|
||||
document.body.append(a)
|
||||
// Programmatically click the element.
|
||||
a.click()
|
||||
// Revoke the blob URL and remove the element.
|
||||
setTimeout(() => {
|
||||
URL.revokeObjectURL(blobURL)
|
||||
a.remove()
|
||||
}, 1000)
|
||||
}
|
44
src/lib/exportSave.ts
Normal file
44
src/lib/exportSave.ts
Normal file
@ -0,0 +1,44 @@
|
||||
import { isTauri } from './isTauri'
|
||||
import { deserialize_files } from '../wasm-lib/pkg/wasm_lib'
|
||||
import { browserSaveFile } from './browserSaveFile'
|
||||
import { save } from '@tauri-apps/api/dialog'
|
||||
import { writeBinaryFile } from '@tauri-apps/api/fs'
|
||||
|
||||
// Saves files locally from an export call.
|
||||
export async function exportSave(data: ArrayBuffer) {
|
||||
// This converts the ArrayBuffer to a Rust equivalent Vec<u8>.
|
||||
let uintArray = new Uint8Array(data)
|
||||
try {
|
||||
const files: { contents: number[]; name: string }[] =
|
||||
deserialize_files(uintArray)
|
||||
for (const file of files) {
|
||||
if (isTauri()) {
|
||||
// Open a dialog to save the file.
|
||||
const filePath = await save({
|
||||
defaultPath: file.name,
|
||||
})
|
||||
|
||||
if (filePath === null) {
|
||||
// The user canceled the save.
|
||||
// Return early.
|
||||
return
|
||||
}
|
||||
|
||||
// Write the file.
|
||||
await writeBinaryFile(filePath, uintArray)
|
||||
} else {
|
||||
// Download the file to the user's computer.
|
||||
// Now we need to download the files to the user's downloads folder.
|
||||
// Or the destination they choose.
|
||||
// Iterate over the files.
|
||||
// Create a new blob.
|
||||
const blob = new Blob([new Uint8Array(file.contents)])
|
||||
// Save the file.
|
||||
browserSaveFile(blob, file.name)
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
// TODO: do something real with the error.
|
||||
console.log(e)
|
||||
}
|
||||
}
|
10
src/wasm-lib/Cargo.lock
generated
10
src/wasm-lib/Cargo.lock
generated
@ -11,6 +11,15 @@ dependencies = [
|
||||
"memchr",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "bincode"
|
||||
version = "1.3.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b1f45e9417d87227c7a56d22e471c6206462cba514c7590c09aff4cf6d1ddcad"
|
||||
dependencies = [
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "bumpalo"
|
||||
version = "3.12.0"
|
||||
@ -241,6 +250,7 @@ checksum = "ca6ad05a4870b2bf5fe995117d3728437bd27d7cd5f06f13c17443ef369775a1"
|
||||
name = "wasm-lib"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"bincode",
|
||||
"lazy_static",
|
||||
"regex",
|
||||
"serde",
|
||||
|
@ -8,9 +8,10 @@ edition = "2021"
|
||||
crate-type = ["cdylib"]
|
||||
|
||||
[dependencies]
|
||||
bincode = "1.3.3"
|
||||
lazy_static = "1.4.0"
|
||||
regex = "1.7.1"
|
||||
serde = {version = "1.0.152", features = ["derive"] }
|
||||
serde-wasm-bindgen = "0.3.1"
|
||||
serde_json = "1.0.93"
|
||||
wasm-bindgen = "0.2.78"
|
||||
serde-wasm-bindgen = "0.3.1"
|
||||
|
18
src/wasm-lib/src/export.rs
Normal file
18
src/wasm-lib/src/export.rs
Normal file
@ -0,0 +1,18 @@
|
||||
//! Functions for exported files from the server.
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
use wasm_bindgen::prelude::*;
|
||||
|
||||
/// A file that has been exported from the server.
|
||||
#[derive(Debug, Deserialize, Serialize)]
|
||||
pub struct File {
|
||||
pub name: String,
|
||||
pub contents: Vec<u8>,
|
||||
}
|
||||
|
||||
#[wasm_bindgen]
|
||||
pub fn deserialize_files(data: Vec<u8>) -> Result<JsValue, JsError> {
|
||||
let files: Vec<File> = bincode::deserialize(&data)?;
|
||||
|
||||
Ok(serde_wasm_bindgen::to_value(&files)?)
|
||||
}
|
@ -1,3 +1,4 @@
|
||||
mod abstract_syntax_tree;
|
||||
mod export;
|
||||
mod recast;
|
||||
mod tokeniser;
|
||||
|
@ -240,8 +240,7 @@ fn recast_pipe_expression(expression: PipeExpression) -> String {
|
||||
let mut maybe_line_break = "\n".to_string();
|
||||
let mut str = recast_value(statement.clone(), indentation.clone(), true);
|
||||
let non_code_meta = expression.non_code_meta.clone();
|
||||
if let Some(non_code_meta_value) = non_code_meta.none_code_nodes.get(&index)
|
||||
{
|
||||
if let Some(non_code_meta_value) = non_code_meta.none_code_nodes.get(&index) {
|
||||
if non_code_meta_value.value != " " {
|
||||
str += non_code_meta_value.value.as_str();
|
||||
indentation = "".to_string();
|
||||
@ -325,10 +324,8 @@ pub fn recast(ast: Program, indentation: String, is_with_block: bool) -> String
|
||||
|
||||
// determine the value of startString
|
||||
let last_white_space_or_comment = if index > 0 {
|
||||
let tmp = if let Some(non_code_node) = ast
|
||||
.non_code_meta
|
||||
.none_code_nodes
|
||||
.get(&(index - 1))
|
||||
let tmp = if let Some(non_code_node) =
|
||||
ast.non_code_meta.none_code_nodes.get(&(index - 1))
|
||||
{
|
||||
non_code_node.value.clone()
|
||||
} else {
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"types": ["vite/client"],
|
||||
"types": ["vite/client", "@types/wicg-file-system-access"],
|
||||
"target": "esnext",
|
||||
"lib": [
|
||||
"dom",
|
||||
|
105
yarn.lock
105
yarn.lock
@ -1710,10 +1710,10 @@
|
||||
resolved "https://registry.yarnpkg.com/@juggle/resize-observer/-/resize-observer-3.4.0.tgz#08d6c5e20cf7e4cc02fd181c4b0c225cd31dbb60"
|
||||
integrity sha512-dfLbk+PwWvFzSxwk3n5ySL0hfBog779o8h68wK/7/APo/7cgyWp5jcXockbxdk5kFRkbeXWm4Fbi9FrdN381sA==
|
||||
|
||||
"@kittycad/lib@^0.0.22":
|
||||
version "0.0.22"
|
||||
resolved "https://registry.yarnpkg.com/@kittycad/lib/-/lib-0.0.22.tgz#3d9b063c6cfe6593cdf7b61d3ffb5c1251262401"
|
||||
integrity sha512-H9AS3/8Ag2fJRZqNNkbOjy/08kEqeOxWEWsmQIzJ/dNGYRD0B7Fm+UM6T8eSEkPP2+KKrIhoHMYEfGd9KjY1uQ==
|
||||
"@kittycad/lib@^0.0.24":
|
||||
version "0.0.24"
|
||||
resolved "https://registry.yarnpkg.com/@kittycad/lib/-/lib-0.0.24.tgz#afc2f0baf8b742344e86332a60e89e85804b4b30"
|
||||
integrity sha512-RT3EThq0s7DQFT9+8HQ9yRgIb5+Q2xwYFYl/aNel5DdkfAya3WGlwhjv2YOtMXsy981JVpabo0HXD3tLfm/9QA==
|
||||
dependencies:
|
||||
node-fetch "3.3.2"
|
||||
openapi-types "^12.0.0"
|
||||
@ -2113,6 +2113,13 @@
|
||||
dependencies:
|
||||
"@types/react" "*"
|
||||
|
||||
"@types/react-modal@^3.16.0":
|
||||
version "3.16.0"
|
||||
resolved "https://registry.yarnpkg.com/@types/react-modal/-/react-modal-3.16.0.tgz#b8d6be10de894139a2ea9f4a2505b1b5d02023df"
|
||||
integrity sha512-iphdqXAyUfByLbxJn5j6d+yh93dbMgshqGP0IuBeaKbZXx0aO+OXsvEkt6QctRdxjeM9/bR+Gp3h9F9djVWTQQ==
|
||||
dependencies:
|
||||
"@types/react" "*"
|
||||
|
||||
"@types/react@*", "@types/react@^18.0.0":
|
||||
version "18.2.18"
|
||||
resolved "https://registry.yarnpkg.com/@types/react/-/react-18.2.18.tgz#c8b233919eef1bdc294f6f34b37f9727ad677516"
|
||||
@ -2154,6 +2161,11 @@
|
||||
resolved "https://registry.yarnpkg.com/@types/uuid/-/uuid-9.0.2.tgz#ede1d1b1e451548d44919dc226253e32a6952c4b"
|
||||
integrity sha512-kNnC1GFBLuhImSnV7w4njQkUiJi0ZXUycu1rUaouPqiKlXkh77JKgdRnTAp1x5eBwcIwbtI+3otwzuIDEuDoxQ==
|
||||
|
||||
"@types/wicg-file-system-access@^2020.9.6":
|
||||
version "2020.9.6"
|
||||
resolved "https://registry.yarnpkg.com/@types/wicg-file-system-access/-/wicg-file-system-access-2020.9.6.tgz#da34476b1e29451c8b7aa1a6db86b185647cd970"
|
||||
integrity sha512-6hogE75Hl2Ov/jgp8ZhDaGmIF/q3J07GtXf8nCJCwKTHq7971po5+DId7grft09zG7plBwpF6ZU0yx9Du4/e1A==
|
||||
|
||||
"@types/ws@^8.5.5":
|
||||
version "8.5.5"
|
||||
resolved "https://registry.yarnpkg.com/@types/ws/-/ws-8.5.5.tgz#af587964aa06682702ee6dcbc7be41a80e4b28eb"
|
||||
@ -3116,6 +3128,11 @@ deep-is@^0.1.3:
|
||||
resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.4.tgz#a6f2dce612fadd2ef1f519b73551f17e85199831"
|
||||
integrity sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==
|
||||
|
||||
deepmerge@^2.1.1:
|
||||
version "2.2.1"
|
||||
resolved "https://registry.yarnpkg.com/deepmerge/-/deepmerge-2.2.1.tgz#5d3ff22a01c00f645405a2fbc17d0778a1801170"
|
||||
integrity sha512-R9hc1Xa/NOBi9WRVUWg19rl1UB7Tt4kuPd+thNJgFZoxXsTz7ncaPaeIm+40oSGuP33DfMb4sZt1QIGiJzC4EA==
|
||||
|
||||
deepmerge@^4.2.2:
|
||||
version "4.3.1"
|
||||
resolved "https://registry.yarnpkg.com/deepmerge/-/deepmerge-4.3.1.tgz#44b5f2147cd3b00d4b56137685966f26fd25dd4a"
|
||||
@ -3198,9 +3215,9 @@ domexception@^4.0.0:
|
||||
webidl-conversions "^7.0.0"
|
||||
|
||||
electron-to-chromium@^1.4.477:
|
||||
version "1.4.478"
|
||||
resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.478.tgz#687198cfcef9b854a79a229feaa6cd8961206290"
|
||||
integrity sha512-qjTA8djMXd+ruoODDFGnRCRBpID+AAfYWCyGtYTNhsuwxI19s8q19gbjKTwRS5z/LyVf5wICaIiPQGLekmbJbA==
|
||||
version "1.4.480"
|
||||
resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.480.tgz#40e32849ca50bc23ce29c1516c5adb3fddac919d"
|
||||
integrity sha512-IXTgg+bITkQv/FLP9FjX6f9KFCs5hQWeh5uNSKxB9mqYj/JXhHDbu+ekS43LVvbkL3eW6/oZy4+r9Om6lan1Uw==
|
||||
|
||||
emittery@^0.13.1:
|
||||
version "0.13.1"
|
||||
@ -3653,6 +3670,11 @@ execa@^5.0.0:
|
||||
signal-exit "^3.0.3"
|
||||
strip-final-newline "^2.0.0"
|
||||
|
||||
exenv@^1.2.0:
|
||||
version "1.2.2"
|
||||
resolved "https://registry.yarnpkg.com/exenv/-/exenv-1.2.2.tgz#2ae78e85d9894158670b03d47bec1f03bd91bb9d"
|
||||
integrity sha512-Z+ktTxTwv9ILfgKCk32OX3n/doe+OcLTRtqK9pcL+JsP3J1/VW8Uvl4ZjLlKqeW4rzK4oesDOGMEMRIZqtP4Iw==
|
||||
|
||||
exit@^0.1.2:
|
||||
version "0.1.2"
|
||||
resolved "https://registry.yarnpkg.com/exit/-/exit-0.1.2.tgz#0632638f8d877cc82107d30a0fff1a17cba1cd0c"
|
||||
@ -3822,6 +3844,19 @@ formdata-polyfill@^4.0.10:
|
||||
dependencies:
|
||||
fetch-blob "^3.1.2"
|
||||
|
||||
formik@^2.4.3:
|
||||
version "2.4.3"
|
||||
resolved "https://registry.yarnpkg.com/formik/-/formik-2.4.3.tgz#6020e85eb3e3e8415b3b19d6f4f65793ab754b24"
|
||||
integrity sha512-2Dy79Szw3zlXmZiokUdKsn+n1ow4G8hRrC/n92cOWHNTWXCRpQXlyvz6HcjW7aSQZrldytvDOavYjhfmDnUq8Q==
|
||||
dependencies:
|
||||
deepmerge "^2.1.1"
|
||||
hoist-non-react-statics "^3.3.0"
|
||||
lodash "^4.17.21"
|
||||
lodash-es "^4.17.21"
|
||||
react-fast-compare "^2.0.1"
|
||||
tiny-warning "^1.0.2"
|
||||
tslib "^2.0.0"
|
||||
|
||||
fraction.js@^4.2.0:
|
||||
version "4.2.0"
|
||||
resolved "https://registry.yarnpkg.com/fraction.js/-/fraction.js-4.2.0.tgz#448e5109a313a3527f5a3ab2119ec4cf0e0e2950"
|
||||
@ -4056,6 +4091,13 @@ he@^1.2.0:
|
||||
resolved "https://registry.yarnpkg.com/he/-/he-1.2.0.tgz#84ae65fa7eafb165fddb61566ae14baf05664f0f"
|
||||
integrity sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==
|
||||
|
||||
hoist-non-react-statics@^3.3.0:
|
||||
version "3.3.2"
|
||||
resolved "https://registry.yarnpkg.com/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz#ece0acaf71d62c2969c2ec59feff42a4b1a85b45"
|
||||
integrity sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==
|
||||
dependencies:
|
||||
react-is "^16.7.0"
|
||||
|
||||
html-encoding-sniffer@^3.0.0:
|
||||
version "3.0.0"
|
||||
resolved "https://registry.yarnpkg.com/html-encoding-sniffer/-/html-encoding-sniffer-3.0.0.tgz#2cb1a8cf0db52414776e5b2a7a04d5dd98158de9"
|
||||
@ -4963,6 +5005,11 @@ locate-path@^6.0.0:
|
||||
dependencies:
|
||||
p-locate "^5.0.0"
|
||||
|
||||
lodash-es@^4.17.21:
|
||||
version "4.17.21"
|
||||
resolved "https://registry.yarnpkg.com/lodash-es/-/lodash-es-4.17.21.tgz#43e626c46e6591b7750beb2b50117390c609e3ee"
|
||||
integrity sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw==
|
||||
|
||||
lodash.clamp@^4.0.0:
|
||||
version "4.0.3"
|
||||
resolved "https://registry.yarnpkg.com/lodash.clamp/-/lodash.clamp-4.0.3.tgz#5c24bedeeeef0753560dc2b4cb4671f90a6ddfaa"
|
||||
@ -5557,7 +5604,7 @@ prompts@^2.0.1:
|
||||
kleur "^3.0.3"
|
||||
sisteransi "^1.0.5"
|
||||
|
||||
prop-types@^15.8.1:
|
||||
prop-types@^15.7.2, prop-types@^15.8.1:
|
||||
version "15.8.1"
|
||||
resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.8.1.tgz#67d87bf1a694f48435cf332c24af10214a3140b5"
|
||||
integrity sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==
|
||||
@ -5621,6 +5668,11 @@ react-dom@^18.2.0:
|
||||
loose-envify "^1.1.0"
|
||||
scheduler "^0.23.0"
|
||||
|
||||
react-fast-compare@^2.0.1:
|
||||
version "2.0.4"
|
||||
resolved "https://registry.yarnpkg.com/react-fast-compare/-/react-fast-compare-2.0.4.tgz#e84b4d455b0fec113e0402c329352715196f81f9"
|
||||
integrity sha512-suNP+J1VU1MWFKcyt7RtjiSWUjvidmQSlqu+eHslq+342xCbGTYmC0mEhPCOHxlW0CywylOC1u2DFAT+bv4dBw==
|
||||
|
||||
react-hot-toast@^2.4.1:
|
||||
version "2.4.1"
|
||||
resolved "https://registry.yarnpkg.com/react-hot-toast/-/react-hot-toast-2.4.1.tgz#df04295eda8a7b12c4f968e54a61c8d36f4c0994"
|
||||
@ -5633,7 +5685,7 @@ react-hotkeys-hook@^4.4.1:
|
||||
resolved "https://registry.yarnpkg.com/react-hotkeys-hook/-/react-hotkeys-hook-4.4.1.tgz#1f7a7a1c9c21d4fa3280bf340fcca8fd77d81994"
|
||||
integrity sha512-sClBMBioFEgFGYLTWWRKvhxcCx1DRznd+wkFHwQZspnRBkHTgruKIHptlK/U/2DPX8BhHoRGzpMVWUXMmdZlmw==
|
||||
|
||||
react-is@^16.13.1:
|
||||
react-is@^16.13.1, react-is@^16.7.0:
|
||||
version "16.13.1"
|
||||
resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.13.1.tgz#789729a4dc36de2999dc156dd6c1d9c18cea56a4"
|
||||
integrity sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==
|
||||
@ -5658,7 +5710,7 @@ react-json-view@^1.21.3:
|
||||
react-lifecycles-compat "^3.0.4"
|
||||
react-textarea-autosize "^8.3.2"
|
||||
|
||||
react-lifecycles-compat@^3.0.4:
|
||||
react-lifecycles-compat@^3.0.0, react-lifecycles-compat@^3.0.4:
|
||||
version "3.0.4"
|
||||
resolved "https://registry.yarnpkg.com/react-lifecycles-compat/-/react-lifecycles-compat-3.0.4.tgz#4f1a273afdfc8f3488a8c516bfda78f872352362"
|
||||
integrity sha512-fBASbA6LnOU9dOU2eW7aQ8xmYBSXUIWr+UmF9b1efZBazGNO+rcXT/icdKnYm2pTwcRylVUYwW7H1PHfLekVzA==
|
||||
@ -5668,6 +5720,16 @@ react-modal-promise@^1.0.2:
|
||||
resolved "https://registry.yarnpkg.com/react-modal-promise/-/react-modal-promise-1.0.2.tgz#122620b7f19eec73683affadfa77c543d88edc40"
|
||||
integrity sha512-dqT618ROhG8qh1+O6EZkia5ELw3zaZWGpMX2YfEH4bgwYENPuFonqKw1W70LFx3K/SCZvVBcD6UYEI12yzYXzg==
|
||||
|
||||
react-modal@^3.16.1:
|
||||
version "3.16.1"
|
||||
resolved "https://registry.yarnpkg.com/react-modal/-/react-modal-3.16.1.tgz#34018528fc206561b1a5467fc3beeaddafb39b2b"
|
||||
integrity sha512-VStHgI3BVcGo7OXczvnJN7yT2TWHJPDXZWyI/a0ssFNhGZWsPmB8cF0z33ewDXq4VfYMO1vXgiv/g8Nj9NDyWg==
|
||||
dependencies:
|
||||
exenv "^1.2.0"
|
||||
prop-types "^15.7.2"
|
||||
react-lifecycles-compat "^3.0.0"
|
||||
warning "^4.0.3"
|
||||
|
||||
react-refresh@^0.14.0:
|
||||
version "0.14.0"
|
||||
resolved "https://registry.yarnpkg.com/react-refresh/-/react-refresh-0.14.0.tgz#4e02825378a5f227079554d4284889354e5f553e"
|
||||
@ -6234,6 +6296,11 @@ thenify-all@^1.0.0:
|
||||
dependencies:
|
||||
any-promise "^1.0.0"
|
||||
|
||||
tiny-warning@^1.0.2:
|
||||
version "1.0.3"
|
||||
resolved "https://registry.yarnpkg.com/tiny-warning/-/tiny-warning-1.0.3.tgz#94a30db453df4c643d0fd566060d60a875d84754"
|
||||
integrity sha512-lBN9zLN/oAf68o3zNXYrdCt1kP8WsiGW8Oo2ka41b2IM5JL/S1CTyX1rW0mb/zSuJun0ZUrDxx4sqvYS2FWzPA==
|
||||
|
||||
tmpl@1.0.5:
|
||||
version "1.0.5"
|
||||
resolved "https://registry.yarnpkg.com/tmpl/-/tmpl-1.0.5.tgz#8683e0b902bb9c20c4f726e3c0b69f36518c07cc"
|
||||
@ -6336,6 +6403,11 @@ tslib@^1.8.1:
|
||||
resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00"
|
||||
integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==
|
||||
|
||||
tslib@^2.0.0:
|
||||
version "2.6.1"
|
||||
resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.6.1.tgz#fd8c9a0ff42590b25703c0acb3de3d3f4ede0410"
|
||||
integrity sha512-t0hLfiEKfMUoqhG+U1oid7Pva4bbDPHYfJNiB7BiIjRkj1pyC++4N3huJfqY6aRH6VTB0rvtzQwjM4K6qpfOig==
|
||||
|
||||
tslib@~2.4:
|
||||
version "2.4.1"
|
||||
resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.4.1.tgz#0d0bfbaac2880b91e22df0768e55be9753a5b17e"
|
||||
@ -6575,9 +6647,9 @@ vite-tsconfig-paths@^4.2.0:
|
||||
tsconfck "^2.1.0"
|
||||
|
||||
vite@^4.4.3:
|
||||
version "4.4.7"
|
||||
resolved "https://registry.yarnpkg.com/vite/-/vite-4.4.7.tgz#71b8a37abaf8d50561aca084dbb77fa342824154"
|
||||
integrity sha512-6pYf9QJ1mHylfVh39HpuSfMPojPSKVxZvnclX1K1FyZ1PXDOcLBibdq5t1qxJSnL63ca8Wf4zts6mD8u8oc9Fw==
|
||||
version "4.4.8"
|
||||
resolved "https://registry.yarnpkg.com/vite/-/vite-4.4.8.tgz#31e4a438f8748695c68bd57ffd262ba93540fdf7"
|
||||
integrity sha512-LONawOUUjxQridNWGQlNizfKH89qPigK36XhMI7COMGztz8KNY0JHim7/xDd71CZwGT4HtSRgI7Hy+RlhG0Gvg==
|
||||
dependencies:
|
||||
esbuild "^0.18.10"
|
||||
postcss "^8.4.26"
|
||||
@ -6604,6 +6676,13 @@ walker@^1.0.8:
|
||||
dependencies:
|
||||
makeerror "1.0.12"
|
||||
|
||||
warning@^4.0.3:
|
||||
version "4.0.3"
|
||||
resolved "https://registry.yarnpkg.com/warning/-/warning-4.0.3.tgz#16e9e077eb8a86d6af7d64aa1e05fd85b4678ca3"
|
||||
integrity sha512-rpJyN222KWIvHJ/F53XSZv0Zl/accqHR8et1kpaMTD/fLCRxtV8iX8czMzY7sVZupTI3zcUTg8eycS2kNF9l6w==
|
||||
dependencies:
|
||||
loose-envify "^1.0.0"
|
||||
|
||||
wasm-pack@^0.12.1:
|
||||
version "0.12.1"
|
||||
resolved "https://registry.yarnpkg.com/wasm-pack/-/wasm-pack-0.12.1.tgz#974c1fbbf5b65c9e135e0d1fba3a97de1a21a489"
|
||||
|
Reference in New Issue
Block a user