diff --git a/package-lock.json b/package-lock.json index 973fd5032..25ebc440f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -4285,22 +4285,22 @@ } }, "node_modules/@microsoft/api-extractor": { - "version": "7.34.2", - "resolved": "https://registry.npmjs.org/@microsoft/api-extractor/-/api-extractor-7.34.2.tgz", - "integrity": "sha512-oREyUU7p3JgjrqapJxEHe83gA1SXOWgaA4XCiY9PvsiLkgGHtn2ibTRgw9GCI/4kZzcb+OQv5waUDxsnQSKfwQ==", + "version": "7.36.4", + "resolved": "https://registry.npmjs.org/@microsoft/api-extractor/-/api-extractor-7.36.4.tgz", + "integrity": "sha512-21UECq8C/8CpHT23yiqTBQ10egKUacIpxkPyYR7hdswo/M5yTWdBvbq+77YC9uPKQJOUfOD1FImBQ1DzpsdeQQ==", "dependencies": { - "@microsoft/api-extractor-model": "7.26.2", + "@microsoft/api-extractor-model": "7.27.6", "@microsoft/tsdoc": "0.14.2", "@microsoft/tsdoc-config": "~0.16.1", - "@rushstack/node-core-library": "3.55.0", - "@rushstack/rig-package": "0.3.17", - "@rushstack/ts-command-line": "4.13.1", + "@rushstack/node-core-library": "3.59.7", + "@rushstack/rig-package": "0.4.1", + "@rushstack/ts-command-line": "4.15.2", "colors": "~1.2.1", "lodash": "~4.17.15", "resolve": "~1.22.1", - "semver": "~7.3.0", + "semver": "~7.5.4", "source-map": "~0.6.1", - "typescript": "~4.8.4" + "typescript": "~5.0.4" }, "bin": { "api-extractor": "bin/api-extractor" @@ -4374,75 +4374,64 @@ "node": ">= 4.0.0" } }, - "node_modules/@microsoft/api-extractor/node_modules/@rushstack/node-core-library": { - "version": "3.55.0", - "resolved": "https://registry.npmjs.org/@rushstack/node-core-library/-/node-core-library-3.55.0.tgz", - "integrity": "sha512-6lSel8w3DeGaD/JCKw64wfezEBijlCQlMwBoYg9Ci5VPy+dZ+FpBkIBrY8mi3Ge4xNzr4gyTbQ5XEt0QP1Kv/w==", + "node_modules/@microsoft/api-extractor/node_modules/@microsoft/api-extractor-model": { + "version": "7.27.6", + "resolved": "https://registry.npmjs.org/@microsoft/api-extractor-model/-/api-extractor-model-7.27.6.tgz", + "integrity": "sha512-eiCnlayyum1f7fS2nA9pfIod5VCNR1G+Tq84V/ijDrKrOFVa598BLw145nCsGDMoFenV6ajNi2PR5WCwpAxW6Q==", + "dependencies": { + "@microsoft/tsdoc": "0.14.2", + "@microsoft/tsdoc-config": "~0.16.1", + "@rushstack/node-core-library": "3.59.7" + } + }, + "node_modules/@microsoft/api-extractor/node_modules/@rushstack/ts-command-line": { + "version": "4.15.2", + "resolved": "https://registry.npmjs.org/@rushstack/ts-command-line/-/ts-command-line-4.15.2.tgz", + "integrity": "sha512-5+C2uoJY8b+odcZD6coEe2XNC4ZjGB4vCMESbqW/8DHRWC/qIHfANdmN9F1wz/lAgxz72i7xRoVtPY2j7e4gpQ==", "dependencies": { + "@types/argparse": "1.0.38", + "argparse": "~1.0.9", "colors": "~1.2.1", - "fs-extra": "~7.0.1", - "import-lazy": "~4.0.0", - "jju": "~1.4.0", - "resolve": "~1.22.1", - "semver": "~7.3.0", - "z-schema": "~5.0.2" - }, - "peerDependencies": { - "@types/node": "^14.18.36" - }, - "peerDependenciesMeta": { - "@types/node": { - "optional": true - } + "string-argv": "~0.3.1" } }, - "node_modules/@microsoft/api-extractor/node_modules/@types/node": { - "version": "14.18.36", - "resolved": "https://registry.npmjs.org/@types/node/-/node-14.18.36.tgz", - "integrity": "sha512-FXKWbsJ6a1hIrRxv+FoukuHnGTgEzKYGi7kilfMae96AL9UNkPFNWJEEYWzdRI9ooIkbr4AKldyuSTLql06vLQ==", - "optional": true, - "peer": true + "node_modules/@microsoft/api-extractor/node_modules/argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "dependencies": { + "sprintf-js": "~1.0.2" + } }, - "node_modules/@microsoft/api-extractor/node_modules/fs-extra": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-7.0.1.tgz", - "integrity": "sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw==", + "node_modules/@microsoft/api-extractor/node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", "dependencies": { - "graceful-fs": "^4.1.2", - "jsonfile": "^4.0.0", - "universalify": "^0.1.0" + "yallist": "^4.0.0" }, "engines": { - "node": ">=6 <7 || >=8" - } - }, - "node_modules/@microsoft/api-extractor/node_modules/jsonfile": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", - "integrity": "sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==", - "optionalDependencies": { - "graceful-fs": "^4.1.6" + "node": ">=10" } }, - "node_modules/@microsoft/api-extractor/node_modules/typescript": { - "version": "4.8.4", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.8.4.tgz", - "integrity": "sha512-QCh+85mCy+h0IGff8r5XWzOVSbBO+KfeYrMQh7NJ58QujwcE22u+NUSmUxqF+un70P9GXKxa2HCNiTTMJknyjQ==", + "node_modules/@microsoft/api-extractor/node_modules/semver": { + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "dependencies": { + "lru-cache": "^6.0.0" + }, "bin": { - "tsc": "bin/tsc", - "tsserver": "bin/tsserver" + "semver": "bin/semver.js" }, "engines": { - "node": ">=4.2.0" + "node": ">=10" } }, - "node_modules/@microsoft/api-extractor/node_modules/universalify": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", - "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", - "engines": { - "node": ">= 4.0.0" - } + "node_modules/@microsoft/api-extractor/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" }, "node_modules/@microsoft/tsdoc": { "version": "0.14.2", @@ -5052,24 +5041,94 @@ "resolved": "https://registry.npmjs.org/@rushstack/eslint-patch/-/eslint-patch-1.2.0.tgz", "integrity": "sha512-sXo/qW2/pAcmT43VoRKOJbDOfV3cYpq3szSVfIThQXNt+E4DfKj361vaAt3c88U5tPUxzEswam7GW48PJqtKAg==" }, - "node_modules/@rushstack/rig-package": { - "version": "0.3.17", - "resolved": "https://registry.npmjs.org/@rushstack/rig-package/-/rig-package-0.3.17.tgz", - "integrity": "sha512-nxvAGeIMnHl1LlZSQmacgcRV4y1EYtgcDIrw6KkeVjudOMonlxO482PhDj3LVZEp6L7emSf6YSO2s5JkHlwfZA==", + "node_modules/@rushstack/node-core-library": { + "version": "3.59.7", + "resolved": "https://registry.npmjs.org/@rushstack/node-core-library/-/node-core-library-3.59.7.tgz", + "integrity": "sha512-ln1Drq0h+Hwa1JVA65x5mlSgUrBa1uHL+V89FqVWQgXd1vVIMhrtqtWGQrhTnFHxru5ppX+FY39VWELF/FjQCw==", "dependencies": { - "resolve": "~1.17.0", - "strip-json-comments": "~3.1.1" + "colors": "~1.2.1", + "fs-extra": "~7.0.1", + "import-lazy": "~4.0.0", + "jju": "~1.4.0", + "resolve": "~1.22.1", + "semver": "~7.5.4", + "z-schema": "~5.0.2" + }, + "peerDependencies": { + "@types/node": "*" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + } } }, - "node_modules/@rushstack/rig-package/node_modules/resolve": { - "version": "1.17.0", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.17.0.tgz", - "integrity": "sha512-ic+7JYiV8Vi2yzQGFWOkiZD5Z9z7O2Zhm9XMaTxdJExKasieFCr+yXZ/WmXsckHiKl12ar0y6XiXDx3m4RHn1w==", + "node_modules/@rushstack/node-core-library/node_modules/fs-extra": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-7.0.1.tgz", + "integrity": "sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw==", "dependencies": { - "path-parse": "^1.0.6" + "graceful-fs": "^4.1.2", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "engines": { + "node": ">=6 <7 || >=8" + } + }, + "node_modules/@rushstack/node-core-library/node_modules/jsonfile": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", + "integrity": "sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==", + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/@rushstack/node-core-library/node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@rushstack/node-core-library/node_modules/semver": { + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@rushstack/node-core-library/node_modules/universalify": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", + "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", + "engines": { + "node": ">= 4.0.0" + } + }, + "node_modules/@rushstack/node-core-library/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + }, + "node_modules/@rushstack/rig-package": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/@rushstack/rig-package/-/rig-package-0.4.1.tgz", + "integrity": "sha512-AGRwpqlXNSp9LhUSz4HKI9xCluqQDt/obsQFdv/NYIekF3pTTPzc+HbQsIsjVjYnJ3DcmxOREVMhvrMEjpiq6g==", + "dependencies": { + "resolve": "~1.22.1", + "strip-json-comments": "~3.1.1" } }, "node_modules/@rushstack/ts-command-line": { @@ -6493,6 +6552,128 @@ "vite": "^4.2.0" } }, + "node_modules/@volar/language-core": { + "version": "1.10.1", + "resolved": "https://registry.npmjs.org/@volar/language-core/-/language-core-1.10.1.tgz", + "integrity": "sha512-JnsM1mIPdfGPxmoOcK1c7HYAsL6YOv0TCJ4aW3AXPZN/Jb4R77epDyMZIVudSGjWMbvv/JfUa+rQ+dGKTmgwBA==", + "dev": true, + "dependencies": { + "@volar/source-map": "1.10.1" + } + }, + "node_modules/@volar/source-map": { + "version": "1.10.1", + "resolved": "https://registry.npmjs.org/@volar/source-map/-/source-map-1.10.1.tgz", + "integrity": "sha512-3/S6KQbqa7pGC8CxPrg69qHLpOvkiPHGJtWPkI/1AXCsktkJ6gIk/5z4hyuMp8Anvs6eS/Kvp/GZa3ut3votKA==", + "dev": true, + "dependencies": { + "muggle-string": "^0.3.1" + } + }, + "node_modules/@volar/typescript": { + "version": "1.10.1", + "resolved": "https://registry.npmjs.org/@volar/typescript/-/typescript-1.10.1.tgz", + "integrity": "sha512-+iiO9yUSRHIYjlteT+QcdRq8b44qH19/eiUZtjNtuh6D9ailYM7DVR0zO2sEgJlvCaunw/CF9Ov2KooQBpR4VQ==", + "dev": true, + "dependencies": { + "@volar/language-core": "1.10.1" + } + }, + "node_modules/@vue/compiler-core": { + "version": "3.3.4", + "resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.3.4.tgz", + "integrity": "sha512-cquyDNvZ6jTbf/+x+AgM2Arrp6G4Dzbb0R64jiG804HRMfRiFXWI6kqUVqZ6ZR0bQhIoQjB4+2bhNtVwndW15g==", + "dev": true, + "dependencies": { + "@babel/parser": "^7.21.3", + "@vue/shared": "3.3.4", + "estree-walker": "^2.0.2", + "source-map-js": "^1.0.2" + } + }, + "node_modules/@vue/compiler-dom": { + "version": "3.3.4", + "resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.3.4.tgz", + "integrity": "sha512-wyM+OjOVpuUukIq6p5+nwHYtj9cFroz9cwkfmP9O1nzH68BenTTv0u7/ndggT8cIQlnBeOo6sUT/gvHcIkLA5w==", + "dev": true, + "dependencies": { + "@vue/compiler-core": "3.3.4", + "@vue/shared": "3.3.4" + } + }, + "node_modules/@vue/language-core": { + "version": "1.8.8", + "resolved": "https://registry.npmjs.org/@vue/language-core/-/language-core-1.8.8.tgz", + "integrity": "sha512-i4KMTuPazf48yMdYoebTkgSOJdFraE4pQf0B+FTOFkbB+6hAfjrSou/UmYWRsWyZV6r4Rc6DDZdI39CJwL0rWw==", + "dev": true, + "dependencies": { + "@volar/language-core": "~1.10.0", + "@volar/source-map": "~1.10.0", + "@vue/compiler-dom": "^3.3.0", + "@vue/reactivity": "^3.3.0", + "@vue/shared": "^3.3.0", + "minimatch": "^9.0.0", + "muggle-string": "^0.3.1", + "vue-template-compiler": "^2.7.14" + }, + "peerDependencies": { + "typescript": "*" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@vue/language-core/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/@vue/language-core/node_modules/minimatch": { + "version": "9.0.3", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", + "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", + "dev": true, + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@vue/reactivity": { + "version": "3.3.4", + "resolved": "https://registry.npmjs.org/@vue/reactivity/-/reactivity-3.3.4.tgz", + "integrity": "sha512-kLTDLwd0B1jG08NBF3R5rqULtv/f8x3rOFByTDz4J53ttIQEDmALqKqXY0J+XQeN0aV2FBxY8nJDf88yvOPAqQ==", + "dev": true, + "dependencies": { + "@vue/shared": "3.3.4" + } + }, + "node_modules/@vue/shared": { + "version": "3.3.4", + "resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.3.4.tgz", + "integrity": "sha512-7OjdcV8vQ74eiz1TZLzZP4JwqM5fA94K6yntPS5Z25r9HDuGNzaGdgvwKYq6S+MxwF0TFRwe50fIR/MYnakdkQ==", + "dev": true + }, + "node_modules/@vue/typescript": { + "version": "1.8.8", + "resolved": "https://registry.npmjs.org/@vue/typescript/-/typescript-1.8.8.tgz", + "integrity": "sha512-jUnmMB6egu5wl342eaUH236v8tdcEPXXkPgj+eI/F6JwW/lb+yAU6U07ZbQ3MVabZRlupIlPESB7ajgAGixhow==", + "dev": true, + "dependencies": { + "@volar/typescript": "~1.10.0", + "@vue/language-core": "1.8.8" + } + }, "node_modules/@webassemblyjs/ast": { "version": "1.11.1", "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.11.1.tgz", @@ -9455,6 +9636,12 @@ "node": ">=12" } }, + "node_modules/de-indent": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/de-indent/-/de-indent-1.0.2.tgz", + "integrity": "sha512-e/1zu3xH5MQryN2zdVaF0OrdNLUbvWxzMbi+iNA6Bky7l1RoP8a2fIbRocyHclXt/arDrrR6lL3TqFD9pMQTsg==", + "devOptional": true + }, "node_modules/debounce": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/debounce/-/debounce-1.2.1.tgz", @@ -15083,6 +15270,12 @@ "node": ">= 8" } }, + "node_modules/kolorist": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/kolorist/-/kolorist-1.8.0.tgz", + "integrity": "sha512-Y+60/zizpJ3HRH8DCss+q95yr6145JXZo46OTpFvDZWLfRCE4qChOyk1b26nMaNpfHHgxagk9dXT5OP0Tfe+dQ==", + "dev": true + }, "node_modules/language-subtag-registry": { "version": "0.3.22", "resolved": "https://registry.npmjs.org/language-subtag-registry/-/language-subtag-registry-0.3.22.tgz", @@ -15616,6 +15809,12 @@ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" }, + "node_modules/muggle-string": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/muggle-string/-/muggle-string-0.3.1.tgz", + "integrity": "sha512-ckmWDJjphvd/FvZawgygcUeQCxzvohjFO5RxTjj4eq8kw359gFF3E1brjfI+viLMxss5JrHTDRHZvu2/tuy0Qg==", + "dev": true + }, "node_modules/multicast-dns": { "version": "7.2.5", "resolved": "https://registry.npmjs.org/multicast-dns/-/multicast-dns-7.2.5.tgz", @@ -20297,6 +20496,41 @@ "randombytes": "^2.1.0" } }, + "node_modules/rollup-plugin-visualizer": { + "version": "5.9.2", + "resolved": "https://registry.npmjs.org/rollup-plugin-visualizer/-/rollup-plugin-visualizer-5.9.2.tgz", + "integrity": "sha512-waHktD5mlWrYFrhOLbti4YgQCn1uR24nYsNuXxg7LkPH8KdTXVWR9DNY1WU0QqokyMixVXJS4J04HNrVTMP01A==", + "dev": true, + "dependencies": { + "open": "^8.4.0", + "picomatch": "^2.3.1", + "source-map": "^0.7.4", + "yargs": "^17.5.1" + }, + "bin": { + "rollup-plugin-visualizer": "dist/bin/cli.js" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "rollup": "2.x || 3.x" + }, + "peerDependenciesMeta": { + "rollup": { + "optional": true + } + } + }, + "node_modules/rollup-plugin-visualizer/node_modules/source-map": { + "version": "0.7.4", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.4.tgz", + "integrity": "sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA==", + "dev": true, + "engines": { + "node": ">= 8" + } + }, "node_modules/run-applescript": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/run-applescript/-/run-applescript-5.0.0.tgz", @@ -22501,6 +22735,41 @@ } } }, + "node_modules/vite-plugin-css-injected-by-js": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/vite-plugin-css-injected-by-js/-/vite-plugin-css-injected-by-js-3.3.0.tgz", + "integrity": "sha512-xG+jyHNCmUqi/TXp6q88wTJGeAOrNLSyUUTp4qEQ9QZLGcHWQQsCsSSKa59rPMQr8sOzfzmWDd8enGqfH/dBew==", + "dev": true, + "peerDependencies": { + "vite": ">2.0.0-0" + } + }, + "node_modules/vite-plugin-dts": { + "version": "3.5.3", + "resolved": "https://registry.npmjs.org/vite-plugin-dts/-/vite-plugin-dts-3.5.3.tgz", + "integrity": "sha512-h94j/+SR1PhLR9jnEtcjZILagE2QZBAV8V1y3T2Ujcet1VI0Et4dZSU1W8fbnp6obB7B3/b8hArqdi2/9HuH+w==", + "dev": true, + "dependencies": { + "@microsoft/api-extractor": "^7.36.4", + "@rollup/pluginutils": "^5.0.2", + "@vue/language-core": "^1.8.8", + "debug": "^4.3.4", + "kolorist": "^1.8.0", + "vue-tsc": "^1.8.8" + }, + "engines": { + "node": "^14.18.0 || >=16.0.0" + }, + "peerDependencies": { + "typescript": "*", + "vite": "*" + }, + "peerDependenciesMeta": { + "vite": { + "optional": true + } + } + }, "node_modules/vite-plugin-svgr": { "version": "2.4.0", "resolved": "https://registry.npmjs.org/vite-plugin-svgr/-/vite-plugin-svgr-2.4.0.tgz", @@ -22802,6 +23071,33 @@ "pbf": "^3.2.1" } }, + "node_modules/vue-template-compiler": { + "version": "2.7.14", + "resolved": "https://registry.npmjs.org/vue-template-compiler/-/vue-template-compiler-2.7.14.tgz", + "integrity": "sha512-zyA5Y3ArvVG0NacJDkkzJuPQDF8RFeRlzV2vLeSnhSpieO6LK2OVbdLPi5MPPs09Ii+gMO8nY4S3iKQxBxDmWQ==", + "devOptional": true, + "dependencies": { + "de-indent": "^1.0.2", + "he": "^1.2.0" + } + }, + "node_modules/vue-tsc": { + "version": "1.8.8", + "resolved": "https://registry.npmjs.org/vue-tsc/-/vue-tsc-1.8.8.tgz", + "integrity": "sha512-bSydNFQsF7AMvwWsRXD7cBIXaNs/KSjvzWLymq/UtKE36697sboX4EccSHFVxvgdBlI1frYPc/VMKJNB7DFeDQ==", + "dev": true, + "dependencies": { + "@vue/language-core": "1.8.8", + "@vue/typescript": "1.8.8", + "semver": "^7.3.8" + }, + "bin": { + "vue-tsc": "bin/vue-tsc.js" + }, + "peerDependencies": { + "typescript": "*" + } + }, "node_modules/w3c-hr-time": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/w3c-hr-time/-/w3c-hr-time-1.0.2.tgz", @@ -23906,8 +24202,8 @@ "postcss": "^8.4.27", "react": "^18.2.0", "react-dom": "^18.2.0", - "vite": "^4.4.7", - "vite-plugin-svgr": "^2.4.0" + "zundo": "2.0.0-beta.12", + "zustand": "^4.3.2" }, "bin": { "studio": "lib/bin/studio.js" @@ -26114,6 +26410,8 @@ "react-tooltip": "^5.18.0", "tailwind-merge": "^1.8.1", "tailwindcss": "^3.3.3", + "vite": "^4.4.7", + "vite-plugin-svgr": "^2.4.0", "zundo": "2.0.0-beta.12", "zustand": "^4.3.2" }, @@ -26137,221 +26435,14 @@ "jest": "^29.5.0", "jest-environment-jsdom": "^29.3.1", "resize-observer-polyfill": "^1.5.1", - "vite-plugin-svgr": "^3.2.0" + "rollup-plugin-visualizer": "^5.9.2", + "vite-plugin-css-injected-by-js": "^3.3.0", + "vite-plugin-dts": "^3.5.3" }, "peerDependencies": { "@yext/studio-plugin": "*" } }, - "packages/studio-ui/node_modules/@svgr/babel-plugin-add-jsx-attribute": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-add-jsx-attribute/-/babel-plugin-add-jsx-attribute-7.0.0.tgz", - "integrity": "sha512-khWbXesWIP9v8HuKCl2NU2HNAyqpSQ/vkIl36Nbn4HIwEYSRWL0H7Gs6idJdha2DkpFDWlsqMELvoCE8lfFY6Q==", - "dev": true, - "engines": { - "node": ">=14" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/gregberge" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "packages/studio-ui/node_modules/@svgr/babel-plugin-remove-jsx-attribute": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-remove-jsx-attribute/-/babel-plugin-remove-jsx-attribute-7.0.0.tgz", - "integrity": "sha512-iiZaIvb3H/c7d3TH2HBeK91uI2rMhZNwnsIrvd7ZwGLkFw6mmunOCoVnjdYua662MqGFxlN9xTq4fv9hgR4VXQ==", - "dev": true, - "engines": { - "node": ">=14" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/gregberge" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "packages/studio-ui/node_modules/@svgr/babel-plugin-remove-jsx-empty-expression": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-remove-jsx-empty-expression/-/babel-plugin-remove-jsx-empty-expression-7.0.0.tgz", - "integrity": "sha512-sQQmyo+qegBx8DfFc04PFmIO1FP1MHI1/QEpzcIcclo5OAISsOJPW76ZIs0bDyO/DBSJEa/tDa1W26pVtt0FRw==", - "dev": true, - "engines": { - "node": ">=14" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/gregberge" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "packages/studio-ui/node_modules/@svgr/babel-plugin-replace-jsx-attribute-value": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-replace-jsx-attribute-value/-/babel-plugin-replace-jsx-attribute-value-7.0.0.tgz", - "integrity": "sha512-i6MaAqIZXDOJeikJuzocByBf8zO+meLwfQ/qMHIjCcvpnfvWf82PFvredEZElErB5glQFJa2KVKk8N2xV6tRRA==", - "dev": true, - "engines": { - "node": ">=14" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/gregberge" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "packages/studio-ui/node_modules/@svgr/babel-plugin-svg-dynamic-title": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-svg-dynamic-title/-/babel-plugin-svg-dynamic-title-7.0.0.tgz", - "integrity": "sha512-BoVSh6ge3SLLpKC0pmmN9DFlqgFy4NxNgdZNLPNJWBUU7TQpDWeBuyVuDW88iXydb5Cv0ReC+ffa5h3VrKfk1w==", - "dev": true, - "engines": { - "node": ">=14" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/gregberge" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "packages/studio-ui/node_modules/@svgr/babel-plugin-svg-em-dimensions": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-svg-em-dimensions/-/babel-plugin-svg-em-dimensions-7.0.0.tgz", - "integrity": "sha512-tNDcBa+hYn0gO+GkP/AuNKdVtMufVhU9fdzu+vUQsR18RIJ9RWe7h/pSBY338RO08wArntwbDk5WhQBmhf2PaA==", - "dev": true, - "engines": { - "node": ">=14" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/gregberge" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "packages/studio-ui/node_modules/@svgr/babel-plugin-transform-react-native-svg": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-transform-react-native-svg/-/babel-plugin-transform-react-native-svg-7.0.0.tgz", - "integrity": "sha512-qw54u8ljCJYL2KtBOjI5z7Nzg8LnSvQOP5hPKj77H4VQL4+HdKbAT5pnkkZLmHKYwzsIHSYKXxHouD8zZamCFQ==", - "dev": true, - "engines": { - "node": ">=14" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/gregberge" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "packages/studio-ui/node_modules/@svgr/babel-plugin-transform-svg-component": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-transform-svg-component/-/babel-plugin-transform-svg-component-7.0.0.tgz", - "integrity": "sha512-CcFECkDj98daOg9jE3Bh3uyD9kzevCAnZ+UtzG6+BQG/jOQ2OA3jHnX6iG4G1MCJkUQFnUvEv33NvQfqrb/F3A==", - "dev": true, - "engines": { - "node": ">=12" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/gregberge" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "packages/studio-ui/node_modules/@svgr/babel-preset": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/@svgr/babel-preset/-/babel-preset-7.0.0.tgz", - "integrity": "sha512-EX/NHeFa30j5UjldQGVQikuuQNHUdGmbh9kEpBKofGUtF0GUPJ4T4rhoYiqDAOmBOxojyot36JIFiDUHUK1ilQ==", - "dev": true, - "dependencies": { - "@svgr/babel-plugin-add-jsx-attribute": "^7.0.0", - "@svgr/babel-plugin-remove-jsx-attribute": "^7.0.0", - "@svgr/babel-plugin-remove-jsx-empty-expression": "^7.0.0", - "@svgr/babel-plugin-replace-jsx-attribute-value": "^7.0.0", - "@svgr/babel-plugin-svg-dynamic-title": "^7.0.0", - "@svgr/babel-plugin-svg-em-dimensions": "^7.0.0", - "@svgr/babel-plugin-transform-react-native-svg": "^7.0.0", - "@svgr/babel-plugin-transform-svg-component": "^7.0.0" - }, - "engines": { - "node": ">=14" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/gregberge" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "packages/studio-ui/node_modules/@svgr/core": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/@svgr/core/-/core-7.0.0.tgz", - "integrity": "sha512-ztAoxkaKhRVloa3XydohgQQCb0/8x9T63yXovpmHzKMkHO6pkjdsIAWKOS4bE95P/2quVh1NtjSKlMRNzSBffw==", - "dev": true, - "dependencies": { - "@babel/core": "^7.21.3", - "@svgr/babel-preset": "^7.0.0", - "camelcase": "^6.2.0", - "cosmiconfig": "^8.1.3" - }, - "engines": { - "node": ">=14" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/gregberge" - } - }, - "packages/studio-ui/node_modules/@svgr/hast-util-to-babel-ast": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/@svgr/hast-util-to-babel-ast/-/hast-util-to-babel-ast-7.0.0.tgz", - "integrity": "sha512-42Ej9sDDEmsJKjrfQ1PHmiDiHagh/u9AHO9QWbeNx4KmD9yS5d1XHmXUNINfUcykAU+4431Cn+k6Vn5mWBYimQ==", - "dev": true, - "dependencies": { - "@babel/types": "^7.21.3", - "entities": "^4.4.0" - }, - "engines": { - "node": ">=14" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/gregberge" - } - }, - "packages/studio-ui/node_modules/@svgr/plugin-jsx": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/@svgr/plugin-jsx/-/plugin-jsx-7.0.0.tgz", - "integrity": "sha512-SWlTpPQmBUtLKxXWgpv8syzqIU8XgFRvyhfkam2So8b3BE0OS0HPe5UfmlJ2KIC+a7dpuuYovPR2WAQuSyMoPw==", - "dev": true, - "dependencies": { - "@babel/core": "^7.21.3", - "@svgr/babel-preset": "^7.0.0", - "@svgr/hast-util-to-babel-ast": "^7.0.0", - "svg-parser": "^2.0.4" - }, - "engines": { - "node": ">=14" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/gregberge" - } - }, "packages/studio-ui/node_modules/@types/node": { "version": "18.17.12", "resolved": "https://registry.npmjs.org/@types/node/-/node-18.17.12.tgz", @@ -26394,18 +26485,6 @@ "postcss": "^8.1.0" } }, - "packages/studio-ui/node_modules/camelcase": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", - "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "packages/studio-ui/node_modules/caniuse-lite": { "version": "1.0.30001525", "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001525.tgz", @@ -26425,58 +26504,6 @@ } ] }, - "packages/studio-ui/node_modules/cosmiconfig": { - "version": "8.3.4", - "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-8.3.4.tgz", - "integrity": "sha512-SF+2P8+o/PTV05rgsAjDzL4OFdVXAulSfC/L19VaeVT7+tpOOSscCt2QLxDZ+CLxF2WOiq6y1K5asvs8qUJT/Q==", - "dev": true, - "dependencies": { - "import-fresh": "^3.3.0", - "js-yaml": "^4.1.0", - "parse-json": "^5.2.0", - "path-type": "^4.0.0" - }, - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/d-fischer" - }, - "peerDependencies": { - "typescript": ">=4.9.5" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "packages/studio-ui/node_modules/entities": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", - "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", - "dev": true, - "engines": { - "node": ">=0.12" - }, - "funding": { - "url": "https://github.com/fb55/entities?sponsor=1" - } - }, - "packages/studio-ui/node_modules/vite-plugin-svgr": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/vite-plugin-svgr/-/vite-plugin-svgr-3.2.0.tgz", - "integrity": "sha512-Uvq6niTvhqJU6ga78qLKBFJSDvxWhOnyfQSoKpDPMAGxJPo5S3+9hyjExE5YDj6Lpa4uaLkGc1cBgxXov+LjSw==", - "dev": true, - "dependencies": { - "@rollup/pluginutils": "^5.0.2", - "@svgr/core": "^7.0.0", - "@svgr/plugin-jsx": "^7.0.0" - }, - "peerDependencies": { - "vite": "^2.6.0 || 3 || 4" - } - }, "packages/studio/node_modules/@types/node": { "version": "18.11.18", "resolved": "https://registry.npmjs.org/@types/node/-/node-18.11.18.tgz", diff --git a/packages/studio-plugin/src/parsers/ComponentTreeParser.ts b/packages/studio-plugin/src/parsers/ComponentTreeParser.ts index a2146e0f7..821726f0e 100644 --- a/packages/studio-plugin/src/parsers/ComponentTreeParser.ts +++ b/packages/studio-plugin/src/parsers/ComponentTreeParser.ts @@ -11,7 +11,8 @@ import { ComponentState, ComponentStateKind, ErrorComponentState, - StandardComponentState, + RepeaterState, + StandardOrModuleComponentState, } from "../types/ComponentState"; import { v4 } from "uuid"; import { FileMetadataKind, TypelessPropVal } from "../types"; @@ -71,13 +72,20 @@ export default class ComponentTreeParser { }; if (component.isKind(SyntaxKind.JsxExpression)) { - throw new Error( - `Jsx nodes of kind "${component.getKindName()}" are not supported for direct use` + - " in page files." + const { selfClosingElement, listExpression } = + StaticParsingHelpers.parseJsxExpression(component); + const parsedRepeaterElement = this.parseRepeaterElement( + defaultImports, + selfClosingElement, + listExpression ); + return { + ...commonComponentState, + ...parsedRepeaterElement, + }; } - if (!TypeGuards.isNotFragmentElement(component)) { + if (!ComponentTreeParser.isNotFragmentElement(component)) { return { ...commonComponentState, kind: ComponentStateKind.Fragment, @@ -98,12 +106,52 @@ export default class ComponentTreeParser { }; } + private static isNotFragmentElement( + element: JsxElement | JsxSelfClosingElement | JsxFragment + ): element is JsxElement | JsxSelfClosingElement { + if (element.isKind(SyntaxKind.JsxFragment)) { + return false; + } + if (element.isKind(SyntaxKind.JsxSelfClosingElement)) { + return true; + } + const name = StaticParsingHelpers.parseJsxElementName(element); + return !["Fragment", "React.Fragment"].includes(name); + } + + private parseRepeaterElement( + defaultImports: Record, + repeatedComponent: JsxSelfClosingElement, + listExpression: string + ): Omit { + const componentName = + StaticParsingHelpers.parseJsxElementName(repeatedComponent); + const parsedRepeatedComponent = this.parseElement( + repeatedComponent, + componentName, + defaultImports + ); + if (parsedRepeatedComponent.kind === ComponentStateKind.BuiltIn) { + throw new Error( + "Error parsing map expression: repetition of built-in components is not supported." + ); + } + return { + kind: ComponentStateKind.Repeater, + listExpression, + repeatedComponent: { + ...parsedRepeatedComponent, + componentName, + }, + }; + } + private parseElement( component: JsxElement | JsxSelfClosingElement, componentName: string, defaultImports: Record ): - | Pick + | Pick | Pick | Omit { const attributes: JsxAttributeLike[] = component.isKind( @@ -149,8 +197,12 @@ export default class ComponentTreeParser { props, }; } - const { metadataUUID, propShape } = fileMetadata; + const { kind: fileMetadataKind, metadataUUID, propShape } = fileMetadata; + const componentStateKind = + fileMetadataKind === FileMetadataKind.Module + ? ComponentStateKind.Module + : ComponentStateKind.Standard; const props = StaticParsingHelpers.parseJsxAttributes( attributes, propShape @@ -173,7 +225,7 @@ export default class ComponentTreeParser { } return { - kind: ComponentStateKind.Standard, + kind: componentStateKind, metadataUUID, props, }; diff --git a/packages/studio-plugin/src/utils/TypeGuards.ts b/packages/studio-plugin/src/utils/TypeGuards.ts index bf1aaf847..4bf46f816 100644 --- a/packages/studio-plugin/src/utils/TypeGuards.ts +++ b/packages/studio-plugin/src/utils/TypeGuards.ts @@ -1,24 +1,23 @@ -import { - JsxElement, - JsxFragment, - JsxSelfClosingElement, - SyntaxKind, -} from "ts-morph"; import { ComponentState, ComponentStateKind, + EditableComponentState, FileMetadata, + FileMetadataKind, + ModuleMetadata, + ModuleState, PropShape, PropType, PropVal, PropValueKind, PropValues, PropValueType, + RepeaterState, SiteSettingsShape, SiteSettingsValues, + StandardOrModuleComponentState, } from "../types"; -import StaticParsingHelpers from "../parsers/helpers/StaticParsingHelpers"; import { SiteSettingsExpression, StreamsDataExpression, @@ -159,17 +158,41 @@ export default class TypeGuards { return typeof value === "string" && value.startsWith("siteSettings."); } - static isNotFragmentElement( - element: JsxElement | JsxSelfClosingElement | JsxFragment - ): element is JsxElement | JsxSelfClosingElement { - if (element.isKind(SyntaxKind.JsxFragment)) { - return false; - } - if (element.isKind(SyntaxKind.JsxSelfClosingElement)) { - return true; - } - const name = StaticParsingHelpers.parseJsxElementName(element); - return !["Fragment", "React.Fragment"].includes(name); + static isModuleMetadata( + metadata?: FileMetadata | null + ): metadata is ModuleMetadata { + return metadata?.kind === FileMetadataKind.Module; + } + + static isModuleState( + componentState: ComponentState + ): componentState is ModuleState { + return componentState.kind === ComponentStateKind.Module; + } + + static isStandardOrModuleComponentState( + componentState: ComponentState + ): componentState is StandardOrModuleComponentState { + return ( + componentState.kind === ComponentStateKind.Module || + componentState.kind === ComponentStateKind.Standard + ); + } + + static isRepeaterState( + componentState: ComponentState + ): componentState is RepeaterState { + return componentState.kind === ComponentStateKind.Repeater; + } + + static isEditableComponentState( + componentState: ComponentState + ): componentState is EditableComponentState { + return ( + componentState.kind === ComponentStateKind.Module || + componentState.kind === ComponentStateKind.Standard || + componentState.kind === ComponentStateKind.Repeater + ); } static isSiteSettingsValues( diff --git a/packages/studio-ui/.gitignore b/packages/studio-ui/.gitignore new file mode 100644 index 000000000..10dcd67fb --- /dev/null +++ b/packages/studio-ui/.gitignore @@ -0,0 +1 @@ +stats.html \ No newline at end of file diff --git a/packages/studio-ui/package.json b/packages/studio-ui/package.json index a23787f66..9d1ff776e 100644 --- a/packages/studio-ui/package.json +++ b/packages/studio-ui/package.json @@ -41,6 +41,8 @@ "react-tooltip": "^5.18.0", "tailwind-merge": "^1.8.1", "tailwindcss": "^3.3.3", + "vite": "^4.4.7", + "vite-plugin-svgr": "^2.4.0", "zundo": "2.0.0-beta.12", "zustand": "^4.3.2" }, @@ -64,7 +66,9 @@ "jest": "^29.5.0", "jest-environment-jsdom": "^29.3.1", "resize-observer-polyfill": "^1.5.1", - "vite-plugin-svgr": "^3.2.0" + "rollup-plugin-visualizer": "^5.9.2", + "vite-plugin-css-injected-by-js": "^3.3.0", + "vite-plugin-dts": "^3.5.3" }, "peerDependencies": { "@yext/studio-plugin": "*" diff --git a/packages/studio-ui/src/components/FieldPicker/FieldDropdown.tsx b/packages/studio-ui/src/components/FieldPicker/FieldDropdown.tsx index a4a97db9f..101001f36 100644 --- a/packages/studio-ui/src/components/FieldPicker/FieldDropdown.tsx +++ b/packages/studio-ui/src/components/FieldPicker/FieldDropdown.tsx @@ -1,6 +1,6 @@ import { useCallback, MouseEvent, CSSProperties } from "react"; import { ReactComponent as VectorIcon } from "../../icons/vector.svg"; -import { startCase } from "lodash"; +import startCase from "lodash/startCase"; const listStyles: CSSProperties = { minWidth: "200px", diff --git a/packages/studio-ui/src/components/HighlightingContainer.tsx b/packages/studio-ui/src/components/HighlightingContainer.tsx index 2dd2a2884..024019472 100644 --- a/packages/studio-ui/src/components/HighlightingContainer.tsx +++ b/packages/studio-ui/src/components/HighlightingContainer.tsx @@ -1,4 +1,4 @@ -import { isEqual } from "lodash"; +import isEqual from "lodash/isEqual"; import { Component, PropsWithChildren, ReactInstance } from "react"; import DOMRectProperties from "../store/models/DOMRectProperties"; import useStudioStore from "../store/useStudioStore"; diff --git a/packages/studio-ui/src/components/PageSettingsButton/EntityPageModal.tsx b/packages/studio-ui/src/components/PageSettingsButton/EntityPageModal.tsx index 97e23ede2..4b143df31 100644 --- a/packages/studio-ui/src/components/PageSettingsButton/EntityPageModal.tsx +++ b/packages/studio-ui/src/components/PageSettingsButton/EntityPageModal.tsx @@ -12,7 +12,7 @@ import { StaticPageSettings } from "./StaticPageModal"; import { streamScopeFormData } from "../AddPageButton/StreamScopeCollector"; import PageDataValidator from "../../utils/PageDataValidator"; import { toast } from "react-toastify"; -import { isEqual } from "lodash"; +import isEqual from "lodash/isEqual"; type EntityPageSettings = StaticPageSettings & StreamScopeForm; diff --git a/packages/studio-ui/src/components/PreviewPanel.tsx b/packages/studio-ui/src/components/PreviewPanel.tsx index 2d782f12d..591182369 100644 --- a/packages/studio-ui/src/components/PreviewPanel.tsx +++ b/packages/studio-ui/src/components/PreviewPanel.tsx @@ -1,18 +1,52 @@ import { Dispatch, SetStateAction, useMemo } from "react"; import useStudioStore from "../store/useStudioStore"; +import usePreviewProps from "../hooks/usePreviewProps"; import ComponentTreePreview from "./ComponentTreePreview"; import useRawSiteSettings from "../hooks/useRawSiteSettings"; +import { ComponentStateHelpers, TypeGuards } from "@yext/studio-plugin"; +import get from "lodash/get"; import { ITooltip } from "react-tooltip"; export default function PreviewPanel(props: { setTooltipProps: Dispatch>; }) { const { setTooltipProps } = props; - const componentTree = useStudioStore((store) => - store.actions.getComponentTree() - ); + const [componentTree, moduleUUIDBeingEdited, getComponentState] = + useStudioStore((store) => [ + store.actions.getComponentTree(), + store.pages.moduleUUIDBeingEdited, + store.actions.getComponentState, + ]); const pageExpressionSources = usePageExpressionSources(); + + const state = moduleUUIDBeingEdited + ? getComponentState(componentTree, moduleUUIDBeingEdited) + : undefined; + const list = + state && TypeGuards.isRepeaterState(state) + ? get(pageExpressionSources, state.listExpression) + : undefined; + const item = Array.isArray(list) ? list[0] : undefined; + + const extractedState = + state && TypeGuards.isEditableComponentState(state) + ? ComponentStateHelpers.extractRepeatedState(state) + : undefined; + const parentPreviewProps = usePreviewProps( + extractedState, + pageExpressionSources, + item + ); + + const expressionSources = useMemo( + () => ({ + ...pageExpressionSources, + ...(moduleUUIDBeingEdited && { props: parentPreviewProps }), + }), + [pageExpressionSources, moduleUUIDBeingEdited, parentPreviewProps] + ); + if (!componentTree) { return null; } @@ -20,7 +54,7 @@ export default function PreviewPanel(props: { return ( ); diff --git a/packages/studio-ui/src/components/RepeaterPreview.tsx b/packages/studio-ui/src/components/RepeaterPreview.tsx new file mode 100644 index 000000000..61b60339c --- /dev/null +++ b/packages/studio-ui/src/components/RepeaterPreview.tsx @@ -0,0 +1,54 @@ +import { RepeaterState } from "@yext/studio-plugin"; +import get from "lodash/get"; +import { Dispatch, SetStateAction, useCallback, useMemo } from "react"; +import { ExpressionSources } from "../utils/getPropsForPreview"; +import ComponentPreview from "./ComponentPreview"; +import { ITooltip } from "react-tooltip"; + +interface RepeaterPreviewProps { + repeaterState: RepeaterState; + expressionSources: ExpressionSources; + setTooltipProps: Dispatch>; +} + +/** + * Renders the preview for a Repeater component. + */ +export default function RepeaterPreview({ + repeaterState, + expressionSources, + setTooltipProps, +}: RepeaterPreviewProps): JSX.Element | null { + const { repeatedComponent, listExpression } = repeaterState; + const repeatedElementState = useMemo( + () => ({ + ...repeatedComponent, + uuid: repeaterState.uuid, + parentUUID: repeaterState.parentUUID, + }), + [repeatedComponent, repeaterState] + ); + + const renderRepeatedElement = useCallback( + (item: unknown, key: number | string) => ( + + ), + [repeatedElementState, expressionSources, setTooltipProps] + ); + + const list = get(expressionSources, listExpression) as unknown; + if (!Array.isArray(list)) { + console.warn( + `Unable to render list repeater. Expected "${listExpression}" to reference an array in `, + expressionSources + ); + return null; + } + return <>{list.map(renderRepeatedElement)}; +} diff --git a/packages/studio-ui/src/components/SiteSettingsPanel.tsx b/packages/studio-ui/src/components/SiteSettingsPanel.tsx index 02133c554..e2725c159 100644 --- a/packages/studio-ui/src/components/SiteSettingsPanel.tsx +++ b/packages/studio-ui/src/components/SiteSettingsPanel.tsx @@ -11,7 +11,7 @@ import { SiteSettingsVal, } from "@yext/studio-plugin"; import React, { useCallback } from "react"; -import { startCase } from "lodash"; +import startCase from "lodash/startCase"; import useStudioStore from "../store/useStudioStore"; import PropInput from "./PropInput"; diff --git a/packages/studio-ui/src/components/common/ColorPicker.tsx b/packages/studio-ui/src/components/common/ColorPicker.tsx index 09f44fbb8..0e25a6ce8 100644 --- a/packages/studio-ui/src/components/common/ColorPicker.tsx +++ b/packages/studio-ui/src/components/common/ColorPicker.tsx @@ -1,5 +1,5 @@ import { ChangeEvent, useEffect, useMemo, useState } from "react"; -import { debounce } from "lodash"; +import debounce from "lodash/debounce"; import PropValueHelpers from "../../utils/PropValueHelpers"; import { PropValueKind, PropValueType } from "@yext/studio-plugin"; diff --git a/packages/studio-ui/src/hooks/useFuncWithZundoBatching.tsx b/packages/studio-ui/src/hooks/useFuncWithZundoBatching.tsx index f4bb997f2..40bc8e7ac 100644 --- a/packages/studio-ui/src/hooks/useFuncWithZundoBatching.tsx +++ b/packages/studio-ui/src/hooks/useFuncWithZundoBatching.tsx @@ -1,6 +1,6 @@ import { useCallback, useMemo } from "react"; import useTemporalStore from "../store/useTemporalStore"; -import { debounce } from "lodash"; +import debounce from "lodash/debounce"; /** * Updates a function so it doesn't trigger Zundo store updates until after a diff --git a/packages/studio-ui/src/hooks/useHasChanges.ts b/packages/studio-ui/src/hooks/useHasChanges.ts index f8262284b..22811178b 100644 --- a/packages/studio-ui/src/hooks/useHasChanges.ts +++ b/packages/studio-ui/src/hooks/useHasChanges.ts @@ -1,5 +1,5 @@ import useStudioStore from "../store/useStudioStore"; -import { isEqual } from "lodash"; +import isEqual from "lodash/isEqual"; export default function useHasChanges() { // TODO(SLAP-2556) Refactor pendingChanges to use PreviousSaveSlice diff --git a/packages/studio-ui/src/index.ts b/packages/studio-ui/src/index.ts index 26c3046be..3fe76c509 100644 --- a/packages/studio-ui/src/index.ts +++ b/packages/studio-ui/src/index.ts @@ -1,2 +1,3 @@ export { default as App } from "./App"; export { default as hotReloadStore } from "./store/hotReloadStore"; +export { StudioHMRUpdateID } from "@yext/studio-plugin"; diff --git a/packages/studio-ui/src/store/StudioActions.ts b/packages/studio-ui/src/store/StudioActions.ts index 25b84da39..11f832796 100644 --- a/packages/studio-ui/src/store/StudioActions.ts +++ b/packages/studio-ui/src/store/StudioActions.ts @@ -9,7 +9,7 @@ import { import FileMetadataSlice from "./models/slices/FileMetadataSlice"; import PageSlice from "./models/slices/PageSlice"; import sendMessage from "../messaging/sendMessage"; -import { cloneDeep } from "lodash"; +import cloneDeep from "lodash/cloneDeep"; import SiteSettingsSlice from "./models/slices/SiteSettingsSlice"; import PreviousSaveSlice from "./models/slices/PreviousSaveSlice"; import StudioConfigSlice from "./models/slices/StudioConfigSlice"; diff --git a/packages/studio-ui/src/store/StudioActions/GenerateTestDataAction.ts b/packages/studio-ui/src/store/StudioActions/GenerateTestDataAction.ts index a620de853..98dc1eeaa 100644 --- a/packages/studio-ui/src/store/StudioActions/GenerateTestDataAction.ts +++ b/packages/studio-ui/src/store/StudioActions/GenerateTestDataAction.ts @@ -10,7 +10,7 @@ import { import { Stream } from "@yext/pages"; import PageSlice from "../models/slices/PageSlice"; import sendMessage from "../../messaging/sendMessage"; -import { isEqual } from "lodash"; +import isEqual from "lodash/isEqual"; import StudioActions from "../StudioActions"; export default class GenerateTestDataAction { diff --git a/packages/studio-ui/src/store/createModuleAction.ts b/packages/studio-ui/src/store/createModuleAction.ts new file mode 100644 index 000000000..16f810493 --- /dev/null +++ b/packages/studio-ui/src/store/createModuleAction.ts @@ -0,0 +1,122 @@ +import { StudioStore } from "./models/StudioStore"; +import path from "path-browserify"; +import { + ComponentState, + ComponentTreeHelpers, + FileMetadataKind, + ModuleMetadata, + PropValueType, +} from "@yext/studio-plugin"; +import differenceWith from "lodash/differenceWith"; +import isEqual from "lodash/isEqual"; +import { v4 } from "uuid"; + +export default function getCreateModuleAction( + get: () => StudioStore +): StudioStore["createModule"] { + function throwIfInvalidFilepath(filepath: string) { + const modulesFolder = get().studioConfig.paths.modules; + const moduleName = path.basename(filepath, ".tsx"); + if (!filepath.startsWith(modulesFolder)) { + throw new Error( + `Error creating module: modulePath is invalid: "${path.relative( + modulesFolder, + filepath + )}".` + ); + } else if (moduleName.charAt(0) !== moduleName.charAt(0).toUpperCase()) { + throw new Error( + "Error creating module: Module names must start with an uppercase letter." + ); + } else if ( + Object.values(get().fileMetadatas.UUIDToFileMetadata).some( + (fileMetadata) => + path.basename(fileMetadata.filepath, ".tsx") === moduleName + ) + ) { + throw new Error( + `Error creating module: module name "${moduleName}" is already used.` + ); + } + } + + function createModuleMetadata( + filepath: string, + descendants: ComponentState[], + activeComponentState: ComponentState + ): ModuleMetadata { + const moduleMetadata: ModuleMetadata = { + kind: FileMetadataKind.Module, + componentTree: [ + { ...activeComponentState, parentUUID: undefined }, + ...descendants, + ], + metadataUUID: v4(), + filepath, + propShape: {}, + }; + if (get().studioConfig.isPagesJSRepo) { + moduleMetadata.propShape = { + document: { + type: PropValueType.Record, + recordKey: "string", + recordValue: "any", + required: true, + }, + }; + } + return moduleMetadata; + } + + function createModule( + filepath: string, + componentTree: ComponentState[], + activeComponentState: ComponentState + ) { + const descendants = ComponentTreeHelpers.getDescendants( + activeComponentState, + componentTree + ); + const moduleMetadata: ModuleMetadata = createModuleMetadata( + filepath, + descendants, + activeComponentState + ); + get().fileMetadatas.setFileMetadata( + moduleMetadata.metadataUUID, + moduleMetadata + ); + const moduleState = get().actions.createComponentState(moduleMetadata); + const updatedPageComponentTree: ComponentState[] = differenceWith( + componentTree, + descendants, + isEqual + ).map((c) => { + if (c.uuid === activeComponentState.uuid) { + return { + ...moduleState, + parentUUID: c.parentUUID, + }; + } + return c; + }); + get().actions.updateComponentTree(updatedPageComponentTree); + get().pages.setActiveComponentUUID(moduleState.uuid); + } + + return (modulePath: string) => { + if (!modulePath) { + throw new Error("Error creating module: a modulePath is required."); + } + const modulesFolder = get().studioConfig.paths.modules; + const filepath = path.join(modulesFolder, modulePath + ".tsx"); + throwIfInvalidFilepath(filepath); + + const componentTree = get().actions.getComponentTree() ?? []; + const activeComponentState = get().actions.getActiveComponentState(); + if (!activeComponentState) { + throw new Error("Tried to create module without active component."); + } + createModule(filepath, componentTree, activeComponentState); + }; +} diff --git a/packages/studio-ui/src/store/slices/createPageSlice.ts b/packages/studio-ui/src/store/slices/createPageSlice.ts index 7482f159b..872a242b6 100644 --- a/packages/studio-ui/src/store/slices/createPageSlice.ts +++ b/packages/studio-ui/src/store/slices/createPageSlice.ts @@ -4,7 +4,7 @@ import { PageState, StreamScope, } from "@yext/studio-plugin"; -import { isEqual } from "lodash"; +import isEqual from "lodash/isEqual"; import initialStudioData from "virtual_yext-studio"; import DOMRectProperties from "../models/DOMRectProperties"; import PageSlice, { PageSliceStates } from "../models/slices/PageSlice"; diff --git a/packages/studio-ui/src/store/zundoMiddleware.ts b/packages/studio-ui/src/store/zundoMiddleware.ts index 3ee3e1ae7..90775fd10 100644 --- a/packages/studio-ui/src/store/zundoMiddleware.ts +++ b/packages/studio-ui/src/store/zundoMiddleware.ts @@ -1,7 +1,7 @@ import PageSlice from "./models/slices/PageSlice"; import SiteSettingSlice from "./models/slices/SiteSettingsSlice"; import { StudioStore } from "./models/StudioStore"; -import { isEqual } from "lodash"; +import isEqual from "lodash/isEqual"; import { ZundoOptions, temporal } from "zundo"; import { TemporalStudioStore } from "./useTemporalStore"; import { StateCreator } from "zustand"; diff --git a/packages/studio-ui/src/utils/getPropsForPreview.ts b/packages/studio-ui/src/utils/getPropsForPreview.ts index a9457b5a9..cb17535ca 100644 --- a/packages/studio-ui/src/utils/getPropsForPreview.ts +++ b/packages/studio-ui/src/utils/getPropsForPreview.ts @@ -8,7 +8,7 @@ import { PropVal, PropType, } from "@yext/studio-plugin"; -import { get } from "lodash"; +import get from "lodash/get"; import TemplateExpressionFormatter from "./TemplateExpressionFormatter"; /** diff --git a/packages/studio-ui/vite.config.ts b/packages/studio-ui/vite.config.ts new file mode 100644 index 000000000..1c23a371f --- /dev/null +++ b/packages/studio-ui/vite.config.ts @@ -0,0 +1,23 @@ +// vite.config.js +import { resolve } from 'path' +import { defineConfig, PluginOption } from 'vite' +import svgr from "vite-plugin-svgr"; +import { visualizer } from "rollup-plugin-visualizer"; +import dts from 'vite-plugin-dts' +import cssInjectedByJsPlugin from 'vite-plugin-css-injected-by-js' + +export default defineConfig({ + plugins: [svgr(), dts(), cssInjectedByJsPlugin(), visualizer() as PluginOption], + build: { + outDir: 'lib', + sourcemap: true, + lib: { + entry: resolve(__dirname, 'src/index.ts'), + formats: ['es'], + fileName: 'src/index', + }, + rollupOptions: { + external: ['virtual_yext-studio-git-data', 'virtual_yext-studio', '@pathToUserProjectRoot/tailwind.config', 'react', 'react-dom', 'react/jsx-runtime'], + }, + }, +}) \ No newline at end of file diff --git a/packages/studio/src/main.tsx b/packages/studio/src/main.tsx index a3559bc9a..14484cffb 100644 --- a/packages/studio/src/main.tsx +++ b/packages/studio/src/main.tsx @@ -1,7 +1,7 @@ import React from "react"; import ReactDOM from "react-dom/client"; -import { App, hotReloadStore } from "@yext/studio-ui"; -import { StudioHMRPayload, StudioHMRUpdateID } from "@yext/studio-plugin"; +import { App, hotReloadStore, StudioHMRUpdateID } from "@yext/studio-ui"; +import type { StudioHMRPayload } from "@yext/studio-plugin"; import "./tailwind-directives.css"; if (import.meta.hot) {