From 8a0ae4e42d217a222d6a127ec640d5f1113832a0 Mon Sep 17 00:00:00 2001 From: Sophie Zhang Date: Mon, 16 Oct 2023 17:08:24 -0400 Subject: text box --- src/client/views/nodes/trails/PresBox.scss | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) (limited to 'src/client/views/nodes/trails/PresBox.scss') diff --git a/src/client/views/nodes/trails/PresBox.scss b/src/client/views/nodes/trails/PresBox.scss index 0b51813a5..ac0d58368 100644 --- a/src/client/views/nodes/trails/PresBox.scss +++ b/src/client/views/nodes/trails/PresBox.scss @@ -15,6 +15,30 @@ //overflow: hidden; transition: 0.7s opacity ease; + .presBox-chatbox { + position: fixed; + bottom: 8px; + right: 8px; + width: 300px; + min-height: 100px; + border-radius: 16px; + padding: 16px; + gap: 8px; + z-index: 999; + display: flex; + flex-direction: column; + justify-content: space-between; + background-color: #ffffff; + box-shadow: 0 2px 5px #7474748d; + + input { + resize: vertical; + // min-height: 125px; + border: none; + outline: none; + } + } + .presBox-listCont { position: relative; height: calc(100% - 67px); -- cgit v1.2.3-70-g09d2 From 612f3d05927113c7b010861c17765fcead4752e5 Mon Sep 17 00:00:00 2001 From: Sophie Zhang Date: Thu, 19 Oct 2023 00:58:37 -0400 Subject: feat: recording --- package-lock.json | 28 + package.json | 1 + report.20231019.001427.35449.0.001.json | 1264 ++++++++++++++++++++ src/client/apis/gpt/GPT.ts | 10 +- .../views/nodes/formattedText/FormattedTextBox.tsx | 1 + src/client/views/nodes/trails/PresBox.scss | 13 +- src/client/views/nodes/trails/PresBox.tsx | 71 +- src/client/views/nodes/trails/PresElementBox.tsx | 2 + 8 files changed, 1374 insertions(+), 16 deletions(-) create mode 100644 report.20231019.001427.35449.0.001.json (limited to 'src/client/views/nodes/trails/PresBox.scss') diff --git a/package-lock.json b/package-lock.json index fbfdf0136..e84f33046 100644 --- a/package-lock.json +++ b/package-lock.json @@ -24804,6 +24804,16 @@ "react-is": "^16.8.1" } }, + "react-textarea-autosize": { + "version": "8.5.3", + "resolved": "https://registry.npmjs.org/react-textarea-autosize/-/react-textarea-autosize-8.5.3.tgz", + "integrity": "sha512-XT1024o2pqCuZSuBt9FwHlaDeNtVrtCXu0Rnz88t1jUGheCLa3PhjE1GH8Ctm2axEtvdCl5SUHYschyQ0L5QHQ==", + "requires": { + "@babel/runtime": "^7.20.13", + "use-composed-ref": "^1.3.0", + "use-latest": "^1.2.1" + } + }, "react-themeable": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/react-themeable/-/react-themeable-1.1.0.tgz", @@ -28351,6 +28361,24 @@ "fast-deep-equal": "^3.1.3" } }, + "use-composed-ref": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/use-composed-ref/-/use-composed-ref-1.3.0.tgz", + "integrity": "sha512-GLMG0Jc/jiKov/3Ulid1wbv3r54K9HlMW29IWcDFPEqFkSO2nS0MuefWgMJpeHQ9YJeXDL3ZUF+P3jdXlZX/cQ==" + }, + "use-isomorphic-layout-effect": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/use-isomorphic-layout-effect/-/use-isomorphic-layout-effect-1.1.2.tgz", + "integrity": "sha512-49L8yCO3iGT/ZF9QttjwLF/ZD9Iwto5LnH5LmEdk/6cFmXddqi2ulF0edxTwjj+7mqvpVVGQWvbXZdn32wRSHA==" + }, + "use-latest": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/use-latest/-/use-latest-1.2.1.tgz", + "integrity": "sha512-xA+AVm/Wlg3e2P/JiItTziwS7FK92LWrDB0p+hgXloIMuVCeJJ8v6f0eeHyPZaJrM+usM1FkFfbNCrJGs8A/zw==", + "requires": { + "use-isomorphic-layout-effect": "^1.1.1" + } + }, "use-memo-one": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/use-memo-one/-/use-memo-one-1.1.3.tgz", diff --git a/package.json b/package.json index d013ad74d..d8996f57e 100644 --- a/package.json +++ b/package.json @@ -305,6 +305,7 @@ "react-reveal": "^1.2.2", "react-select": "^3.2.0", "react-table": "^6.11.5", + "react-textarea-autosize": "^8.5.3", "react-transition-group": "^4.4.2", "react-typist": "^2.0.5", "readline": "^1.3.0", diff --git a/report.20231019.001427.35449.0.001.json b/report.20231019.001427.35449.0.001.json new file mode 100644 index 000000000..9dbe388b0 --- /dev/null +++ b/report.20231019.001427.35449.0.001.json @@ -0,0 +1,1264 @@ + +{ + "header": { + "reportVersion": 1, + "event": "Allocation failed - JavaScript heap out of memory", + "trigger": "FatalError", + "filename": "report.20231019.001427.35449.0.001.json", + "dumpEventTime": "2023-10-19T00:14:27Z", + "dumpEventTimeStamp": "1697688867046", + "processId": 35449, + "cwd": "/Users/smallwhale/Desktop/Projects/Dash-Web", + "commandLine": [ + "/Users/smallwhale/.nvm/versions/node/v12.16.0/bin/node", + "--max-old-space-size=2048", + "/Users/smallwhale/Desktop/Projects/Dash-Web/node_modules/ts-node-dev/lib/wrap.js", + "/Users/smallwhale/Desktop/Projects/Dash-Web/node_modules/fork-ts-checker-webpack-plugin/lib/service.js" + ], + "nodejsVersion": "v12.16.0", + "wordSize": 64, + "arch": "x64", + "platform": "darwin", + "componentVersions": { + "node": "12.16.0", + "v8": "7.8.279.23-node.31", + "uv": "1.34.0", + "zlib": "1.2.11", + "brotli": "1.0.7", + "ares": "1.15.0", + "modules": "72", + "nghttp2": "1.40.0", + "napi": "5", + "llhttp": "2.0.4", + "http_parser": "2.9.3", + "openssl": "1.1.1d", + "cldr": "35.1", + "icu": "64.2", + "tz": "2019c", + "unicode": "12.1" + }, + "release": { + "name": "node", + "lts": "Erbium", + "headersUrl": "https://nodejs.org/download/release/v12.16.0/node-v12.16.0-headers.tar.gz", + "sourceUrl": "https://nodejs.org/download/release/v12.16.0/node-v12.16.0.tar.gz" + }, + "osName": "Darwin", + "osRelease": "22.4.0", + "osVersion": "Darwin Kernel Version 22.4.0: Mon Mar 6 21:01:02 PST 2023; root:xnu-8796.101.5~3/RELEASE_ARM64_T8112", + "osMachine": "x86_64", + "cpus": [ + { + "model": "Apple M2", + "speed": 2400, + "user": 12520700, + "nice": 0, + "sys": 7484500, + "idle": 106635510, + "irq": 0 + }, + { + "model": "Apple M2", + "speed": 2400, + "user": 11888410, + "nice": 0, + "sys": 6595360, + "idle": 108221120, + "irq": 0 + }, + { + "model": "Apple M2", + "speed": 2400, + "user": 10596860, + "nice": 0, + "sys": 5620320, + "idle": 110583510, + "irq": 0 + }, + { + "model": "Apple M2", + "speed": 2400, + "user": 9300520, + "nice": 0, + "sys": 4805160, + "idle": 112784220, + "irq": 0 + }, + { + "model": "Apple M2", + "speed": 2400, + "user": 6989740, + "nice": 0, + "sys": 1675740, + "idle": 118483920, + "irq": 0 + }, + { + "model": "Apple M2", + "speed": 2400, + "user": 4302540, + "nice": 0, + "sys": 1125240, + "idle": 121745690, + "irq": 0 + }, + { + "model": "Apple M2", + "speed": 2400, + "user": 2444020, + "nice": 0, + "sys": 714220, + "idle": 124035440, + "irq": 0 + }, + { + "model": "Apple M2", + "speed": 2400, + "user": 1720230, + "nice": 0, + "sys": 536420, + "idle": 124948860, + "irq": 0 + } + ], + "networkInterfaces": [ + { + "name": "lo0", + "internal": true, + "mac": "00:00:00:00:00:00", + "address": "127.0.0.1", + "netmask": "255.0.0.0", + "family": "IPv4" + }, + { + "name": "lo0", + "internal": true, + "mac": "00:00:00:00:00:00", + "address": "::1", + "netmask": "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff", + "family": "IPv6", + "scopeid": 0 + }, + { + "name": "lo0", + "internal": true, + "mac": "00:00:00:00:00:00", + "address": "fe80::1", + "netmask": "ffff:ffff:ffff:ffff::", + "family": "IPv6", + "scopeid": 1 + }, + { + "name": "anpi1", + "internal": false, + "mac": "42:10:d5:5b:93:9f", + "address": "fe80::4010:d5ff:fe5b:939f", + "netmask": "ffff:ffff:ffff:ffff::", + "family": "IPv6", + "scopeid": 4 + }, + { + "name": "anpi0", + "internal": false, + "mac": "42:10:d5:5b:93:9e", + "address": "fe80::4010:d5ff:fe5b:939e", + "netmask": "ffff:ffff:ffff:ffff::", + "family": "IPv6", + "scopeid": 5 + }, + { + "name": "ap1", + "internal": false, + "mac": "be:3e:53:8e:59:0e", + "address": "fe80::bc3e:53ff:fe8e:590e", + "netmask": "ffff:ffff:ffff:ffff::", + "family": "IPv6", + "scopeid": 11 + }, + { + "name": "en0", + "internal": false, + "mac": "9c:3e:53:8e:59:0e", + "address": "fe80::1813:6293:c0ab:dc3e", + "netmask": "ffff:ffff:ffff:ffff::", + "family": "IPv6", + "scopeid": 12 + }, + { + "name": "en0", + "internal": false, + "mac": "9c:3e:53:8e:59:0e", + "address": "10.38.55.120", + "netmask": "255.255.192.0", + "family": "IPv4" + }, + { + "name": "en0", + "internal": false, + "mac": "9c:3e:53:8e:59:0e", + "address": "2620:6e:6000:3100:1005:c105:5692:58fb", + "netmask": "ffff:ffff:ffff:ffff::", + "family": "IPv6", + "scopeid": 0 + }, + { + "name": "en0", + "internal": false, + "mac": "9c:3e:53:8e:59:0e", + "address": "2620:6e:6000:3100:f817:2dd1:7d87:eac0", + "netmask": "ffff:ffff:ffff:ffff::", + "family": "IPv6", + "scopeid": 0 + }, + { + "name": "en0", + "internal": false, + "mac": "9c:3e:53:8e:59:0e", + "address": "fd33:5b24:c439:447c:1c8e:ee8a:48d8:e08e", + "netmask": "ffff:ffff:ffff:ffff::", + "family": "IPv6", + "scopeid": 0 + }, + { + "name": "en0", + "internal": false, + "mac": "9c:3e:53:8e:59:0e", + "address": "fdf0:d80b:58c0:4218:18e3:aed6:fbb3:1296", + "netmask": "ffff:ffff:ffff:ffff::", + "family": "IPv6", + "scopeid": 0 + }, + { + "name": "awdl0", + "internal": false, + "mac": "e2:65:e7:ac:a7:5d", + "address": "fe80::e065:e7ff:feac:a75d", + "netmask": "ffff:ffff:ffff:ffff::", + "family": "IPv6", + "scopeid": 13 + }, + { + "name": "llw0", + "internal": false, + "mac": "e2:65:e7:ac:a7:5d", + "address": "fe80::e065:e7ff:feac:a75d", + "netmask": "ffff:ffff:ffff:ffff::", + "family": "IPv6", + "scopeid": 14 + }, + { + "name": "utun0", + "internal": false, + "mac": "00:00:00:00:00:00", + "address": "fe80::272c:9ded:66c9:4c0e", + "netmask": "ffff:ffff:ffff:ffff::", + "family": "IPv6", + "scopeid": 15 + }, + { + "name": "utun1", + "internal": false, + "mac": "00:00:00:00:00:00", + "address": "fe80::75dc:d3c9:41be:fe2b", + "netmask": "ffff:ffff:ffff:ffff::", + "family": "IPv6", + "scopeid": 16 + }, + { + "name": "utun2", + "internal": false, + "mac": "00:00:00:00:00:00", + "address": "fe80::ce81:b1c:bd2c:69e", + "netmask": "ffff:ffff:ffff:ffff::", + "family": "IPv6", + "scopeid": 17 + } + ], + "host": "sophies-mbp-612.devices.brown.edu" + }, + "javascriptStack": { + "message": "No stack.", + "stack": [ + "Unavailable." + ] + }, + "nativeStack": [ + { + "pc": "0x000000010015c8ca", + "symbol": "report::TriggerNodeReport(v8::Isolate*, node::Environment*, char const*, char const*, std::__1::basic_string, std::__1::allocator> const&, v8::Local) [/Users/smallwhale/.nvm/versions/node/v12.16.0/bin/node]" + }, + { + "pc": "0x0000000100080f3e", + "symbol": "node::OnFatalError(char const*, char const*) [/Users/smallwhale/.nvm/versions/node/v12.16.0/bin/node]" + }, + { + "pc": "0x0000000100185467", + "symbol": "v8::Utils::ReportOOMFailure(v8::internal::Isolate*, char const*, bool) [/Users/smallwhale/.nvm/versions/node/v12.16.0/bin/node]" + }, + { + "pc": "0x0000000100185403", + "symbol": "v8::internal::V8::FatalProcessOutOfMemory(v8::internal::Isolate*, char const*, bool) [/Users/smallwhale/.nvm/versions/node/v12.16.0/bin/node]" + }, + { + "pc": "0x000000010030b5f5", + "symbol": "v8::internal::Heap::FatalProcessOutOfMemory(char const*) [/Users/smallwhale/.nvm/versions/node/v12.16.0/bin/node]" + }, + { + "pc": "0x000000010030ccc4", + "symbol": "v8::internal::Heap::RecomputeLimits(v8::internal::GarbageCollector) [/Users/smallwhale/.nvm/versions/node/v12.16.0/bin/node]" + }, + { + "pc": "0x0000000100309b37", + "symbol": "v8::internal::Heap::PerformGarbageCollection(v8::internal::GarbageCollector, v8::GCCallbackFlags) [/Users/smallwhale/.nvm/versions/node/v12.16.0/bin/node]" + }, + { + "pc": "0x0000000100307afd", + "symbol": "v8::internal::Heap::CollectGarbage(v8::internal::AllocationSpace, v8::internal::GarbageCollectionReason, v8::GCCallbackFlags) [/Users/smallwhale/.nvm/versions/node/v12.16.0/bin/node]" + }, + { + "pc": "0x00000001003132ba", + "symbol": "v8::internal::Heap::AllocateRawWithLightRetry(int, v8::internal::AllocationType, v8::internal::AllocationOrigin, v8::internal::AllocationAlignment) [/Users/smallwhale/.nvm/versions/node/v12.16.0/bin/node]" + }, + { + "pc": "0x0000000100313341", + "symbol": "v8::internal::Heap::AllocateRawWithRetryOrFail(int, v8::internal::AllocationType, v8::internal::AllocationOrigin, v8::internal::AllocationAlignment) [/Users/smallwhale/.nvm/versions/node/v12.16.0/bin/node]" + }, + { + "pc": "0x00000001002e065b", + "symbol": "v8::internal::Factory::NewFillerObject(int, bool, v8::internal::AllocationType, v8::internal::AllocationOrigin) [/Users/smallwhale/.nvm/versions/node/v12.16.0/bin/node]" + }, + { + "pc": "0x0000000100618a18", + "symbol": "v8::internal::Runtime_AllocateInYoungGeneration(int, unsigned long*, v8::internal::Isolate*) [/Users/smallwhale/.nvm/versions/node/v12.16.0/bin/node]" + }, + { + "pc": "0x0000000100950c19", + "symbol": "Builtins_CEntry_Return1_DontSaveFPRegs_ArgvOnStack_NoBuiltinExit [/Users/smallwhale/.nvm/versions/node/v12.16.0/bin/node]" + }, + { + "pc": "0x00002368c975aaed", + "symbol": "" + } + ], + "javascriptHeap": { + "totalMemory": 2152210432, + "totalCommittedMemory": 2150555464, + "usedMemory": 2140643800, + "availableMemory": 47978928, + "memoryLimit": 2197815296, + "heapSpaces": { + "read_only_space": { + "memorySize": 262144, + "committedMemory": 33088, + "capacity": 32808, + "used": 32808, + "available": 0 + }, + "new_space": { + "memorySize": 2097152, + "committedMemory": 1158104, + "capacity": 1047456, + "used": 110920, + "available": 936536 + }, + "old_space": { + "memorySize": 1951547392, + "committedMemory": 1951490488, + "capacity": 1945024816, + "used": 1944634744, + "available": 390072 + }, + "code_space": { + "memorySize": 14585856, + "committedMemory": 14251936, + "capacity": 12921184, + "used": 12921184, + "available": 0 + }, + "map_space": { + "memorySize": 1576960, + "committedMemory": 1480920, + "capacity": 1273280, + "used": 1273280, + "available": 0 + }, + "large_object_space": { + "memorySize": 182091776, + "committedMemory": 182091776, + "capacity": 181668080, + "used": 181668080, + "available": 0 + }, + "code_large_object_space": { + "memorySize": 49152, + "committedMemory": 49152, + "capacity": 2784, + "used": 2784, + "available": 0 + }, + "new_large_object_space": { + "memorySize": 0, + "committedMemory": 0, + "capacity": 1047456, + "used": 0, + "available": 1047456 + } + } + }, + "resourceUsage": { + "userCpuSeconds": 285.707, + "kernelCpuSeconds": 105.722, + "cpuConsumptionPercent": 80.0469, + "maxRss": 2142366597120, + "pageFaults": { + "IORequired": 1061, + "IONotRequired": 36578633 + }, + "fsActivity": { + "reads": 0, + "writes": 0 + } + }, + "libuv": [ + ], + "environmentVariables": { + "npm_config_save_dev": "", + "npm_config_legacy_bundling": "", + "npm_config_dry_run": "", + "npm_package_dependencies_request": "^2.88.2", + "npm_package_dependencies_express_flash": "0.0.2", + "npm_package_dependencies__fortawesome_fontawesome_svg_core": "^6.3.0", + "NVM_INC": "/Users/smallwhale/.nvm/versions/node/v12.16.0/include/node", + "npm_config_viewer": "man", + "npm_config_only": "", + "npm_config_commit_hooks": "true", + "npm_config_browser": "", + "npm_package_gitHead": "8a0ae4e42d217a222d6a127ec640d5f1113832a0", + "npm_package_dependencies_webpack_dev_middleware": "^5.3.1", + "npm_package_dependencies_webpack_cli": "^4.10.0", + "npm_package_devDependencies_prettier": "^2.7.1", + "npm_package_devDependencies_awesome_typescript_loader": "^5.2.1", + "npm_package_devDependencies__types_archiver": "^3.1.1", + "MANPATH": "/Users/smallwhale/.nvm/versions/node/v12.16.0/share/man:/Users/smallwhale/.nvm/versions/node/v18.16.0/share/man:/opt/homebrew/share/man:/usr/share/man:/usr/local/share/man:/Users/smallwhale/.nvm/versions/node/v18.16.0/share/man:/opt/homebrew/share/man::", + "npm_config_also": "", + "npm_package_dependencies_react_jsx_parser": "^1.29.0", + "npm_package_dependencies_mongoose": "^5.13.14", + "npm_package_dependencies_connect_flash": "^0.1.1", + "npm_package_browser_child_process": "false", + "npm_config_sign_git_commit": "", + "npm_config_rollback": "true", + "npm_package_dependencies_material_ui": "^0.20.2", + "npm_package_devDependencies__types_sharp": "^0.23.1", + "npm_package_devDependencies__types_passport_local": "^1.0.34", + "npm_package_devDependencies__types_dotenv": "^6.1.1", + "npm_package_devDependencies__types_cookie_parser": "^1.4.2", + "TERM_PROGRAM": "vscode", + "NODE": "/Users/smallwhale/.nvm/versions/node/v12.16.0/bin/node", + "npm_config_usage": "", + "npm_config_audit": "true", + "npm_package_dependencies_reveal_js": "^4.3.0", + "npm_package_dependencies_process": "^0.11.10", + "npm_package_dependencies_pdfjs": "^2.4.7", + "npm_package_dependencies_html_to_image": "^0.1.3", + "npm_package_devDependencies_file_loader": "^3.0.1", + "npm_package_devDependencies__types_express_flash": "0.0.0", + "npm_package_scripts_monitor": "cross-env MONITORED=true NODE_OPTIONS=--max_old_space_size=4096 ts-node src/server/index.ts", + "INIT_CWD": "/Users/smallwhale/Desktop/Projects/Dash-Web", + "npm_package_dependencies_rehype_raw": "^6.1.1", + "npm_package_dependencies_react_audio_waveform": "0.0.5", + "npm_package_dependencies_path_browserify": "^1.0.1", + "npm_package_dependencies_nodemailer": "^5.1.1", + "npm_package_dependencies_axios": "^0.19.2", + "npm_package_devDependencies_typescript": "^4.7.4", + "NVM_CD_FLAGS": "-q", + "npm_config_globalignorefile": "/Users/smallwhale/.nvm/versions/node/v12.16.0/etc/npmignore", + "npm_package_dependencies_react_grid_layout": "^1.3.4", + "npm_package_dependencies_prosemirror_find_replace": "^0.9.0", + "npm_package_dependencies_normalize_css": "^8.0.1", + "npm_package_devDependencies_mocha": "^5.2.0", + "npm_package_devDependencies__types_express_session": "^1.17.5", + "TERM": "xterm-256color", + "SHELL": "/bin/zsh", + "npm_config_shell": "/bin/zsh", + "npm_config_maxsockets": "50", + "npm_config_init_author_url": "", + "npm_package_dependencies_prosemirror_dev_tools": "^3.1.0", + "npm_package_dependencies_p_limit": "^2.2.0", + "npm_package_dependencies_bson": "^4.6.1", + "npm_package_dependencies__types_dom_speech_recognition": "0.0.1", + "npm_package_dependencies__emotion_styled": "^11.11.0", + "npm_package_devDependencies_style_loader": "^0.23.1", + "npm_package_devDependencies__types_react_datepicker": "^3.1.8", + "npm_config_shrinkwrap": "true", + "npm_config_parseable": "", + "npm_config_metrics_registry": "https://registry.npmjs.org/", + "npm_package_dependencies_xregexp": "^4.4.1", + "npm_package_dependencies_shelljs": "^0.8.5", + "npm_package_dependencies_bezier_curve": "^1.0.0", + "npm_package_dependencies__mui_icons_material": "^5.11.16", + "npm_package_devDependencies_tslint": "^5.20.1", + "npm_package_devDependencies__types_react_transition_group": "^4.4.5", + "npm_package_scripts_tsc": "tsc", + "HOMEBREW_REPOSITORY": "/opt/homebrew", + "TMPDIR": "/var/folders/bv/1xck6d7j7bz14bvhgdsllbj40000gn/T/", + "npm_config_timing": "", + "npm_config_init_license": "ISC", + "npm_package_dependencies_socket_io": "^2.5.0", + "npm_package_dependencies_probe_image_size": "^4.0.0", + "npm_package_dependencies_canvas": "^2.9.3", + "npm_package_dependencies__hig_theme_data": "^2.23.1", + "npm_package_devDependencies__types_react_select": "^3.1.2", + "npm_package_devDependencies__types_prosemirror_model": "^1.16.1", + "npm_config_if_present": "", + "npm_package_dependencies_typescript_collections": "^1.3.3", + "npm_package_dependencies_rimraf": "^3.0.0", + "npm_package_dependencies_react_autosuggest": "^9.4.3", + "npm_package_dependencies_flexlayout_react": "^0.3.11", + "npm_package_dependencies_find_in_files": "^0.5.0", + "npm_package_devDependencies__types_chai": "^4.3.0", + "TERM_PROGRAM_VERSION": "1.83.0", + "npm_package_dependencies_prosemirror_inputrules": "^1.1.3", + "npm_package_dependencies_bcrypt_nodejs": "0.0.3", + "npm_package_dependencies_async": "^2.6.2", + "npm_config_sign_git_tag": "", + "npm_config_init_author_email": "", + "npm_config_cache_max": "Infinity", + "npm_package_dependencies_uuid": "^3.4.0", + "npm_package_dependencies_supercluster": "^7.1.4", + "npm_package_dependencies_remark_gfm": "^3.0.1", + "npm_package_dependencies_connect_mongo": "^2.0.3", + "npm_package_dependencies_browser_assert": "^1.2.1", + "npm_package_devDependencies_sass_loader": "^7.3.1", + "npm_package_scripts_start_release_debug": "cross-env RELEASE=true USE_AZURE=true NODE_OPTIONS=--max_old_space_size=4096 ts-node-dev --inspect -- src/server/index.ts", + "ZDOTDIR": "/Users/smallwhale", + "ORIGINAL_XDG_CURRENT_DESKTOP": "undefined", + "MallocNanoZone": "0", + "npm_config_preid": "", + "npm_config_long": "", + "npm_config_local_address": "", + "npm_config_git_tag_version": "true", + "npm_config_cert": "", + "npm_package_dependencies_js_datepicker": "^4.6.6", + "npm_package_devDependencies__types_webpack_hot_middleware": "^2.25.6", + "npm_package_devDependencies__types_mongodb": "^3.6.20", + "npm_package_devDependencies__types_mocha": "^5.2.6", + "npm_config_registry": "https://registry.npmjs.org/", + "npm_config_noproxy": "", + "npm_config_fetch_retries": "2", + "npm_package_dependencies_react_compound_slider": "^2.5.0", + "npm_package_dependencies_prosemirror_history": "^1.2.0", + "npm_package_devDependencies__types_react_color": "^2.17.6", + "npm_package_devDependencies__types_google_maps_react": "^2.0.5", + "npm_package_devDependencies__types_color": "^3.0.3", + "npm_package_dependencies_react_dom": "^18.2.0", + "npm_package_dependencies_passport_local": "^1.0.0", + "npm_package_dependencies__octokit_core": "^4.0.4", + "npm_package_devDependencies__types_async": "^2.4.1", + "npm_package_scripts_debug": "cross-env NODE_OPTIONS=--max_old_space_size=8192 ts-node-dev --transpile-only --inspect -- src/server/index.ts", + "npm_package_scripts_oldstart": "cross-env NODE_OPTIONS=--max_old_space_size=4096 ts-node-dev --debug -- src/server/index.ts", + "npm_config_versions": "", + "npm_config_message": "%s", + "npm_config_key": "", + "npm_package_readmeFilename": "README.md", + "npm_package_dependencies_react_refresh_typescript": "^2.0.7", + "npm_package_dependencies_react_dropzone": "^14.2.3", + "npm_package_dependencies_image_size": "^0.7.5", + "npm_package_dependencies_html_to_text": "^5.1.1", + "npm_package_dependencies_express_validator": "^5.3.1", + "npm_package_devDependencies_eslint_plugin_jsx_a11y": "^6.6.0", + "npm_package_node_child_process": "empty", + "npm_package_dependencies_react_resizable_rotatable_draggable": "^0.2.0", + "npm_package_dependencies_got": "^12.0.1", + "npm_package_dependencies__types_d3_color": "^2.0.3", + "npm_package_devDependencies_webpack": "^5.69.1", + "npm_package_devDependencies__types_nodemailer": "^4.6.6", + "npm_package_description": "Install Node.js, then, from the project directory, run", + "NVM_DIR": "/Users/smallwhale/.nvm", + "USER": "smallwhale", + "npm_package_dependencies__types_d3_scale": "^3.3.2", + "npm_package_devDependencies_dotenv": "^8.6.0", + "npm_package_devDependencies__types_react": "^18.0.15", + "npm_package_devDependencies__types_prosemirror_transform": "^1.1.5", + "npm_package_devDependencies__types_prosemirror_history": "^1.0.3", + "npm_package_dependencies_readline": "^1.3.0", + "npm_package_dependencies__types_supercluster": "^7.1.0", + "npm_package_dependencies__azure_storage_blob": "^12.14.0", + "COMMAND_MODE": "unix2003", + "npm_config_globalconfig": "/Users/smallwhale/.nvm/versions/node/v12.16.0/etc/npmrc", + "npm_package_dependencies_depcheck": "^0.9.2", + "npm_package_dependencies__types_web": "0.0.53", + "npm_config_prefer_online": "", + "npm_config_logs_max": "10", + "npm_config_always_auth": "", + "npm_package_dependencies_react_icons": "^4.3.1", + "npm_package_dependencies_passport_google_oauth20": "^2.0.0", + "npm_package_devDependencies_webpack_dev_server": "^3.11.3", + "npm_package_devDependencies__types_brotli": "^1.3.1", + "npm_package_dependencies_url_loader": "^1.1.2", + "npm_package_dependencies_stream_browserify": "^3.0.0", + "npm_package_dependencies_prosemirror_transform": "^1.3.4", + "npm_package_dependencies_lodash": "^4.17.21", + "npm_package_dependencies_i": "^0.3.7", + "npm_package_devDependencies_tslint_loader": "^3.6.0", + "SSH_AUTH_SOCK": "/private/tmp/com.apple.launchd.Rzc48vZMGY/Listeners", + "npm_package_dependencies_words_to_numbers": "^1.5.1", + "npm_package_dependencies_valid_url": "^1.0.9", + "npm_package_dependencies_styled_components": "^4.4.1", + "npm_package_dependencies_csv_parser": "^3.0.0", + "npm_package_dependencies_class_transformer": "^0.2.0", + "npm_package_devDependencies_eslint": "^8.36.0", + "npm_package_devDependencies__types_prosemirror_inputrules": "^1.0.4", + "npm_package_devDependencies__types_express": "^4.17.13", + "__CF_USER_TEXT_ENCODING": "0x1F5:0x0:0x0", + "npm_execpath": "/Users/smallwhale/.nvm/versions/node/v12.16.0/lib/node_modules/npm/bin/npm-cli.js", + "npm_config_global_style": "", + "npm_config_cache_lock_retries": "10", + "npm_package_dependencies_wikijs": "^6.3.3", + "npm_package_dependencies_bluebird": "^3.7.2", + "npm_package_devDependencies__types_react_typist": "^2.0.3", + "npm_config_update_notifier": "true", + "npm_config_cafile": "", + "npm_package_dependencies_util": "^0.12.4", + "npm_package_dependencies_raw_loader": "^1.0.0", + "npm_package_dependencies_https_browserify": "^1.0.0", + "npm_package_dependencies_brotli": "^1.3.3", + "npm_package_dependencies__mui_material": "^5.13.1", + "npm_package_dependencies__fortawesome_react_fontawesome": "^0.2.0", + "npm_package_devDependencies__types_passport_google_oauth20": "^2.0.11", + "npm_package_dependencies_cors": "^2.8.5", + "npm_package_dependencies_bezier_js": "^4.1.1", + "npm_package_dependencies__fortawesome_free_brands_svg_icons": "^6.3.0", + "npm_config_heading": "npm", + "npm_config_audit_level": "low", + "npm_package_dependencies_chrome": "^0.1.0", + "npm_package_dependencies__react_three_fiber": "^6.2.3", + "npm_package_devDependencies_eslint_plugin_prettier": "^4.2.1", + "npm_package_devDependencies_copy_webpack_plugin": "^4.6.0", + "npm_package_devDependencies__types_react_measure": "^2.0.8", + "npm_package_devDependencies__types_react_dom": "^18.0.6", + "npm_package_devDependencies__types_mobile_detect": "^1.3.4", + "npm_config_searchlimit": "20", + "npm_config_read_only": "", + "npm_config_offline": "", + "npm_config_fetch_retry_mintimeout": "10000", + "npm_package_dependencies_react_typist": "^2.0.5", + "npm_package_dependencies_mobx_react_devtools": "^6.1.1", + "npm_package_dependencies_md5_file": "^5.0.0", + "npm_package_dependencies_forever_agent": "^0.6.1", + "npm_package_devDependencies__types_xregexp": "^4.4.0", + "npm_package_devDependencies__types_typescript": "^2.0.0", + "npm_package_devDependencies__types_request": "^2.48.8", + "npm_package_devDependencies__types_prosemirror_commands": "^1.0.4", + "npm_config_json": "", + "npm_config_access": "", + "npm_config_argv": "{\"remain\":[],\"cooked\":[\"start\"],\"original\":[\"start\"]}", + "npm_package_dependencies__fortawesome_free_solid_svg_icons": "^6.3.0", + "npm_package_devDependencies__types_socket_io": "^2.1.13", + "PATH": "/Users/smallwhale/.nvm/versions/node/v12.16.0/lib/node_modules/npm/node_modules/npm-lifecycle/node-gyp-bin:/Users/smallwhale/Desktop/Projects/Dash-Web/node_modules/.bin:/Users/smallwhale/.nvm/versions/node/v12.16.0/bin:/Users/smallwhale/.nvm/versions/node/v18.16.0/bin:/Library/Frameworks/Python.framework/Versions/3.11/bin:/opt/homebrew/bin:/opt/homebrew/sbin:/usr/local/bin:/System/Cryptexes/App/usr/bin:/usr/bin:/bin:/usr/sbin:/sbin:/Library/Frameworks/Mono.framework/Versions/Current/Commands:/var/run/com.apple.security.cryptexd/codex.system/bootstrap/usr/local/bin:/var/run/com.apple.security.cryptexd/codex.system/bootstrap/usr/bin:/var/run/com.apple.security.cryptexd/codex.system/bootstrap/usr/appleinternal/bin:/Users/smallwhale/.nvm/versions/node/v18.16.0/bin:/Library/Frameworks/Python.framework/Versions/3.11/bin:/opt/homebrew/bin:/opt/homebrew/sbin", + "npm_config_allow_same_version": "", + "npm_package_dependencies_webrtc_adapter": "^7.7.1", + "npm_package_dependencies_react_reveal": "^1.2.2", + "npm_package_dependencies_prosemirror_schema_list": "^1.1.6", + "npm_package_dependencies__material_ui_core": "^4.12.3", + "npm_package_devDependencies__types_rimraf": "^2.0.5", + "npm_package_devDependencies__types_connect_flash": "0.0.34", + "npm_config_https_proxy": "", + "npm_config_engine_strict": "", + "npm_config_description": "true", + "npm_package_dependencies_pug": "^2.0.4", + "npm_package_dependencies_prosemirror_keymap": "^1.1.5", + "npm_package_dependencies_pdfjs_dist": "^2.14.305", + "npm_package_dependencies_mobile_detect": "^1.4.5", + "npm_package_dependencies_image_size_stream": "^1.1.0", + "npm_package_dependencies_golden_layout": "^1.5.9", + "npm_package_dependencies_child_process": "^1.0.2", + "npm_package_dependencies__types_d3_axis": "^2.1.3", + "_": "/Users/smallwhale/Desktop/Projects/Dash-Web/node_modules/.bin/cross-env", + "LaunchInstanceID": "BA61DDCB-E273-45DE-B08F-DCC79F8578DB", + "npm_config_userconfig": "/Users/smallwhale/.npmrc", + "npm_config_init_module": "/Users/smallwhale/.npm-init.js", + "npm_package_dependencies__react_google_maps_api": "^2.7.0", + "USER_ZDOTDIR": "/Users/smallwhale", + "__CFBundleIdentifier": "com.microsoft.VSCode", + "npm_config_cidr": "", + "npm_package_dependencies_puppeteer": "^3.3.0", + "npm_package_dependencies_prosemirror_view": "^1.26.5", + "npm_package_dependencies_mongodb": "^3.7.3", + "npm_package_dependencies_google_auth_library": "^4.2.4", + "npm_package_dependencies_bootstrap": "^4.6.1", + "npm_package_devDependencies_eslint_config_airbnb": "^19.0.4", + "PWD": "/Users/smallwhale/Desktop/Projects/Dash-Web", + "npm_config_user": "501", + "npm_config_node_version": "12.16.0", + "npm_package_dependencies_node_sass": "^4.14.1", + "npm_package_dependencies_howler": "^2.2.3", + "npm_package_dependencies_expressjs": "^1.0.1", + "npm_package_dependencies_core_js": "^3.28.0", + "npm_package_dependencies_browndash_components": "^0.1.36", + "npm_package_devDependencies_eslint_plugin_react_hooks": "^4.6.0", + "npm_package_devDependencies__types_lodash": "^4.14.179", + "JAVA_HOME": "/opt/homebrew/Cellar/openjdk@17/17.0.8.1/libexec/openjdk.jdk/Contents/Home", + "npm_lifecycle_event": "start", + "npm_package_dependencies_react_table": "^6.11.5", + "npm_package_dependencies_react_loading": "^2.0.3", + "npm_package_dependencies_mobx": "^5.15.7", + "npm_package_dependencies_babel": "^6.23.0", + "npm_package_devDependencies_jsdom": "^15.2.1", + "npm_package_devDependencies_chai": "^4.3.6", + "npm_config_save": "true", + "npm_config_ignore_prepublish": "", + "npm_config_editor": "vi", + "npm_config_auth_type": "legacy", + "npm_package_dependencies_npm": "^6.14.18", + "npm_package_dependencies_node_stream_zip": "^1.15.0", + "npm_package_dependencies_image_data_uri": "^2.0.1", + "npm_package_scripts_start_release": "cross-env RELEASE=true USE_AZURE=false NODE_OPTIONS=--max_old_space_size=4096 ts-node-dev -- src/server/index.ts", + "npm_package_name": "dash", + "LANG": "en_US.UTF-8", + "npm_config_tag": "latest", + "npm_config_script_shell": "", + "npm_package_dependencies_query_string": "^6.14.1", + "npm_package_dependencies_mobx_utils": "^5.6.2", + "npm_package_dependencies_file_saver": "^2.0.5", + "npm_package_dependencies_body_parser": "^1.19.2", + "npm_package_dependencies__types_reveal": "^3.3.33", + "npm_package_devDependencies_eslint_plugin_import": "^2.26.0", + "npm_package_devDependencies__types_prosemirror_view": "^1.23.1", + "npm_config_progress": "true", + "npm_config_global": "", + "npm_config_before": "", + "npm_package_dependencies_xoauth2": "^1.2.0", + "npm_package_dependencies_standard_http_error": "^2.0.1", + "npm_package_dependencies_react_loader_spinner": "^5.3.4", + "npm_package_dependencies_http_browserify": "^1.7.0", + "npm_package_dependencies__types_d3_selection": "^2.0.1", + "npm_package_dependencies__hig_flyout": "^1.3.1", + "npm_package_devDependencies_fork_ts_checker_webpack_plugin": "^1.6.0", + "npm_package_scripts_build": "cross-env NODE_OPTIONS=--max_old_space_size=8192 webpack --env production", + "npm_package_scripts_start": "cross-env NODE_OPTIONS=--max_old_space_size=4096 ts-node-dev --debug --transpile-only -- src/server/index.ts", + "npm_config_searchstaleness": "900", + "npm_config_optional": "true", + "npm_config_ham_it_up": "", + "npm_package_dependencies_sharp": "^0.23.4", + "npm_package_dependencies_rc_switch": "^1.9.2", + "npm_package_dependencies_googlephotos": "^0.2.5", + "npm_package_dependencies_exifr": "^7.1.3", + "npm_package_dependencies__types_google_maps": "^3.2.3", + "npm_package_dependencies__types_bezier_js": "^4.1.0", + "npm_package_dependencies__ffmpeg_core": "0.10.0", + "npm_package_devDependencies_ts_loader": "^5.3.3", + "npm_package_devDependencies__types_bcrypt_nodejs": "0.0.30", + "VSCODE_GIT_ASKPASS_EXTRA_ARGS": "--ms-enable-electron-run-as-node", + "XPC_FLAGS": "0x0", + "npm_config_save_prod": "", + "npm_config_force": "", + "npm_config_bin_links": "true", + "npm_package_devDependencies__types_youtube": "0.0.39", + "npm_config_searchopts": "", + "npm_package_dependencies_react_beautiful_dnd": "^13.1.0", + "npm_package_dependencies_jszip": "^3.7.1", + "npm_package_dependencies_csv_stringify": "^6.3.0", + "npm_package_devDependencies__types_react_icons": "^3.0.0", + "npm_config_node_gyp": "/Users/smallwhale/.nvm/versions/node/v12.16.0/lib/node_modules/npm/node_modules/node-gyp/bin/node-gyp.js", + "npm_config_depth": "Infinity", + "npm_package_dependencies_google_maps_react": "^2.0.6", + "npm_package_dependencies_express_session": "^1.17.2", + "npm_package_devDependencies_eslint_plugin_node": "^11.1.0", + "npm_package_devDependencies_eslint_config_prettier": "^8.5.0", + "npm_package_main": "index.js", + "npm_config_sso_poll_frequency": "500", + "npm_config_rebuild_bundle": "true", + "npm_package_dependencies_chart_js": "^3.8.0", + "npm_package_dependencies__emotion_react": "^11.11.0", + "npm_package_devDependencies__types_prosemirror_menu": "^1.0.6", + "npm_package_devDependencies__types_prosemirror_keymap": "^1.0.4", + "npm_package_devDependencies__types_pdfjs_dist": "^2.10.378", + "npm_package_devDependencies__types_exif": "^0.6.3", + "npm_package_version": "1.0.0", + "XPC_SERVICE_NAME": "0", + "npm_config_unicode": "true", + "VSCODE_INJECTION": "1", + "npm_package_dependencies_typescript_language_server": "^0.4.0", + "npm_package_dependencies_prosemirror_model": "^1.18.1", + "npm_package_dependencies__ffmpeg_ffmpeg": "0.10.0", + "SHLVL": "2", + "HOME": "/Users/smallwhale", + "npm_config_fetch_retry_maxtimeout": "60000", + "npm_package_dependencies_request_promise": "^4.2.6", + "npm_package_dependencies_react_markdown": "^8.0.3", + "npm_package_dependencies__hig_theme_context": "^2.1.3", + "npm_package_devDependencies__types_react_autosuggest": "^9.3.14", + "npm_package_devDependencies__types_mongoose": "^5.11.97", + "npm_package_devDependencies__types_d3": "^7.4.0", + "npm_package_devDependencies__types_animejs": "^2.0.2", + "npm_package_scripts_test": "mocha -r ts-node/register test/**/*.ts", + "VSCODE_GIT_ASKPASS_MAIN": "/Applications/Visual Studio Code.app/Contents/Resources/app/extensions/git/dist/askpass-main.js", + "npm_config_tag_version_prefix": "v", + "npm_config_strict_ssl": "true", + "npm_config_sso_type": "oauth", + "npm_config_scripts_prepend_node_path": "warn-only", + "npm_config_save_prefix": "^", + "npm_config_loglevel": "notice", + "npm_config_ca": "", + "npm_package_dependencies_three": "^0.127.0", + "npm_package_dependencies_openai": "^3.2.1", + "npm_package_dependencies_mobx_react": "^5.4.4", + "npm_package_dependencies_google_translate_api_browser": "^3.0.1", + "npm_package_dependencies_cookie_parser": "^1.4.6", + "npm_package_dependencies_adm_zip": "^0.4.16", + "npm_package_devDependencies_eslint_config_node": "^4.1.0", + "npm_config_save_exact": "", + "npm_config_group": "20", + "npm_config_fetch_retry_factor": "10", + "npm_config_dev": "", + "npm_package_devDependencies_webpack_hot_middleware": "^2.25.1", + "npm_package_devDependencies_cross_env": "^5.2.1", + "HOMEBREW_PREFIX": "/opt/homebrew", + "npm_config_version": "", + "npm_config_prefer_offline": "", + "npm_config_cache_lock_stale": "60000", + "npm_package_devDependencies__types_prosemirror_state": "^1.2.8", + "npm_package_devDependencies__types_body_parser": "^1.19.2", + "npm_config_otp": "", + "npm_config_cache_min": "10", + "npm_package_dependencies_react_color": "^2.19.3", + "npm_package_dependencies_d3": "^7.6.1", + "npm_package_devDependencies_ts_node": "^10.9.1", + "npm_package_devDependencies__types_react_grid_layout": "^1.3.2", + "npm_config_searchexclude": "", + "npm_config_cache": "/Users/smallwhale/.npm", + "npm_package_dependencies_tough_cookie": "^4.0.0", + "npm_package_dependencies_googleapis": "^40.0.0", + "npm_package_devDependencies__types_valid_url": "^1.0.3", + "npm_package_devDependencies__types_passport": "^1.0.9", + "npm_package_devDependencies__types_adm_zip": "^0.4.34", + "LOGNAME": "smallwhale", + "npm_lifecycle_script": "cross-env NODE_OPTIONS=--max_old_space_size=4096 ts-node-dev --debug --transpile-only -- src/server/index.ts", + "npm_config_color": "true", + "npm_package_dependencies_solr_node": "^1.2.1", + "npm_package_dependencies_react_transition_group": "^4.4.2", + "npm_package_dependencies_iink_js": "^1.5.4", + "npm_package_dependencies_html_webpack_plugin": "^5.5.0", + "npm_config_proxy": "", + "npm_config_package_lock": "true", + "npm_package_dependencies_prosemirror_state": "^1.4.1", + "npm_package_dependencies_nodemon": "^1.19.4", + "npm_package_dependencies_function_plot": "^1.22.8", + "npm_package_dependencies_equation_editor_react": "github:bobzel/equation-editor-react#useLocally", + "npm_package_devDependencies__types_socket_io_parser": "^3.0.0", + "VSCODE_GIT_IPC_HANDLE": "/var/folders/bv/1xck6d7j7bz14bvhgdsllbj40000gn/T/vscode-git-b8c8318074.sock", + "npm_config_package_lock_only": "", + "npm_config_fund": "true", + "npm_package_dependencies_react": "^18.2.0", + "npm_package_dependencies_bingmaps_react": "^1.2.10", + "npm_package_devDependencies_scss_loader": "0.0.1", + "npm_package_devDependencies__types_cookie_session": "^2.0.44", + "npm_config_save_optional": "", + "npm_package_dependencies_textarea_caret": "^3.1.0", + "npm_package_dependencies_react_measure": "^2.5.2", + "npm_package_dependencies_exif": "^0.6.0", + "NVM_BIN": "/Users/smallwhale/.nvm/versions/node/v12.16.0/bin", + "npm_config_ignore_scripts": "", + "npm_config_user_agent": "npm/6.13.4 node/v12.16.0 darwin x64", + "npm_package_dependencies_react_resizable": "^1.11.1", + "npm_package_dependencies_prosemirror_commands": "^1.2.1", + "npm_package_dependencies_memorystream": "^0.3.1", + "npm_package_dependencies_formidable": "1.2.1", + "npm_package_devDependencies__types_uuid": "^3.4.10", + "npm_config_cache_lock_wait": "10000", + "npm_package_dependencies_socket_io_client": "^2.5.0", + "npm_package_dependencies_recharts": "^2.1.12", + "npm_package_dependencies_react_chartjs_2": "^4.3.0", + "npm_package_dependencies_fluent_ffmpeg": "^2.1.2", + "npm_package_dependencies__types_cors": "^2.8.12", + "npm_package_devDependencies__types_node": "^10.17.60", + "npm_package_devDependencies__types_file_saver": "^2.0.5", + "VSCODE_GIT_ASKPASS_NODE": "/Applications/Visual Studio Code.app/Contents/Frameworks/Code Helper (Plugin).app/Contents/MacOS/Code Helper (Plugin)", + "GIT_ASKPASS": "/Applications/Visual Studio Code.app/Contents/Resources/app/extensions/git/dist/askpass.sh", + "INFOPATH": "/opt/homebrew/share/info:/opt/homebrew/share/info:", + "HOMEBREW_CELLAR": "/opt/homebrew/Cellar", + "npm_config_production": "", + "npm_package_dependencies_jsonschema": "^1.4.0", + "npm_package_dependencies_ffmpeg": "0.0.4", + "npm_package_dependencies_cookie_session": "^2.0.0", + "npm_package_dependencies_color": "^3.2.1", + "npm_package_devDependencies__types_webpack": "^4.41.32", + "npm_package_devDependencies__types_request_promise": "^4.1.48", + "npm_package_devDependencies__types_prosemirror_schema_list": "^1.0.3", + "npm_config_send_metrics": "", + "npm_config_save_bundle": "", + "npm_package_dependencies_web_request": "^1.0.7", + "npm_package_dependencies_react_datepicker": "^3.8.0", + "npm_package_dependencies_express": "^4.17.3", + "npm_package_dependencies_D": "^1.0.0", + "npm_package_dependencies__types_formidable": "1.0.31", + "npm_package_devDependencies__types_rc_switch": "^1.9.2", + "npm_package_devDependencies__types_prosemirror_dev_tools": "^2.1.0", + "npm_package_devDependencies__types_jquery": "^3.5.14", + "npm_config_umask": "0022", + "npm_config_node_options": "", + "npm_config_init_version": "1.0.0", + "npm_package_dependencies_react_textarea_autosize": "^8.5.3", + "npm_package_dependencies_https": "^1.0.0", + "npm_package_dependencies_array_batcher": "^1.2.3", + "npm_package_dependencies__fortawesome_free_regular_svg_icons": "^6.3.0", + "npm_package_devDependencies__types_shelljs": "^0.8.11", + "npm_package_devDependencies__types_libxmljs": "^0.18.7", + "npm_package_devDependencies__types_express_validator": "^3.0.0", + "npm_package_devDependencies__types_bluebird": "^3.5.36", + "npm_config_init_author_name": "", + "npm_config_git": "git", + "npm_config_scope": "", + "npm_package_dependencies_react_select": "^3.2.0", + "npm_package_dependencies_pdf_parse": "^1.1.1", + "npm_package_dependencies_colors": "^1.4.0", + "npm_package_dependencies_archiver": "^3.1.1", + "npm_package_devDependencies_css_loader": "^2.1.1", + "npm_package_devDependencies__types_socket_io_client": "^1.4.36", + "SECURITYSESSIONID": "186a4", + "npm_config_unsafe_perm": "true", + "npm_config_tmp": "/var/folders/bv/1xck6d7j7bz14bvhgdsllbj40000gn/T", + "npm_config_onload_script": "", + "npm_package_dependencies_serializr": "^1.5.4", + "npm_package_dependencies_fit_curve": "^0.1.7", + "npm_package_dependencies__webscopeio_react_textarea_autocomplete": "^4.9.1", + "npm_package_dependencies__types_three": "^0.126.2", + "npm_package_devDependencies_ts_node_dev": "^2.0.0", + "npm_node_execpath": "/Users/smallwhale/.nvm/versions/node/v12.16.0/bin/node", + "npm_config_prefix": "/Users/smallwhale/.nvm/versions/node/v12.16.0", + "npm_config_link": "", + "npm_config_format_package_lock": "true", + "npm_package_dependencies_passport": "^0.4.0", + "npm_package_devDependencies_eslint_plugin_react": "^7.30.1", + "npm_package_devDependencies__types_react_table": "^6.8.9", + "npm_package_devDependencies__types_react_reconciler": "^0.26.4", + "COLORTERM": "truecolor", + "NODE_OPTIONS": "--max_old_space_size=4096", + "TS_NODE_DEV": "true", + "_CLIENT_OPENAI_KEY": "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", + "_CLIENT_GITHUB_ACCESS_TOKEN": "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", + "VIPSHOME": "/usr/local/Cellar/vips/8.8.1", + "TYPESCRIPT_PATH": "/Users/smallwhale/Desktop/Projects/Dash-Web/node_modules/typescript/lib/typescript.js", + "TSCONFIG": "/Users/smallwhale/Desktop/Projects/Dash-Web/tsconfig.json", + "COMPILER_OPTIONS": "{}", + "TSLINT": "true", + "CONTEXT": "/Users/smallwhale/Desktop/Projects/Dash-Web", + "TSLINTAUTOFIX": "false", + "ESLINT": "false", + "ESLINT_OPTIONS": "{}", + "WATCH": "", + "WORK_DIVISION": "1", + "MEMORY_LIMIT": "2048", + "CHECK_SYNTACTIC_ERRORS": "false", + "USE_INCREMENTAL_API": "true", + "VUE": "false" + }, + "userLimits": { + "core_file_size_blocks": { + "soft": 0, + "hard": "unlimited" + }, + "data_seg_size_kbytes": { + "soft": "unlimited", + "hard": "unlimited" + }, + "file_size_blocks": { + "soft": "unlimited", + "hard": "unlimited" + }, + "max_locked_memory_bytes": { + "soft": "unlimited", + "hard": "unlimited" + }, + "max_memory_size_kbytes": { + "soft": "unlimited", + "hard": "unlimited" + }, + "open_files": { + "soft": 1048575, + "hard": "unlimited" + }, + "stack_size_bytes": { + "soft": 8372224, + "hard": 67092480 + }, + "cpu_time_seconds": { + "soft": "unlimited", + "hard": "unlimited" + }, + "max_user_processes": { + "soft": 1333, + "hard": 2000 + }, + "virtual_memory_kbytes": { + "soft": "unlimited", + "hard": "unlimited" + } + }, + "sharedObjects": [ + "/Users/smallwhale/.nvm/versions/node/v12.16.0/bin/node", + "/System/Library/Frameworks/CoreFoundation.framework/Versions/A/CoreFoundation", + "/usr/lib/libobjc.A.dylib", + "/System/Library/PrivateFrameworks/CoreServicesInternal.framework/Versions/A/CoreServicesInternal", + "/usr/lib/liboah.dylib", + "/usr/lib/libfakelink.dylib", + "/usr/lib/libicucore.A.dylib", + "/usr/lib/libSystem.B.dylib", + "/System/Library/PrivateFrameworks/SoftLinking.framework/Versions/A/SoftLinking", + "/usr/lib/libc++abi.dylib", + "/usr/lib/libc++.1.dylib", + "/usr/lib/system/libcache.dylib", + "/usr/lib/system/libcommonCrypto.dylib", + "/usr/lib/system/libcompiler_rt.dylib", + "/usr/lib/system/libcopyfile.dylib", + "/usr/lib/system/libcorecrypto.dylib", + "/usr/lib/system/libdispatch.dylib", + "/usr/lib/system/libdyld.dylib", + "/usr/lib/system/libkeymgr.dylib", + "/usr/lib/system/libmacho.dylib", + "/usr/lib/system/libquarantine.dylib", + "/usr/lib/system/libremovefile.dylib", + "/usr/lib/system/libsystem_asl.dylib", + "/usr/lib/system/libsystem_blocks.dylib", + "/usr/lib/system/libsystem_c.dylib", + "/usr/lib/system/libsystem_collections.dylib", + "/usr/lib/system/libsystem_configuration.dylib", + "/usr/lib/system/libsystem_containermanager.dylib", + "/usr/lib/system/libsystem_coreservices.dylib", + "/usr/lib/system/libsystem_darwin.dylib", + "/usr/lib/system/libsystem_dnssd.dylib", + "/usr/lib/system/libsystem_featureflags.dylib", + "/usr/lib/system/libsystem_info.dylib", + "/usr/lib/system/libsystem_m.dylib", + "/usr/lib/system/libsystem_malloc.dylib", + "/usr/lib/system/libsystem_networkextension.dylib", + "/usr/lib/system/libsystem_notify.dylib", + "/usr/lib/system/libsystem_sandbox.dylib", + "/usr/lib/system/libsystem_secinit.dylib", + "/usr/lib/system/libsystem_kernel.dylib", + "/usr/lib/system/libsystem_platform.dylib", + "/usr/lib/system/libsystem_pthread.dylib", + "/usr/lib/system/libsystem_symptoms.dylib", + "/usr/lib/system/libsystem_trace.dylib", + "/usr/lib/system/libunwind.dylib", + "/usr/lib/system/libxpc.dylib", + "/System/Library/Frameworks/IOKit.framework/Versions/A/IOKit", + "/System/Library/Frameworks/CoreServices.framework/Versions/A/CoreServices", + "/usr/lib/libDiagnosticMessagesClient.dylib", + "/usr/lib/libenergytrace.dylib", + "/usr/lib/libbsm.0.dylib", + "/usr/lib/libz.1.dylib", + "/usr/lib/system/libkxld.dylib", + "/System/Library/Frameworks/CFNetwork.framework/Versions/A/CFNetwork", + "/System/Library/Frameworks/CoreServices.framework/Versions/A/Frameworks/FSEvents.framework/Versions/A/FSEvents", + "/System/Library/Frameworks/CoreServices.framework/Versions/A/Frameworks/CarbonCore.framework/Versions/A/CarbonCore", + "/System/Library/Frameworks/CoreServices.framework/Versions/A/Frameworks/Metadata.framework/Versions/A/Metadata", + "/System/Library/Frameworks/CoreServices.framework/Versions/A/Frameworks/OSServices.framework/Versions/A/OSServices", + "/System/Library/Frameworks/CoreServices.framework/Versions/A/Frameworks/SearchKit.framework/Versions/A/SearchKit", + "/System/Library/Frameworks/CoreServices.framework/Versions/A/Frameworks/AE.framework/Versions/A/AE", + "/System/Library/Frameworks/CoreServices.framework/Versions/A/Frameworks/LaunchServices.framework/Versions/A/LaunchServices", + "/System/Library/Frameworks/CoreServices.framework/Versions/A/Frameworks/DictionaryServices.framework/Versions/A/DictionaryServices", + "/System/Library/Frameworks/CoreServices.framework/Versions/A/Frameworks/SharedFileList.framework/Versions/A/SharedFileList", + "/System/Library/Frameworks/Security.framework/Versions/A/Security", + "/System/Library/Frameworks/SystemConfiguration.framework/Versions/A/SystemConfiguration", + "/usr/lib/libapple_nghttp2.dylib", + "/usr/lib/libcompression.dylib", + "/usr/lib/libnetwork.dylib", + "/usr/lib/libsqlite3.dylib", + "/System/Library/Frameworks/Foundation.framework/Versions/C/Foundation", + "/System/Library/Frameworks/Network.framework/Versions/A/Network", + "/usr/lib/libCoreEntitlements.dylib", + "/System/Library/PrivateFrameworks/MessageSecurity.framework/Versions/A/MessageSecurity", + "/System/Library/PrivateFrameworks/ProtocolBuffer.framework/Versions/A/ProtocolBuffer", + "/usr/lib/libMobileGestalt.dylib", + "/System/Library/PrivateFrameworks/AppleFSCompression.framework/Versions/A/AppleFSCompression", + "/usr/lib/libcoretls.dylib", + "/usr/lib/libcoretls_cfhelpers.dylib", + "/usr/lib/libpam.2.dylib", + "/usr/lib/libxar.1.dylib", + "/System/Library/PrivateFrameworks/CoreAutoLayout.framework/Versions/A/CoreAutoLayout", + "/System/Library/Frameworks/DiskArbitration.framework/Versions/A/DiskArbitration", + "/usr/lib/libarchive.2.dylib", + "/usr/lib/libxml2.2.dylib", + "/usr/lib/liblangid.dylib", + "/System/Library/Frameworks/Combine.framework/Versions/A/Combine", + "/usr/lib/swift/libswiftCore.dylib", + "/usr/lib/swift/libswiftCoreFoundation.dylib", + "/usr/lib/swift/libswiftDarwin.dylib", + "/usr/lib/swift/libswiftDispatch.dylib", + "/usr/lib/swift/libswiftIOKit.dylib", + "/usr/lib/swift/libswiftObjectiveC.dylib", + "/usr/lib/swift/libswiftXPC.dylib", + "/usr/lib/swift/libswift_Concurrency.dylib", + "/usr/lib/swift/libswift_StringProcessing.dylib", + "/usr/lib/swift/libswiftos.dylib", + "/System/Library/PrivateFrameworks/AppleSystemInfo.framework/Versions/A/AppleSystemInfo", + "/System/Library/PrivateFrameworks/IOMobileFramebuffer.framework/Versions/A/IOMobileFramebuffer", + "/System/Library/Frameworks/IOSurface.framework/Versions/A/IOSurface", + "/usr/lib/libpcap.A.dylib", + "/usr/lib/libdns_services.dylib", + "/usr/lib/liblzma.5.dylib", + "/usr/lib/libbz2.1.0.dylib", + "/usr/lib/libiconv.2.dylib", + "/usr/lib/libcharset.1.dylib", + "/usr/lib/swift/libswift_RegexParser.dylib", + "/usr/lib/libheimdal-asn1.dylib", + "/usr/lib/libCheckFix.dylib", + "/System/Library/PrivateFrameworks/TCC.framework/Versions/A/TCC", + "/System/Library/PrivateFrameworks/CoreNLP.framework/Versions/A/CoreNLP", + "/System/Library/PrivateFrameworks/MetadataUtilities.framework/Versions/A/MetadataUtilities", + "/System/Library/Frameworks/Accelerate.framework/Versions/A/Accelerate", + "/usr/lib/libmecab.dylib", + "/usr/lib/libCRFSuite.dylib", + "/usr/lib/libgermantok.dylib", + "/usr/lib/libThaiTokenizer.dylib", + "/System/Library/Frameworks/Accelerate.framework/Versions/A/Frameworks/vImage.framework/Versions/A/vImage", + "/System/Library/Frameworks/Accelerate.framework/Versions/A/Frameworks/vecLib.framework/Versions/A/vecLib", + "/System/Library/Frameworks/Accelerate.framework/Versions/A/Frameworks/vecLib.framework/Versions/A/libvMisc.dylib", + "/System/Library/Frameworks/Accelerate.framework/Versions/A/Frameworks/vecLib.framework/Versions/A/libvDSP.dylib", + "/System/Library/Frameworks/Accelerate.framework/Versions/A/Frameworks/vecLib.framework/Versions/A/libBLAS.dylib", + "/System/Library/Frameworks/Accelerate.framework/Versions/A/Frameworks/vecLib.framework/Versions/A/libLAPACK.dylib", + "/System/Library/Frameworks/Accelerate.framework/Versions/A/Frameworks/vecLib.framework/Versions/A/libLinearAlgebra.dylib", + "/System/Library/Frameworks/Accelerate.framework/Versions/A/Frameworks/vecLib.framework/Versions/A/libSparseBLAS.dylib", + "/System/Library/Frameworks/Accelerate.framework/Versions/A/Frameworks/vecLib.framework/Versions/A/libQuadrature.dylib", + "/System/Library/Frameworks/Accelerate.framework/Versions/A/Frameworks/vecLib.framework/Versions/A/libBNNS.dylib", + "/System/Library/Frameworks/Accelerate.framework/Versions/A/Frameworks/vecLib.framework/Versions/A/libSparse.dylib", + "/System/Library/PrivateFrameworks/MIL.framework/Versions/A/MIL", + "/System/Library/Frameworks/OpenDirectory.framework/Versions/A/Frameworks/CFOpenDirectory.framework/Versions/A/CFOpenDirectory", + "/System/Library/Frameworks/OpenDirectory.framework/Versions/A/OpenDirectory", + "/System/Library/PrivateFrameworks/APFS.framework/Versions/A/APFS", + "/System/Library/Frameworks/SecurityFoundation.framework/Versions/A/SecurityFoundation", + "/usr/lib/libutil.dylib", + "/System/Library/PrivateFrameworks/InstalledContentLibrary.framework/Versions/A/InstalledContentLibrary", + "/System/Library/PrivateFrameworks/CoreServicesStore.framework/Versions/A/CoreServicesStore", + "/usr/lib/libapp_launch_measurement.dylib", + "/System/Library/PrivateFrameworks/AppleMobileFileIntegrity.framework/Versions/A/AppleMobileFileIntegrity", + "/usr/lib/libmis.dylib", + "/System/Library/PrivateFrameworks/MobileSystemServices.framework/Versions/A/MobileSystemServices", + "/System/Library/PrivateFrameworks/ConfigProfileHelper.framework/Versions/A/ConfigProfileHelper", + "/System/Library/PrivateFrameworks/CoreAnalytics.framework/Versions/A/CoreAnalytics", + "/System/Library/PrivateFrameworks/AppleSauce.framework/Versions/A/AppleSauce", + "/System/Library/PrivateFrameworks/LanguageModeling.framework/Versions/A/LanguageModeling", + "/usr/lib/libxslt.1.dylib", + "/usr/lib/libcmph.dylib", + "/System/Library/PrivateFrameworks/CoreEmoji.framework/Versions/A/CoreEmoji", + "/System/Library/PrivateFrameworks/LinguisticData.framework/Versions/A/LinguisticData", + "/System/Library/PrivateFrameworks/Lexicon.framework/Versions/A/Lexicon", + "/System/Library/PrivateFrameworks/BackgroundTaskManagement.framework/Versions/A/BackgroundTaskManagement", + "/usr/lib/libTLE.dylib", + "/System/Library/Frameworks/ApplicationServices.framework/Versions/A/ApplicationServices", + "/System/Library/Frameworks/CoreGraphics.framework/Versions/A/CoreGraphics", + "/System/Library/Frameworks/CoreText.framework/Versions/A/CoreText", + "/System/Library/Frameworks/ImageIO.framework/Versions/A/ImageIO", + "/System/Library/Frameworks/ColorSync.framework/Versions/A/ColorSync", + "/System/Library/Frameworks/ApplicationServices.framework/Versions/A/Frameworks/ATS.framework/Versions/A/ATS", + "/System/Library/Frameworks/ApplicationServices.framework/Versions/A/Frameworks/HIServices.framework/Versions/A/HIServices", + "/System/Library/Frameworks/ApplicationServices.framework/Versions/A/Frameworks/PrintCore.framework/Versions/A/PrintCore", + "/System/Library/Frameworks/ApplicationServices.framework/Versions/A/Frameworks/QD.framework/Versions/A/QD", + "/System/Library/Frameworks/ApplicationServices.framework/Versions/A/Frameworks/ColorSyncLegacy.framework/Versions/A/ColorSyncLegacy", + "/System/Library/Frameworks/ApplicationServices.framework/Versions/A/Frameworks/SpeechSynthesis.framework/Versions/A/SpeechSynthesis", + "/System/Library/PrivateFrameworks/SkyLight.framework/Versions/A/SkyLight", + "/System/Library/PrivateFrameworks/FontServices.framework/libFontParser.dylib", + "/System/Library/PrivateFrameworks/RunningBoardServices.framework/Versions/A/RunningBoardServices", + "/System/Library/PrivateFrameworks/IOSurfaceAccelerator.framework/Versions/A/IOSurfaceAccelerator", + "/System/Library/PrivateFrameworks/WatchdogClient.framework/Versions/A/WatchdogClient", + "/System/Library/Frameworks/CoreDisplay.framework/Versions/A/CoreDisplay", + "/System/Library/Frameworks/CoreMedia.framework/Versions/A/CoreMedia", + "/System/Library/PrivateFrameworks/IOAccelerator.framework/Versions/A/IOAccelerator", + "/System/Library/Frameworks/Metal.framework/Versions/A/Metal", + "/System/Library/Frameworks/CoreVideo.framework/Versions/A/CoreVideo", + "/System/Library/Frameworks/MetalPerformanceShaders.framework/Versions/A/MetalPerformanceShaders", + "/System/Library/PrivateFrameworks/MultitouchSupport.framework/Versions/A/MultitouchSupport", + "/System/Library/Frameworks/QuartzCore.framework/Versions/A/QuartzCore", + "/System/Library/Frameworks/VideoToolbox.framework/Versions/A/VideoToolbox", + "/System/Library/PrivateFrameworks/BaseBoard.framework/Versions/A/BaseBoard", + "/System/Library/PrivateFrameworks/AppleJPEG.framework/Versions/A/AppleJPEG", + "/usr/lib/libexpat.1.dylib", + "/System/Library/Frameworks/ImageIO.framework/Versions/A/Resources/libPng.dylib", + "/System/Library/Frameworks/ImageIO.framework/Versions/A/Resources/libTIFF.dylib", + "/System/Library/Frameworks/ImageIO.framework/Versions/A/Resources/libGIF.dylib", + "/System/Library/Frameworks/ImageIO.framework/Versions/A/Resources/libJP2.dylib", + "/usr/lib/libate.dylib", + "/System/Library/Frameworks/ImageIO.framework/Versions/A/Resources/libJPEG.dylib", + "/System/Library/Frameworks/ImageIO.framework/Versions/A/Resources/libRadiance.dylib", + "/System/Library/PrivateFrameworks/GPUWrangler.framework/Versions/A/GPUWrangler", + "/System/Library/PrivateFrameworks/IOPresentment.framework/Versions/A/IOPresentment", + "/System/Library/PrivateFrameworks/DSExternalDisplay.framework/Versions/A/DSExternalDisplay", + "/System/Library/PrivateFrameworks/GPUCompiler.framework/Versions/31001/Libraries/libllvm-flatbuffers.dylib", + "/System/Library/Frameworks/OpenGL.framework/Versions/A/Libraries/libCoreFSCache.dylib", + "/System/Library/PrivateFrameworks/GPUCompiler.framework/Versions/31001/Libraries/libGPUCompilerUtils.dylib", + "/System/Library/PrivateFrameworks/CMCaptureCore.framework/Versions/A/CMCaptureCore", + "/usr/lib/libspindump.dylib", + "/System/Library/Frameworks/CoreAudio.framework/Versions/A/CoreAudio", + "/System/Library/Frameworks/ExtensionFoundation.framework/Versions/A/ExtensionFoundation", + "/System/Library/PrivateFrameworks/CoreTime.framework/Versions/A/CoreTime", + "/System/Library/PrivateFrameworks/AppServerSupport.framework/Versions/A/AppServerSupport", + "/System/Library/PrivateFrameworks/perfdata.framework/Versions/A/perfdata", + "/System/Library/PrivateFrameworks/AudioToolboxCore.framework/Versions/A/AudioToolboxCore", + "/System/Library/PrivateFrameworks/caulk.framework/Versions/A/caulk", + "/usr/lib/libAudioStatistics.dylib", + "/System/Library/PrivateFrameworks/SystemPolicy.framework/Versions/A/SystemPolicy", + "/usr/lib/libSMC.dylib", + "/System/Library/Frameworks/CoreMIDI.framework/Versions/A/CoreMIDI", + "/usr/lib/libAudioToolboxUtility.dylib", + "/System/Library/PrivateFrameworks/OSAServicesClient.framework/Versions/A/OSAServicesClient", + "/usr/lib/libperfcheck.dylib", + "/System/Library/PrivateFrameworks/PlugInKit.framework/Versions/A/PlugInKit", + "/System/Library/PrivateFrameworks/AssertionServices.framework/Versions/A/AssertionServices", + "/System/Library/Frameworks/OpenGL.framework/Versions/A/OpenGL", + "/System/Library/Frameworks/OpenGL.framework/Versions/A/Libraries/libGLU.dylib", + "/System/Library/Frameworks/OpenGL.framework/Versions/A/Libraries/libGFXShared.dylib", + "/System/Library/Frameworks/OpenGL.framework/Versions/A/Libraries/libGL.dylib", + "/System/Library/Frameworks/OpenGL.framework/Versions/A/Libraries/libGLImage.dylib", + "/System/Library/Frameworks/OpenGL.framework/Versions/A/Libraries/libCVMSPluginSupport.dylib", + "/usr/lib/libRosetta.dylib", + "/System/Library/Frameworks/OpenGL.framework/Versions/A/Libraries/libCoreVMClient.dylib", + "/System/Library/Frameworks/MetalPerformanceShaders.framework/Versions/A/Frameworks/MPSCore.framework/Versions/A/MPSCore", + "/System/Library/Frameworks/MetalPerformanceShaders.framework/Versions/A/Frameworks/MPSImage.framework/Versions/A/MPSImage", + "/System/Library/Frameworks/MetalPerformanceShaders.framework/Versions/A/Frameworks/MPSNeuralNetwork.framework/Versions/A/MPSNeuralNetwork", + "/System/Library/Frameworks/MetalPerformanceShaders.framework/Versions/A/Frameworks/MPSMatrix.framework/Versions/A/MPSMatrix", + "/System/Library/Frameworks/MetalPerformanceShaders.framework/Versions/A/Frameworks/MPSRayIntersector.framework/Versions/A/MPSRayIntersector", + "/System/Library/Frameworks/MetalPerformanceShaders.framework/Versions/A/Frameworks/MPSNDArray.framework/Versions/A/MPSNDArray", + "/System/Library/Frameworks/MetalPerformanceShaders.framework/Versions/A/Frameworks/MPSFunctions.framework/Versions/A/MPSFunctions", + "/System/Library/PrivateFrameworks/MetalTools.framework/Versions/A/MetalTools", + "/System/Library/PrivateFrameworks/AggregateDictionary.framework/Versions/A/AggregateDictionary", + "/usr/lib/libIOReport.dylib", + "/System/Library/Frameworks/CoreImage.framework/Versions/A/CoreImage", + "/System/Library/PrivateFrameworks/PhotosensitivityProcessing.framework/Versions/A/PhotosensitivityProcessing", + "/System/Library/Frameworks/OpenCL.framework/Versions/A/OpenCL", + "/System/Library/PrivateFrameworks/GraphVisualizer.framework/Versions/A/GraphVisualizer", + "/System/Library/PrivateFrameworks/FontServices.framework/Versions/A/FontServices", + "/System/Library/Frameworks/UniformTypeIdentifiers.framework/Versions/A/UniformTypeIdentifiers", + "/System/Library/PrivateFrameworks/OTSVG.framework/Versions/A/OTSVG", + "/System/Library/Frameworks/ApplicationServices.framework/Versions/A/Frameworks/ATS.framework/Versions/A/Resources/libFontRegistry.dylib", + "/System/Library/PrivateFrameworks/FontServices.framework/libhvf.dylib", + "/System/Library/PrivateFrameworks/FontServices.framework/libXTFontStaticRegistryData.dylib", + "/System/Library/PrivateFrameworks/VideoToolboxParavirtualizationSupport.framework/Versions/A/VideoToolboxParavirtualizationSupport", + "/System/Library/PrivateFrameworks/AppleVA.framework/Versions/A/AppleVA", + "/System/Library/Frameworks/ApplicationServices.framework/Versions/A/Frameworks/ATSUI.framework/Versions/A/ATSUI", + "/usr/lib/libcups.2.dylib", + "/System/Library/Frameworks/Kerberos.framework/Versions/A/Kerberos", + "/System/Library/Frameworks/GSS.framework/Versions/A/GSS", + "/usr/lib/libresolv.9.dylib", + "/System/Library/PrivateFrameworks/Heimdal.framework/Versions/A/Heimdal", + "/System/Library/Frameworks/Kerberos.framework/Versions/A/Libraries/libHeimdalProxy.dylib", + "/System/Library/PrivateFrameworks/CommonAuth.framework/Versions/A/CommonAuth", + "/System/Library/Frameworks/AVFAudio.framework/Versions/A/AVFAudio", + "/System/Library/PrivateFrameworks/AXCoreUtilities.framework/Versions/A/AXCoreUtilities", + "/System/Library/Frameworks/AudioToolbox.framework/Versions/A/AudioToolbox", + "/System/Library/PrivateFrameworks/AudioSession.framework/Versions/A/AudioSession", + "/System/Library/Frameworks/IOBluetooth.framework/Versions/A/IOBluetooth", + "/System/Library/PrivateFrameworks/MediaExperience.framework/Versions/A/MediaExperience", + "/System/Library/PrivateFrameworks/AudioSession.framework/libSessionUtility.dylib", + "/System/Library/PrivateFrameworks/AudioResourceArbitration.framework/Versions/A/AudioResourceArbitration", + "/System/Library/PrivateFrameworks/PowerLog.framework/Versions/A/PowerLog", + "/System/Library/Frameworks/CoreData.framework/Versions/A/CoreData", + "/System/Library/Frameworks/CoreBluetooth.framework/Versions/A/CoreBluetooth", + "/System/Library/Frameworks/AudioUnit.framework/Versions/A/AudioUnit", + "/System/Library/PrivateFrameworks/CoreUtils.framework/Versions/A/CoreUtils", + "/System/Library/PrivateFrameworks/CoreUtilsExtras.framework/Versions/A/CoreUtilsExtras", + "/System/Library/PrivateFrameworks/IO80211.framework/Versions/A/IO80211", + "/System/Library/PrivateFrameworks/MobileKeyBag.framework/Versions/A/MobileKeyBag", + "/System/Library/PrivateFrameworks/MallocStackLogging.framework/Versions/A/MallocStackLogging" + ] +} \ No newline at end of file diff --git a/src/client/apis/gpt/GPT.ts b/src/client/apis/gpt/GPT.ts index d7e7f07fa..66689f2f6 100644 --- a/src/client/apis/gpt/GPT.ts +++ b/src/client/apis/gpt/GPT.ts @@ -26,7 +26,7 @@ const openai = new OpenAIApi(configuration); const gptTrailSlideCustomization = async (inputText: string) => { const prompt = - 'We are adding customization to a slide in a presentation. Given a natural language input, translate it into a json with the required fields: [title, presentation_transition, presentation_effect, and config_zoom]. title is the title/name of the slide. presentation_transition is a number in milliseconds for how long it should take to transition to a slide. presentation_effect is an effect applied to the slide when we transition to it. Its only possible values are: [None, Fade in, Flip, Rotate, Bounce, Roll]. config zoom is a number from 0 to 1.0 indicating the percentage we should be zooming into the slide.If the input does not contain info a specific key, please set their value to null. Please only return the json with these keys and their values.'; + 'We are adding customization to a slide in a presentation. Given a natural language input, translate it into a json with the required fields: [title, presentation_transition, presentation_effect, and config_zoom]. title is the title/name of the slide. presentation_transition is a number in milliseconds for how long it should take to transition to a slide. presentation_effect is an effect applied to the slide when we transition to it. Its only possible values are: [None, Fade in, Flip, Rotate, Bounce, Roll]. config zoom is a number from 0 to 1.0 indicating the percentage we should be zooming into the slide. If the input does not contain info a specific key, please set their value to null. Please only return the json with these keys and their values.'; try { const response = await openai.createChatCompletion({ @@ -55,10 +55,6 @@ const gptAPICall = async (inputText: string, callType: GPTCallType) => { if (callType === GPTCallType.SUMMARY) inputText += '.'; const opts: GPTCallOpts = callTypeMap[callType]; try { - // const configuration = new Configuration({ - // apiKey: process.env.OPENAI_KEY, - // }); - // const openai = new OpenAIApi(configuration); const response = await openai.createCompletion({ model: opts.model, max_tokens: opts.maxTokens, @@ -74,10 +70,6 @@ const gptAPICall = async (inputText: string, callType: GPTCallType) => { const gptImageCall = async (prompt: string, n?: number) => { try { - // const configuration = new Configuration({ - // apiKey: process.env.OPENAI_KEY, - // }); - // const openai = new OpenAIApi(configuration); const response = await openai.createImage({ prompt: prompt, n: n ?? 1, diff --git a/src/client/views/nodes/formattedText/FormattedTextBox.tsx b/src/client/views/nodes/formattedText/FormattedTextBox.tsx index 90ebf5206..eab62c20b 100644 --- a/src/client/views/nodes/formattedText/FormattedTextBox.tsx +++ b/src/client/views/nodes/formattedText/FormattedTextBox.tsx @@ -966,6 +966,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent { + console.log('breakup'); if (this._editorView && this._recordingDictation) { this.stopDictation(true); this._break = true; diff --git a/src/client/views/nodes/trails/PresBox.scss b/src/client/views/nodes/trails/PresBox.scss index ac0d58368..370b155fd 100644 --- a/src/client/views/nodes/trails/PresBox.scss +++ b/src/client/views/nodes/trails/PresBox.scss @@ -18,8 +18,8 @@ .presBox-chatbox { position: fixed; bottom: 8px; - right: 8px; - width: 300px; + left: 8px; + width: calc(100% - 16px); min-height: 100px; border-radius: 16px; padding: 16px; @@ -31,11 +31,12 @@ background-color: #ffffff; box-shadow: 0 2px 5px #7474748d; - input { - resize: vertical; - // min-height: 125px; - border: none; + .pres-chatbox { outline: none; + border: none; + font-size: 16px; + letter-spacing: 1px; + color: #404040; } } diff --git a/src/client/views/nodes/trails/PresBox.tsx b/src/client/views/nodes/trails/PresBox.tsx index ebf9c211c..051a1fbfd 100644 --- a/src/client/views/nodes/trails/PresBox.tsx +++ b/src/client/views/nodes/trails/PresBox.tsx @@ -40,6 +40,9 @@ import { PresEffect, PresEffectDirection, PresMovement, PresStatus } from './Pre import { IconButton, Type } from 'browndash-components'; import { AiOutlineSend } from 'react-icons/ai'; import { gptTrailSlideCustomization } from '../../../apis/gpt/GPT'; +import { DictationManager } from '../../../util/DictationManager'; +import { BiMicrophone, BiX } from 'react-icons/bi'; +import TextareaAutosize from 'react-textarea-autosize'; export interface pinDataTypes { scrollable?: boolean; @@ -112,6 +115,7 @@ export class PresBox extends ViewBoxBaseComponent() { @observable chatActive: boolean = false; @observable chatInput: string = ''; public slideToModify: Doc | null = null; + @observable isRecording: boolean = false; @action setChatInput = (input: string) => { @@ -123,6 +127,11 @@ export class PresBox extends ViewBoxBaseComponent() { this.chatActive = active; }; + @action + public setIsRecording = (isRecording: boolean) => { + this.isRecording = isRecording; + }; + @computed get isTreeOrStack() { return [CollectionViewType.Tree, CollectionViewType.Stacking].includes(StrCast(this.layoutDoc._type_collection) as any); @@ -260,6 +269,24 @@ export class PresBox extends ViewBoxBaseComponent() { } }; + // GPT + + recordDictation = () => { + DictationManager.Controls.listen({ + interimHandler: this.setDictationContent, + continuous: { indefinite: false }, + }).then(results => { + if (results && [DictationManager.Controls.Infringed].includes(results)) { + DictationManager.Controls.stop(); + } + }); + }; + stopDictation = (abort: boolean) => DictationManager.Controls.stop(!abort); + + setDictationContent = (value: string) => { + this.setChatInput(value); + }; + @action customizeWithGPT = async (input: string) => { // const testInput = 'change title to Customized Slide, transition for 2.3s with fade in effect'; @@ -2714,8 +2741,50 @@ export class PresBox extends ViewBoxBaseComponent() { {/* presbox chatbox */} {this.chatActive && (
- this.setChatInput(e.target.value)} />
+ } + onClick={() => { + this.setChatActive(false); + }} + /> +
+ { + this.setChatInput(e.target.value); + }} + onSelect={e => { + this.stopDictation(true); + }} + onKeyDown={e => e.stopPropagation()} + onKeyPress={e => e.stopPropagation()} + onPointerDown={e => e.stopPropagation()} + onClick={e => e.stopPropagation()} + onPointerUp={e => e.stopPropagation()} + /> + {/* this.setChatInput(e.target.value)} /> */} +
+ } + onClick={() => { + if (!this.isRecording) { + this.recordDictation(); + } else { + this.stopDictation(true); + } + }} + /> () { onClick={() => { PresBox.Instance.setChatActive(true); PresBox.Instance.slideToModify = this.rootDoc; + PresBox.Instance.recordDictation(); // this.customizeWithGPT(''); }}> e.stopPropagation()} /> -- cgit v1.2.3-70-g09d2 From 414abda35b79c2d670451df8938740bd891881e1 Mon Sep 17 00:00:00 2001 From: Sophie Zhang Date: Thu, 19 Oct 2023 02:14:16 -0400 Subject: fixed key events (chatbox) --- src/client/apis/gpt/GPT.ts | 9 +++- src/client/views/nodes/trails/PresBox.scss | 3 -- src/client/views/nodes/trails/PresBox.tsx | 81 ++++++++++++++++++++++++------ 3 files changed, 74 insertions(+), 19 deletions(-) (limited to 'src/client/views/nodes/trails/PresBox.scss') diff --git a/src/client/apis/gpt/GPT.ts b/src/client/apis/gpt/GPT.ts index 66689f2f6..6806802f3 100644 --- a/src/client/apis/gpt/GPT.ts +++ b/src/client/apis/gpt/GPT.ts @@ -25,8 +25,13 @@ const configuration = new Configuration({ const openai = new OpenAIApi(configuration); const gptTrailSlideCustomization = async (inputText: string) => { - const prompt = - 'We are adding customization to a slide in a presentation. Given a natural language input, translate it into a json with the required fields: [title, presentation_transition, presentation_effect, and config_zoom]. title is the title/name of the slide. presentation_transition is a number in milliseconds for how long it should take to transition to a slide. presentation_effect is an effect applied to the slide when we transition to it. Its only possible values are: [None, Fade in, Flip, Rotate, Bounce, Roll]. config zoom is a number from 0 to 1.0 indicating the percentage we should be zooming into the slide. If the input does not contain info a specific key, please set their value to null. Please only return the json with these keys and their values.'; + let prompt = + 'We are adding customization to a slide in a presentation. Given a natural language input, translate it into a json with the required fields: [title, presentation_transition, presentation_movement, presentation_effect, config_zoom, presentation_effectDirection].'; + + prompt += + 'title is the title/name of the slide. presentation_transition is a number in milliseconds for how long it should take to transition to a slide. presentation_movement is how the slide is moved onscreen. Its only possible values are: [none, center, zoom, pan, jump]. If the input contains zoom, make sure to set presentation_movement to zoom. presentation_effect is an effect applied to the slide when we transition to it. Its only possible values are: [None, Fade in, Flip, Rotate, Bounce, Roll]. presentation_effectDirection is what direction the slide comes in from. Its only possible values are: [Enter from left, Enter from right, Enter from bottom, Enter from Top, Enter from center]. config_zoom is a number from 0 to 1.0 indicating the percentage we should be zooming into the slide.'; + + prompt += 'If the input does not contain info a specific key, please set their value to null. Please only return the json with these keys and their values.'; try { const response = await openai.createChatCompletion({ diff --git a/src/client/views/nodes/trails/PresBox.scss b/src/client/views/nodes/trails/PresBox.scss index 370b155fd..1b76a39ad 100644 --- a/src/client/views/nodes/trails/PresBox.scss +++ b/src/client/views/nodes/trails/PresBox.scss @@ -34,9 +34,6 @@ .pres-chatbox { outline: none; border: none; - font-size: 16px; - letter-spacing: 1px; - color: #404040; } } diff --git a/src/client/views/nodes/trails/PresBox.tsx b/src/client/views/nodes/trails/PresBox.tsx index 051a1fbfd..0d5edcd83 100644 --- a/src/client/views/nodes/trails/PresBox.tsx +++ b/src/client/views/nodes/trails/PresBox.tsx @@ -36,6 +36,7 @@ import { DocFocusOptions, DocumentView, OpenWhere, OpenWhereMod } from '../Docum import { FieldView, FieldViewProps } from '../FieldView'; import { ScriptingBox } from '../ScriptingBox'; import './PresBox.scss'; +import ReactLoading from 'react-loading'; import { PresEffect, PresEffectDirection, PresMovement, PresStatus } from './PresEnums'; import { IconButton, Type } from 'browndash-components'; import { AiOutlineSend } from 'react-icons/ai'; @@ -112,16 +113,23 @@ export class PresBox extends ViewBoxBaseComponent() { @observable _forceKeyEvents: boolean = false; // GPT + private _inputref: HTMLTextAreaElement | null = null; @observable chatActive: boolean = false; @observable chatInput: string = ''; public slideToModify: Doc | null = null; @observable isRecording: boolean = false; + @observable isLoading: boolean = false; @action setChatInput = (input: string) => { this.chatInput = input; }; + @action + setIsLoading = (isLoading: boolean) => { + this.isLoading = isLoading; + }; + @action public setChatActive = (active: boolean) => { this.chatActive = active; @@ -272,6 +280,8 @@ export class PresBox extends ViewBoxBaseComponent() { // GPT recordDictation = () => { + this.setIsRecording(true); + this.setChatInput(''); DictationManager.Controls.listen({ interimHandler: this.setDictationContent, continuous: { indefinite: false }, @@ -281,17 +291,38 @@ export class PresBox extends ViewBoxBaseComponent() { } }); }; - stopDictation = (abort: boolean) => DictationManager.Controls.stop(!abort); + stopDictation = (abort: boolean) => { + this.setIsRecording(false); + DictationManager.Controls.stop(!abort); + }; setDictationContent = (value: string) => { this.setChatInput(value); + // // Get the current cursor position + // if (!this._inputref) return; + // const cursorPosition = this._inputref.selectionStart; + // const currentValue = this.chatInput; + + // // split before and after + // const textBeforeCursor = currentValue.slice(0, cursorPosition); + // const textAfterCursor = currentValue.slice(cursorPosition); + + // // insertion + // const updatedText = textBeforeCursor + value + textAfterCursor; + + // // Update the textarea value + // this.setChatInput(updatedText); + + // // set new cursor pos + // const newCursorPosition = cursorPosition + value.length; + // this._inputref.setSelectionRange(newCursorPosition, newCursorPosition); }; @action customizeWithGPT = async (input: string) => { // const testInput = 'change title to Customized Slide, transition for 2.3s with fade in effect'; if (!this.slideToModify) return; - + this.setIsLoading(true); try { const res = await gptTrailSlideCustomization(input); if (typeof res === 'string') { @@ -307,6 +338,7 @@ export class PresBox extends ViewBoxBaseComponent() { } catch (err) { console.error(err); } + this.setIsLoading(false); }; //TODO: al: it seems currently that tempMedia doesn't stop onslidechange after clicking the button; the time the tempmedia stop depends on the start & end time @@ -1280,6 +1312,7 @@ export class PresBox extends ViewBoxBaseComponent() { @action keyEvents = (e: KeyboardEvent) => { if (e.target instanceof HTMLInputElement) return; + if (e.target instanceof HTMLTextAreaElement) return; let handled = false; const anchorNode = document.activeElement as HTMLDivElement; if (anchorNode && anchorNode.className?.includes('lm_title')) return; @@ -2742,17 +2775,31 @@ export class PresBox extends ViewBoxBaseComponent() { {this.chatActive && (
- } - onClick={() => { - this.setChatActive(false); - }} - /> + {this.isLoading ? ( + + ) : ( + } + onClick={() => { + this.setChatActive(false); + }} + /> + )}
+ {/*
{ + const newContent = e.currentTarget.innerHTML; + console.log('content', newContent); + this.setChatInput(newContent); + }}> + {this.chatInput} +
*/} (this._inputref = r)} minRows={3} placeholder="Customize..." className="pres-chatbox" @@ -2761,10 +2808,16 @@ export class PresBox extends ViewBoxBaseComponent() { onChange={e => { this.setChatInput(e.target.value); }} - onSelect={e => { + // onSelect={e => { + // this.stopDictation(true); + // }} + onKeyDown={e => { + // if (e.key === 'Enter') { + // this.customizeWithGPT(this.chatInput); + // } this.stopDictation(true); + e.stopPropagation(); }} - onKeyDown={e => e.stopPropagation()} onKeyPress={e => e.stopPropagation()} onPointerDown={e => e.stopPropagation()} onClick={e => e.stopPropagation()} @@ -2787,7 +2840,7 @@ export class PresBox extends ViewBoxBaseComponent() { /> } onClick={() => { -- cgit v1.2.3-70-g09d2 From eb5746da51bf44aeacb41d6337f666e178fae88e Mon Sep 17 00:00:00 2001 From: Sophie Zhang Date: Thu, 29 Feb 2024 01:25:37 -0500 Subject: added curr slide info to slide customization --- src/client/apis/gpt/customization.ts | 24 +++++++---- src/client/views/nodes/trails/PresBox.scss | 1 + src/client/views/nodes/trails/PresBox.tsx | 53 +++++++++++++++++------- src/client/views/nodes/trails/PresElementBox.tsx | 4 +- 4 files changed, 56 insertions(+), 26 deletions(-) (limited to 'src/client/views/nodes/trails/PresBox.scss') diff --git a/src/client/apis/gpt/customization.ts b/src/client/apis/gpt/customization.ts index db5ef6eb5..946208eeb 100644 --- a/src/client/apis/gpt/customization.ts +++ b/src/client/apis/gpt/customization.ts @@ -35,7 +35,7 @@ interface PromptInfo { const prompts: { [key: string]: PromptInfo } = { trails: { description: - 'We are adding customization to a slide in a presentation. Given a natural language input, translate it into a json with the required fields: [title, presentation_transition, presentation_effect, config_zoom, presentation_effectDirection].', + 'We are customizing the properties and transition of a slide in a presentation. You are given the current properties of the slide in a json with the fields [title, presentation_transition, presentation_effect, config_zoom, presentation_effectDirection], as well as the prompt for how the user wants to change it. Return a json with the required fields: [title, presentation_transition, presentation_effect, config_zoom, presentation_effectDirection] by applying the changes in the prompt to the current state of the slide.', features: [], }, }; @@ -44,19 +44,24 @@ export const addCustomizationProperty = (type: CustomizationType, name: string, values ? prompts[type].features.push({ name, description, values }) : prompts[type].features.push({ name, description }); }; +export const gptSlideProperties = ['title', 'presentation_transition', 'presentation_effect', 'presentation_effectDirection', 'config_zoom']; + const setupPresSlideCustomization = () => { addCustomizationProperty(CustomizationType.PRES_TRAIL_SLIDE, 'title', 'is the title/name of the slide.'); addCustomizationProperty(CustomizationType.PRES_TRAIL_SLIDE, 'presentation_transition', 'is a number in milliseconds for how long it should take to transition/move to a slide.'); addCustomizationProperty(CustomizationType.PRES_TRAIL_SLIDE, 'presentation_effect', 'is an effect applied to the slide when we transition to it.', ['None', 'Fade in', 'Flip', 'Rotate', 'Bounce', 'Roll']); + addCustomizationProperty(CustomizationType.PRES_TRAIL_SLIDE, 'presentation_effectDirection', 'is what direction the effect is applied.', ['Enter from left', 'Enter from right', 'Enter from bottom', 'Enter from Top', 'Enter from center']); + addCustomizationProperty(CustomizationType.PRES_TRAIL_SLIDE, 'config_zoom', 'is a number from 0 to 1.0 indicating the percentage we should zoom into the slide.'); }; setupPresSlideCustomization(); -export const gptTrailSlideCustomization = async (inputText: string) => { +export const gptTrailSlideCustomization = async (inputText: string, properties: any) => { + console.log('properties', properties); let prompt = prompts.trails.description; prompts.trails.features.forEach(feature => { - prompt += feature.name + feature.description; + prompt += feature.name + ' ' + feature.description; if (feature.values) { prompt += `Its only possible values are [${feature.values.join(', ')}].`; } @@ -65,16 +70,21 @@ export const gptTrailSlideCustomization = async (inputText: string) => { // prompt += // 'title is the title/name of the slide. presentation_transition is a number in milliseconds for how long it should take to transition/move to a slide. presentation_effect is an effect applied to the slide when we transition to it. Its only possible values are: [None, Fade in, Flip, Rotate, Bounce, Roll]. presentation_effectDirection is what direction the effect is applied. Its only possible values are: [Enter from left, Enter from right, Enter from bottom, Enter from Top, Enter from center]. config_zoom is a number from 0 to 1.0 indicating the percentage we should zoom into the slide.'; - prompt += 'If the input does not contain info a specific key, please set their value to null. Please only return the json with these keys and their values.'; + prompt += 'Set unchanged values to null. Please only return the json with these keys and their values.'; + + console.log('messages', [ + { role: 'system', content: prompt }, + { role: 'user', content: `Prompt: ${inputText}, Current properties: ${JSON.stringify(properties)}` }, + ]); try { const response = await openai.chat.completions.create({ - model: 'gpt-3.5-turbo', + model: 'gpt-4', messages: [ { role: 'system', content: prompt }, - { role: 'user', content: inputText }, + { role: 'user', content: `Prompt: ${inputText}, Current properties: ${JSON.stringify(properties)}` }, ], - temperature: 0.1, + temperature: 0, max_tokens: 1000, }); return response.choices[0].message?.content; diff --git a/src/client/views/nodes/trails/PresBox.scss b/src/client/views/nodes/trails/PresBox.scss index 1537ad0b8..5fc356299 100644 --- a/src/client/views/nodes/trails/PresBox.scss +++ b/src/client/views/nodes/trails/PresBox.scss @@ -34,6 +34,7 @@ .pres-chatbox { outline: none; border: none; + resize: none; } } diff --git a/src/client/views/nodes/trails/PresBox.tsx b/src/client/views/nodes/trails/PresBox.tsx index 1b1b65e46..ba80facce 100644 --- a/src/client/views/nodes/trails/PresBox.tsx +++ b/src/client/views/nodes/trails/PresBox.tsx @@ -38,10 +38,10 @@ import './PresBox.scss'; import ReactLoading from 'react-loading'; import { PresEffect, PresEffectDirection, PresMovement, PresStatus } from './PresEnums'; import ReactTextareaAutosize from 'react-textarea-autosize'; -import { IconButton, Type } from 'browndash-components'; +import { Dropdown, IconButton, Type } from 'browndash-components'; import { BiMicrophone, BiX } from 'react-icons/bi'; import { AiOutlineSend } from 'react-icons/ai'; -import { gptTrailSlideCustomization } from '../../../apis/gpt/customization'; +import { gptSlideProperties, gptTrailSlideCustomization } from '../../../apis/gpt/customization'; import { DictationManager } from '../../../util/DictationManager'; export interface pinDataTypes { scrollable?: boolean; @@ -263,7 +263,7 @@ export class PresBox extends ViewBoxBaseComponent() { } }; - // GPT + // Recording for GPT customization recordDictation = () => { this.setIsRecording(true); @@ -283,6 +283,7 @@ export class PresBox extends ViewBoxBaseComponent() { }; setDictationContent = (value: string) => { + console.log('Dictation value', value); this.setChatInput(value); // // Get the current cursor position // if (!this._inputref) return; @@ -306,24 +307,31 @@ export class PresBox extends ViewBoxBaseComponent() { @action customizeWithGPT = async (input: string) => { - console.log(this.slideToModify); + console.log('Slide to modify', this.slideToModify); // const testInput = 'change title to Customized Slide, transition for 2.3s with fade in effect'; // if (!this.slideToModify) return; this.setIsRecording(false); this.setIsLoading(true); + + let currSlideProperties: { [key: string]: any } = {}; + for (const key of gptSlideProperties) { + currSlideProperties[key] = this.activeItem[key]; + } + console.log('current slide props', currSlideProperties); + try { - const res = await gptTrailSlideCustomization(input); - console.log('slide result', res); - // if (typeof res === 'string') { - // const resObj = JSON.parse(res); - // console.log('Result ', resObj); - // // this.activeItem - // for (let key in resObj) { - // if (resObj[key]) { - // this.slideToModify[key] = resObj[key]; - // } - // } - // } + const res = await gptTrailSlideCustomization(input, currSlideProperties); + console.log('GPT Result:', res); + if (typeof res === 'string') { + const resObj = JSON.parse(res); + console.log('Parsed GPT Result ', resObj); + // this.activeItem + for (let key in resObj) { + if (resObj[key]) { + this.activeItem[key] = resObj[key]; + } + } + } } catch (err) { console.error(err); } @@ -1833,6 +1841,19 @@ export class PresBox extends ViewBoxBaseComponent() { })}>
Movement + {/* { + if (typeof val === 'string') this.setFormData({ ...this.formData, type: val as BugType }); + }} + dropdownType={DropdownType.SELECT} + type={Type.TERT} + fillWidth + /> */}
{ diff --git a/src/client/views/nodes/trails/PresElementBox.tsx b/src/client/views/nodes/trails/PresElementBox.tsx index ed2f25fb6..4abfc5a94 100644 --- a/src/client/views/nodes/trails/PresElementBox.tsx +++ b/src/client/views/nodes/trails/PresElementBox.tsx @@ -409,8 +409,6 @@ export class PresElementBox extends ViewBoxBaseComponent() { return presBoxDocView ? presBoxDocView._props.PanelWidth() : width ? width : 300; } - // GPT - @computed get presButtons() { const presBox = this.presBox; const presBoxColor = StrCast(presBox?._backgroundColor); @@ -520,7 +518,7 @@ export class PresElementBox extends ViewBoxBaseComponent() { className={'slideButton'} onClick={() => { PresBox.Instance.setChatActive(true); - PresBox.Instance.slideToModify = this.rootDoc; + PresBox.Instance.slideToModify = this.Document; PresBox.Instance.recordDictation(); }}> e.stopPropagation()} /> -- cgit v1.2.3-70-g09d2 From b2abe62ff72fc6afd7a768b80dfb80d3ed7baa87 Mon Sep 17 00:00:00 2001 From: Sophie Zhang Date: Thu, 29 Feb 2024 12:36:30 -0500 Subject: styling --- src/client/views/nodes/trails/PresBox.scss | 28 ++ src/client/views/nodes/trails/PresBox.tsx | 402 +++++++++++++++-------------- 2 files changed, 236 insertions(+), 194 deletions(-) (limited to 'src/client/views/nodes/trails/PresBox.scss') diff --git a/src/client/views/nodes/trails/PresBox.scss b/src/client/views/nodes/trails/PresBox.scss index 5fc356299..dd0007d82 100644 --- a/src/client/views/nodes/trails/PresBox.scss +++ b/src/client/views/nodes/trails/PresBox.scss @@ -1,5 +1,33 @@ @import '../../global/globalCssVariables.module.scss'; +.pres-chat { + // padding: 8px; + display: flex; + flex-direction: column; + gap: 8px; + // display: flex; + // align-items: center; + // gap: 16px; +} + +.pres-chatbox-container { + padding: 16px; + outline: 1px solid #999999; + border-radius: 16px; + display: flex; + align-items: center; + justify-content: space-between; +} + +.pres-chatbox { + outline: none; + border: none; + resize: none; + font-family: Verdana, Geneva, sans-serif; + background-color: transparent; + overflow-y: hidden; +} + .presBox-cont { cursor: auto; position: absolute; diff --git a/src/client/views/nodes/trails/PresBox.tsx b/src/client/views/nodes/trails/PresBox.tsx index ba80facce..7d78d4648 100644 --- a/src/client/views/nodes/trails/PresBox.tsx +++ b/src/client/views/nodes/trails/PresBox.tsx @@ -38,7 +38,7 @@ import './PresBox.scss'; import ReactLoading from 'react-loading'; import { PresEffect, PresEffectDirection, PresMovement, PresStatus } from './PresEnums'; import ReactTextareaAutosize from 'react-textarea-autosize'; -import { Dropdown, IconButton, Type } from 'browndash-components'; +import { Button, Dropdown, IconButton, Type } from 'browndash-components'; import { BiMicrophone, BiX } from 'react-icons/bi'; import { AiOutlineSend } from 'react-icons/ai'; import { gptSlideProperties, gptTrailSlideCustomization } from '../../../apis/gpt/customization'; @@ -131,7 +131,7 @@ export class PresBox extends ViewBoxBaseComponent() { @action public setChatActive = (active: boolean) => { - this.chatActive = active; + this.toggleProperties(); }; @action @@ -307,7 +307,6 @@ export class PresBox extends ViewBoxBaseComponent() { @action customizeWithGPT = async (input: string) => { - console.log('Slide to modify', this.slideToModify); // const testInput = 'change title to Customized Slide, transition for 2.3s with fade in effect'; // if (!this.slideToModify) return; this.setIsRecording(false); @@ -315,7 +314,16 @@ export class PresBox extends ViewBoxBaseComponent() { let currSlideProperties: { [key: string]: any } = {}; for (const key of gptSlideProperties) { - currSlideProperties[key] = this.activeItem[key]; + if (this.activeItem[key]) { + currSlideProperties[key] = this.activeItem[key]; + } else { + // default values + if (key === 'presentation_transition') { + currSlideProperties[key] = 500; + } else if (key === 'config_zoom') { + currSlideProperties[key] = 1.0; + } + } } console.log('current slide props', currSlideProperties); @@ -847,8 +855,7 @@ export class PresBox extends ViewBoxBaseComponent() { navigateToActiveItem = (afterNav?: () => void) => { const activeItem: Doc = this.activeItem; console.log('active item', activeItem); - // GPT update - this.slideToModify = activeItem; + const targetDoc: Doc = this.targetDoc; const finished = () => { afterNav?.(); @@ -1797,6 +1804,12 @@ export class PresBox extends ViewBoxBaseComponent() { } return null; } + + @computed get gptDropdown() { + const activeItem = this.activeItem; + return
; + } + @computed get transitionDropdown() { const activeItem = this.activeItem; const preseEffect = (effect: PresEffect) => ( @@ -1829,19 +1842,77 @@ export class PresBox extends ViewBoxBaseComponent() { const zoom = NumCast(activeItem.config_zoom, 1) * 100; const effect = activeItem.presentation_effect ? activeItem.presentation_effect : PresMovement.None; return ( -
{ - e.stopPropagation(); - this._openMovementDropdown = false; - this._openEffectDropdown = false; - this._openBulletEffectDropdown = false; - })}> -
- Movement - {/* + {/* GPT Component */} +
+ Customize with GPT +
+
+ (this._inputref = r)} + minRows={1} + placeholder="Customize..." + className="pres-chatbox" + autoFocus={true} + value={this.chatInput} + onChange={e => { + this.setChatInput(e.target.value); + }} + onKeyDown={e => { + this.stopDictation(true); + e.stopPropagation(); + }} + /> + } + onClick={() => { + if (!this.isRecording) { + this.recordDictation(); + } else { + this.stopDictation(true); + } + }} + /> +
+
+
+
{ + e.stopPropagation(); + this._openMovementDropdown = false; + this._openEffectDropdown = false; + this._openBulletEffectDropdown = false; + })}> +
+ Movement + {/* () { type={Type.TERT} fillWidth /> */} -
{ - e.stopPropagation(); - this._openMovementDropdown = !this._openMovementDropdown; - })} - style={{ - color: SettingsManager.userColor, - background: SettingsManager.userVariantColor, - borderBottomLeftRadius: this._openMovementDropdown ? 0 : 5, - border: this._openMovementDropdown ? `solid 2px ${SettingsManager.userVariantColor}` : `solid 1px ${SettingsManager.userColor}`, - }}> - {this.movementName(activeItem)} -
{ + e.stopPropagation(); + this._openMovementDropdown = !this._openMovementDropdown; + })} style={{ color: SettingsManager.userColor, - background: SettingsManager.userBackgroundColor, - display: this._openMovementDropdown ? 'grid' : 'none', + background: SettingsManager.userVariantColor, + borderBottomLeftRadius: this._openMovementDropdown ? 0 : 5, + border: this._openMovementDropdown ? `solid 2px ${SettingsManager.userVariantColor}` : `solid 1px ${SettingsManager.userColor}`, }}> - {presMovement(PresMovement.None)} - {presMovement(PresMovement.Center)} - {presMovement(PresMovement.Zoom)} - {presMovement(PresMovement.Pan)} - {presMovement(PresMovement.Jump)} -
-
-
-
Zoom (% screen filled)
-
- this.updateZoom(e.target.value)} />% + {this.movementName(activeItem)} + +
+ {presMovement(PresMovement.None)} + {presMovement(PresMovement.Center)} + {presMovement(PresMovement.Zoom)} + {presMovement(PresMovement.Pan)} + {presMovement(PresMovement.Jump)} +
-
-
this.updateZoom(String(zoom), 0.1)}> - +
+
Zoom (% screen filled)
+
+ this.updateZoom(e.target.value)} />%
-
this.updateZoom(String(zoom), -0.1)}> - +
+
this.updateZoom(String(zoom), 0.1)}> + +
+
this.updateZoom(String(zoom), -0.1)}> + +
-
- {PresBox.inputter('0', '1', '100', zoom, activeItem.presentation_movement === PresMovement.Zoom, this.updateZoom)} -
-
Transition Time
-
- e.stopPropagation()} onChange={action(e => this.updateTransitionTime(e.target.value))} /> s -
-
-
this.updateTransitionTime(String(transitionSpeed), 1000)}> - + {PresBox.inputter('0', '1', '100', zoom, activeItem.presentation_movement === PresMovement.Zoom, this.updateZoom)} +
+
Transition Time
+
+ e.stopPropagation()} onChange={action(e => this.updateTransitionTime(e.target.value))} /> s
-
this.updateTransitionTime(String(transitionSpeed), -1000)}> - +
+
this.updateTransitionTime(String(transitionSpeed), 1000)}> + +
+
this.updateTransitionTime(String(transitionSpeed), -1000)}> + +
+ {PresBox.inputter('0.1', '0.1', '100', transitionSpeed, true, this.updateTransitionTime)} +
+
Fast
+
Medium
+
Slow
+
- {PresBox.inputter('0.1', '0.1', '100', transitionSpeed, true, this.updateTransitionTime)} -
-
Fast
-
Medium
-
Slow
-
-
-
- Effects -
-
Play Audio Annotation
- (activeItem.presPlayAudio = !BoolCast(activeItem.presPlayAudio))} - checked={BoolCast(activeItem.presPlayAudio)} - /> -
-
-
Zoom Text Selections
- (activeItem.presentation_zoomText = !BoolCast(activeItem.presentation_zoomText))} - checked={BoolCast(activeItem.presentation_zoomText)} - /> -
-
{ - e.stopPropagation(); - this._openEffectDropdown = !this._openEffectDropdown; - })} - style={{ - color: SettingsManager.userColor, - background: SettingsManager.userVariantColor, - borderBottomLeftRadius: this._openEffectDropdown ? 0 : 5, - border: this._openEffectDropdown ? `solid 2px ${SettingsManager.userVariantColor}` : `solid 1px ${SettingsManager.userColor}`, - }}> - {effect?.toString()} - +
+ Effects +
+
Play Audio Annotation
+ (activeItem.presPlayAudio = !BoolCast(activeItem.presPlayAudio))} + checked={BoolCast(activeItem.presPlayAudio)} + /> +
+
+
Zoom Text Selections
+ (activeItem.presentation_zoomText = !BoolCast(activeItem.presentation_zoomText))} + checked={BoolCast(activeItem.presentation_zoomText)} + /> +
{ + e.stopPropagation(); + this._openEffectDropdown = !this._openEffectDropdown; + })} style={{ color: SettingsManager.userColor, - background: SettingsManager.userBackgroundColor, - display: this._openEffectDropdown ? 'grid' : 'none', - }} - onPointerDown={e => e.stopPropagation()}> - {Object.values(PresEffect) - .filter(v => isNaN(Number(v))) - .map(effect => preseEffect(effect))} + background: SettingsManager.userVariantColor, + borderBottomLeftRadius: this._openEffectDropdown ? 0 : 5, + border: this._openEffectDropdown ? `solid 2px ${SettingsManager.userVariantColor}` : `solid 1px ${SettingsManager.userColor}`, + }}> + {effect?.toString()} + +
e.stopPropagation()}> + {Object.values(PresEffect) + .filter(v => isNaN(Number(v))) + .map(effect => preseEffect(effect))} +
-
-
-
Effect direction
-
- {StrCast(this.activeItem.presentation_effectDirection)} +
+
Effect direction
+
+ {StrCast(this.activeItem.presentation_effectDirection)} +
+
+
+ {presDirection(PresEffectDirection.Left, 'angle-right', 1, 2, {})} + {presDirection(PresEffectDirection.Right, 'angle-left', 3, 2, {})} + {presDirection(PresEffectDirection.Top, 'angle-down', 2, 1, {})} + {presDirection(PresEffectDirection.Bottom, 'angle-up', 2, 3, {})} + {presDirection(PresEffectDirection.Center, '', 2, 2, { width: 10, height: 10, alignSelf: 'center' })}
-
- {presDirection(PresEffectDirection.Left, 'angle-right', 1, 2, {})} - {presDirection(PresEffectDirection.Right, 'angle-left', 3, 2, {})} - {presDirection(PresEffectDirection.Top, 'angle-down', 2, 1, {})} - {presDirection(PresEffectDirection.Bottom, 'angle-up', 2, 3, {})} - {presDirection(PresEffectDirection.Center, '', 2, 2, { width: 10, height: 10, alignSelf: 'center' })} -
-
-
-
this.applyTo(this.childDocs)}> - Apply to all +
+
this.applyTo(this.childDocs)}> + Apply to all +
-
+ ); } } @@ -2764,65 +2836,7 @@ export class PresBox extends ViewBoxBaseComponent() { } */}
{/* presbox chatbox */} - {this.chatActive && ( -
-
- {this.isLoading ? ( - - ) : ( - } - onClick={() => { - this.setChatActive(false); - }} - /> - )} -
- (this._inputref = r)} - minRows={3} - placeholder="Customize..." - className="pres-chatbox" - autoFocus={true} - value={this.chatInput} - onChange={e => { - this.setChatInput(e.target.value); - }} - onKeyDown={e => { - this.stopDictation(true); - e.stopPropagation(); - }} - /> - {/* this.setChatInput(e.target.value)} /> */} -
- } - onClick={() => { - if (!this.isRecording) { - this.recordDictation(); - } else { - this.stopDictation(true); - } - }} - /> - } - onClick={() => { - this.customizeWithGPT(this.chatInput); - }} - /> -
-
- )} + {this.chatActive &&
}
); } -- cgit v1.2.3-70-g09d2 From 216cdb95bb106893f3e1937ba86546f6455ee688 Mon Sep 17 00:00:00 2001 From: Sophie Zhang Date: Thu, 7 Mar 2024 01:32:34 -0500 Subject: feat: added preliminary ease function editor --- src/Utils.ts | 1 + .../views/nodes/trails/CubicBezierEditor.tsx | 134 +++++++++++++++++++++ src/client/views/nodes/trails/PresBox.scss | 14 +++ src/client/views/nodes/trails/PresBox.tsx | 47 +++++--- 4 files changed, 182 insertions(+), 14 deletions(-) create mode 100644 src/client/views/nodes/trails/CubicBezierEditor.tsx (limited to 'src/client/views/nodes/trails/PresBox.scss') diff --git a/src/Utils.ts b/src/Utils.ts index e8bd35ac4..5f60e5f2a 100644 --- a/src/Utils.ts +++ b/src/Utils.ts @@ -644,6 +644,7 @@ const easeFunc = (transition: 'ease' | 'linear' | undefined, currentTime: number }; export function smoothScroll(duration: number, element: HTMLElement | HTMLElement[], to: number, transition: 'ease' | 'linear' | undefined, stopper?: () => void) { + console.log('smooth scroll'); stopper?.(); const elements = element instanceof HTMLElement ? [element] : element; const starts = elements.map(element => element.scrollTop); diff --git a/src/client/views/nodes/trails/CubicBezierEditor.tsx b/src/client/views/nodes/trails/CubicBezierEditor.tsx new file mode 100644 index 000000000..0744709aa --- /dev/null +++ b/src/client/views/nodes/trails/CubicBezierEditor.tsx @@ -0,0 +1,134 @@ +import React, { useEffect, useState } from 'react'; + +type Props = { + setFunc: (newPoints: { p1: number[]; p2: number[] }) => void; +}; + +const ANIMATION_DURATION = 750; +// const ANIMATION_TIMING_FUNC = "cubic-bezier(.42,.97,.52,1.49)"; +const ANIMATION_TIMING_FUNC = 'cubic-bezier(0.3, .2, .2, 1.4)'; +const CONTAINER_WIDTH = 200; +const EDITOR_WIDTH = 100; +const OFFSET = (CONTAINER_WIDTH - EDITOR_WIDTH) / 2; + +const CubicBezierEditor = ({ setFunc }: Props) => { + const [animating, setAnimating] = useState(false); + const [cPoints, setCPoints] = useState({ p1: [0.67, 0.2], p2: [0.37, 0.88] }); + const [c1Down, setC1Down] = useState(false); + const [c2Down, setC2Down] = useState(false); + + const roundToHundredth = (num: number) => { + return Math.round(num * 100) / 100; + }; + + useEffect(() => { + if (animating) { + setTimeout(() => { + setAnimating(false); + }, ANIMATION_DURATION * 2); + } + }, [animating]); + + useEffect(() => { + if (!c1Down) return; + window.addEventListener('pointerup', () => { + setC1Down(false); + }); + const handlePointerMove = (e: PointerEvent) => { + const newX = cPoints.p1[0] + e.movementX / EDITOR_WIDTH; + if (newX < 0 || newX > 1) { + return; + } + + setCPoints(prev => ({ + ...prev, + p1: [roundToHundredth(prev.p1[0] + e.movementX / EDITOR_WIDTH), roundToHundredth(prev.p1[1] - e.movementY / EDITOR_WIDTH)], + })); + setFunc({ + ...cPoints, + p1: [roundToHundredth(cPoints.p1[0] + e.movementX / EDITOR_WIDTH), roundToHundredth(cPoints.p1[1] - e.movementY / EDITOR_WIDTH)], + }); + }; + + window.addEventListener('pointermove', handlePointerMove); + + return () => window.removeEventListener('pointermove', handlePointerMove); + }, [c1Down, cPoints]); + + useEffect(() => { + if (!c2Down) return; + window.addEventListener('pointerup', () => { + setC2Down(false); + }); + const handlePointerMove = (e: PointerEvent) => { + const newX = cPoints.p2[0] + e.movementX / EDITOR_WIDTH; + if (newX < 0 || newX > 1) { + return; + } + + setCPoints(prev => ({ + ...prev, + p2: [roundToHundredth(prev.p2[0] + e.movementX / EDITOR_WIDTH), roundToHundredth(prev.p2[1] - e.movementY / EDITOR_WIDTH)], + })); + setFunc({ + ...cPoints, + p1: [roundToHundredth(cPoints.p2[0] + e.movementX / EDITOR_WIDTH), roundToHundredth(cPoints.p2[1] - e.movementY / EDITOR_WIDTH)], + }); + }; + + window.addEventListener('pointermove', handlePointerMove); + + return () => window.removeEventListener('pointermove', handlePointerMove); + }, [c2Down, cPoints]); + + return ( +
+ + {/* Outlines */} + + {/* Box Outline */} + + {/* Editor */} + + {/* Bottom left */} + + { + e.stopPropagation(); + setC1Down(true); + }} + onPointerUp={e => { + setC1Down(false); + }} + /> + {/* Top right */} + + { + e.stopPropagation(); + setC2Down(true); + }} + onPointerUp={e => { + setC2Down(false); + }} + /> + +
+ ); +}; + +export default CubicBezierEditor; diff --git a/src/client/views/nodes/trails/PresBox.scss b/src/client/views/nodes/trails/PresBox.scss index dd0007d82..0aceb1b28 100644 --- a/src/client/views/nodes/trails/PresBox.scss +++ b/src/client/views/nodes/trails/PresBox.scss @@ -28,6 +28,20 @@ overflow-y: hidden; } +// Bezier editor + +.presBox-bezier-editor { + border: 1px solid rgb(221, 221, 221); + border-radius: 4px; +} + +.presBox-easing-function-options { + display: flex; + flex-direction: column; + align-items: center; + gap: 1rem; +} + .presBox-cont { cursor: auto; position: absolute; diff --git a/src/client/views/nodes/trails/PresBox.tsx b/src/client/views/nodes/trails/PresBox.tsx index cd3114940..cc05a5c5f 100644 --- a/src/client/views/nodes/trails/PresBox.tsx +++ b/src/client/views/nodes/trails/PresBox.tsx @@ -43,6 +43,7 @@ import { BiMicrophone, BiX } from 'react-icons/bi'; import { AiOutlineSend } from 'react-icons/ai'; import { gptSlideProperties, gptTrailSlideCustomization } from '../../../apis/gpt/customization'; import { DictationManager } from '../../../util/DictationManager'; +import CubicBezierEditor from './CubicBezierEditor'; export interface pinDataTypes { scrollable?: boolean; dataviz?: number[]; @@ -91,6 +92,10 @@ const easeItems = [ text: 'Linear', val: 'linear', }, + // { + // text: 'Custom', + // val: 'custom', + // }, ]; @observer @@ -162,6 +167,16 @@ export class PresBox extends ViewBoxBaseComponent() { this.isRecording = isRecording; }; + // Easing function variables + + @observable easeDropdownVal = 'ease'; + + // @observable bezierControlPoints: { p1: number[]; p2: number[] } = { p1: [0.67, 0.2], p2: [0.37, 0.88] }; + @action setBezierControlPoints = (newPoints: { p1: number[]; p2: number[] }) => { + // this.bezierControlPoints = newPoints; + this.setEaseFunc(this.activeItem, `cubic-bezier(${newPoints.p1[0]}, ${newPoints.p1[1]}, ${newPoints.p2[0]}, ${newPoints.p2[1]})`); + }; + @computed get isTreeOrStack() { return [CollectionViewType.Tree, CollectionViewType.Stacking].includes(StrCast(this.layoutDoc._type_collection) as any); @@ -2021,20 +2036,24 @@ export class PresBox extends ViewBoxBaseComponent() {
Slow
{/* Easing function */} - { - if (typeof val === 'string') this.setEaseFunc(this.activeItem, val); - }} - dropdownType={DropdownType.SELECT} - type={Type.TERT} - fillWidth - /> - {/* Custom */} +
+ { + if (typeof val === 'string') this.setEaseFunc(this.activeItem, val); + }} + dropdownType={DropdownType.SELECT} + type={Type.TERT} + // fillWidth + /> + {/* Custom */} +

