From 66ec0fe8ba3ada10b3048d0a9bbcc6ef7f77994d Mon Sep 17 00:00:00 2001 From: wil Date: Thu, 27 Jun 2024 18:19:17 -0400 Subject: [PATCH] Editor2.0/editor state data (#555) editor state holds the info of the state of the editor, timeline, and generation metadata editor state json is the json version of editor state, with a snapshot timestamp assuming editor state holds all the correct information, the editor state json will be the serialized version of editor state and this way, information wont be lost. --------- Co-authored-by: wil --- .../EditorStateJSON/editor_state_json.ts | 11 ++ .../EditorState/EditorStateJSON/index.ts | 1 + .../EditorStateJSON/object_3d_json.ts | 27 +++++ .../EditorStateJSON/scene_state_json.ts | 7 ++ .../EditorStateJSON/timeline_state_json.ts | 9 ++ .../Editor/EditorState/editor_state.ts | 35 ++++++ .../PageEnigma/Editor/EditorState/index.ts | 2 + .../Editor/EditorState/object_3d.ts | 98 +++++++++++++++++ .../Editor/EditorState/scene_state.ts | 100 ++++++++++++++++++ .../Editor/EditorState/timeline_state.ts | 64 +++++++++++ .../models/sceneGenerationMetadata.ts | 2 +- app/utilities.ts | 9 ++ package-lock.json | 39 ++----- package.json | 2 + 14 files changed, 375 insertions(+), 31 deletions(-) create mode 100644 app/pages/PageEnigma/Editor/EditorState/EditorStateJSON/editor_state_json.ts create mode 100644 app/pages/PageEnigma/Editor/EditorState/EditorStateJSON/index.ts create mode 100644 app/pages/PageEnigma/Editor/EditorState/EditorStateJSON/object_3d_json.ts create mode 100644 app/pages/PageEnigma/Editor/EditorState/EditorStateJSON/scene_state_json.ts create mode 100644 app/pages/PageEnigma/Editor/EditorState/EditorStateJSON/timeline_state_json.ts create mode 100644 app/pages/PageEnigma/Editor/EditorState/editor_state.ts create mode 100644 app/pages/PageEnigma/Editor/EditorState/index.ts create mode 100644 app/pages/PageEnigma/Editor/EditorState/object_3d.ts create mode 100644 app/pages/PageEnigma/Editor/EditorState/scene_state.ts create mode 100644 app/pages/PageEnigma/Editor/EditorState/timeline_state.ts diff --git a/app/pages/PageEnigma/Editor/EditorState/EditorStateJSON/editor_state_json.ts b/app/pages/PageEnigma/Editor/EditorState/EditorStateJSON/editor_state_json.ts new file mode 100644 index 0000000000..5729bd7e18 --- /dev/null +++ b/app/pages/PageEnigma/Editor/EditorState/EditorStateJSON/editor_state_json.ts @@ -0,0 +1,11 @@ +import { SceneGenereationMetaData } from "../../../models/sceneGenerationMetadata"; +import { SceneStateJson } from "./scene_state_json"; +import { TimelineStateJson } from "./timeline_state_json"; + +export interface EditorStateJson { + version: number; + sceneGenerationMetaData: SceneGenereationMetaData; + sceneStateJson: SceneStateJson; + timelineStateJson: TimelineStateJson; + snapshotTime: string; // make one via `new Date().toISOString()` +} diff --git a/app/pages/PageEnigma/Editor/EditorState/EditorStateJSON/index.ts b/app/pages/PageEnigma/Editor/EditorState/EditorStateJSON/index.ts new file mode 100644 index 0000000000..cbd495ef9b --- /dev/null +++ b/app/pages/PageEnigma/Editor/EditorState/EditorStateJSON/index.ts @@ -0,0 +1 @@ +export * from "./editor_state_json"; diff --git a/app/pages/PageEnigma/Editor/EditorState/EditorStateJSON/object_3d_json.ts b/app/pages/PageEnigma/Editor/EditorState/EditorStateJSON/object_3d_json.ts new file mode 100644 index 0000000000..218391bf10 --- /dev/null +++ b/app/pages/PageEnigma/Editor/EditorState/EditorStateJSON/object_3d_json.ts @@ -0,0 +1,27 @@ +export interface Object3DJSON { + position: { + x: number; + y: number; + z: number; + }; + rotation: { + x: number; + y: number; + z: number; + }; + scale: { + x: number; + y: number; + z: number; + }; + object_name: string; + object_uuid: string; + object_user_data_name: string; + media_file_token: string; + color: string; + metalness: number; + shininess: number; + specular: number; + locked: boolean; + visible: boolean | undefined; +} diff --git a/app/pages/PageEnigma/Editor/EditorState/EditorStateJSON/scene_state_json.ts b/app/pages/PageEnigma/Editor/EditorState/EditorStateJSON/scene_state_json.ts new file mode 100644 index 0000000000..532994eeab --- /dev/null +++ b/app/pages/PageEnigma/Editor/EditorState/EditorStateJSON/scene_state_json.ts @@ -0,0 +1,7 @@ +// import * as THREE from "three"; +import { Object3DJSON } from "./object_3d_json"; + +export interface SceneStateJson { + version: number; + sceneItems: Object3DJSON[]; +} diff --git a/app/pages/PageEnigma/Editor/EditorState/EditorStateJSON/timeline_state_json.ts b/app/pages/PageEnigma/Editor/EditorState/EditorStateJSON/timeline_state_json.ts new file mode 100644 index 0000000000..cebd5cd322 --- /dev/null +++ b/app/pages/PageEnigma/Editor/EditorState/EditorStateJSON/timeline_state_json.ts @@ -0,0 +1,9 @@ +export interface TimelineStateJson { + version: number; + timelineItemsJson: string; + transformJson: string; + animationJson: string; + audioJson: string; + lipsyncJson: string; + emotionJson: string; +} diff --git a/app/pages/PageEnigma/Editor/EditorState/editor_state.ts b/app/pages/PageEnigma/Editor/EditorState/editor_state.ts new file mode 100644 index 0000000000..8562fb5c9c --- /dev/null +++ b/app/pages/PageEnigma/Editor/EditorState/editor_state.ts @@ -0,0 +1,35 @@ +import { SceneGenereationMetaData } from "../../models/sceneGenerationMetadata"; +import { EditorStateJson } from "./EditorStateJSON"; +// import Scene from "../scene"; +// import { TimeLine } from "../timeline"; +import { SceneState } from "./scene_state"; +import { TimelineState } from "./timeline_state"; + +export class EditorState { + version: number; + sceneGenerationMetaData: SceneGenereationMetaData | undefined; + sceneState: SceneState | undefined; + timelineState: TimelineState | undefined; + + constructor({ editorVersion }: { editorVersion: number }) { + this.version = editorVersion; + } + + public async toJSON() { + if ( + !this.sceneGenerationMetaData || + !this.sceneState || + !this.timelineState + ) { + throw "Error in EditorState.toJSON: data undefined"; + } + const result: EditorStateJson = { + version: this.version, + sceneGenerationMetaData: this.sceneGenerationMetaData, + sceneStateJson: await this.sceneState.toJSON(), + timelineStateJson: await this.timelineState.toJSON(), + snapshotTime: new Date().toISOString(), + }; + return result; + } +} diff --git a/app/pages/PageEnigma/Editor/EditorState/index.ts b/app/pages/PageEnigma/Editor/EditorState/index.ts new file mode 100644 index 0000000000..264cbb6837 --- /dev/null +++ b/app/pages/PageEnigma/Editor/EditorState/index.ts @@ -0,0 +1,2 @@ +export * from "./editor_state"; +export * from "./EditorStateJSON"; diff --git a/app/pages/PageEnigma/Editor/EditorState/object_3d.ts b/app/pages/PageEnigma/Editor/EditorState/object_3d.ts new file mode 100644 index 0000000000..e20791e3fb --- /dev/null +++ b/app/pages/PageEnigma/Editor/EditorState/object_3d.ts @@ -0,0 +1,98 @@ +import * as THREE from "three"; +import { Object3DJSON } from "./EditorStateJSON/object_3d_json"; + +export class Object3D { + version: number; + + position: THREE.Vector3; + rotation: THREE.Euler; + scale: THREE.Vector3; + + object_uuid: string; + object_name: string; + object_user_data_name: string; // changable name + media_file_token: string; + color: string; + metalness: number; + shininess: number; + specular: number; + locked: boolean; + visible: boolean; + + constructor(version: number, media_file_token: string) { + this.version = version; + this.media_file_token = media_file_token; + + this.position = new THREE.Vector3(0.0, 0.0, 0.0); + this.rotation = new THREE.Euler(0.0, 0.0, 0.0); + this.scale = new THREE.Vector3(1.0, 1.0, 1.0); + + this.object_name = ""; + this.object_user_data_name = ""; + this.object_uuid = ""; + + this.color = ""; + + this.metalness = 0.0; + this.shininess = 0.0; + this.specular = 0.5; + this.locked = false; + this.visible = true; + } + + getColorAsHexString(object: THREE.Object3D): string { + if ( + object instanceof THREE.Mesh && + object.material instanceof THREE.MeshBasicMaterial + ) { + return "#" + object.material.color.getHexString(); + } + return "#FFFFFF"; + } + + public async initialize(object: THREE.Object3D) { + this.position = object.position; + this.rotation = object.rotation; + this.scale = object.scale; + + this.object_name = object.name; + this.object_user_data_name = object.userData.name; + this.object_uuid = object.uuid; + this.color = object.userData["color"]; + this.metalness = object.userData["metalness"]; + this.shininess = object.userData["shininess"]; + this.specular = object.userData["specular"]; + this.locked = object.userData["locked"]; + } + + public async toJSON(): Promise { + const json: Object3DJSON = { + position: { + x: this.position.x, + y: this.position.y, + z: this.position.z, + }, + rotation: { + x: this.rotation.x, + y: this.rotation.y, + z: this.rotation.z, + }, + scale: { + x: this.scale.x, + y: this.scale.y, + z: this.scale.z, + }, + object_name: this.object_name, + object_uuid: this.object_uuid, + object_user_data_name: this.object_user_data_name, + media_file_token: this.media_file_token, + color: this.color, + metalness: this.metalness, + shininess: this.shininess, + specular: this.specular, + locked: this.locked, + visible: this.visible, + }; + return json; + } +} diff --git a/app/pages/PageEnigma/Editor/EditorState/scene_state.ts b/app/pages/PageEnigma/Editor/EditorState/scene_state.ts new file mode 100644 index 0000000000..615000bb43 --- /dev/null +++ b/app/pages/PageEnigma/Editor/EditorState/scene_state.ts @@ -0,0 +1,100 @@ +// import * as THREE from "three"; +import { Object3D } from "./object_3d"; +import { Object3DJSON } from "./EditorStateJSON/object_3d_json"; +import Scene from "../../Editor/scene"; +import { SceneStateJson } from "./EditorStateJSON/scene_state_json"; +const DEFAULT_SCENE_VER = 1.0; + +export class SceneState { + version: number; + sceneItems: Object3D[] | undefined; + + constructor({ scene, version }: { scene?: Scene; version?: number }) { + this.version = version ?? scene?.version ?? DEFAULT_SCENE_VER; + } + + public async initiateFromScene({ scene }: { scene: Scene }): Promise { + if (this.version < 1) { + this.saveFromSceneObjectVer0(scene) + .then((result) => { + this.sceneItems = result; + }) + .catch((e) => { + throw e; + }); + } + + const result = new Array(); + // TODO turn the sceneItems into an object3d-json + // reject if something goes wrong + // or else send the result via resolve + this.sceneItems = result; + return; + } + + public async initiateFromObject3DJson({ + objectJsons, + }: { + objectJsons: Object3DJSON[]; + }): Promise { + const sceneItems = objectJsons.map((jsonObject: Object3DJSON) => { + console.log(jsonObject); + const object3D = new Object3D(this.version, "placeholder-token"); + // TODO: now translate that jsonObject back into a ThreeJS 3D object + return object3D; + }); + this.sceneItems = sceneItems; + return; + } + + public async saveFromSceneObjectVer0(scene: Scene): Promise { + console.log("saveFromSceneObjectVer0", scene); + const results: Object3D[] = []; + // TODO: turn sceneItems fron type of Object3D into Object3DJSON, the old way + + // if (this.scene.scene != null) { + // for (const child of this.scene.scene.children) { + // if (child.userData["media_id"] != undefined) { + // if (this.lookUpDictionary[child.uuid] == null) { + // this.lookUpDictionary[child.uuid] = new Object3D( + // this.version, + // child.userData["media_id"], + // ); + // } + // const proxyObject3D: Object3D = this.lookUpDictionary[child.uuid]; + // proxyObject3D.position.copy(child.position); + // proxyObject3D.rotation.copy(child.rotation); + // proxyObject3D.scale.copy(child.scale); + // proxyObject3D.object_user_data_name = child.userData.name; + // proxyObject3D.object_name = child.name; + // proxyObject3D.object_uuid = child.uuid; + // proxyObject3D.color = child.userData["color"]; + // proxyObject3D.metalness = child.userData["metalness"]; + // proxyObject3D.shininess = child.userData["shininess"]; + // proxyObject3D.specular = child.userData["specular"]; + // proxyObject3D.locked = child.userData["locked"]; + // const json_data = await proxyObject3D.toJSON(); + // results.push(json_data); + // } + // } + // } else { + // console.log("Scene doesn't exist needs to be assigned"); + // } + // console.log(results); + return results; + } + + public async toJSON(): Promise { + const result: SceneStateJson = { + version: this.version, + sceneItems: [], + }; + if (this.sceneItems) { + for (let i = 0; i < this.sceneItems.length; i = i + 1) { + const itemJson = await this.sceneItems[i].toJSON(); + result.sceneItems.push(itemJson); + } + } + return result; + } +} diff --git a/app/pages/PageEnigma/Editor/EditorState/timeline_state.ts b/app/pages/PageEnigma/Editor/EditorState/timeline_state.ts new file mode 100644 index 0000000000..a6b9227783 --- /dev/null +++ b/app/pages/PageEnigma/Editor/EditorState/timeline_state.ts @@ -0,0 +1,64 @@ +import { deepCopySerializableObjects as deepCopy } from "~/utilities"; +import { AnimationEngine } from "../animation_engine"; +import AudioEngine from "../audio_engine"; +import EmotionEngine from "../emotion_engine"; +import { LipSyncEngine } from "../lip_sync_engine"; +import { TimeLine } from "../timeline"; +import TransformEngine from "../transform_engine"; +import { TimelineStateJson } from "./EditorStateJSON/timeline_state_json"; +import { ClipUI } from "../../datastructures/clips/clip_ui"; + +export class TimelineState { + version: number; + timeline_items: ClipUI[] | undefined; + transform_engine: TransformEngine | undefined; + animation_engine: AnimationEngine | undefined; + audio_engine: AudioEngine | undefined; + lipsync_engine: LipSyncEngine | undefined; + emotion_engine: EmotionEngine | undefined; + + constructor({ editorVersion }: { editorVersion: number }) { + this.version = editorVersion; + } + + public async initializeFromTimeline(timeline: TimeLine): Promise { + return new Promise((resolve, reject) => { + try { + this.timeline_items = deepCopy(timeline.timeline_items); + this.transform_engine = deepCopy(timeline.transform_engine); + this.animation_engine = deepCopy(timeline.animation_engine); + this.audio_engine = deepCopy(timeline.audio_engine); + this.lipsync_engine = deepCopy(timeline.lipSync_engine); + this.emotion_engine = deepCopy(timeline.emotion_engine); + resolve(); + } catch (e) { + reject(e); + } + }); + } + public async initializeFromTimelineStateJson( + jsonObject: TimelineStateJson, + ): Promise { + return new Promise((resolve, reject) => { + try { + console.log(jsonObject); + //TODO: parse json object back into each engine object + resolve(); + } catch (e) { + reject(e); + } + }); + } + public async toJSON() { + const result: TimelineStateJson = { + version: this.version, + timelineItemsJson: JSON.stringify(this.timeline_items), + transformJson: JSON.stringify(this.transform_engine), + animationJson: JSON.stringify(this.animation_engine), + audioJson: JSON.stringify(this.audio_engine), + lipsyncJson: JSON.stringify(this.lipsync_engine), + emotionJson: JSON.stringify(this.emotion_engine), + }; + return result; + } +} diff --git a/app/pages/PageEnigma/models/sceneGenerationMetadata.ts b/app/pages/PageEnigma/models/sceneGenerationMetadata.ts index a0da5b8a7f..bda3c06ffb 100644 --- a/app/pages/PageEnigma/models/sceneGenerationMetadata.ts +++ b/app/pages/PageEnigma/models/sceneGenerationMetadata.ts @@ -7,7 +7,7 @@ export interface SceneGenereationMetaData { negativePrompt: string; cameraAspectRatio: CameraAspectRatio; - globalIPAMediaToken: string | null; + globalIPAMediaToken: string | undefined; upscale: boolean; faceDetail: boolean; diff --git a/app/utilities.ts b/app/utilities.ts index 770b33192b..c78e7fa1b8 100644 --- a/app/utilities.ts +++ b/app/utilities.ts @@ -1,5 +1,14 @@ import { Params } from "@remix-run/react"; import { JobStatus } from "./enums"; +import deepEqual from "deep-equal"; + +export const isObjectSerializable = (obj: object) => { + return deepEqual(obj, deepCopySerializableObjects(obj)); +}; + +export const deepCopySerializableObjects = (obj: object) => { + return JSON.parse(JSON.stringify(obj)); +}; export const kebabCase = (str: string) => str diff --git a/package-lock.json b/package-lock.json index 0db14fe35d..18c0a4a146 100644 --- a/package-lock.json +++ b/package-lock.json @@ -29,6 +29,7 @@ "common": "file:common", "csstype": "^3.1.3", "dayjs": "^1.11.10", + "deep-equal": "^2.2.3", "detect-gpu": "^5.0.38", "http-proxy-middleware": "^3.0.0", "isbot": "^4.1.0", @@ -56,6 +57,7 @@ "@storybook/react": "^8.1.10", "@storybook/react-vite": "^8.1.10", "@storybook/test": "^8.1.10", + "@types/deep-equal": "^1.0.4", "@types/jest": "^29.5.12", "@types/react": "^18.2.20", "@types/react-copy-to-clipboard": "^5.0.7", @@ -7238,6 +7240,12 @@ "@types/ms": "*" } }, + "node_modules/@types/deep-equal": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@types/deep-equal/-/deep-equal-1.0.4.tgz", + "integrity": "sha512-tqdiS4otQP4KmY0PR3u6KbZ5EWvhNdUoS/jc93UuK23C220lOZ/9TvjfxdPcKvqwwDVtmtSCrnr0p/2dirAxkA==", + "dev": true + }, "node_modules/@types/detect-port": { "version": "1.3.5", "resolved": "https://registry.npmjs.org/@types/detect-port/-/detect-port-1.3.5.tgz", @@ -8350,7 +8358,6 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.1.tgz", "integrity": "sha512-ahC5W1xgou+KTXix4sAO8Ki12Q+jf4i0+tmk3sC+zgcynshkHxzpXdImBehiUYKKKDwvfFiJl1tZt6ewscS1Mg==", - "dev": true, "dependencies": { "call-bind": "^1.0.5", "is-array-buffer": "^3.0.4" @@ -10175,7 +10182,6 @@ "version": "2.2.3", "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-2.2.3.tgz", "integrity": "sha512-ZIwpnevOurS8bpT4192sqAowWM76JDKSHYzMLty3BZGSswgq6pBaH3DhCSW5xVAZICZyKdOBPjwww5wfgT/6PA==", - "dev": true, "dependencies": { "array-buffer-byte-length": "^1.0.0", "call-bind": "^1.0.5", @@ -10281,7 +10287,6 @@ "version": "1.2.1", "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz", "integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==", - "dev": true, "dependencies": { "define-data-property": "^1.0.1", "has-property-descriptors": "^1.0.0", @@ -10738,7 +10743,6 @@ "version": "1.1.3", "resolved": "https://registry.npmjs.org/es-get-iterator/-/es-get-iterator-1.1.3.tgz", "integrity": "sha512-sPZmqHBe6JIiTfN5q2pEi//TwxmAFHwj/XEuYjTuse78i8KxaqMTTzxPoFKuzRpDpTJ+0NAbpfenkmH2rePtuw==", - "dev": true, "dependencies": { "call-bind": "^1.0.2", "get-intrinsic": "^1.1.3", @@ -12404,7 +12408,6 @@ "version": "1.2.3", "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz", "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==", - "dev": true, "funding": { "url": "https://github.com/sponsors/ljharb" } @@ -12866,7 +12869,6 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.2.tgz", "integrity": "sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==", - "dev": true, "funding": { "url": "https://github.com/sponsors/ljharb" } @@ -13424,7 +13426,6 @@ "version": "1.0.7", "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.7.tgz", "integrity": "sha512-NGnrKwXzSms2qUUih/ILZ5JBqNTSa1+ZmP6flaIp6KmSElgE9qdndzS3cqjrDovwFdmwsGsLdeFgB6suw+1e9g==", - "dev": true, "dependencies": { "es-errors": "^1.3.0", "hasown": "^2.0.0", @@ -13519,7 +13520,6 @@ "version": "3.0.4", "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.4.tgz", "integrity": "sha512-wcjaerHw0ydZwfhiKbXJWLDY8A7yV7KhjQOpb83hGgGfId/aQa4TOvwyzn2PuswW2gPCYEL/nEAiSVpdOj1lXw==", - "dev": true, "dependencies": { "call-bind": "^1.0.2", "get-intrinsic": "^1.2.1" @@ -13556,7 +13556,6 @@ "version": "1.0.4", "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz", "integrity": "sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==", - "dev": true, "dependencies": { "has-bigints": "^1.0.1" }, @@ -13579,7 +13578,6 @@ "version": "1.1.2", "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.2.tgz", "integrity": "sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==", - "dev": true, "dependencies": { "call-bind": "^1.0.2", "has-tostringtag": "^1.0.0" @@ -13641,7 +13639,6 @@ "version": "1.0.5", "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.5.tgz", "integrity": "sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==", - "dev": true, "dependencies": { "has-tostringtag": "^1.0.0" }, @@ -13785,7 +13782,6 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/is-map/-/is-map-2.0.2.tgz", "integrity": "sha512-cOZFQQozTha1f4MxLFzlgKYPTyj26picdZTx82hbc/Xf4K/tZOOXSCkMvU4pKioRXGDLJRn0GM7Upe7kR721yg==", - "dev": true, "funding": { "url": "https://github.com/sponsors/ljharb" } @@ -13830,7 +13826,6 @@ "version": "1.0.7", "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.7.tgz", "integrity": "sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==", - "dev": true, "dependencies": { "has-tostringtag": "^1.0.0" }, @@ -13883,7 +13878,6 @@ "version": "1.1.4", "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz", "integrity": "sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==", - "dev": true, "dependencies": { "call-bind": "^1.0.2", "has-tostringtag": "^1.0.0" @@ -13899,7 +13893,6 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/is-set/-/is-set-2.0.2.tgz", "integrity": "sha512-+2cnTEZeY5z/iXGbLhPrOAaK/Mau5k5eXq9j14CpRTftq0pAJu2MwVRSZhyZWBzx3o6X795Lz6Bpb6R0GKf37g==", - "dev": true, "funding": { "url": "https://github.com/sponsors/ljharb" } @@ -13908,7 +13901,6 @@ "version": "1.0.3", "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.3.tgz", "integrity": "sha512-nA2hv5XIhLR3uVzDDfCIknerhx8XUKnstuOERPNNIinXG7v9u+ohXF67vxm4TPTEPU6lm61ZkwP3c9PCB97rhg==", - "dev": true, "dependencies": { "call-bind": "^1.0.7" }, @@ -13935,7 +13927,6 @@ "version": "1.0.7", "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz", "integrity": "sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==", - "dev": true, "dependencies": { "has-tostringtag": "^1.0.0" }, @@ -13950,7 +13941,6 @@ "version": "1.0.4", "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.4.tgz", "integrity": "sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==", - "dev": true, "dependencies": { "has-symbols": "^1.0.2" }, @@ -13996,7 +13986,6 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/is-weakmap/-/is-weakmap-2.0.1.tgz", "integrity": "sha512-NSBR4kH5oVj1Uwvv970ruUkCV7O1mzgVFO4/rev2cLRda9Tm9HrL70ZPut4rOHgY0FNrUu9BCbXA2sdQ+x0chA==", - "dev": true, "funding": { "url": "https://github.com/sponsors/ljharb" } @@ -14017,7 +14006,6 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/is-weakset/-/is-weakset-2.0.2.tgz", "integrity": "sha512-t2yVvttHkQktwnNNmBQ98AhENLdPUTDTE21uPqAQ0ARwQfGeQKRVS0NNurH7bTf7RrvcVn1OOge45CnBeHCSmg==", - "dev": true, "dependencies": { "call-bind": "^1.0.2", "get-intrinsic": "^1.1.1" @@ -14041,8 +14029,7 @@ "node_modules/isarray": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", - "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", - "dev": true + "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==" }, "node_modules/isbot": { "version": "4.4.0", @@ -18545,7 +18532,6 @@ "version": "1.1.6", "resolved": "https://registry.npmjs.org/object-is/-/object-is-1.1.6.tgz", "integrity": "sha512-F8cZ+KfGlSGi09lJT7/Nd6KJZ9ygtvYC0/UYYLI9nmQKLMnydpB9yvbv9K1uSkEu7FU9vYPmVwLg328tX+ot3Q==", - "dev": true, "dependencies": { "call-bind": "^1.0.7", "define-properties": "^1.2.1" @@ -18561,7 +18547,6 @@ "version": "1.1.1", "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", - "dev": true, "engines": { "node": ">= 0.4" } @@ -18570,7 +18555,6 @@ "version": "4.1.5", "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.5.tgz", "integrity": "sha512-byy+U7gp+FVwmyzKPYhW2h5l3crpmGsxl7X2s8y43IgxvG4g3QZ6CffDtsNQy1WsmZpQbO+ybo0AlW7TY6DcBQ==", - "dev": true, "dependencies": { "call-bind": "^1.0.5", "define-properties": "^1.2.1", @@ -20329,7 +20313,6 @@ "version": "1.5.2", "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.2.tgz", "integrity": "sha512-NcDiDkTLuPR+++OCKB0nWafEmhg/Da8aUPLPMQbK+bxKKCm1/S5he+AqYa4PlMCVBalb4/yxIRub6qkEx5yJbw==", - "dev": true, "dependencies": { "call-bind": "^1.0.6", "define-properties": "^1.2.1", @@ -21147,7 +21130,6 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/set-function-name/-/set-function-name-2.0.2.tgz", "integrity": "sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ==", - "dev": true, "dependencies": { "define-data-property": "^1.1.4", "es-errors": "^1.3.0", @@ -21483,7 +21465,6 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/stop-iteration-iterator/-/stop-iteration-iterator-1.0.0.tgz", "integrity": "sha512-iCGQj+0l0HOdZ2AEeBADlsRC+vsnDsZsbdSiH1yNSjcfKM7fdpCMfqAL/dwF5BLiw/XhRft/Wax6zQbhq2BcjQ==", - "dev": true, "dependencies": { "internal-slot": "^1.0.4" }, @@ -24409,7 +24390,6 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz", "integrity": "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==", - "dev": true, "dependencies": { "is-bigint": "^1.0.1", "is-boolean-object": "^1.1.0", @@ -24451,7 +24431,6 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/which-collection/-/which-collection-1.0.1.tgz", "integrity": "sha512-W8xeTUwaln8i3K/cY1nGXzdnVZlidBcagyNFtBdD5kxnb4TvGKR7FfSIS3mYpwWS1QUCutfKz8IY8RjftB0+1A==", - "dev": true, "dependencies": { "is-map": "^2.0.1", "is-set": "^2.0.1", diff --git a/package.json b/package.json index 115268b0a5..ffd16d9ed2 100644 --- a/package.json +++ b/package.json @@ -41,6 +41,7 @@ "common": "file:common", "csstype": "^3.1.3", "dayjs": "^1.11.10", + "deep-equal": "^2.2.3", "detect-gpu": "^5.0.38", "http-proxy-middleware": "^3.0.0", "isbot": "^4.1.0", @@ -68,6 +69,7 @@ "@storybook/react": "^8.1.10", "@storybook/react-vite": "^8.1.10", "@storybook/test": "^8.1.10", + "@types/deep-equal": "^1.0.4", "@types/jest": "^29.5.12", "@types/react": "^18.2.20", "@types/react-copy-to-clipboard": "^5.0.7",