Custom Timing Function

+ +
Effects -- cgit v1.2.3-70-g09d2 From d9570eb985afc20a440277c1debea89707ab52a1 Mon Sep 17 00:00:00 2001 From: Sophie Zhang Date: Thu, 7 Mar 2024 12:11:25 -0500 Subject: state --- .../views/nodes/trails/CubicBezierEditor.tsx | 35 ++++++++++-- src/client/views/nodes/trails/PresBox.scss | 10 +++- src/client/views/nodes/trails/PresBox.tsx | 62 ++++++++++++++++++---- 3 files changed, 92 insertions(+), 15 deletions(-) (limited to 'src/client/views/nodes/trails/PresBox.scss') diff --git a/src/client/views/nodes/trails/CubicBezierEditor.tsx b/src/client/views/nodes/trails/CubicBezierEditor.tsx index 0744709aa..06a246675 100644 --- a/src/client/views/nodes/trails/CubicBezierEditor.tsx +++ b/src/client/views/nodes/trails/CubicBezierEditor.tsx @@ -2,6 +2,7 @@ import React, { useEffect, useState } from 'react'; type Props = { setFunc: (newPoints: { p1: number[]; p2: number[] }) => void; + currPoints: { p1: number[]; p2: number[] }; }; const ANIMATION_DURATION = 750; @@ -11,9 +12,25 @@ const CONTAINER_WIDTH = 200; const EDITOR_WIDTH = 100; const OFFSET = (CONTAINER_WIDTH - EDITOR_WIDTH) / 2; -const CubicBezierEditor = ({ setFunc }: Props) => { +export const TIMING_DEFAULT_MAPPINGS = { + ease: 'cubic-bezier(0.25, 0.1, 0.25, 1.0)', + linear: 'cubic-bezier(0.0, 0.0, 1.0, 1.0)', + 'ease-in': 'cubic-bezier(0.42, 0, 1.0, 1.0)', + 'ease-out': 'cubic-bezier(0, 0, 0.58, 1.0)', + 'ease-in-out': 'cubic-bezier(0.42, 0, 0.58, 1.0)', +}; + +const CubicBezierEditor = ({ setFunc, currPoints }: Props) => { const [animating, setAnimating] = useState(false); - const [cPoints, setCPoints] = useState({ p1: [0.67, 0.2], p2: [0.37, 0.88] }); + // Should let parent control state + const [cPoints, setCPoints] = useState( + currPoints + ? currPoints + : { + p1: [0.25, 0.1], + p2: [0.25, 1.0], + } + ); const [c1Down, setC1Down] = useState(false); const [c2Down, setC2Down] = useState(false); @@ -72,7 +89,7 @@ const CubicBezierEditor = ({ setFunc }: Props) => { })); setFunc({ ...cPoints, - p1: [roundToHundredth(cPoints.p2[0] + e.movementX / EDITOR_WIDTH), roundToHundredth(cPoints.p2[1] - e.movementY / EDITOR_WIDTH)], + p2: [roundToHundredth(cPoints.p2[0] + e.movementX / EDITOR_WIDTH), roundToHundredth(cPoints.p2[1] - e.movementY / EDITOR_WIDTH)], }); }; @@ -82,7 +99,17 @@ const CubicBezierEditor = ({ setFunc }: Props) => { }, [c2Down, cPoints]); return ( -
+
{ + // e.stopPropagation; + // }} + // onPointerMove={e => { + // e.stopPropagation; + // }} + // onPointerUp={e => { + // e.stopPropagation; + // }} + > {/* Outlines */} diff --git a/src/client/views/nodes/trails/PresBox.scss b/src/client/views/nodes/trails/PresBox.scss index 0aceb1b28..7f687c2dc 100644 --- a/src/client/views/nodes/trails/PresBox.scss +++ b/src/client/views/nodes/trails/PresBox.scss @@ -1,5 +1,12 @@ @import '../../global/globalCssVariables.module.scss'; +.presBox-gpt-chat { + padding: 8px; + display: flex; + flex-direction: column; + gap: 1rem; +} + .pres-chat { // padding: 8px; display: flex; @@ -40,6 +47,7 @@ flex-direction: column; align-items: center; gap: 1rem; + padding: 8px; } .presBox-cont { @@ -703,7 +711,7 @@ grid-template-rows: max-content auto; justify-self: center; margin-top: 10px; - padding-right: 10px; + // padding-right: 10px; letter-spacing: normal; width: 100%; height: max-content; diff --git a/src/client/views/nodes/trails/PresBox.tsx b/src/client/views/nodes/trails/PresBox.tsx index cc05a5c5f..115e124df 100644 --- a/src/client/views/nodes/trails/PresBox.tsx +++ b/src/client/views/nodes/trails/PresBox.tsx @@ -43,7 +43,7 @@ import { BiMicrophone, BiX } from 'react-icons/bi'; import { AiOutlineSend } from 'react-icons/ai'; import { gptSlideProperties, gptTrailSlideCustomization } from '../../../apis/gpt/customization'; import { DictationManager } from '../../../util/DictationManager'; -import CubicBezierEditor from './CubicBezierEditor'; +import CubicBezierEditor, { TIMING_DEFAULT_MAPPINGS } from './CubicBezierEditor'; export interface pinDataTypes { scrollable?: boolean; dataviz?: number[]; @@ -92,10 +92,10 @@ const easeItems = [ text: 'Linear', val: 'linear', }, - // { - // text: 'Custom', - // val: 'custom', - // }, + { + text: 'Custom', + val: 'custom', + }, ]; @observer @@ -177,6 +177,42 @@ export class PresBox extends ViewBoxBaseComponent() { this.setEaseFunc(this.activeItem, `cubic-bezier(${newPoints.p1[0]}, ${newPoints.p1[1]}, ${newPoints.p2[0]}, ${newPoints.p2[1]})`); }; + @computed + get currCPoints() { + console.log('getting curr c points'); + let strPoints = StrCast(this.activeItem.presEaseFunc) ?? 'ease'; + if (!strPoints.startsWith('cubic')) { + switch (StrCast(this.activeItem.presEaseFunc)) { + case 'linear': + strPoints = 'cubic-bezier(0.0, 0.0, 1.0, 1.0)'; + break; + case 'ease': + strPoints = 'cubic-bezier(0.25, 0.1, 0.25, 1.0)'; + break; + case 'ease-in': + strPoints = 'cubic-bezier(0.42, 0, 1.0, 1.0)'; + break; + case 'ease-out': + strPoints = 'cubic-bezier(0, 0, 0.58, 1.0)'; + break; + case 'ease-in-out': + strPoints = 'cubic-bezier(0.42, 0, 0.58, 1.0)'; + break; + } + } + console.log('str points', strPoints); + const components = strPoints + .split('(')[1] + .split(')')[0] + .split(',') + .map(elem => parseFloat(elem)); + console.log('bezier components', components); + return { + p1: [components[0], components[1]], + p2: [components[2], components[3]], + }; + } + @computed get isTreeOrStack() { return [CollectionViewType.Tree, CollectionViewType.Stacking].includes(StrCast(this.layoutDoc._type_collection) as any); @@ -1889,8 +1925,8 @@ export class PresBox extends ViewBoxBaseComponent() { return ( <> {/* GPT Component */} -
- Customize with GPT +
+

Customize with GPT

() { formLabel={'Easing Function'} closeOnSelect={true} items={easeItems} - selectedVal={this.activeItem.presEaseFunc ? StrCast(this.activeItem.presEaseFunc) : 'ease'} + selectedVal={this.activeItem.presEaseFunc ? (StrCast(this.activeItem.presEaseFunc).startsWith('cubic') ? 'custom' : StrCast(this.activeItem.presEaseFunc)) : 'ease'} setSelectedVal={val => { - if (typeof val === 'string') this.setEaseFunc(this.activeItem, val); + if (typeof val === 'string') { + if (val !== 'custom') { + this.setEaseFunc(this.activeItem, val); + } else { + this.setEaseFunc(this.activeItem, TIMING_DEFAULT_MAPPINGS.ease); + } + } }} dropdownType={DropdownType.SELECT} type={Type.TERT} @@ -2052,7 +2094,7 @@ export class PresBox extends ViewBoxBaseComponent() { /> {/* Custom */}

Custom Timing Function

- +
-- cgit v1.2.3-70-g09d2 From ac093e7e4f483a7d5c15d72b4f203d4ff0a39927 Mon Sep 17 00:00:00 2001 From: Sophie Zhang Date: Thu, 21 Mar 2024 00:50:53 -0400 Subject: preliminary react-spring anims --- package-lock.json | 61 ++++++ package.json | 1 + .../collectionFreeForm/CollectionFreeFormView.tsx | 3 +- src/client/views/nodes/DocumentView.tsx | 23 ++- .../views/nodes/trails/CubicBezierEditor.tsx | 69 ++++++- src/client/views/nodes/trails/PresBox.scss | 52 +++-- src/client/views/nodes/trails/PresBox.tsx | 216 +++++++++++++++------ src/client/views/nodes/trails/SlideEffect.tsx | 131 +++++++++++++ 8 files changed, 472 insertions(+), 84 deletions(-) create mode 100644 src/client/views/nodes/trails/SlideEffect.tsx (limited to 'src/client/views/nodes/trails/PresBox.scss') diff --git a/package-lock.json b/package-lock.json index f072539c7..e96715795 100644 --- a/package-lock.json +++ b/package-lock.json @@ -30,6 +30,7 @@ "@mui/material": "^5.14.19", "@octokit/core": "^5.0.2", "@react-google-maps/api": "^2.19.2", + "@react-spring/web": "^9.7.3", "@turf/turf": "^6.5.0", "@types/bezier-js": "^4.1.3", "@types/brotli": "^1.3.4", @@ -5884,6 +5885,66 @@ "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0" } }, + "node_modules/@react-spring/animated": { + "version": "9.7.3", + "resolved": "https://registry.npmjs.org/@react-spring/animated/-/animated-9.7.3.tgz", + "integrity": "sha512-5CWeNJt9pNgyvuSzQH+uy2pvTg8Y4/OisoscZIR8/ZNLIOI+CatFBhGZpDGTF/OzdNFsAoGk3wiUYTwoJ0YIvw==", + "dependencies": { + "@react-spring/shared": "~9.7.3", + "@react-spring/types": "~9.7.3" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0" + } + }, + "node_modules/@react-spring/core": { + "version": "9.7.3", + "resolved": "https://registry.npmjs.org/@react-spring/core/-/core-9.7.3.tgz", + "integrity": "sha512-IqFdPVf3ZOC1Cx7+M0cXf4odNLxDC+n7IN3MDcVCTIOSBfqEcBebSv+vlY5AhM0zw05PDbjKrNmBpzv/AqpjnQ==", + "dependencies": { + "@react-spring/animated": "~9.7.3", + "@react-spring/shared": "~9.7.3", + "@react-spring/types": "~9.7.3" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/react-spring/donate" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0" + } + }, + "node_modules/@react-spring/shared": { + "version": "9.7.3", + "resolved": "https://registry.npmjs.org/@react-spring/shared/-/shared-9.7.3.tgz", + "integrity": "sha512-NEopD+9S5xYyQ0pGtioacLhL2luflh6HACSSDUZOwLHoxA5eku1UPuqcJqjwSD6luKjjLfiLOspxo43FUHKKSA==", + "dependencies": { + "@react-spring/types": "~9.7.3" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0" + } + }, + "node_modules/@react-spring/types": { + "version": "9.7.3", + "resolved": "https://registry.npmjs.org/@react-spring/types/-/types-9.7.3.tgz", + "integrity": "sha512-Kpx/fQ/ZFX31OtlqVEFfgaD1ACzul4NksrvIgYfIFq9JpDHFwQkMVZ10tbo0FU/grje4rcL4EIrjekl3kYwgWw==" + }, + "node_modules/@react-spring/web": { + "version": "9.7.3", + "resolved": "https://registry.npmjs.org/@react-spring/web/-/web-9.7.3.tgz", + "integrity": "sha512-BXt6BpS9aJL/QdVqEIX9YoUy8CE6TJrU0mNCqSoxdXlIeNcEBWOfIyE6B14ENNsyQKS3wOWkiJfco0tCr/9tUg==", + "dependencies": { + "@react-spring/animated": "~9.7.3", + "@react-spring/core": "~9.7.3", + "@react-spring/shared": "~9.7.3", + "@react-spring/types": "~9.7.3" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0", + "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0" + } + }, "node_modules/@react-stately/calendar": { "version": "3.4.4", "resolved": "https://registry.npmjs.org/@react-stately/calendar/-/calendar-3.4.4.tgz", diff --git a/package.json b/package.json index a232a9127..2102eced2 100644 --- a/package.json +++ b/package.json @@ -113,6 +113,7 @@ "@mui/material": "^5.14.19", "@octokit/core": "^5.0.2", "@react-google-maps/api": "^2.19.2", + "@react-spring/web": "^9.7.3", "@turf/turf": "^6.5.0", "@types/bezier-js": "^4.1.3", "@types/brotli": "^1.3.4", diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx index a62ea2eb9..5cc921d85 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx @@ -10,7 +10,6 @@ import { DocData, Height, Width } from '../../../../fields/DocSymbols'; import { Id } from '../../../../fields/FieldSymbols'; import { InkData, InkField, InkTool, PointData, Segment } from '../../../../fields/InkField'; import { List } from '../../../../fields/List'; -import { RichTextField } from '../../../../fields/RichTextField'; import { listSpec } from '../../../../fields/Schema'; import { ScriptField } from '../../../../fields/ScriptField'; import { BoolCast, Cast, DocCast, NumCast, ScriptCast, StrCast } from '../../../../fields/Types'; @@ -57,8 +56,8 @@ import { MarqueeView } from './MarqueeView'; import { PropertiesView } from '../../PropertiesView'; import { ExtractColors } from '../../ExtractColors'; import { smartLayout, smartLayout2, StyleInputDocument } from '../../../apis/gpt/customization'; -import { RichTextField } from '../../../../fields/RichTextField'; import { extname } from 'path'; +import { RichTextField } from '../../../../fields/RichTextField'; export interface collectionFreeformViewProps { NativeWidth?: () => number; diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx index d131f72d5..3c1896474 100644 --- a/src/client/views/nodes/DocumentView.tsx +++ b/src/client/views/nodes/DocumentView.tsx @@ -48,6 +48,7 @@ import { KeyValueBox } from './KeyValueBox'; import { LinkAnchorBox } from './LinkAnchorBox'; import { FormattedTextBox } from './formattedText/FormattedTextBox'; import { PresEffect, PresEffectDirection } from './trails'; +import SlideEffect, { EffectType } from './trails/SlideEffect'; interface Window { MediaRecorder: MediaRecorder; } @@ -1004,18 +1005,34 @@ export class DocumentViewInternal extends DocComponent{renderDoc}; + case PresEffect.Zoom: return {renderDoc} case PresEffect.Fade: return {renderDoc}; case PresEffect.Flip: return {renderDoc}; case PresEffect.Rotate: return {renderDoc}; - case PresEffect.Bounce: return {renderDoc}; + case PresEffect.Bounce: return {renderDoc} case PresEffect.Roll: return {renderDoc}; case PresEffect.Lightspeed: return {renderDoc}; } + // switch (StrCast(presEffectDoc?.presentation_effect, StrCast(presEffectDoc?.followLinkAnimEffect))) { + // default: + // // package used: react-awesome-reveal + // case PresEffect.None: return renderDoc; + // case PresEffect.Zoom: return {renderDoc}; + // case PresEffect.Fade: return {renderDoc}; + // case PresEffect.Flip: return {renderDoc}; + // case PresEffect.Rotate: return {renderDoc}; + // case PresEffect.Bounce: return {renderDoc}; + // case PresEffect.Roll: return {renderDoc}; + // case PresEffect.Lightspeed: return {renderDoc}; + // } } public static recordAudioAnnotation(dataDoc: Doc, field: string, onRecording?: (stop: () => void) => void, onEnd?: () => void) { let gumStream: any; diff --git a/src/client/views/nodes/trails/CubicBezierEditor.tsx b/src/client/views/nodes/trails/CubicBezierEditor.tsx index 06a246675..d6ce9db1f 100644 --- a/src/client/views/nodes/trails/CubicBezierEditor.tsx +++ b/src/client/views/nodes/trails/CubicBezierEditor.tsx @@ -1,8 +1,10 @@ import React, { useEffect, useState } from 'react'; +import { StrCast } from '../../../../fields/Types'; type Props = { setFunc: (newPoints: { p1: number[]; p2: number[] }) => void; currPoints: { p1: number[]; p2: number[] }; + easeFunc: string; }; const ANIMATION_DURATION = 750; @@ -20,7 +22,7 @@ export const TIMING_DEFAULT_MAPPINGS = { 'ease-in-out': 'cubic-bezier(0.42, 0, 0.58, 1.0)', }; -const CubicBezierEditor = ({ setFunc, currPoints }: Props) => { +const CubicBezierEditor = ({ setFunc, currPoints, easeFunc }: Props) => { const [animating, setAnimating] = useState(false); // Should let parent control state const [cPoints, setCPoints] = useState( @@ -38,6 +40,49 @@ const CubicBezierEditor = ({ setFunc, currPoints }: Props) => { return Math.round(num * 100) / 100; }; + const convertToPoints = (func: string) => { + console.log('getting curr c points'); + let strPoints = func ? func : 'ease'; + if (!strPoints.startsWith('cubic')) { + switch (func) { + case 'linear': + strPoints = 'cubic-bezier(0.0, 0.0, 1.0, 1.0)'; + break; + case 'ease': + strPoints = 'cubic-bezier(0.25, 0.1, 0.25, 1.0)'; + break; + case 'ease-in': + strPoints = 'cubic-bezier(0.42, 0, 1.0, 1.0)'; + break; + case 'ease-out': + strPoints = 'cubic-bezier(0, 0, 0.58, 1.0)'; + break; + case 'ease-in-out': + strPoints = 'cubic-bezier(0.42, 0, 0.58, 1.0)'; + break; + default: + strPoints = 'cubic-bezier(0.25, 0.1, 0.25, 1.0)'; + } + } + console.log('str points', strPoints); + const components = strPoints + .split('(')[1] + .split(')')[0] + .split(',') + .map(elem => parseFloat(elem)); + console.log('bezier components', components); + return { + p1: [components[0], components[1]], + p2: [components[2], components[3]], + }; + }; + + useEffect(() => { + if (!easeFunc.startsWith('cubic')) { + setCPoints(convertToPoints(easeFunc)); + } + }, [easeFunc]); + useEffect(() => { if (animating) { setTimeout(() => { @@ -124,6 +169,20 @@ const CubicBezierEditor = ({ setFunc, currPoints }: Props) => { fill="transparent" /> {/* Bottom left */} + { + setC1Down(true); + }} + onPointerUp={() => { + setC1Down(false); + }} + x1={`${0 + OFFSET}`} + y1={`${EDITOR_WIDTH + OFFSET}`} + x2={`${cPoints.p1[0] * EDITOR_WIDTH + OFFSET}`} + y2={`${EDITOR_WIDTH - cPoints.p1[1] * EDITOR_WIDTH + OFFSET}`} + stroke="#00000000" + strokeWidth="5" + /> { }} /> {/* Top right */} + { + e.stopPropagation(); + setC2Down(true); + }} + onPointerUp={e => { + setC2Down(false); + }} x1={`${EDITOR_WIDTH + OFFSET}`} y1={`${0 + OFFSET}`} x2={`${cPoints.p2[0] * EDITOR_WIDTH + OFFSET}`} y2={`${EDITOR_WIDTH - cPoints.p2[1] * EDITOR_WIDTH + OFFSET}`} stroke="#00000000" + strokeWidth="5" /> isNaN(Number(v))) + .map(effect => ({ + text: effect, + val: effect, + })); + @observer export class PresBox extends ViewBoxBaseComponent() { public static LayoutString(fieldKey: string) { @@ -962,6 +980,7 @@ export class PresBox extends ViewBoxBaseComponent() { (DocumentManager.Instance.getFirstDocumentView(targetDoc)?.ComponentView as ScriptingBox)?.onRun?.(); return; } + console.log('pres_effect_dir', StrCast(activeItem.presentation_effectDirection)); const effect = activeItem.presentation_effect && activeItem.presentation_effect !== PresEffect.None ? activeItem.presentation_effect : undefined; // default with effect: 750ms else 500ms const presTime = NumCast(activeItem.presentation_transition, effect ? 750 : 500); @@ -1665,7 +1684,7 @@ export class PresBox extends ViewBoxBaseComponent() { }; @undoBatch - updateEffectDirection = (effect: PresEffectDirection, all?: boolean) => (all ? this.childDocs : this.selectedArray).forEach(doc => (doc.presentation_effectDirection = effect)); + updateEffectDirection = (effectDir: PresEffectDirection, all?: boolean) => (all ? this.childDocs : this.selectedArray).forEach(doc => (doc.presentation_effectDirection = effectDir)); @undoBatch updateEffect = (effect: PresEffect, bullet: boolean, all?: boolean) => (all ? this.childDocs : this.selectedArray).forEach(doc => (bullet ? (doc.presBulletEffect = effect) : (doc.presentation_effect = effect))); @@ -1677,25 +1696,46 @@ export class PresBox extends ViewBoxBaseComponent() { }; public static inputter = (min: string, step: string, max: string, value: number, active: boolean, change: (val: string) => void, hmargin?: number) => { return ( - { PresBox._sliderBatch = UndoManager.StartBatch('pres slider'); document.addEventListener('pointerup', PresBox.endBatch, true); e.stopPropagation(); - }} - onChange={e => { - e.stopPropagation(); - change(e.target.value); - }} - /> + }}> + { + e.stopPropagation(); + change(val.toString()); + }} + step={parseFloat(step)} + min={parseFloat(min)} + max={parseFloat(max)} + value={value} + size="small" + defaultValue={value} + aria-label="Small" + valueLabelDisplay="auto" + /> +
+ // { + // PresBox._sliderBatch = UndoManager.StartBatch('pres slider'); + // document.addEventListener('pointerup', PresBox.endBatch, true); + // e.stopPropagation(); + // }} + // onChange={e => { + // e.stopPropagation(); + // change(e.target.value); + // }} + // /> ); }; @@ -1920,10 +1960,12 @@ export class PresBox extends ViewBoxBaseComponent() { ); }; + if (activeItem && this.targetDoc) { const transitionSpeed = activeItem.presentation_transition ? NumCast(activeItem.presentation_transition) / 1000 : 0.5; const zoom = NumCast(activeItem.config_zoom, 1) * 100; const effect = activeItem.presentation_effect ? activeItem.presentation_effect : PresMovement.None; + return ( <> {/* GPT Component */} @@ -1971,16 +2013,6 @@ export class PresBox extends ViewBoxBaseComponent() { this.customizeWithGPT(this.chatInput); }} /> - - {/* } - onClick={() => { - this.customizeWithGPT(this.chatInput); - }} - /> */}
() { this._openEffectDropdown = false; this._openBulletEffectDropdown = false; })}> -
+
Movement - {/* { - if (typeof val === 'string') this.setFormData({ ...this.formData, type: val as BugType }); - }} - dropdownType={DropdownType.SELECT} - type={Type.TERT} - fillWidth - /> */} -
{ e.stopPropagation(); @@ -2037,20 +2056,32 @@ export class PresBox extends ViewBoxBaseComponent() { {presMovement(PresMovement.Pan)} {presMovement(PresMovement.Jump)}
-
+
*/} + { + this.updateMovement(val as PresMovement); + }} + dropdownType={DropdownType.SELECT} + type={Type.TERT} + />
Zoom (% screen filled)
this.updateZoom(e.target.value)} />%
-
+ {/*
this.updateZoom(String(zoom), 0.1)}>
this.updateZoom(String(zoom), -0.1)}>
-
+
*/}
{PresBox.inputter('0', '1', '100', zoom, activeItem.presentation_movement === PresMovement.Zoom, this.updateZoom)}
@@ -2058,23 +2089,23 @@ export class PresBox extends ViewBoxBaseComponent() {
e.stopPropagation()} onChange={action(e => this.updateTransitionTime(e.target.value))} /> s
-
+ {/*
this.updateTransitionTime(String(transitionSpeed), 1000)}>
this.updateTransitionTime(String(transitionSpeed), -1000)}>
-
+
*/}
- {PresBox.inputter('0.1', '0.1', '100', transitionSpeed, true, this.updateTransitionTime)} + {PresBox.inputter('0.1', '0.1', '10', transitionSpeed, true, this.updateTransitionTime)}
Fast
Medium
Slow
{/* Easing function */} -
+
() { }} dropdownType={DropdownType.SELECT} type={Type.TERT} - // fillWidth /> {/* Custom */}

Custom Timing Function

- +
-
+
Effects -
+ (activeItem.presPlayAudio = !BoolCast(activeItem.presPlayAudio))} + color={SettingsManager.userColor} + /> + {/*
Play Audio Annotation
() { onChange={() => (activeItem.presPlayAudio = !BoolCast(activeItem.presPlayAudio))} checked={BoolCast(activeItem.presPlayAudio)} /> -
-
+
*/} + (activeItem.presentation_zoomText = !BoolCast(activeItem.presentation_zoomText))} + color={SettingsManager.userColor} + /> + {/*
Zoom Text Selections
() { onChange={() => (activeItem.presentation_zoomText = !BoolCast(activeItem.presentation_zoomText))} checked={BoolCast(activeItem.presentation_zoomText)} /> -
-
*/} + {/* Effect dropdown */} + { + this.updateEffect(val as PresEffect, false); + }} + dropdownType={DropdownType.SELECT} + type={Type.TERT} + /> + {/*
{ e.stopPropagation(); @@ -2148,20 +2205,59 @@ export class PresBox extends ViewBoxBaseComponent() { .filter(v => isNaN(Number(v))) .map(effect => preseEffect(effect))}
-
+
*/} + {/* Effect direction */}
Effect direction
{StrCast(this.activeItem.presentation_effectDirection)}
-
+
+ } + onClick={() => this.updateEffectDirection(PresEffectDirection.Center)} + /> + } + onClick={() => this.updateEffectDirection(PresEffectDirection.Left)} + /> + } + onClick={() => this.updateEffectDirection(PresEffectDirection.Right)} + /> + } + onClick={() => this.updateEffectDirection(PresEffectDirection.Top)} + /> + } + onClick={() => this.updateEffectDirection(PresEffectDirection.Bottom)} + /> +
+ {/*
{presDirection(PresEffectDirection.Left, 'angle-right', 1, 2, {})} {presDirection(PresEffectDirection.Right, 'angle-left', 3, 2, {})} {presDirection(PresEffectDirection.Top, 'angle-down', 2, 1, {})} {presDirection(PresEffectDirection.Bottom, 'angle-up', 2, 3, {})} {presDirection(PresEffectDirection.Center, '', 2, 2, { width: 10, height: 10, alignSelf: 'center' })} -
+
*/} + {/* Effect spring settings */}
this.applyTo(this.childDocs)}> diff --git a/src/client/views/nodes/trails/SlideEffect.tsx b/src/client/views/nodes/trails/SlideEffect.tsx new file mode 100644 index 000000000..918ea93bd --- /dev/null +++ b/src/client/views/nodes/trails/SlideEffect.tsx @@ -0,0 +1,131 @@ +import { Button } from '@mui/material'; +import { useSpring, animated, easings } from '@react-spring/web'; +import React, { useEffect, useState } from 'react'; + +export enum EffectType { + ZOOM = 'zoom', + FADE = 'fade', + BOUNCE = 'bounce', +} + +interface Props { + effectType: EffectType; + friction: number; + tension: number; + mass: number; + children: React.ReactNode; +} + +export default function SpringAnimation({ friction, tension, mass, effectType, children }: Props) { + const [springs, api] = useSpring( + () => ({ + from: { + x: 0, + y: 0, + opacity: 0, + scale: 1, + }, + config: { + tension: tension, + friction: friction, + mass: mass, + }, + onStart: () => { + console.log('started'); + }, + onRest: () => { + console.log('resting'); + }, + }), + [tension, friction, mass] + ); + + // Whether the animation is currently playing + const [animating, setAnimating] = useState(false); + + const zoomConfig = { + from: { + x: 0, + y: 0, + opacity: 0, + scale: 0, + }, + to: { + x: 0, + y: 0, + opacity: 1, + scale: 1, + config: { + tension: tension, + friction: friction, + mass: mass, + }, + }, + }; + + const bounceConfig = { + from: { + opacity: 0, + x: -200, + y: 0, + }, + to: [ + { + opacity: 1, + x: 0, + y: 0, + config: { + tension: tension, + friction: friction, + mass: mass, + }, + }, + ], + }; + + const handleClick = () => { + if (effectType === EffectType.BOUNCE) { + api.start(bounceConfig); + } else if (effectType === EffectType.ZOOM) { + api.start(zoomConfig); + } + }; + + useEffect(() => { + setTimeout(() => { + handleClick(); + }, 200); + }, []); + + return ( +
{ + // handleClick(); + // }} + > + {/* style={{ + width: "50px", + height: "50px", + backgroundColor: "#ff6d6d", + borderRadius: "4px", + ...springs, + }} */} + + {children} + + {/* */} +
+ ); +} -- cgit v1.2.3-70-g09d2 From eecc7ee1d14719d510ec2975826022c565a35e5f Mon Sep 17 00:00:00 2001 From: Sophie Zhang Date: Tue, 9 Apr 2024 12:15:08 -0400 Subject: pushing progress --- src/client/apis/gpt/customization.ts | 5 +++++ src/client/views/nodes/trails/PresBox.scss | 10 +++++++--- src/client/views/nodes/trails/PresBox.tsx | 14 +++++++------- src/client/views/nodes/trails/SlideEffect.tsx | 1 + 4 files changed, 20 insertions(+), 10 deletions(-) (limited to 'src/client/views/nodes/trails/PresBox.scss') diff --git a/src/client/apis/gpt/customization.ts b/src/client/apis/gpt/customization.ts index 946208eeb..bc3f57210 100644 --- a/src/client/apis/gpt/customization.ts +++ b/src/client/apis/gpt/customization.ts @@ -52,6 +52,11 @@ const setupPresSlideCustomization = () => { addCustomizationProperty(CustomizationType.PRES_TRAIL_SLIDE, 'presentation_effect', 'is an effect applied to the slide when we transition to it.', ['None', 'Fade in', 'Flip', 'Rotate', 'Bounce', 'Roll']); addCustomizationProperty(CustomizationType.PRES_TRAIL_SLIDE, 'presentation_effectDirection', 'is what direction the effect is applied.', ['Enter from left', 'Enter from right', 'Enter from bottom', 'Enter from Top', 'Enter from center']); addCustomizationProperty(CustomizationType.PRES_TRAIL_SLIDE, 'config_zoom', 'is a number from 0 to 1.0 indicating the percentage we should zoom into the slide.'); + addCustomizationProperty( + CustomizationType.PRES_TRAIL_SLIDE, + 'presEffectTiming', + "is a json object of the format: {type: string, stiffness: number, damping: number, mass: number}. Type is always “custom”. Controls the spring-based timing of the presentation effect animation. Stiffness, damping, and mass control the physics-based properties of spring animations. This is used to create a more natural looking timing, bouncy effects, etc. Use spring physics to adjust these parameters to match the user's description of how they want to animate the effect." + ); }; setupPresSlideCustomization(); diff --git a/src/client/views/nodes/trails/PresBox.scss b/src/client/views/nodes/trails/PresBox.scss index 23c170cf7..43f9ec78e 100644 --- a/src/client/views/nodes/trails/PresBox.scss +++ b/src/client/views/nodes/trails/PresBox.scss @@ -230,6 +230,11 @@ } } +.presBox-toggles { + display: flex; + overflow-x: auto; +} + .presBox-ribbon { position: relative; display: inline; @@ -695,15 +700,14 @@ background-color: $white; display: flex; color: $black; - margin-top: 5px; - margin-bottom: 5px; border-radius: 5px; - margin-right: 5px; width: max-content; justify-content: center; align-items: center; padding-right: 10px; padding-left: 10px; + margin: 4px; + text-wrap: nowrap; } .ribbon-toggle.active { diff --git a/src/client/views/nodes/trails/PresBox.tsx b/src/client/views/nodes/trails/PresBox.tsx index 8745bf1a4..9019f9945 100644 --- a/src/client/views/nodes/trails/PresBox.tsx +++ b/src/client/views/nodes/trails/PresBox.tsx @@ -1726,7 +1726,7 @@ export class PresBox extends ViewBoxBaseComponent() { if (activeItem.type === DocumentType.AUDIO) duration = NumCast(activeItem.duration); return (
-
+
Hide before presented
}>
() { Lightbox
- Transition movement style
}> + {/* Transition movement style
}>
this.updateEaseFunc(activeItem)}> {`${StrCast(activeItem.presEaseFunc, 'ease')}`}
- + */}
{[DocumentType.AUDIO, DocumentType.VID].includes(targetType as any as DocumentType) ? null : ( <> @@ -2207,28 +2207,28 @@ export class PresBox extends ViewBoxBaseComponent() { type={Type.TERT} color={activeItem.presentation_effectDirection === PresEffectDirection.Left ? SettingsManager.userVariantColor : SettingsManager.userBackgroundColor} tooltip="Left" - icon={} + icon={} onClick={() => this.updateEffectDirection(PresEffectDirection.Left)} /> } + icon={} onClick={() => this.updateEffectDirection(PresEffectDirection.Right)} /> } + icon={} onClick={() => this.updateEffectDirection(PresEffectDirection.Top)} /> } + icon={} onClick={() => this.updateEffectDirection(PresEffectDirection.Bottom)} />
diff --git a/src/client/views/nodes/trails/SlideEffect.tsx b/src/client/views/nodes/trails/SlideEffect.tsx index af0e7461b..7e2985a6a 100644 --- a/src/client/views/nodes/trails/SlideEffect.tsx +++ b/src/client/views/nodes/trails/SlideEffect.tsx @@ -19,6 +19,7 @@ interface Props { children: React.ReactNode; } +// TODO: add visibility detector when the slide comes into view export default function SpringAnimation({ dir, friction, tension, mass, effectType, children }: Props) { const [springs, api] = useSpring( () => ({ -- cgit v1.2.3-70-g09d2 From 9e221fdb995d5a489fb34133d2ab98d7907219bd Mon Sep 17 00:00:00 2001 From: Sophie Zhang Date: Wed, 10 Apr 2024 15:47:36 -0400 Subject: feat: starting flip --- src/client/views/nodes/trails/PresBox.scss | 4 -- src/client/views/nodes/trails/SlideEffect.scss | 18 +++++ src/client/views/nodes/trails/SlideEffect.tsx | 94 +++++++++++++++++++++----- 3 files changed, 95 insertions(+), 21 deletions(-) create mode 100644 src/client/views/nodes/trails/SlideEffect.scss (limited to 'src/client/views/nodes/trails/PresBox.scss') diff --git a/src/client/views/nodes/trails/PresBox.scss b/src/client/views/nodes/trails/PresBox.scss index 43f9ec78e..c937730ab 100644 --- a/src/client/views/nodes/trails/PresBox.scss +++ b/src/client/views/nodes/trails/PresBox.scss @@ -8,13 +8,9 @@ } .pres-chat { - // padding: 8px; display: flex; flex-direction: column; gap: 8px; - // display: flex; - // align-items: center; - // gap: 16px; } .presBox-icon-list { diff --git a/src/client/views/nodes/trails/SlideEffect.scss b/src/client/views/nodes/trails/SlideEffect.scss new file mode 100644 index 000000000..7d2929225 --- /dev/null +++ b/src/client/views/nodes/trails/SlideEffect.scss @@ -0,0 +1,18 @@ +.flip-container { + display: flex; + align-items: center; + height: 100%; + justify-content: center; +} + +.flip-side { + position: absolute; + // max-width: 500px; + // max-height: 500px; + // width: 350px; + // height: 200px; + will-change: transform, opacity; +} + +.flip-back { +} diff --git a/src/client/views/nodes/trails/SlideEffect.tsx b/src/client/views/nodes/trails/SlideEffect.tsx index e3423069b..eee52c3ec 100644 --- a/src/client/views/nodes/trails/SlideEffect.tsx +++ b/src/client/views/nodes/trails/SlideEffect.tsx @@ -12,7 +12,7 @@ interface Props { } // TODO: add visibility detector when the slide comes into view -export default function SpringAnimation({ dir, friction, tension, mass, presEffect: presEffect, children }: Props) { +export default function SpringAnimation({ dir, friction, tension, mass, presEffect, children }: Props) { const [springs, api] = useSpring( () => ({ from: { @@ -154,7 +154,36 @@ export default function SpringAnimation({ dir, friction, tension, mass, presEffe ], }; - const flipConfig = {}; + // Flip + // const flipConfig = { + // from: { + // // opacity: 0, + // transform: `perspective(600px) rotateX(0deg)`, + // }, + // to: { + // // opacity: 1, + // transform: `perspective(600px) rotateX(180deg)`, + // config: { + // tension: tension, + // friction: friction, + // mass: mass, + // }, + // }, + // }; + + const flipConfig = { + from: { + x: 0, + }, + to: { + x: 180, + config: { + tension: tension, + friction: friction, + mass: mass, + }, + }, + }; const startAnimation = () => { if (presEffect === PresEffect.Bounce) { @@ -168,7 +197,51 @@ export default function SpringAnimation({ dir, friction, tension, mass, presEffe } }; - const flipRender = () => {}; + // const flipRender = () => { + // return ( + //
+ // 1 - o), transform }} /> + // + // {children} + // + //
+ // ); + // }; + + const flipRender = () => { + return ( +
+ `perspective(600px) rotateX(${val}deg)`) }} /> + `perspective(600px) rotateX(${val}deg)`), rotateX: '180deg' }}> + {children} + +
+ ); + }; + + const getRenderDoc = () => { + switch (presEffect) { + case PresEffect.Rotate: + return `rotate(${val}deg)`) }}>{children}; + case PresEffect.Flip: + return flipRender(); + default: + return ( + + {children} + + ); + } + }; useEffect(() => { // TODO: Control start with slide visibility instead @@ -177,18 +250,5 @@ export default function SpringAnimation({ dir, friction, tension, mass, presEffe }, 200); }, []); - return ( -
- {presEffect !== PresEffect.Rotate ? ( - - {children} - - ) : ( - `rotate(${val}deg)`) }}>{children} - )} -
- ); + return
{getRenderDoc()}
; } -- cgit v1.2.3-70-g09d2 From 70b582db9a8cecc742be3c2b5f043a70a15c7991 Mon Sep 17 00:00:00 2001 From: Sophie Zhang Date: Thu, 18 Apr 2024 11:13:52 -0400 Subject: dropdowns, ui, roll --- src/client/views/nodes/DocumentView.tsx | 11 +- src/client/views/nodes/trails/PresBox.scss | 9 + src/client/views/nodes/trails/PresBox.tsx | 201 ++++++++++++++--------- src/client/views/nodes/trails/PresElementBox.tsx | 9 +- src/client/views/nodes/trails/SlideEffect.tsx | 51 ++++-- 5 files changed, 174 insertions(+), 107 deletions(-) (limited to 'src/client/views/nodes/trails/PresBox.scss') diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx index eaa2c6abc..801d96b35 100644 --- a/src/client/views/nodes/DocumentView.tsx +++ b/src/client/views/nodes/DocumentView.tsx @@ -997,7 +997,7 @@ export class DocumentViewInternal extends DocComponent, root: Doc) { - const dir = presEffectDoc?.presentation_effectDirection ?? presEffectDoc?.followLinkAnimDirection; + let dir = presEffectDoc?.presentation_effectDirection ?? presEffectDoc?.followLinkAnimDirection; const effectProps = { left: dir === PresEffectDirection.Left, right: dir === PresEffectDirection.Right, @@ -1021,21 +1021,24 @@ export class DocumentViewInternal extends DocComponent{renderDoc} case PresEffect.Fade: return {renderDoc} case PresEffect.Flip: return {renderDoc} case PresEffect.Rotate: return {renderDoc} - // Potential change to move in since anything can be "bouncy" case PresEffect.Bounce: return {renderDoc} case PresEffect.Roll: return {renderDoc} - case PresEffect.Lightspeed: return {renderDoc}; + // keep as preset, doesn't really make sense with spring config + case PresEffect.Lightspeed: return {renderDoc}; } // switch (StrCast(presEffectDoc?.presentation_effect, StrCast(presEffectDoc?.followLinkAnimEffect))) { // default: diff --git a/src/client/views/nodes/trails/PresBox.scss b/src/client/views/nodes/trails/PresBox.scss index c937730ab..adc59d812 100644 --- a/src/client/views/nodes/trails/PresBox.scss +++ b/src/client/views/nodes/trails/PresBox.scss @@ -17,6 +17,7 @@ display: flex; gap: 8px; } + .pres-chatbox-container { padding: 16px; outline: 1px solid #999999; @@ -37,6 +38,14 @@ // Bezier editor +.presBox-show-hide-dropdown { + cursor: pointer; + padding: 8px 0; + display: flex; + align-items: center; + gap: 4px; +} + .presBox-bezier-editor { border: 1px solid rgb(221, 221, 221); border-radius: 4px; diff --git a/src/client/views/nodes/trails/PresBox.tsx b/src/client/views/nodes/trails/PresBox.tsx index b192dc3db..62458acfe 100644 --- a/src/client/views/nodes/trails/PresBox.tsx +++ b/src/client/views/nodes/trails/PresBox.tsx @@ -137,15 +137,22 @@ export class PresBox extends ViewBoxBaseComponent() { }; @action - public setChatActive = (active: boolean) => { - this.toggleProperties(); - }; + public setChatActive = (active: boolean) => {}; @action public setIsRecording = (isRecording: boolean) => { this.isRecording = isRecording; }; + @observable showBezierEditor = false; + @action setBezierEditorVisibility = (visible: boolean) => { + this.showBezierEditor = visible; + }; + @observable showSpringEditor = true; + @action setSpringEditorVisibility = (visible: boolean) => { + this.showSpringEditor = visible; + }; + // Easing function variables @observable easeDropdownVal = 'ease'; @@ -2098,6 +2105,7 @@ export class PresBox extends ViewBoxBaseComponent() { setSelectedVal={val => { if (typeof val === 'string') { if (val !== 'custom') { + this.setBezierEditorVisibility(true); this.setEaseFunc(this.activeItem, val); } else { this.setEaseFunc(this.activeItem, TIMING_DEFAULT_MAPPINGS.ease); @@ -2108,8 +2116,24 @@ export class PresBox extends ViewBoxBaseComponent() { type={Type.TERT} /> {/* Custom */} -

Custom Timing Function

- +
{ + e.stopPropagation(); + this.setBezierEditorVisibility(!this.showBezierEditor); + }}> + {`${this.showBezierEditor ? 'Hide' : 'Show'} Timing Editor`} + +
+ {this.showBezierEditor && ( + <> +

+ Custom Timing Function +

+ + + )}
@@ -2235,87 +2259,94 @@ export class PresBox extends ViewBoxBaseComponent() { onClick={() => this.updateEffectDirection(PresEffectDirection.Bottom)} />
- {/*
- {presDirection(PresEffectDirection.Left, 'angle-right', 1, 2, {})} - {presDirection(PresEffectDirection.Right, 'angle-left', 3, 2, {})} - {presDirection(PresEffectDirection.Top, 'angle-down', 2, 1, {})} - {presDirection(PresEffectDirection.Bottom, 'angle-up', 2, 3, {})} - {presDirection(PresEffectDirection.Center, '', 2, 2, { width: 10, height: 10, alignSelf: 'center' })} -
*/} - {/* Effect spring settings */} - { - console.log('effect timing', val); - this.updateEffectTiming(activeItem, { - type: val as SpringType, - ...springMappings[val], - }); - }} - dropdownType={DropdownType.SELECT} - type={Type.TERT} - /> -
Tension
+ {/* Spring settings */} + {/* No spring settings for jackinthebox (lightspeed) */}
{ + className="presBox-show-hide-dropdown" + onClick={e => { e.stopPropagation(); + this.setSpringEditorVisibility(!this.showSpringEditor); }}> - { - if (!timingConfig) return; - this.updateEffectTiming(activeItem, { ...timingConfig, type: SpringType.CUSTOM, stiffness: val as number }); - }} - valueLabelDisplay="auto" - /> + {`${this.showSpringEditor ? 'Hide' : 'Show'} Spring Settings`} +
-
Damping
-
{ - e.stopPropagation(); - }}> - { - if (!timingConfig) return; - this.updateEffectTiming(activeItem, { ...timingConfig, type: SpringType.CUSTOM, damping: val as number }); - }} - valueLabelDisplay="auto" - /> -
-
Mass
-
{ - e.stopPropagation(); - }}> - { - if (!timingConfig) return; - this.updateEffectTiming(activeItem, { ...timingConfig, type: SpringType.CUSTOM, mass: val as number }); - }} - valueLabelDisplay="auto" - /> -
- -
-
+ {effect !== PresEffect.Lightspeed && this.showSpringEditor && ( + <> + { + this.updateEffectTiming(activeItem, { + type: val as SpringType, + ...springMappings[val], + }); + }} + dropdownType={DropdownType.SELECT} + type={Type.TERT} + /> +
Tension
+
{ + e.stopPropagation(); + }}> + { + if (!timingConfig) return; + this.updateEffectTiming(activeItem, { ...timingConfig, type: SpringType.CUSTOM, stiffness: val as number }); + }} + valueLabelDisplay="auto" + /> +
+
Damping
+
{ + e.stopPropagation(); + }}> + { + if (!timingConfig) return; + this.updateEffectTiming(activeItem, { ...timingConfig, type: SpringType.CUSTOM, damping: val as number }); + }} + valueLabelDisplay="auto" + /> +
+
Mass
+
{ + e.stopPropagation(); + }}> + { + if (!timingConfig) return; + this.updateEffectTiming(activeItem, { ...timingConfig, type: SpringType.CUSTOM, mass: val as number }); + }} + valueLabelDisplay="auto" + /> +
+ +
+
+ + )} + {/* Effect spring settings */}
this.applyTo(this.childDocs)}> @@ -2734,6 +2765,12 @@ export class PresBox extends ViewBoxBaseComponent() { @action toggleProperties = () => (SettingsManager.Instance.propertiesWidth = SettingsManager.Instance.propertiesWidth > 0 ? 0 : 250); + @action + openProperties = () => { + // need to also focus slide + SettingsManager.Instance.propertiesWidth = 250; + }; + @computed get toolbar() { const propIcon = SettingsManager.Instance.propertiesWidth > 0 ? 'angle-double-right' : 'angle-double-left'; const propTitle = SettingsManager.Instance.propertiesWidth > 0 ? 'Close Presentation Panel' : 'Open Presentation Panel'; diff --git a/src/client/views/nodes/trails/PresElementBox.tsx b/src/client/views/nodes/trails/PresElementBox.tsx index 4abfc5a94..449b8e07f 100644 --- a/src/client/views/nodes/trails/PresElementBox.tsx +++ b/src/client/views/nodes/trails/PresElementBox.tsx @@ -513,15 +513,16 @@ export class PresElementBox extends ViewBoxBaseComponent() { ); items.push( - Customize
}> + Edit
}>
{ - PresBox.Instance.setChatActive(true); + PresBox.Instance.navigateToActiveItem(); + PresBox.Instance.openProperties(); PresBox.Instance.slideToModify = this.Document; - PresBox.Instance.recordDictation(); + // PresBox.Instance.recordDictation(); }}> - e.stopPropagation()} /> + e.stopPropagation()} />
); diff --git a/src/client/views/nodes/trails/SlideEffect.tsx b/src/client/views/nodes/trails/SlideEffect.tsx index d4dfae059..20ff4b0b9 100644 --- a/src/client/views/nodes/trails/SlideEffect.tsx +++ b/src/client/views/nodes/trails/SlideEffect.tsx @@ -139,6 +139,7 @@ export default function SpringAnimation({ doc, delay, dir, friction, tension, ma }, }; default: + // no movement for center return { from: { opacity: 0, @@ -165,23 +166,6 @@ export default function SpringAnimation({ doc, delay, dir, friction, tension, ma ], }; - // Flip - // const flipConfig = { - // from: { - // // opacity: 0, - // transform: `perspective(600px) rotateX(0deg)`, - // }, - // to: { - // // opacity: 1, - // transform: `perspective(600px) rotateX(180deg)`, - // config: { - // tension: tension, - // friction: friction, - // mass: mass, - // }, - // }, - // }; - const flipConfig = { from: { x: 0, @@ -196,6 +180,32 @@ export default function SpringAnimation({ doc, delay, dir, friction, tension, ma }, }; + const rollConfig = { + from: { + opacity: 0, + x: -100, + y: -120, + }, + to: { + opacity: 1, + x: 0, + y: 0, + config: { + tension: tension, + friction: friction, + mass: mass, + }, + }, + }; + + const lightspeedConfig = { + from: { + opacity: 0, + }, + to: [], + loop: true, + }; + // Switch animation depending on slide effect const startAnimation = () => { switch (presEffect) { @@ -215,6 +225,7 @@ export default function SpringAnimation({ doc, delay, dir, friction, tension, ma api.start(flipConfig); break; case PresEffect.Roll: + api.start(rollConfig); break; case PresEffect.Lightspeed: break; @@ -269,6 +280,12 @@ export default function SpringAnimation({ doc, delay, dir, friction, tension, ma )}
); + case PresEffect.Roll: + return ( + `translate3d(${val}%, 0, 0) rotate3d(0, 0, 1, ${val2}deg)`) }}> + {children} + + ); default: return ( Date: Thu, 25 Apr 2024 11:17:35 -0400 Subject: ui framework for effect animations --- src/client/apis/gpt/customization.ts | 26 ++- src/client/views/nodes/DocumentView.tsx | 12 +- src/client/views/nodes/trails/PresBox.scss | 29 +++ src/client/views/nodes/trails/PresBox.tsx | 241 ++++++++++++++----------- src/client/views/nodes/trails/SlideEffect.scss | 2 +- src/client/views/nodes/trails/SlideEffect.tsx | 86 ++++++--- src/client/views/nodes/trails/SpringUtils.ts | 9 + 7 files changed, 259 insertions(+), 146 deletions(-) (limited to 'src/client/views/nodes/trails/PresBox.scss') diff --git a/src/client/apis/gpt/customization.ts b/src/client/apis/gpt/customization.ts index 8960bc651..a1ab2bd5f 100644 --- a/src/client/apis/gpt/customization.ts +++ b/src/client/apis/gpt/customization.ts @@ -39,8 +39,27 @@ const setupPresSlideCustomization = () => { setupPresSlideCustomization(); -export const gptTrailSlideCustomization = async (inputText: string, properties: any) => { - console.log('properties', properties); +export const getSlideTransitionSuggestions = async (inputText: string, properties: any) => { + /** + * Prompt: Generate an entrance animations from slower and gentler + * to bouncier and more high energy + * + * Format: + * { + * name: Slow Fade, Quick Flip, Springy + * effect: BOUNCE + * effectDirection: LEFT + * timingConfig: { + * + * + * + * } + * } + */ + const res = await new Promise(resolve => resolve('result')); +}; + +export const gptTrailSlideCustomization = async (inputText: string, properties: any | any[], applyToWhole?: boolean) => { let prompt = prompts.trails.description; prompts.trails.features.forEach(feature => { @@ -50,9 +69,6 @@ export const gptTrailSlideCustomization = async (inputText: string, properties: } }); - // prompt += - // 'title is the title/name of the slide. presentation_transition is a number in milliseconds for how long it should take to transition/move to a slide. presentation_effect is an effect applied to the slide when we transition to it. Its only possible values are: [None, Fade in, Flip, Rotate, Bounce, Roll]. presentation_effectDirection is what direction the effect is applied. Its only possible values are: [Enter from left, Enter from right, Enter from bottom, Enter from Top, Enter from center]. config_zoom is a number from 0 to 1.0 indicating the percentage we should zoom into the slide.'; - prompt += 'Set unchanged values to null. Please only return the json with these keys and their values.'; console.log('messages', [ diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx index 801d96b35..b372c1927 100644 --- a/src/client/views/nodes/DocumentView.tsx +++ b/src/client/views/nodes/DocumentView.tsx @@ -1031,12 +1031,12 @@ export class DocumentViewInternal extends DocComponent{renderDoc} - case PresEffect.Fade: return {renderDoc} - case PresEffect.Flip: return {renderDoc} - case PresEffect.Rotate: return {renderDoc} - case PresEffect.Bounce: return {renderDoc} - case PresEffect.Roll: return {renderDoc} + case PresEffect.Zoom: return {renderDoc} + case PresEffect.Fade: return {renderDoc} + case PresEffect.Flip: return {renderDoc} + case PresEffect.Rotate: return {renderDoc} + case PresEffect.Bounce: return {renderDoc} + case PresEffect.Roll: return {renderDoc} // keep as preset, doesn't really make sense with spring config case PresEffect.Lightspeed: return {renderDoc}; } diff --git a/src/client/views/nodes/trails/PresBox.scss b/src/client/views/nodes/trails/PresBox.scss index adc59d812..09de4b0f4 100644 --- a/src/client/views/nodes/trails/PresBox.scss +++ b/src/client/views/nodes/trails/PresBox.scss @@ -36,6 +36,35 @@ overflow-y: hidden; } +// Effect Animations + +.presBox-effect-row { + display: flex; + gap: 4px; + margin: 4px; +} + +.presBox-effect-container { + overflow: hidden; + position: relative; + width: 80px; + height: 80px; + /* background-color: #1f2028; */ + border: 1px solid rgb(118, 118, 118); + border-radius: 8px; +} + +.presBox-effect-demo-box { + width: 40px; + height: 40px; + position: absolute; + top: 20px; + left: 20px; + border-radius: 4px; + // default bg + background-color: rgb(37, 161, 255); +} + // Bezier editor .presBox-show-hide-dropdown { diff --git a/src/client/views/nodes/trails/PresBox.tsx b/src/client/views/nodes/trails/PresBox.tsx index 5ce010cf7..9644935b2 100644 --- a/src/client/views/nodes/trails/PresBox.tsx +++ b/src/client/views/nodes/trails/PresBox.tsx @@ -49,6 +49,7 @@ import Slider from '@mui/material/Slider'; import { FaArrowDown, FaArrowLeft, FaArrowRight, FaArrowUp, FaCompressArrowsAlt } from 'react-icons/fa'; import SpringAnimationPreview from './SlideEffectPreview'; import { effectTimings, SpringType, springMappings, effectItems, easeItems, movementItems, SpringSettings, presEffectDefaultTimings } from './SpringUtils'; +import SlideEffect from './SlideEffect'; export interface pinDataTypes { scrollable?: boolean; @@ -1322,7 +1323,7 @@ export class PresBox extends ViewBoxBaseComponent() { this.updateCurrentPresentation(DocCast(doc.embedContainer)); }; - //Command click + // Command click @action multiSelect = (doc: Doc, ref: HTMLElement, drag: HTMLElement) => { if (!this.selectedArray.has(doc)) { @@ -1666,6 +1667,7 @@ export class PresBox extends ViewBoxBaseComponent() { PresBox._sliderBatch.end(); document.removeEventListener('pointerup', PresBox.endBatch, true); }; + public static inputter = (min: string, step: string, max: string, value: number, active: boolean, change: (val: string) => void, hmargin?: number) => { return (
() { ); }; + // Applies the slide transiiton settings to all docs in the array @undoBatch applyTo = (array: Doc[]) => { this.updateMovement(this.activeItem.presentation_movement as PresMovement, true); @@ -2145,16 +2148,6 @@ export class PresBox extends ViewBoxBaseComponent() { onClick={() => (activeItem.presPlayAudio = !BoolCast(activeItem.presPlayAudio))} color={SettingsManager.userColor} /> - {/*
-
Play Audio Annotation
- (activeItem.presPlayAudio = !BoolCast(activeItem.presPlayAudio))} - checked={BoolCast(activeItem.presPlayAudio)} - /> -
*/} () { onClick={() => (activeItem.presentation_zoomText = !BoolCast(activeItem.presentation_zoomText))} color={SettingsManager.userColor} /> - {/*
-
Zoom Text Selections
- (activeItem.presentation_zoomText = !BoolCast(activeItem.presentation_zoomText))} - checked={BoolCast(activeItem.presentation_zoomText)} - /> -
*/} {/* Effect dropdown */} () { dropdownType={DropdownType.SELECT} type={Type.TERT} /> - {/*
{ - e.stopPropagation(); - this._openEffectDropdown = !this._openEffectDropdown; - })} - style={{ - color: SettingsManager.userColor, - background: SettingsManager.userVariantColor, - borderBottomLeftRadius: this._openEffectDropdown ? 0 : 5, - border: this._openEffectDropdown ? `solid 2px ${SettingsManager.userVariantColor}` : `solid 1px ${SettingsManager.userColor}`, - }}> - {effect?.toString()} - -
e.stopPropagation()}> - {Object.values(PresEffect) - .filter(v => isNaN(Number(v))) - .map(effect => preseEffect(effect))} + {/* Effect generations */} +
+ {/* Chat for idea generation */} +
+

Customize with GPT

+
+
+ (this._inputref = r)} + minRows={1} + placeholder="Customize..." + className="pres-chatbox" + autoFocus={true} + value={this.chatInput} + onChange={e => { + this.setChatInput(e.target.value); + }} + onKeyDown={e => { + this.stopDictation(true); + e.stopPropagation(); + }} + /> + } + onClick={() => { + if (!this.isRecording) { + this.recordDictation(); + } else { + this.stopDictation(true); + } + }} + /> +
+
-
*/} + {/* Preview Animations */} +
+
+ +
+
+
+
+ +
+
+
+
+
+
+ +
+
+
+
+ +
+
+
+
+
{/* Effect direction */} {/* Only applies to certain effects */} - {effect === PresEffect.Flip || - effect === PresEffect.Bounce || - (effect === PresEffect.Roll && ( - <> -
-
Effect direction
-
- {StrCast(this.activeItem.presentation_effectDirection)} -
+ {(effect === PresEffect.Flip || effect === PresEffect.Bounce || effect === PresEffect.Roll) && ( + <> +
+
Effect direction
+
+ {StrCast(this.activeItem.presentation_effectDirection)}
-
- +
+ {/* } onClick={() => this.updateEffectDirection(PresEffectDirection.Center)} - /> - } - onClick={() => this.updateEffectDirection(PresEffectDirection.Left)} - /> - } - onClick={() => this.updateEffectDirection(PresEffectDirection.Right)} - /> - {effect !== PresEffect.Roll && ( - <> - } - onClick={() => this.updateEffectDirection(PresEffectDirection.Top)} - /> - } - onClick={() => this.updateEffectDirection(PresEffectDirection.Bottom)} - /> - - )} -
- - ))} + /> */} + } + onClick={() => this.updateEffectDirection(PresEffectDirection.Left)} + /> + } + onClick={() => this.updateEffectDirection(PresEffectDirection.Right)} + /> + {effect !== PresEffect.Roll && ( + <> + } + onClick={() => this.updateEffectDirection(PresEffectDirection.Top)} + /> + } + onClick={() => this.updateEffectDirection(PresEffectDirection.Bottom)} + /> + + )} +
+ + )} {/* Spring settings */} {/* No spring settings for jackinthebox (lightspeed) */} -
{ - e.stopPropagation(); - this.setSpringEditorVisibility(!this.showSpringEditor); - }}> - {`${this.showSpringEditor ? 'Hide' : 'Show'} Spring Settings`} - -
{effect !== PresEffect.Lightspeed && ( <> () { dropdownType={DropdownType.SELECT} type={Type.TERT} /> +
{ + e.stopPropagation(); + this.setSpringEditorVisibility(!this.showSpringEditor); + }}> + {`${this.showSpringEditor ? 'Hide' : 'Show'} Spring Settings`} + +
{this.showSpringEditor && ( <>
Tension
@@ -2363,11 +2391,12 @@ export class PresBox extends ViewBoxBaseComponent() { )} {/* Effect spring settings */}
-
+
*/}
); diff --git a/src/client/views/nodes/trails/SlideEffect.scss b/src/client/views/nodes/trails/SlideEffect.scss index 144052c1f..cadda0ccc 100644 --- a/src/client/views/nodes/trails/SlideEffect.scss +++ b/src/client/views/nodes/trails/SlideEffect.scss @@ -20,5 +20,5 @@ .flip-back { // Get the background color of node instead - background-color: rgb(223, 223, 223); + // background-color: rgb(223, 223, 223); } diff --git a/src/client/views/nodes/trails/SlideEffect.tsx b/src/client/views/nodes/trails/SlideEffect.tsx index bd667b925..251649d6a 100644 --- a/src/client/views/nodes/trails/SlideEffect.tsx +++ b/src/client/views/nodes/trails/SlideEffect.tsx @@ -7,20 +7,26 @@ import { NumCast } from '../../../../fields/Types'; interface Props { // pass in doc to extract width, height, bg - doc: Doc; - // wait for the transition movement to end before starting effect - delay: number; + doc?: Doc; dir: PresEffectDirection; presEffect: PresEffect; friction: number; tension: number; mass: number; children: React.ReactNode; + infinite?: boolean; } +const DEFAULT_WIDTH = 40; +const PREVIEW_OFFSET = 60; +const ACTUAL_OFFSET = 200; +const infiniteOptions = { + loop: true, + delay: 500, +}; + // TODO: add visibility detector when the slide comes into view -export default function SpringAnimation({ doc, delay, dir, friction, tension, mass, presEffect, children }: Props) { - console.log('delay:', delay); +export default function SpringAnimation({ doc, dir, friction, tension, mass, presEffect, children, infinite }: Props) { const [springs, api] = useSpring( () => ({ from: { @@ -34,12 +40,8 @@ export default function SpringAnimation({ doc, delay, dir, friction, tension, ma friction: friction, mass: mass, }, - onStart: () => { - console.log('started'); - }, - onRest: () => { - console.log('resting'); - }, + onStart: () => {}, + onRest: () => {}, }), [tension, friction, mass] ); @@ -110,7 +112,7 @@ export default function SpringAnimation({ doc, delay, dir, friction, tension, ma return { from: { opacity: 0, - x: -200, + x: infinite ? -PREVIEW_OFFSET : -ACTUAL_OFFSET, y: 0, }, }; @@ -118,7 +120,7 @@ export default function SpringAnimation({ doc, delay, dir, friction, tension, ma return { from: { opacity: 0, - x: 200, + x: infinite ? PREVIEW_OFFSET : ACTUAL_OFFSET, y: 0, }, }; @@ -127,7 +129,7 @@ export default function SpringAnimation({ doc, delay, dir, friction, tension, ma from: { opacity: 0, x: 0, - y: -200, + y: infinite ? -PREVIEW_OFFSET : -ACTUAL_OFFSET, }, }; case PresEffectDirection.Bottom: @@ -135,7 +137,7 @@ export default function SpringAnimation({ doc, delay, dir, friction, tension, ma from: { opacity: 0, x: 0, - y: 200, + y: infinite ? PREVIEW_OFFSET : ACTUAL_OFFSET, }, }; default: @@ -164,6 +166,7 @@ export default function SpringAnimation({ doc, delay, dir, friction, tension, ma }, }, ], + loop: true, }; const flipConfig = { @@ -196,7 +199,7 @@ export default function SpringAnimation({ doc, delay, dir, friction, tension, ma from: { opacity: 0, x: 100, - y: -120, + y: 120, }, }; case PresEffectDirection.Top: @@ -246,35 +249,41 @@ export default function SpringAnimation({ doc, delay, dir, friction, tension, ma opacity: 0, }, to: [], - loop: true, }; // Switch animation depending on slide effect const startAnimation = () => { + let config: any = zoomConfig; switch (presEffect) { case PresEffect.Bounce: - api.start(bounceConfig); + config = bounceConfig; break; case PresEffect.Zoom: - api.start(zoomConfig); + config = zoomConfig; break; case PresEffect.Rotate: - api.start(rotateConfig); + config = rotateConfig; break; case PresEffect.Fade: - api.start(fadeConfig); + config = fadeConfig; break; case PresEffect.Flip: - api.start(flipConfig); + config = flipConfig; break; case PresEffect.Roll: - api.start(rollConfig); + config = rollConfig; break; case PresEffect.Lightspeed: break; default: break; } + + if (infinite) { + config = { ...config, ...infiniteOptions }; + } + + api.start(config); }; // const flipRender = () => { @@ -308,15 +317,30 @@ export default function SpringAnimation({ doc, delay, dir, friction, tension, ma
{dir === PresEffectDirection.Bottom || dir === PresEffectDirection.Top ? ( <> - `perspective(600px) rotateX(${val}deg)`), width: NumCast(doc.width), height: NumCast(doc.height) }} /> - `perspective(600px) rotateX(${val}deg)`), rotateX: '180deg', width: NumCast(doc.width), height: NumCast(doc.height) }}> + `perspective(600px) rotateX(${val}deg)`), + width: doc ? NumCast(doc.width) : DEFAULT_WIDTH, + height: doc ? NumCast(doc.height) : DEFAULT_WIDTH, + backgroundColor: infinite ? '#a825ff' : 'rgb(223, 223, 223);', + }} + /> + `perspective(600px) rotateX(${val}deg)`), rotateX: '180deg', width: doc ? NumCast(doc.width) : DEFAULT_WIDTH, height: doc ? NumCast(doc.height) : DEFAULT_WIDTH }}> {children} ) : ( <> - `perspective(600px) rotateY(${val}deg)`), width: NumCast(doc.width), height: NumCast(doc.height) }} /> - `perspective(600px) rotateY(${val}deg)`), rotateY: '180deg', width: NumCast(doc.width), height: NumCast(doc.height) }}> + `perspective(600px) rotateY(${val}deg)`), width: doc ? NumCast(doc.width) : DEFAULT_WIDTH, height: doc ? NumCast(doc.height) : DEFAULT_WIDTH }} + /> + `perspective(600px) rotateY(${val}deg)`), rotateY: '180deg', width: doc ? NumCast(doc.width) : DEFAULT_WIDTH, height: doc ? NumCast(doc.height) : DEFAULT_WIDTH }}> {children} @@ -350,7 +374,7 @@ export default function SpringAnimation({ doc, delay, dir, friction, tension, ma // }, []); useEffect(() => { - if (!inView) return; + if (infinite || !inView) return; console.log('in view'); // TODO: Control start with slide visibility instead setTimeout(() => { @@ -358,5 +382,11 @@ export default function SpringAnimation({ doc, delay, dir, friction, tension, ma }, 100); }, [inView]); + useEffect(() => { + if (infinite) { + startAnimation(); + } + }, []); + return
{getRenderDoc()}
; } diff --git a/src/client/views/nodes/trails/SpringUtils.ts b/src/client/views/nodes/trails/SpringUtils.ts index 0518e0623..42a0add84 100644 --- a/src/client/views/nodes/trails/SpringUtils.ts +++ b/src/client/views/nodes/trails/SpringUtils.ts @@ -16,6 +16,15 @@ export interface SpringSettings { mass: number; } +// Overall config + +export interface AnimationSettings { + effect: PresEffect; + stiffness: number; + damping: number; + mass: number; +} + // Options in the movement easing dropdown export const easeItems = [ { -- cgit v1.2.3-70-g09d2 From e7db6f3490968fd2dcfbe879b991f326dbb5a3d7 Mon Sep 17 00:00:00 2001 From: Sophie Zhang Date: Sun, 28 Apr 2024 13:12:24 -0400 Subject: save prog --- src/client/apis/gpt/customization.ts | 24 +++- src/client/views/nodes/trails/PresBox.scss | 5 +- src/client/views/nodes/trails/PresBox.tsx | 186 ++++++++++++++++++++++------- 3 files changed, 170 insertions(+), 45 deletions(-) (limited to 'src/client/views/nodes/trails/PresBox.scss') diff --git a/src/client/apis/gpt/customization.ts b/src/client/apis/gpt/customization.ts index a1ab2bd5f..9c751f8bd 100644 --- a/src/client/apis/gpt/customization.ts +++ b/src/client/apis/gpt/customization.ts @@ -39,7 +39,7 @@ const setupPresSlideCustomization = () => { setupPresSlideCustomization(); -export const getSlideTransitionSuggestions = async (inputText: string, properties: any) => { +export const getSlideTransitionSuggestions = async (inputText: string, history?: string) => { /** * Prompt: Generate an entrance animations from slower and gentler * to bouncier and more high energy @@ -56,7 +56,27 @@ export const getSlideTransitionSuggestions = async (inputText: string, propertie * } * } */ - const res = await new Promise(resolve => resolve('result')); + + const prompt = + "I want to generate four distinct types of slide effect animations. Return a json of the form {effect: string, stiffness: number, damping: number, mass: number}[] with four elements. Effect is the type of animation; its only possible values are ['Zoom', 'Fade in', 'Bounce', 'Flip', 'Rotate', 'Roll']. Stiffness, damping, and mass Stiffness, damping, and mass control the physics-based properties of spring animations. This is used to create a more natural looking timing, bouncy effects, etc. Use spring physics to adjust these parameters to animate the effect."; + + const customInput = inputText ?? 'Make them as contrasting as possible with different effects and timings ranging from gentle to energetic.'; + + try { + const response = await openai.chat.completions.create({ + model: 'gpt-4', + messages: [ + { role: 'system', content: prompt }, + { role: 'user', content: `${customInput}` }, + ], + temperature: 0, + max_tokens: 1000, + }); + return response.choices[0].message?.content; + } catch (err) { + console.log(err); + return 'Error connecting with API.'; + } }; export const gptTrailSlideCustomization = async (inputText: string, properties: any | any[], applyToWhole?: boolean) => { diff --git a/src/client/views/nodes/trails/PresBox.scss b/src/client/views/nodes/trails/PresBox.scss index 09de4b0f4..7a2733146 100644 --- a/src/client/views/nodes/trails/PresBox.scss +++ b/src/client/views/nodes/trails/PresBox.scss @@ -40,11 +40,12 @@ .presBox-effect-row { display: flex; - gap: 4px; + gap: 8px; margin: 4px; } .presBox-effect-container { + cursor: pointer; overflow: hidden; position: relative; width: 80px; @@ -61,7 +62,7 @@ top: 20px; left: 20px; border-radius: 4px; - // default bg + // default bg background-color: rgb(37, 161, 255); } diff --git a/src/client/views/nodes/trails/PresBox.tsx b/src/client/views/nodes/trails/PresBox.tsx index 9644935b2..67f787b1e 100644 --- a/src/client/views/nodes/trails/PresBox.tsx +++ b/src/client/views/nodes/trails/PresBox.tsx @@ -42,13 +42,13 @@ import ReactTextareaAutosize from 'react-textarea-autosize'; import { Button, Dropdown, DropdownType, IconButton, Toggle, ToggleType, Type } from 'browndash-components'; import { BiMicrophone, BiX } from 'react-icons/bi'; import { AiOutlineSend } from 'react-icons/ai'; -import { gptSlideProperties, gptTrailSlideCustomization } from '../../../apis/gpt/customization'; +import { getSlideTransitionSuggestions, gptSlideProperties, gptTrailSlideCustomization } from '../../../apis/gpt/customization'; import { DictationManager } from '../../../util/DictationManager'; import CubicBezierEditor, { TIMING_DEFAULT_MAPPINGS } from './CubicBezierEditor'; import Slider from '@mui/material/Slider'; import { FaArrowDown, FaArrowLeft, FaArrowRight, FaArrowUp, FaCompressArrowsAlt } from 'react-icons/fa'; import SpringAnimationPreview from './SlideEffectPreview'; -import { effectTimings, SpringType, springMappings, effectItems, easeItems, movementItems, SpringSettings, presEffectDefaultTimings } from './SpringUtils'; +import { effectTimings, SpringType, springMappings, effectItems, easeItems, movementItems, SpringSettings, presEffectDefaultTimings, AnimationSettings } from './SpringUtils'; import SlideEffect from './SlideEffect'; export interface pinDataTypes { @@ -121,17 +121,57 @@ export class PresBox extends ViewBoxBaseComponent() { // GPT private _inputref: HTMLTextAreaElement | null = null; + private _inputref2: HTMLTextAreaElement | null = null; @observable chatActive: boolean = false; @observable chatInput: string = ''; public slideToModify: Doc | null = null; @observable isRecording: boolean = false; @observable isLoading: boolean = false; + @observable generatedAnimations: AnimationSettings[] = [ + { + effect: PresEffect.Bounce, + stiffness: 400, + damping: 15, + mass: 1, + }, + { + effect: PresEffect.Fade, + stiffness: 100, + damping: 15, + mass: 1, + }, + { + effect: PresEffect.Flip, + stiffness: 100, + damping: 15, + mass: 1, + }, + { + effect: PresEffect.Roll, + stiffness: 100, + damping: 15, + mass: 1, + }, + ]; + + @action + setGeneratedAnimations = (settings: AnimationSettings[]) => { + this.generatedAnimations = settings; + }; + + @observable animationChat: string = ''; + @action setChatInput = (input: string) => { this.chatInput = input; }; + @action + setAnimationChat = (input: string) => { + this.animationChat = input; + }; + @action setIsLoading = (isLoading: boolean) => { this.isLoading = isLoading; @@ -366,6 +406,41 @@ export class PresBox extends ViewBoxBaseComponent() { // this._inputref.setSelectionRange(newCursorPosition, newCursorPosition); }; + @action + customizeAnimations = async (input: string) => { + // const testInput = 'change title to Customized Slide, transition for 2.3s with fade in effect'; + // if (!this.slideToModify) return; + this.setIsLoading(true); + + try { + const res = await getSlideTransitionSuggestions(this.animationChat); + console.log('GPT Result:', res); + if (typeof res === 'string') { + const resObj = JSON.parse(res); + console.log('Parsed GPT Result ', resObj); + // this.activeItem + this.setGeneratedAnimations(resObj as AnimationSettings[]); + // this.updateEffect(resObj.effect as PresEffect, false); + // this.updateEffectTiming(this.activeItem, { + // type: SpringType.CUSTOM, + // stiffness: resObj.stiffness, + // damping: resObj.damping, + // mass: resObj.mass, + // }); + + // for (let key in resObj) { + // if (resObj[key]) { + // console.log('typeof property', typeof resObj[key]); + // this.activeItem[key] = resObj[key]; + // } + // } + } + } catch (err) { + console.error(err); + } + this.setIsLoading(false); + }; + @action customizeWithGPT = async (input: string) => { // const testInput = 'change title to Customized Slide, transition for 2.3s with fade in effect'; @@ -2176,35 +2251,26 @@ export class PresBox extends ViewBoxBaseComponent() {

Customize with GPT

-
+
{ + e.stopPropagation(); + }}> (this._inputref = r)} minRows={1} - placeholder="Customize..." + placeholder="Get animation suggestions..." className="pres-chatbox" autoFocus={true} - value={this.chatInput} + value={this.animationChat} onChange={e => { - this.setChatInput(e.target.value); + this.setAnimationChat(e.target.value); }} onKeyDown={e => { this.stopDictation(true); e.stopPropagation(); }} /> - } - onClick={() => { - if (!this.isRecording) { - this.recordDictation(); - } else { - this.stopDictation(true); - } - }} - />
{/* Preview Animations */} -
-
- -
-
-
-
- -
-
-
-
-
-
- -
-
+
+
+
+ +
+
+
+
+ +
+
+
-
- -
-
+
+
+ +
+
+
+
+ +
+
+
-- cgit v1.2.3-70-g09d2 From 53ccca391d317f3d9b7c5cb693979451a4655836 Mon Sep 17 00:00:00 2001 From: Sophie Zhang Date: Sun, 28 Apr 2024 13:48:41 -0400 Subject: fix transform origin --- src/client/views/nodes/trails/PresBox.scss | 12 ++++++++---- src/client/views/nodes/trails/PresBox.tsx | 2 +- 2 files changed, 9 insertions(+), 5 deletions(-) (limited to 'src/client/views/nodes/trails/PresBox.scss') diff --git a/src/client/views/nodes/trails/PresBox.scss b/src/client/views/nodes/trails/PresBox.scss index 7a2733146..2c56cf698 100644 --- a/src/client/views/nodes/trails/PresBox.scss +++ b/src/client/views/nodes/trails/PresBox.scss @@ -47,9 +47,12 @@ .presBox-effect-container { cursor: pointer; overflow: hidden; - position: relative; + // position: relative; width: 80px; height: 80px; + display: flex; + justify-content: center; + align-items: center; /* background-color: #1f2028; */ border: 1px solid rgb(118, 118, 118); border-radius: 8px; @@ -58,12 +61,13 @@ .presBox-effect-demo-box { width: 40px; height: 40px; - position: absolute; - top: 20px; - left: 20px; + // position: absolute; + // top: 20px; + // left: 20px; border-radius: 4px; // default bg background-color: rgb(37, 161, 255); + // transform-origin: center; } // Bezier editor diff --git a/src/client/views/nodes/trails/PresBox.tsx b/src/client/views/nodes/trails/PresBox.tsx index d6bfda54f..2d93f8656 100644 --- a/src/client/views/nodes/trails/PresBox.tsx +++ b/src/client/views/nodes/trails/PresBox.tsx @@ -2301,7 +2301,7 @@ export class PresBox extends ViewBoxBaseComponent() { }); }}> -
+
))} -- cgit v1.2.3-70-g09d2 From 90016b133395c93f897c614ffee761b6da587e0f Mon Sep 17 00:00:00 2001 From: Sophie Zhang Date: Tue, 30 Apr 2024 18:29:08 -0400 Subject: pre deleting unneeded --- src/client/views/nodes/trails/PresBox.scss | 6 ++++++ src/client/views/nodes/trails/PresBox.tsx | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) (limited to 'src/client/views/nodes/trails/PresBox.scss') diff --git a/src/client/views/nodes/trails/PresBox.scss b/src/client/views/nodes/trails/PresBox.scss index 2c56cf698..58c9b0b42 100644 --- a/src/client/views/nodes/trails/PresBox.scss +++ b/src/client/views/nodes/trails/PresBox.scss @@ -38,6 +38,12 @@ // Effect Animations +.presBox-effects { + display: grid; + grid-template-columns: auto auto; + gap: 8px; +} + .presBox-effect-row { display: flex; gap: 8px; diff --git a/src/client/views/nodes/trails/PresBox.tsx b/src/client/views/nodes/trails/PresBox.tsx index 2d93f8656..cf97dee1a 100644 --- a/src/client/views/nodes/trails/PresBox.tsx +++ b/src/client/views/nodes/trails/PresBox.tsx @@ -2286,7 +2286,7 @@ export class PresBox extends ViewBoxBaseComponent() {
{/* Preview Animations */} -
+
{this.generatedAnimations.map((elem, i) => (
Date: Tue, 14 May 2024 13:37:58 -0400 Subject: cleaning, bug fixing --- src/client/views/PropertiesView.tsx | 3 + .../views/nodes/trails/CubicBezierEditor.tsx | 95 ++--- src/client/views/nodes/trails/PresBox.scss | 10 +- src/client/views/nodes/trails/PresBox.tsx | 466 ++++++++++----------- src/client/views/nodes/trails/PresElementBox.tsx | 3 +- src/client/views/nodes/trails/SlideEffect.scss | 5 - src/client/views/nodes/trails/SlideEffect.tsx | 5 +- .../views/nodes/trails/SlideEffectPreview.tsx | 94 ----- 8 files changed, 273 insertions(+), 408 deletions(-) delete mode 100644 src/client/views/nodes/trails/SlideEffectPreview.tsx (limited to 'src/client/views/nodes/trails/PresBox.scss') diff --git a/src/client/views/PropertiesView.tsx b/src/client/views/PropertiesView.tsx index 15974b9a7..a95477749 100644 --- a/src/client/views/PropertiesView.tsx +++ b/src/client/views/PropertiesView.tsx @@ -1675,6 +1675,9 @@ export class PropertiesView extends ObservableReactComponent
Presentation +
window.open('https://brown-dash.github.io/Dash-Documentation/features/trails/')}> + } color={SettingsManager.userColor} /> +
{this.editableTitle} diff --git a/src/client/views/nodes/trails/CubicBezierEditor.tsx b/src/client/views/nodes/trails/CubicBezierEditor.tsx index e12fca20c..aba777e55 100644 --- a/src/client/views/nodes/trails/CubicBezierEditor.tsx +++ b/src/client/views/nodes/trails/CubicBezierEditor.tsx @@ -1,5 +1,4 @@ import React, { useEffect, useState } from 'react'; -import { StrCast } from '../../../../fields/Types'; type Props = { setFunc: (newPoints: { p1: number[]; p2: number[] }) => void; @@ -23,15 +22,14 @@ export const TIMING_DEFAULT_MAPPINGS = { const CubicBezierEditor = ({ setFunc, currPoints, easeFunc }: Props) => { const [animating, setAnimating] = useState(false); - // Should let parent control state - const [cPoints, setCPoints] = useState( - currPoints - ? currPoints - : { - p1: [0.25, 0.1], - p2: [0.25, 1.0], - } - ); + // const [cPoints, setCPoints] = useState( + // currPoints + // ? currPoints + // : { + // p1: [0.25, 0.1], + // p2: [0.25, 1.0], + // } + // ); const [c1Down, setC1Down] = useState(false); const [c2Down, setC2Down] = useState(false); @@ -73,11 +71,11 @@ const CubicBezierEditor = ({ setFunc, currPoints, easeFunc }: Props) => { }; }; - useEffect(() => { - if (!easeFunc.startsWith('cubic')) { - setCPoints(convertToPoints(easeFunc)); - } - }, [easeFunc]); + // useEffect(() => { + // if (!easeFunc.startsWith('cubic')) { + // setFunc(convertToPoints(easeFunc)); + // } + // }, [easeFunc]); useEffect(() => { if (animating) { @@ -93,25 +91,25 @@ const CubicBezierEditor = ({ setFunc, currPoints, easeFunc }: Props) => { setC1Down(false); }); const handlePointerMove = (e: PointerEvent) => { - const newX = cPoints.p1[0] + e.movementX / EDITOR_WIDTH; + const newX = currPoints.p1[0] + e.movementX / EDITOR_WIDTH; if (newX < 0 || newX > 1) { return; } - setCPoints(prev => ({ - ...prev, - p1: [roundToHundredth(prev.p1[0] + e.movementX / EDITOR_WIDTH), roundToHundredth(prev.p1[1] - e.movementY / EDITOR_WIDTH)], - })); + // setCPoints(prev => ({ + // ...prev, + // p1: [roundToHundredth(prev.p1[0] + e.movementX / EDITOR_WIDTH), roundToHundredth(prev.p1[1] - e.movementY / EDITOR_WIDTH)], + // })); setFunc({ - ...cPoints, - p1: [roundToHundredth(cPoints.p1[0] + e.movementX / EDITOR_WIDTH), roundToHundredth(cPoints.p1[1] - e.movementY / EDITOR_WIDTH)], + ...currPoints, + p1: [roundToHundredth(currPoints.p1[0] + e.movementX / EDITOR_WIDTH), roundToHundredth(currPoints.p1[1] - e.movementY / EDITOR_WIDTH)], }); }; window.addEventListener('pointermove', handlePointerMove); return () => window.removeEventListener('pointermove', handlePointerMove); - }, [c1Down, cPoints]); + }, [c1Down, currPoints]); useEffect(() => { if (!c2Down) return; @@ -119,38 +117,31 @@ const CubicBezierEditor = ({ setFunc, currPoints, easeFunc }: Props) => { setC2Down(false); }); const handlePointerMove = (e: PointerEvent) => { - const newX = cPoints.p2[0] + e.movementX / EDITOR_WIDTH; + const newX = currPoints.p2[0] + e.movementX / EDITOR_WIDTH; if (newX < 0 || newX > 1) { return; } - setCPoints(prev => ({ - ...prev, - p2: [roundToHundredth(prev.p2[0] + e.movementX / EDITOR_WIDTH), roundToHundredth(prev.p2[1] - e.movementY / EDITOR_WIDTH)], - })); + // setCPoints(prev => ({ + // ...prev, + // p2: [roundToHundredth(prev.p2[0] + e.movementX / EDITOR_WIDTH), roundToHundredth(prev.p2[1] - e.movementY / EDITOR_WIDTH)], + // })); setFunc({ - ...cPoints, - p2: [roundToHundredth(cPoints.p2[0] + e.movementX / EDITOR_WIDTH), roundToHundredth(cPoints.p2[1] - e.movementY / EDITOR_WIDTH)], + ...currPoints, + p2: [roundToHundredth(currPoints.p2[0] + e.movementX / EDITOR_WIDTH), roundToHundredth(currPoints.p2[1] - e.movementY / EDITOR_WIDTH)], }); }; window.addEventListener('pointermove', handlePointerMove); return () => window.removeEventListener('pointermove', handlePointerMove); - }, [c2Down, cPoints]); + }, [c2Down, currPoints]); return (
{ - // e.stopPropagation; - // }} onPointerMove={e => { e.stopPropagation; - }} - // onPointerUp={e => { - // e.stopPropagation; - // }} - > + }}> {/* Outlines */} @@ -158,9 +149,9 @@ const CubicBezierEditor = ({ setFunc, currPoints, easeFunc }: Props) => { {/* Editor */} @@ -174,15 +165,15 @@ const CubicBezierEditor = ({ setFunc, currPoints, easeFunc }: Props) => { }} x1={`${0 + OFFSET}`} y1={`${EDITOR_WIDTH + OFFSET}`} - x2={`${cPoints.p1[0] * EDITOR_WIDTH + OFFSET}`} - y2={`${EDITOR_WIDTH - cPoints.p1[1] * EDITOR_WIDTH + OFFSET}`} + x2={`${currPoints.p1[0] * EDITOR_WIDTH + OFFSET}`} + y2={`${EDITOR_WIDTH - currPoints.p1[1] * EDITOR_WIDTH + OFFSET}`} stroke="#00000000" strokeWidth="5" /> - + { @@ -204,15 +195,15 @@ const CubicBezierEditor = ({ setFunc, currPoints, easeFunc }: Props) => { }} x1={`${EDITOR_WIDTH + OFFSET}`} y1={`${0 + OFFSET}`} - x2={`${cPoints.p2[0] * EDITOR_WIDTH + OFFSET}`} - y2={`${EDITOR_WIDTH - cPoints.p2[1] * EDITOR_WIDTH + OFFSET}`} + x2={`${currPoints.p2[0] * EDITOR_WIDTH + OFFSET}`} + y2={`${EDITOR_WIDTH - currPoints.p2[1] * EDITOR_WIDTH + OFFSET}`} stroke="#00000000" strokeWidth="5" /> - + { diff --git a/src/client/views/nodes/trails/PresBox.scss b/src/client/views/nodes/trails/PresBox.scss index 58c9b0b42..60d4e580d 100644 --- a/src/client/views/nodes/trails/PresBox.scss +++ b/src/client/views/nodes/trails/PresBox.scss @@ -1,7 +1,7 @@ @import '../../global/globalCssVariables.module.scss'; .presBox-gpt-chat { - padding: 8px; + padding: 16px; display: flex; flex-direction: column; gap: 1rem; @@ -53,13 +53,11 @@ .presBox-effect-container { cursor: pointer; overflow: hidden; - // position: relative; width: 80px; height: 80px; display: flex; justify-content: center; align-items: center; - /* background-color: #1f2028; */ border: 1px solid rgb(118, 118, 118); border-radius: 8px; } @@ -67,13 +65,9 @@ .presBox-effect-demo-box { width: 40px; height: 40px; - // position: absolute; - // top: 20px; - // left: 20px; border-radius: 4px; // default bg background-color: rgb(37, 161, 255); - // transform-origin: center; } // Bezier editor @@ -95,7 +89,7 @@ display: flex; flex-direction: column; gap: 1rem; - // padding: 8px; + padding: 16px; } .presBox-option-center { diff --git a/src/client/views/nodes/trails/PresBox.tsx b/src/client/views/nodes/trails/PresBox.tsx index 4890c115b..02233d241 100644 --- a/src/client/views/nodes/trails/PresBox.tsx +++ b/src/client/views/nodes/trails/PresBox.tsx @@ -47,9 +47,9 @@ import { DictationManager } from '../../../util/DictationManager'; import CubicBezierEditor, { TIMING_DEFAULT_MAPPINGS } from './CubicBezierEditor'; import Slider from '@mui/material/Slider'; import { FaArrowDown, FaArrowLeft, FaArrowRight, FaArrowUp, FaCompressArrowsAlt } from 'react-icons/fa'; -import SpringAnimationPreview from './SlideEffectPreview'; import { effectTimings, SpringType, springMappings, effectItems, easeItems, movementItems, SpringSettings, presEffectDefaultTimings, AnimationSettings, springPreviewColors } from './SpringUtils'; import SlideEffect from './SlideEffect'; +import { IoMdInformationCircleOutline } from 'react-icons/io'; export interface pinDataTypes { scrollable?: boolean; @@ -387,24 +387,6 @@ export class PresBox extends ViewBoxBaseComponent() { setDictationContent = (value: string) => { console.log('Dictation value', value); this.setChatInput(value); - // // Get the current cursor position - // if (!this._inputref) return; - // const cursorPosition = this._inputref.selectionStart; - // const currentValue = this.chatInput; - - // // split before and after - // const textBeforeCursor = currentValue.slice(0, cursorPosition); - // const textAfterCursor = currentValue.slice(cursorPosition); - - // // insertion - // const updatedText = textBeforeCursor + value + textAfterCursor; - - // // Update the textarea value - // this.setChatInput(updatedText); - - // // set new cursor pos - // const newCursorPosition = cursorPosition + value.length; - // this._inputref.setSelectionRange(newCursorPosition, newCursorPosition); }; @action @@ -415,7 +397,6 @@ export class PresBox extends ViewBoxBaseComponent() { try { const res = await getSlideTransitionSuggestions(this.animationChat); - console.log('GPT Result:', res); if (typeof res === 'string') { const resObj = JSON.parse(res); console.log('Parsed GPT Result ', resObj); @@ -448,11 +429,10 @@ export class PresBox extends ViewBoxBaseComponent() { } } } - console.log('current slide props', currSlideProperties); + console.log('current slide props ', currSlideProperties); try { const res = await gptTrailSlideCustomization(input, currSlideProperties); - console.log('GPT Result:', res); if (typeof res === 'string') { const resObj = JSON.parse(res); console.log('Parsed GPT Result ', resObj); @@ -1798,46 +1778,51 @@ export class PresBox extends ViewBoxBaseComponent() { let duration = activeItem.presentation_duration ? NumCast(activeItem.presentation_duration) / 1000 : 0; if (activeItem.type === DocumentType.AUDIO) duration = NumCast(activeItem.duration); return ( -
-
- Hide before presented
}> -
this.updateHideBefore(activeItem)}> - Hide before -
- - {'Hide while presented'}
}> -
this.updateHide(activeItem)}> - Hide -
- - {'Hide after presented'}
}> -
this.updateHideAfter(activeItem)}> - Hide after -
- +
+
+
+ Hide before presented
}> +
this.updateHideBefore(activeItem)}> + Hide before +
+ + {'Hide while presented'}
}> +
this.updateHide(activeItem)}> + Hide +
+ + {'Hide after presented'}
}> +
this.updateHideAfter(activeItem)}> + Hide after +
+ - {'Open in lightbox view'}
}> -
this.updateOpenDoc(activeItem)}> - Lightbox -
- - {/* Transition movement style
}> + {'Open in lightbox view'}
}> +
this.updateOpenDoc(activeItem)}> + Lightbox +
+ + {/* Transition movement style
}>
() { {`${StrCast(activeItem.presEaseFunc, 'ease')}`}
*/} -
- {[DocumentType.AUDIO, DocumentType.VID].includes(targetType as any as DocumentType) ? null : ( - <> -
-
Slide Duration
-
- e.stopPropagation()} onChange={e => this.updateDurationTime(e.target.value)} /> s -
- {/*
+
+ {[DocumentType.AUDIO, DocumentType.VID].includes(targetType as any as DocumentType) ? null : ( + <> +
+
Slide Duration
+
+ e.stopPropagation()} onChange={e => this.updateDurationTime(e.target.value)} /> s +
+ {/*
this.updateDurationTime(String(duration), 1000)}>
@@ -1861,15 +1846,16 @@ export class PresBox extends ViewBoxBaseComponent() {
*/} -
- {PresBox.inputter('0.1', '0.1', '20', duration, targetType !== DocumentType.AUDIO, this.updateDurationTime)} -
-
Short
-
Medium
-
Long
-
- - )} +
+ {PresBox.inputter('0.1', '0.1', '20', duration, targetType !== DocumentType.AUDIO, this.updateDurationTime)} +
+
Short
+
Medium
+
Long
+
+ + )} +
); } @@ -1887,74 +1873,76 @@ export class PresBox extends ViewBoxBaseComponent() {
); return ( -
-
-
Progressivize Collection
- { - activeItem.presentation_indexed = activeItem.presentation_indexed === undefined ? 0 : undefined; - activeItem.presentation_hideBefore = activeItem.presentation_indexed !== undefined; - const tagDoc = PresBox.targetRenderedDoc(this.activeItem); - const type = DocCast(tagDoc?.annotationOn)?.type ?? tagDoc.type; - activeItem.presentation_indexedStart = type === DocumentType.COL ? 1 : 0; - // a progressivized slide doesn't have sub-slides, but rather iterates over the data list of the target being progressivized. - // to avoid creating a new slide to correspond to each of the target's data list, we create a computedField to refernce the target's data list. - let dataField = Doc.LayoutFieldKey(tagDoc); - if (Cast(tagDoc[dataField], listSpec(Doc), null)?.filter(d => d instanceof Doc) === undefined) dataField = dataField + '_annotations'; - - if (DocCast(activeItem.presentation_targetDoc).annotationOn) activeItem.data = ComputedField.MakeFunction(`this.presentation_targetDoc.annotationOn?.["${dataField}"]`); - else activeItem.data = ComputedField.MakeFunction(`this.presentation_targetDoc?.["${dataField}"]`); - }} - checked={Cast(activeItem.presentation_indexed, 'number', null) !== undefined ? true : false} - /> -
-
-
Progressivize First Bullet
- (activeItem.presentation_indexedStart = activeItem.presentation_indexedStart ? 0 : 1)} - checked={!NumCast(activeItem.presentation_indexedStart)} - /> -
-
-
Expand Current Bullet
- (activeItem.presBulletExpand = !activeItem.presBulletExpand)} - checked={BoolCast(activeItem.presBulletExpand)} - /> -
+
+
+
+
Progressivize Collection
+ { + activeItem.presentation_indexed = activeItem.presentation_indexed === undefined ? 0 : undefined; + activeItem.presentation_hideBefore = activeItem.presentation_indexed !== undefined; + const tagDoc = PresBox.targetRenderedDoc(this.activeItem); + const type = DocCast(tagDoc?.annotationOn)?.type ?? tagDoc.type; + activeItem.presentation_indexedStart = type === DocumentType.COL ? 1 : 0; + // a progressivized slide doesn't have sub-slides, but rather iterates over the data list of the target being progressivized. + // to avoid creating a new slide to correspond to each of the target's data list, we create a computedField to refernce the target's data list. + let dataField = Doc.LayoutFieldKey(tagDoc); + if (Cast(tagDoc[dataField], listSpec(Doc), null)?.filter(d => d instanceof Doc) === undefined) dataField = dataField + '_annotations'; + + if (DocCast(activeItem.presentation_targetDoc).annotationOn) activeItem.data = ComputedField.MakeFunction(`this.presentation_targetDoc.annotationOn?.["${dataField}"]`); + else activeItem.data = ComputedField.MakeFunction(`this.presentation_targetDoc?.["${dataField}"]`); + }} + checked={Cast(activeItem.presentation_indexed, 'number', null) !== undefined ? true : false} + /> +
+
+
Progressivize First Bullet
+ (activeItem.presentation_indexedStart = activeItem.presentation_indexedStart ? 0 : 1)} + checked={!NumCast(activeItem.presentation_indexedStart)} + /> +
+
+
Expand Current Bullet
+ (activeItem.presBulletExpand = !activeItem.presBulletExpand)} + checked={BoolCast(activeItem.presBulletExpand)} + /> +
-
- Bullet Effect -
{ - e.stopPropagation(); - this._openBulletEffectDropdown = !this._openBulletEffectDropdown; - })} - style={{ - color: SettingsManager.userColor, - background: SettingsManager.userVariantColor, - borderBottomLeftRadius: this._openBulletEffectDropdown ? 0 : 5, - border: this._openBulletEffectDropdown ? `solid 2px ${SettingsManager.userVariantColor}` : `solid 1px ${SettingsManager.userColor}`, - }}> - {effect?.toString()} - +
+ Bullet Effect
e.stopPropagation()}> - {Object.values(PresEffect) - .filter(v => isNaN(Number(v))) - .map(effect => bulletEffect(effect))} + className="presBox-dropdown" + onClick={action(e => { + e.stopPropagation(); + this._openBulletEffectDropdown = !this._openBulletEffectDropdown; + })} + style={{ + color: SettingsManager.userColor, + background: SettingsManager.userVariantColor, + borderBottomLeftRadius: this._openBulletEffectDropdown ? 0 : 5, + border: this._openBulletEffectDropdown ? `solid 2px ${SettingsManager.userVariantColor}` : `solid 1px ${SettingsManager.userColor}`, + }}> + {effect?.toString()} + +
e.stopPropagation()}> + {Object.values(PresEffect) + .filter(v => isNaN(Number(v))) + .map(effect => bulletEffect(effect))} +
@@ -2016,22 +2004,27 @@ export class PresBox extends ViewBoxBaseComponent() { if (activeItem && this.targetDoc) { const transitionSpeed = activeItem.presentation_transition ? NumCast(activeItem.presentation_transition) / 1000 : 0.5; const zoom = NumCast(activeItem.config_zoom, 1) * 100; - const effect = activeItem.presentation_effect ? activeItem.presentation_effect : PresEffect.None; + const effect = StrCast(activeItem.presentation_effect) ? StrCast(activeItem.presentation_effect) : PresEffect.None; + const direction = StrCast(activeItem.presentation_effectDirection); return ( <> - {/* GPT Component */} - {/* This chatbox is for customizing the properties of trails, like transition time, movement type (zoom, pan) */} + {/* This chatbox is for customizing the properties of trails, like transition time, movement type (zoom, pan) using GPT*/}
-

Customize with GPT

+ + Customize Slide Properties{' '} +
window.open('https://brown-dash.github.io/Dash-Documentation/features/trails/')}> + } color={SettingsManager.userColor} /> +
+
(this._inputref = r)} - minRows={1} - placeholder="Customize..." + // ref={r => (this._inputref = r)} + // minRows={1} + placeholder="Describe how you would like to modify the slide properties." className="pres-chatbox" - autoFocus={true} + // autoFocus={true} value={this.chatInput} onChange={e => { this.setChatInput(e.target.value); @@ -2079,7 +2072,10 @@ export class PresBox extends ViewBoxBaseComponent() { this._openEffectDropdown = false; this._openBulletEffectDropdown = false; })}> -
+
Movement () {
this.updateZoom(e.target.value)} />%
- {/*
-
this.updateZoom(String(zoom), 0.1)}> - -
-
this.updateZoom(String(zoom), -0.1)}> - -
-
*/}
{PresBox.inputter('0', '1', '100', zoom, activeItem.presentation_movement === PresMovement.Zoom, this.updateZoom)}
@@ -2113,14 +2101,6 @@ export class PresBox extends ViewBoxBaseComponent() {
e.stopPropagation()} onChange={action(e => this.updateTransitionTime(e.target.value))} /> s
- {/*
-
this.updateTransitionTime(String(transitionSpeed), 1000)}> - -
-
this.updateTransitionTime(String(transitionSpeed), -1000)}> - -
-
*/}
{PresBox.inputter('0.1', '0.1', '10', transitionSpeed, true, this.updateTransitionTime)}
@@ -2129,61 +2109,59 @@ export class PresBox extends ViewBoxBaseComponent() {
Slow
{/* Easing function */} -
- { - if (typeof val === 'string') { - if (val !== 'custom') { - this.setBezierEditorVisibility(true); - this.setEaseFunc(this.activeItem, val); - } else { - this.setEaseFunc(this.activeItem, TIMING_DEFAULT_MAPPINGS.ease); - } + { + if (typeof val === 'string') { + if (val !== 'custom') { + this.setBezierEditorVisibility(true); + this.setEaseFunc(this.activeItem, val); + } else { + this.setEaseFunc(this.activeItem, TIMING_DEFAULT_MAPPINGS.ease); } - }} - dropdownType={DropdownType.SELECT} - type={Type.TERT} - /> - {/* Custom */} -
{ - e.stopPropagation(); - this.setBezierEditorVisibility(!this.showBezierEditor); - }}> - {`${this.showBezierEditor ? 'Hide' : 'Show'} Timing Editor`} - -
+ } + }} + dropdownType={DropdownType.SELECT} + type={Type.TERT} + /> + {/* Custom */} +
{ + e.stopPropagation(); + this.setBezierEditorVisibility(!this.showBezierEditor); + }}> + {`${this.showBezierEditor ? 'Hide' : 'Show'} Timing Editor`} +
-
- {this.showBezierEditor && ( - <> -

- Custom Timing Function -

- - - )} -
+ + {this.showBezierEditor && ( +
+

+ Custom Timing Function +

+ +
+ )} + {/* This chatbox is for getting slide effect transition suggestions from gpt and visualizing them */}
Effects
(this._inputref2 = r)} - minRows={1} - placeholder="Get effect suggestions..." + // ref={r => (this._inputref2 = r)} + // minRows={1} + placeholder="Customize prompt for effect suggestions. Leave blank for random results." className="pres-chatbox" - autoFocus={true} + // autoFocus={true} value={this.animationChat} onChange={e => { this.setAnimationChat(e.target.value); @@ -2217,10 +2195,9 @@ export class PresBox extends ViewBoxBaseComponent() { this._openEffectDropdown = false; this._openBulletEffectDropdown = false; })}> -
+
+ Click on a box to apply the effect.
- {/* Chat for idea generation */} - {/* Preview Animations */}
{this.generatedAnimations.map((elem, i) => ( @@ -2269,13 +2246,6 @@ export class PresBox extends ViewBoxBaseComponent() {
- {/* } - onClick={() => this.updateEffectDirection(PresEffectDirection.Center)} - /> */} () { valueLabelDisplay="auto" />
- -
-
+ Preview Effect +
+
+ +
+
+
+
)} @@ -2405,26 +2380,23 @@ export class PresBox extends ViewBoxBaseComponent() {
{/* Toggles */} - (activeItem.presPlayAudio = !BoolCast(activeItem.presPlayAudio))} - color={SettingsManager.userColor} - /> - (activeItem.presentation_zoomText = !BoolCast(activeItem.presentation_zoomText))} - color={SettingsManager.userColor} - /> -
); diff --git a/src/client/views/nodes/trails/PresElementBox.tsx b/src/client/views/nodes/trails/PresElementBox.tsx index 268b1c803..1c6b38aeb 100644 --- a/src/client/views/nodes/trails/PresElementBox.tsx +++ b/src/client/views/nodes/trails/PresElementBox.tsx @@ -513,11 +513,12 @@ export class PresElementBox extends ViewBoxBaseComponent() { ); items.push( - Edit
}> + Customize Slide
}>
{ this.presBoxView?.regularSelect(this.slideDoc, this._itemRef.current!, this._dragRef.current!, true, false); + PresBox.Instance.navigateToActiveItem(); PresBox.Instance.openProperties(); PresBox.Instance.slideToModify = this.Document; }}> diff --git a/src/client/views/nodes/trails/SlideEffect.scss b/src/client/views/nodes/trails/SlideEffect.scss index cadda0ccc..cc851354e 100644 --- a/src/client/views/nodes/trails/SlideEffect.scss +++ b/src/client/views/nodes/trails/SlideEffect.scss @@ -7,10 +7,6 @@ .flip-side { position: absolute; - // max-width: 500px; - // max-height: 500px; - // width: 350px; - // height: 200px; will-change: transform, opacity; backface-visibility: hidden; } @@ -19,6 +15,5 @@ } .flip-back { - // Get the background color of node instead // background-color: rgb(223, 223, 223); } diff --git a/src/client/views/nodes/trails/SlideEffect.tsx b/src/client/views/nodes/trails/SlideEffect.tsx index e04f53f06..db2ac1ea0 100644 --- a/src/client/views/nodes/trails/SlideEffect.tsx +++ b/src/client/views/nodes/trails/SlideEffect.tsx @@ -27,7 +27,10 @@ const infiniteOptions = { delay: 500, }; -// TODO: add visibility detector when the slide comes into view +/** + * This component wraps around the doc to create an effect animation, and also wraps the preview animations + * for the effects as well. + */ export default function SpringAnimation({ doc, dir, friction, tension, mass, presEffect, children, infinite }: Props) { const [springs, api] = useSpring( () => ({ diff --git a/src/client/views/nodes/trails/SlideEffectPreview.tsx b/src/client/views/nodes/trails/SlideEffectPreview.tsx deleted file mode 100644 index d4c16586a..000000000 --- a/src/client/views/nodes/trails/SlideEffectPreview.tsx +++ /dev/null @@ -1,94 +0,0 @@ -import { useSpring, animated, easings } from '@react-spring/web'; -import React, { useEffect, useState } from 'react'; - -interface Props { - friction: number; - tension: number; - mass: number; - children: React.ReactNode; -} - -export default function SpringAnimationPreview({ friction, tension, mass, children }: Props) { - const [springs, api] = useSpring( - () => ({ - from: { - x: 0, - y: 0, - opacity: 1, - scale: 1, - }, - config: { - tension: tension, - friction: friction, - mass: mass, - }, - onStart: () => { - // console.log('started'); - }, - onRest: () => { - // console.log('resting'); - }, - }), - [tension, friction, mass] - ); - - // Whether the animation is currently playing - const [animating, setAnimating] = useState(false); - - const bounceConfig = { - from: { - x: -50, - y: 0, - }, - to: [ - { - x: 50, - y: 0, - config: { - tension: tension, - friction: friction, - mass: mass, - }, - }, - { - x: -50, - y: 0, - config: { - duration: 500, - easing: easings.easeInOutCubic, - }, - }, - ], - }; - - const animate = () => { - api.start(bounceConfig); - }; - - useEffect(() => { - animate(); - }, []); - - return ( -
{ - animate(); - }}> - - {children} - -
- ); -} -- cgit v1.2.3-70-g09d2