Guide generator (#231)
* Replace sw, sns battlesuit images * Add gen guide page * Make supports configurable * Extract DifficultySelect & Improve Ex Signet Ordering style * Extract BattlesuitSelect * Use BattlesuitSelect for support valk * Swap support if duplicated * Add sigil selector * Set initial ex signets * Change layout * Add sigil icon to single value * Add equipment select * Fix difficulty box label * Implement SignetBox * Add Signet form control * Improve rendering perf of stigma and weapon select * Implement image converter * Fix signet select * Remove FontHead * Remove wrong new line * Fix warnings * Add custom style configurator * Make labels of DiffucltyBox and ValkBox configurable * Add background and improve layout * Improve ex signet fontsize * Style boundaries of left bottom boxes * Apply fonts directly * Style signet box * Add Signet group label * Style ValkBox * Add support valk label * Style layout of SignetBox * Add shadow to difficulty box * Add sigil label * Adjust signet group label * Add equipment label * Configure colors of left bottom boxes * Add tag, rank, signature * Add icon to current value of battlesuit select * Adjust form styles * Add signet group select * Implement import/export data * Fix dashed border of difficulty box * Add gen link to elysian realm home * Prefix types
This commit is contained in:
Binary file not shown.
|
Before Width: | Height: | Size: 214 KiB After Width: | Height: | Size: 264 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 380 KiB After Width: | Height: | Size: 445 KiB |
@@ -16,14 +16,12 @@
|
||||
- name: Active Skill (CN Live Data)
|
||||
krName: 액티브 스킬 (CN Live Data)
|
||||
description: |-
|
||||
[SP Cost: 0][CD: 0] Use the bow to aim and shoot (max aiming duration:
|
||||
3s), dealing 675.0% ATK of Ice DMG.
|
||||
[SP Cost: 0][CD: 0] Use the bow to aim and shoot (max aiming duration: 3s), dealing 675.0% ATK of Ice DMG.
|
||||
Herrscher of Human:Ego equip bonus: Inflicts Ego Blossom to the target, which makes the enemy to take 15.0% more Ice DMG for 10s (can be refreshed). In Herrscher of Human form, inflicting Ego Blossom deals 10 x 20.0% ATK of Ice DMG.
|
||||
|
||||
The weapon active's CD and charging time are based on the shooting mode.
|
||||
krDescription: |-
|
||||
[SP 소모: 0][재사용 대기 시간: 0초] 화살로 적을 조준 사격해(최대 3초 동안 조준), 목표에게
|
||||
675.0%의 빙결 대미지를 가한다.
|
||||
[SP 소모: 0][재사용 대기 시간: 0초] 화살로 적을 조준 사격해(최대 3초 동안 조준), 목표에게 675.0%의 빙결 대미지를 가한다.
|
||||
진아·인류의 율자 장착 보너스: 진아 개화 효과를 목표에 발동시키며, 10초간 적이 받는 빙결 피해 15.0% 증가 (갱신 가능). 인간의 율자 형태에서, 진아 개화 발동 시, 공격력 10 x 20.0%의 빙결 대미지를 가한다.
|
||||
|
||||
무기 액티브 스킬의 재사용 대기시간과 충전 시간은 장착 캐릭터의 사격 유형에 따라 결정된다.
|
||||
@@ -60,14 +58,12 @@
|
||||
- name: Active Skill (CN Live Data)
|
||||
krName: 액티브 스킬 (CN Live Data)
|
||||
description: |-
|
||||
[SP Cost: 0][CD: 0] Use the bow to aim and shoot (max aiming duration:
|
||||
3s), dealing 550.0% ATK of Ice DMG.
|
||||
[SP Cost: 0][CD: 0] Use the bow to aim and shoot (max aiming duration: 3s), dealing 550.0% ATK of Ice DMG.
|
||||
Herrscher of Human:Ego equip bonus: Inflicts Ego Blossom to the target, which makes the enemy to take 12.0% more Ice DMG for 10s (can be refreshed). In Herrscher of Human form, inflicting Ego Blossom deals 10 x 15.0% ATK of Ice DMG.
|
||||
|
||||
The weapon active's CD and charging time are based on the shooting mode.
|
||||
krDescription: |-
|
||||
[SP 소모: 0][재사용 대기 시간: 0초] 화살로 적을 조준 사격해(최대 3초 동안 조준), 목표에게
|
||||
555.0%의 빙결 대미지를 가한다.
|
||||
[SP 소모: 0][재사용 대기 시간: 0초] 화살로 적을 조준 사격해(최대 3초 동안 조준), 목표에게 555.0%의 빙결 대미지를 가한다.
|
||||
진아·인류의 율자 장착 보너스: 진아 개화 효과를 목표에 발동시키며, 10초간 적이 받는 빙결 피해 12.0% 증가 (갱신 가능). 인간의 율자 형태에서, 진아 개화 발동 시, 공격력 10 x 15.0%의 빙결 대미지를 가한다.
|
||||
|
||||
무기 액티브 스킬의 재사용 대기시간과 충전 시간은 장착 캐릭터의 사격 유형에 따라 결정된다.
|
||||
|
||||
Generated
+452
-170
@@ -9,9 +9,14 @@
|
||||
"version": "1.0.0",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"@dnd-kit/core": "^6.0.5",
|
||||
"@dnd-kit/sortable": "^7.0.1",
|
||||
"@dnd-kit/utilities": "^3.2.0",
|
||||
"@mdi/js": "^6.5.95",
|
||||
"@mdi/react": "^1.5.0",
|
||||
"@types/file-saver": "^2.0.5",
|
||||
"date-fns": "^2.27.0",
|
||||
"html-to-image": "^1.10.6",
|
||||
"next": "^12.1.6",
|
||||
"next-i18next": "^10.1.0",
|
||||
"nprogress": "^0.2.0",
|
||||
@@ -20,6 +25,7 @@
|
||||
"react": "^17.0.2",
|
||||
"react-dom": "^17.0.2",
|
||||
"react-indiana-drag-scroll": "^2.1.0",
|
||||
"react-select": "^5.4.0",
|
||||
"theme-ui": "^0.12.1",
|
||||
"yaml": "^2.1.1"
|
||||
},
|
||||
@@ -31,6 +37,7 @@
|
||||
"cheerio": "^1.0.0-rc.10",
|
||||
"eslint": "8.5.0",
|
||||
"eslint-config-next": "12.0.7",
|
||||
"file-saver": "^2.0.5",
|
||||
"filenamify": "^4.3.0",
|
||||
"http-server": "^14.1.0",
|
||||
"node-fetch": "^2.6.7",
|
||||
@@ -249,9 +256,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@babel/helper-plugin-utils": {
|
||||
"version": "7.14.5",
|
||||
"resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.14.5.tgz",
|
||||
"integrity": "sha512-/37qQCE3K0vvZKwoK4XU/irIJQdIfCJuhU5eKnNxpFDsOkgFaUAwbv+RYw6eYgsC0E4hS7r5KqGULUogqui0fQ==",
|
||||
"version": "7.18.9",
|
||||
"resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.18.9.tgz",
|
||||
"integrity": "sha512-aBXPT3bmtLryXaoJLyYPXPlSD4p1ld9aYeR+sJNOZjJJGiOpb+fKfh3NkcCu7J54nUJwCERPBExCCpyCOHnu/w==",
|
||||
"engines": {
|
||||
"node": ">=6.9.0"
|
||||
}
|
||||
@@ -337,11 +344,11 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@babel/plugin-syntax-jsx": {
|
||||
"version": "7.14.5",
|
||||
"resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.14.5.tgz",
|
||||
"integrity": "sha512-ohuFIsOMXJnbOMRfX7/w7LocdR6R7whhuRD4ax8IipLcLPlZGJKkBxgHp++U4N/vKyU16/YDQr2f5seajD3jIw==",
|
||||
"version": "7.18.6",
|
||||
"resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.18.6.tgz",
|
||||
"integrity": "sha512-6mmljtAedFGTWu2p/8WIORGwy+61PLgOMPOdazc7YoJ9ZCWUyFy3A6CpPkRKLKD1ToAesxX8KGEViAiLo9N+7Q==",
|
||||
"dependencies": {
|
||||
"@babel/helper-plugin-utils": "^7.14.5"
|
||||
"@babel/helper-plugin-utils": "^7.18.6"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=6.9.0"
|
||||
@@ -351,9 +358,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@babel/runtime": {
|
||||
"version": "7.15.4",
|
||||
"resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.15.4.tgz",
|
||||
"integrity": "sha512-99catp6bHCaxr4sJ/DbTGgHS4+Rs2RVd2g7iOap6SLGPDknRK9ztKNsE/Fg6QhSeh1FGE5f6gHGQmvvn3I3xhw==",
|
||||
"version": "7.18.9",
|
||||
"resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.18.9.tgz",
|
||||
"integrity": "sha512-lkqXDcvlFT5rvEjiu6+QYO+1GXrEHRo2LOtS7E4GtX5ESIZOgepqsZBVIj6Pv+a6zqsya9VCgiK1KAK4BvJDAw==",
|
||||
"dependencies": {
|
||||
"regenerator-runtime": "^0.13.4"
|
||||
},
|
||||
@@ -474,18 +481,87 @@
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/@emotion/babel-plugin": {
|
||||
"version": "11.7.1",
|
||||
"resolved": "https://registry.npmjs.org/@emotion/babel-plugin/-/babel-plugin-11.7.1.tgz",
|
||||
"integrity": "sha512-K3/6Y+J/sIAjplf3uIteWLhPuOyuMNnE+iyYnTF/m294vc6IL90kTHp7y8ldZYbpKlP17rpOWDKM9DvTcrOmNQ==",
|
||||
"node_modules/@dnd-kit/accessibility": {
|
||||
"version": "3.0.1",
|
||||
"resolved": "https://registry.npmjs.org/@dnd-kit/accessibility/-/accessibility-3.0.1.tgz",
|
||||
"integrity": "sha512-HXRrwS9YUYQO9lFRc/49uO/VICbM+O+ZRpFDe9Pd1rwVv2PCNkRiTZRdxrDgng/UkvdC3Re9r2vwPpXXrWeFzg==",
|
||||
"dependencies": {
|
||||
"@babel/helper-module-imports": "^7.12.13",
|
||||
"@babel/plugin-syntax-jsx": "^7.12.13",
|
||||
"@babel/runtime": "^7.13.10",
|
||||
"@emotion/hash": "^0.8.0",
|
||||
"@emotion/memoize": "^0.7.5",
|
||||
"@emotion/serialize": "^1.0.2",
|
||||
"babel-plugin-macros": "^2.6.1",
|
||||
"tslib": "^2.0.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": ">=16.8.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@dnd-kit/accessibility/node_modules/tslib": {
|
||||
"version": "2.4.0",
|
||||
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz",
|
||||
"integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ=="
|
||||
},
|
||||
"node_modules/@dnd-kit/core": {
|
||||
"version": "6.0.5",
|
||||
"resolved": "https://registry.npmjs.org/@dnd-kit/core/-/core-6.0.5.tgz",
|
||||
"integrity": "sha512-3nL+Zy5cT+1XwsWdlXIvGIFvbuocMyB4NBxTN74DeBaBqeWdH9JsnKwQv7buZQgAHmAH+eIENfS1ginkvW6bCw==",
|
||||
"dependencies": {
|
||||
"@dnd-kit/accessibility": "^3.0.0",
|
||||
"@dnd-kit/utilities": "^3.2.0",
|
||||
"tslib": "^2.0.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": ">=16.8.0",
|
||||
"react-dom": ">=16.8.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@dnd-kit/core/node_modules/tslib": {
|
||||
"version": "2.4.0",
|
||||
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz",
|
||||
"integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ=="
|
||||
},
|
||||
"node_modules/@dnd-kit/sortable": {
|
||||
"version": "7.0.1",
|
||||
"resolved": "https://registry.npmjs.org/@dnd-kit/sortable/-/sortable-7.0.1.tgz",
|
||||
"integrity": "sha512-n77qAzJQtMMywu25sJzhz3gsHnDOUlEjTtnRl8A87rWIhnu32zuP+7zmFjwGgvqfXmRufqiHOSlH7JPC/tnJ8Q==",
|
||||
"dependencies": {
|
||||
"@dnd-kit/utilities": "^3.2.0",
|
||||
"tslib": "^2.0.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@dnd-kit/core": "^6.0.4",
|
||||
"react": ">=16.8.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@dnd-kit/sortable/node_modules/tslib": {
|
||||
"version": "2.4.0",
|
||||
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz",
|
||||
"integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ=="
|
||||
},
|
||||
"node_modules/@dnd-kit/utilities": {
|
||||
"version": "3.2.0",
|
||||
"resolved": "https://registry.npmjs.org/@dnd-kit/utilities/-/utilities-3.2.0.tgz",
|
||||
"integrity": "sha512-h65/pn2IPCCIWwdlR2BMLqRkDxpTEONA+HQW3n765HBijLYGyrnTCLa2YQt8VVjjSQD6EfFlTE6aS2Q/b6nb2g==",
|
||||
"dependencies": {
|
||||
"tslib": "^2.0.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": ">=16.8.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@dnd-kit/utilities/node_modules/tslib": {
|
||||
"version": "2.4.0",
|
||||
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz",
|
||||
"integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ=="
|
||||
},
|
||||
"node_modules/@emotion/babel-plugin": {
|
||||
"version": "11.10.2",
|
||||
"resolved": "https://registry.npmjs.org/@emotion/babel-plugin/-/babel-plugin-11.10.2.tgz",
|
||||
"integrity": "sha512-xNQ57njWTFVfPAc3cjfuaPdsgLp5QOSuRsj9MA6ndEhH/AzuZM86qIQzt6rq+aGBwj3n5/TkLmU5lhAfdRmogA==",
|
||||
"dependencies": {
|
||||
"@babel/helper-module-imports": "^7.16.7",
|
||||
"@babel/plugin-syntax-jsx": "^7.17.12",
|
||||
"@babel/runtime": "^7.18.3",
|
||||
"@emotion/hash": "^0.9.0",
|
||||
"@emotion/memoize": "^0.8.0",
|
||||
"@emotion/serialize": "^1.1.0",
|
||||
"babel-plugin-macros": "^3.1.0",
|
||||
"convert-source-map": "^1.5.0",
|
||||
"escape-string-regexp": "^4.0.0",
|
||||
"find-root": "^1.1.0",
|
||||
@@ -496,6 +572,11 @@
|
||||
"@babel/core": "^7.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@emotion/babel-plugin/node_modules/@emotion/memoize": {
|
||||
"version": "0.8.0",
|
||||
"resolved": "https://registry.npmjs.org/@emotion/memoize/-/memoize-0.8.0.tgz",
|
||||
"integrity": "sha512-G/YwXTkv7Den9mXDO7AhLWkE3q+I92B+VqAE+dYG4NGPaHZGvt3G8Q0p9vmE+sq7rTGphUbAvmQ9YpbfMQGGlA=="
|
||||
},
|
||||
"node_modules/@emotion/babel-plugin/node_modules/escape-string-regexp": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz",
|
||||
@@ -521,26 +602,31 @@
|
||||
"integrity": "sha512-xGPXiFVl4YED9Jh7Euv2V220mriG9u4B2TA6Ybjc1catrstKD2PpIdU3U0RKpkVBC2EhmL/F0sPCr9vrFTNRag=="
|
||||
},
|
||||
"node_modules/@emotion/cache": {
|
||||
"version": "11.7.1",
|
||||
"resolved": "https://registry.npmjs.org/@emotion/cache/-/cache-11.7.1.tgz",
|
||||
"integrity": "sha512-r65Zy4Iljb8oyjtLeCuBH8Qjiy107dOYC6SJq7g7GV5UCQWMObY4SJDPGFjiiVpPrOJ2hmJOoBiYTC7hwx9E2A==",
|
||||
"version": "11.10.3",
|
||||
"resolved": "https://registry.npmjs.org/@emotion/cache/-/cache-11.10.3.tgz",
|
||||
"integrity": "sha512-Psmp/7ovAa8appWh3g51goxu/z3iVms7JXOreq136D8Bbn6dYraPnmL6mdM8GThEx9vwSn92Fz+mGSjBzN8UPQ==",
|
||||
"dependencies": {
|
||||
"@emotion/memoize": "^0.7.4",
|
||||
"@emotion/sheet": "^1.1.0",
|
||||
"@emotion/utils": "^1.0.0",
|
||||
"@emotion/weak-memoize": "^0.2.5",
|
||||
"@emotion/memoize": "^0.8.0",
|
||||
"@emotion/sheet": "^1.2.0",
|
||||
"@emotion/utils": "^1.2.0",
|
||||
"@emotion/weak-memoize": "^0.3.0",
|
||||
"stylis": "4.0.13"
|
||||
}
|
||||
},
|
||||
"node_modules/@emotion/cache/node_modules/@emotion/memoize": {
|
||||
"version": "0.8.0",
|
||||
"resolved": "https://registry.npmjs.org/@emotion/memoize/-/memoize-0.8.0.tgz",
|
||||
"integrity": "sha512-G/YwXTkv7Den9mXDO7AhLWkE3q+I92B+VqAE+dYG4NGPaHZGvt3G8Q0p9vmE+sq7rTGphUbAvmQ9YpbfMQGGlA=="
|
||||
},
|
||||
"node_modules/@emotion/cache/node_modules/stylis": {
|
||||
"version": "4.0.13",
|
||||
"resolved": "https://registry.npmjs.org/stylis/-/stylis-4.0.13.tgz",
|
||||
"integrity": "sha512-xGPXiFVl4YED9Jh7Euv2V220mriG9u4B2TA6Ybjc1catrstKD2PpIdU3U0RKpkVBC2EhmL/F0sPCr9vrFTNRag=="
|
||||
},
|
||||
"node_modules/@emotion/hash": {
|
||||
"version": "0.8.0",
|
||||
"resolved": "https://registry.npmjs.org/@emotion/hash/-/hash-0.8.0.tgz",
|
||||
"integrity": "sha512-kBJtf7PH6aWwZ6fka3zQ0p6SBYzx4fl1LoZXE2RrnYST9Xljm7WfKJrU4g/Xr3Beg72MLrp1AWNUmuYJTL7Cow=="
|
||||
"version": "0.9.0",
|
||||
"resolved": "https://registry.npmjs.org/@emotion/hash/-/hash-0.9.0.tgz",
|
||||
"integrity": "sha512-14FtKiHhy2QoPIzdTcvh//8OyBlknNs2nXRwIhG904opCby3l+9Xaf/wuPvICBF0rc1ZCNBd3nKe9cd2mecVkQ=="
|
||||
},
|
||||
"node_modules/@emotion/is-prop-valid": {
|
||||
"version": "1.1.1",
|
||||
@@ -556,16 +642,16 @@
|
||||
"integrity": "sha512-igX9a37DR2ZPGYtV6suZ6whr8pTFtyHL3K/oLUotxpSVO2ASaprmAe2Dkq7tBo7CRY7MMDrAa9nuQP9/YG8FxQ=="
|
||||
},
|
||||
"node_modules/@emotion/react": {
|
||||
"version": "11.7.1",
|
||||
"resolved": "https://registry.npmjs.org/@emotion/react/-/react-11.7.1.tgz",
|
||||
"integrity": "sha512-DV2Xe3yhkF1yT4uAUoJcYL1AmrnO5SVsdfvu+fBuS7IbByDeTVx9+wFmvx9Idzv7/78+9Mgx2Hcmr7Fex3tIyw==",
|
||||
"version": "11.10.0",
|
||||
"resolved": "https://registry.npmjs.org/@emotion/react/-/react-11.10.0.tgz",
|
||||
"integrity": "sha512-K6z9zlHxxBXwN8TcpwBKcEsBsOw4JWCCmR+BeeOWgqp8GIU1yA2Odd41bwdAAr0ssbQrbJbVnndvv7oiv1bZeQ==",
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.13.10",
|
||||
"@emotion/cache": "^11.7.1",
|
||||
"@emotion/serialize": "^1.0.2",
|
||||
"@emotion/sheet": "^1.1.0",
|
||||
"@emotion/utils": "^1.0.0",
|
||||
"@emotion/weak-memoize": "^0.2.5",
|
||||
"@babel/runtime": "^7.18.3",
|
||||
"@emotion/babel-plugin": "^11.10.0",
|
||||
"@emotion/cache": "^11.10.0",
|
||||
"@emotion/serialize": "^1.1.0",
|
||||
"@emotion/utils": "^1.2.0",
|
||||
"@emotion/weak-memoize": "^0.3.0",
|
||||
"hoist-non-react-statics": "^3.3.1"
|
||||
},
|
||||
"peerDependencies": {
|
||||
@@ -582,21 +668,26 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@emotion/serialize": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/@emotion/serialize/-/serialize-1.0.2.tgz",
|
||||
"integrity": "sha512-95MgNJ9+/ajxU7QIAruiOAdYNjxZX7G2mhgrtDWswA21VviYIRP1R5QilZ/bDY42xiKsaktP4egJb3QdYQZi1A==",
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/@emotion/serialize/-/serialize-1.1.0.tgz",
|
||||
"integrity": "sha512-F1ZZZW51T/fx+wKbVlwsfchr5q97iW8brAnXmsskz4d0hVB4O3M/SiA3SaeH06x02lSNzkkQv+n3AX3kCXKSFA==",
|
||||
"dependencies": {
|
||||
"@emotion/hash": "^0.8.0",
|
||||
"@emotion/memoize": "^0.7.4",
|
||||
"@emotion/unitless": "^0.7.5",
|
||||
"@emotion/utils": "^1.0.0",
|
||||
"@emotion/hash": "^0.9.0",
|
||||
"@emotion/memoize": "^0.8.0",
|
||||
"@emotion/unitless": "^0.8.0",
|
||||
"@emotion/utils": "^1.2.0",
|
||||
"csstype": "^3.0.2"
|
||||
}
|
||||
},
|
||||
"node_modules/@emotion/serialize/node_modules/@emotion/memoize": {
|
||||
"version": "0.8.0",
|
||||
"resolved": "https://registry.npmjs.org/@emotion/memoize/-/memoize-0.8.0.tgz",
|
||||
"integrity": "sha512-G/YwXTkv7Den9mXDO7AhLWkE3q+I92B+VqAE+dYG4NGPaHZGvt3G8Q0p9vmE+sq7rTGphUbAvmQ9YpbfMQGGlA=="
|
||||
},
|
||||
"node_modules/@emotion/sheet": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/@emotion/sheet/-/sheet-1.1.0.tgz",
|
||||
"integrity": "sha512-u0AX4aSo25sMAygCuQTzS+HsImZFuS8llY8O7b9MDRzbJM0kVJlAz6KNDqcG7pOuQZJmj/8X/rAW+66kMnMW+g=="
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/@emotion/sheet/-/sheet-1.2.0.tgz",
|
||||
"integrity": "sha512-OiTkRgpxescko+M51tZsMq7Puu/KP55wMT8BgpcXVG2hqXc0Vo0mfymJ/Uj24Hp0i083ji/o0aLddh08UEjq8w=="
|
||||
},
|
||||
"node_modules/@emotion/styled": {
|
||||
"version": "11.6.0",
|
||||
@@ -624,19 +715,19 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@emotion/unitless": {
|
||||
"version": "0.7.5",
|
||||
"resolved": "https://registry.npmjs.org/@emotion/unitless/-/unitless-0.7.5.tgz",
|
||||
"integrity": "sha512-OWORNpfjMsSSUBVrRBVGECkhWcULOAJz9ZW8uK9qgxD+87M7jHRcvh/A96XXNhXTLmKcoYSQtBEX7lHMO7YRwg=="
|
||||
"version": "0.8.0",
|
||||
"resolved": "https://registry.npmjs.org/@emotion/unitless/-/unitless-0.8.0.tgz",
|
||||
"integrity": "sha512-VINS5vEYAscRl2ZUDiT3uMPlrFQupiKgHz5AA4bCH1miKBg4qtwkim1qPmJj/4WG6TreYMY111rEFsjupcOKHw=="
|
||||
},
|
||||
"node_modules/@emotion/utils": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@emotion/utils/-/utils-1.0.0.tgz",
|
||||
"integrity": "sha512-mQC2b3XLDs6QCW+pDQDiyO/EdGZYOygE8s5N5rrzjSI4M3IejPE/JPndCBwRT9z982aqQNi6beWs1UeayrQxxA=="
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/@emotion/utils/-/utils-1.2.0.tgz",
|
||||
"integrity": "sha512-sn3WH53Kzpw8oQ5mgMmIzzyAaH2ZqFEbozVVBSYp538E06OSE6ytOp7pRAjNQR+Q/orwqdQYJSe2m3hCOeznkw=="
|
||||
},
|
||||
"node_modules/@emotion/weak-memoize": {
|
||||
"version": "0.2.5",
|
||||
"resolved": "https://registry.npmjs.org/@emotion/weak-memoize/-/weak-memoize-0.2.5.tgz",
|
||||
"integrity": "sha512-6U71C2Wp7r5XtFtQzYrW5iKFT67OixrSxjI4MptCHzdSVlgabczzqLe0ZSgnub/5Kp4hSbpDB1tMytZY9pwxxA=="
|
||||
"version": "0.3.0",
|
||||
"resolved": "https://registry.npmjs.org/@emotion/weak-memoize/-/weak-memoize-0.3.0.tgz",
|
||||
"integrity": "sha512-AHPmaAx+RYfZz0eYu6Gviiagpmiyw98ySSlQvCUhVGDRtDFe4DBS0x1bSjdF3gqUDYOczB+yYvBTtEylYSdRhg=="
|
||||
},
|
||||
"node_modules/@eslint/eslintrc": {
|
||||
"version": "1.0.5",
|
||||
@@ -1293,6 +1384,11 @@
|
||||
"integrity": "sha512-eZxlbI8GZscaGS7kkc/trHTT5xgrjH3/1n2JDwusC9iahPKWMRvRjJSAN5mCXviuTGQ/lHnhvv8Q1YTpnfz9gA==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/@types/file-saver": {
|
||||
"version": "2.0.5",
|
||||
"resolved": "https://registry.npmjs.org/@types/file-saver/-/file-saver-2.0.5.tgz",
|
||||
"integrity": "sha512-zv9kNf3keYegP5oThGLaPk8E081DFDuwfqjtiTzm6PoxChdJ1raSuADf2YGCVIyrSynLrgc8JWv296s7Q7pQSQ=="
|
||||
},
|
||||
"node_modules/@types/hoist-non-react-statics": {
|
||||
"version": "3.3.1",
|
||||
"resolved": "https://registry.npmjs.org/@types/hoist-non-react-statics/-/hoist-non-react-statics-3.3.1.tgz",
|
||||
@@ -1359,6 +1455,14 @@
|
||||
"csstype": "^3.0.2"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/react-transition-group": {
|
||||
"version": "4.4.5",
|
||||
"resolved": "https://registry.npmjs.org/@types/react-transition-group/-/react-transition-group-4.4.5.tgz",
|
||||
"integrity": "sha512-juKD/eiSM3/xZYzjuzH6ZwpP+/lejltmiS3QEzV/vmb/Q8+HfDmxu+Baga8UEMGBqV88Nbg4l2hY/K2DkyaLLA==",
|
||||
"dependencies": {
|
||||
"@types/react": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/scheduler": {
|
||||
"version": "0.16.2",
|
||||
"resolved": "https://registry.npmjs.org/@types/scheduler/-/scheduler-0.16.2.tgz",
|
||||
@@ -1733,13 +1837,17 @@
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/babel-plugin-macros": {
|
||||
"version": "2.8.0",
|
||||
"resolved": "https://registry.npmjs.org/babel-plugin-macros/-/babel-plugin-macros-2.8.0.tgz",
|
||||
"integrity": "sha512-SEP5kJpfGYqYKpBrj5XU3ahw5p5GOHJ0U5ssOSQ/WBVdwkD2Dzlce95exQTs3jOVWPPKLBN2rlEWkCK7dSmLvg==",
|
||||
"version": "3.1.0",
|
||||
"resolved": "https://registry.npmjs.org/babel-plugin-macros/-/babel-plugin-macros-3.1.0.tgz",
|
||||
"integrity": "sha512-Cg7TFGpIr01vOQNODXOOaGz2NpCU5gl8x1qJFbb6hbZxR7XrcE2vtbAsTAbJ7/xwJtUuJEw8K8Zr/AE0LHlesg==",
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.7.2",
|
||||
"cosmiconfig": "^6.0.0",
|
||||
"resolve": "^1.12.0"
|
||||
"@babel/runtime": "^7.12.5",
|
||||
"cosmiconfig": "^7.0.0",
|
||||
"resolve": "^1.19.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10",
|
||||
"npm": ">=6"
|
||||
}
|
||||
},
|
||||
"node_modules/balanced-match": {
|
||||
@@ -1996,18 +2104,18 @@
|
||||
}
|
||||
},
|
||||
"node_modules/cosmiconfig": {
|
||||
"version": "6.0.0",
|
||||
"resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-6.0.0.tgz",
|
||||
"integrity": "sha512-xb3ZL6+L8b9JLLCx3ZdoZy4+2ECphCMo2PwqgP1tlfVq6M6YReyzBJtvWWtbDSpNr9hn96pkCiZqUcFEc+54Qg==",
|
||||
"version": "7.0.1",
|
||||
"resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-7.0.1.tgz",
|
||||
"integrity": "sha512-a1YWNUV2HwGimB7dU2s1wUMurNKjpx60HxBB6xUM8Re+2s1g1IIfJvFR0/iCF+XHdE0GMTKTuLR32UQff4TEyQ==",
|
||||
"dependencies": {
|
||||
"@types/parse-json": "^4.0.0",
|
||||
"import-fresh": "^3.1.0",
|
||||
"import-fresh": "^3.2.1",
|
||||
"parse-json": "^5.0.0",
|
||||
"path-type": "^4.0.0",
|
||||
"yaml": "^1.7.2"
|
||||
"yaml": "^1.10.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
"node": ">=10"
|
||||
}
|
||||
},
|
||||
"node_modules/cosmiconfig/node_modules/yaml": {
|
||||
@@ -2171,6 +2279,15 @@
|
||||
"node": ">=6.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/dom-helpers": {
|
||||
"version": "5.2.1",
|
||||
"resolved": "https://registry.npmjs.org/dom-helpers/-/dom-helpers-5.2.1.tgz",
|
||||
"integrity": "sha512-nRCa7CK3VTrM2NmGkIy4cbK7IZlgBE/PYMn55rrXefr5xXDP0LdtfPnblFDoVdcAfslJ7or6iqAUnx0CCGIWQA==",
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.8.7",
|
||||
"csstype": "^3.0.2"
|
||||
}
|
||||
},
|
||||
"node_modules/dom-serializer": {
|
||||
"version": "1.4.1",
|
||||
"resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-1.4.1.tgz",
|
||||
@@ -2663,18 +2780,6 @@
|
||||
"eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8"
|
||||
}
|
||||
},
|
||||
"node_modules/eslint-plugin-jsx-a11y/node_modules/@babel/runtime": {
|
||||
"version": "7.16.5",
|
||||
"resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.16.5.tgz",
|
||||
"integrity": "sha512-TXWihFIS3Pyv5hzR7j6ihmeLkZfrXGxAr5UfSl8CHf+6q/wpiYDkUau0czckpYG8QmnCIuPpdLtuA9VmuGGyMA==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"regenerator-runtime": "^0.13.4"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=6.9.0"
|
||||
}
|
||||
},
|
||||
"node_modules/eslint-plugin-react": {
|
||||
"version": "7.27.1",
|
||||
"resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.27.1.tgz",
|
||||
@@ -3050,6 +3155,12 @@
|
||||
"node": "^10.12.0 || >=12.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/file-saver": {
|
||||
"version": "2.0.5",
|
||||
"resolved": "https://registry.npmjs.org/file-saver/-/file-saver-2.0.5.tgz",
|
||||
"integrity": "sha512-P9bmyZ3h/PRG+Nzga+rbdI4OEpNDzAVyy74uVO9ATgzLK6VtAsYybF/+TOCvrc0MO793d6+42lLyZTw7/ArVzA==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/filename-reserved-regex": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/filename-reserved-regex/-/filename-reserved-regex-2.0.0.tgz",
|
||||
@@ -3404,6 +3515,11 @@
|
||||
"void-elements": "3.1.0"
|
||||
}
|
||||
},
|
||||
"node_modules/html-to-image": {
|
||||
"version": "1.10.6",
|
||||
"resolved": "https://registry.npmjs.org/html-to-image/-/html-to-image-1.10.6.tgz",
|
||||
"integrity": "sha512-+iFUWRJDmRRB92IxEAVoiuYQQXRp91yuI4Om7+lswwL3OOzoQ+H7laGLuZFK6ks2Z6Nz0wYm0UzahIO+D1Zxag=="
|
||||
},
|
||||
"node_modules/htmlparser2": {
|
||||
"version": "6.1.0",
|
||||
"resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-6.1.0.tgz",
|
||||
@@ -4011,6 +4127,11 @@
|
||||
"integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/memoize-one": {
|
||||
"version": "5.2.1",
|
||||
"resolved": "https://registry.npmjs.org/memoize-one/-/memoize-one-5.2.1.tgz",
|
||||
"integrity": "sha512-zYiwtZUcYyXKo/np96AGZAckk+FWWsUdJ3cHGGmld7+AhvcWmQyGCYUh1hc4Q/pkOhb65dQR/pqCyK0cOaHz4Q=="
|
||||
},
|
||||
"node_modules/memorystream": {
|
||||
"version": "0.3.1",
|
||||
"resolved": "https://registry.npmjs.org/memorystream/-/memorystream-0.3.1.tgz",
|
||||
@@ -4711,7 +4832,6 @@
|
||||
"version": "15.7.2",
|
||||
"resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.7.2.tgz",
|
||||
"integrity": "sha512-8QQikdH7//R2vurIJSutZ1smHYTcLpRWEOlHnzcWHmBYrOGUysKwSsrC89BCiFj3CbrfJ/nXFdJepOVrY1GCHQ==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"loose-envify": "^1.4.0",
|
||||
"object-assign": "^4.1.1",
|
||||
@@ -4721,8 +4841,7 @@
|
||||
"node_modules/prop-types/node_modules/react-is": {
|
||||
"version": "16.13.1",
|
||||
"resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz",
|
||||
"integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==",
|
||||
"dev": true
|
||||
"integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ=="
|
||||
},
|
||||
"node_modules/punycode": {
|
||||
"version": "2.1.1",
|
||||
@@ -4838,6 +4957,39 @@
|
||||
"react-dom": "^15.0.0 || ^16.0.0 || ^17.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/react-select": {
|
||||
"version": "5.4.0",
|
||||
"resolved": "https://registry.npmjs.org/react-select/-/react-select-5.4.0.tgz",
|
||||
"integrity": "sha512-CjE9RFLUvChd5SdlfG4vqxZd55AZJRrLrHzkQyTYeHlpOztqcgnyftYAolJ0SGsBev6zAs6qFrjm6KU3eo2hzg==",
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.12.0",
|
||||
"@emotion/cache": "^11.4.0",
|
||||
"@emotion/react": "^11.8.1",
|
||||
"@types/react-transition-group": "^4.4.0",
|
||||
"memoize-one": "^5.0.0",
|
||||
"prop-types": "^15.6.0",
|
||||
"react-transition-group": "^4.3.0"
|
||||
},
|
||||
"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-transition-group": {
|
||||
"version": "4.4.5",
|
||||
"resolved": "https://registry.npmjs.org/react-transition-group/-/react-transition-group-4.4.5.tgz",
|
||||
"integrity": "sha512-pZcd1MCJoiKiBR2NRxeCRg13uCXbydPnmB4EOeRrY7480qNWO8IIgQG6zlDkm6uRMsURXPuKq0GWtiM59a5Q6g==",
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.5.5",
|
||||
"dom-helpers": "^5.0.1",
|
||||
"loose-envify": "^1.4.0",
|
||||
"prop-types": "^15.6.2"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": ">=16.6.0",
|
||||
"react-dom": ">=16.6.0"
|
||||
}
|
||||
},
|
||||
"node_modules/read-pkg": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-3.0.0.tgz",
|
||||
@@ -5752,9 +5904,9 @@
|
||||
}
|
||||
},
|
||||
"@babel/helper-plugin-utils": {
|
||||
"version": "7.14.5",
|
||||
"resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.14.5.tgz",
|
||||
"integrity": "sha512-/37qQCE3K0vvZKwoK4XU/irIJQdIfCJuhU5eKnNxpFDsOkgFaUAwbv+RYw6eYgsC0E4hS7r5KqGULUogqui0fQ=="
|
||||
"version": "7.18.9",
|
||||
"resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.18.9.tgz",
|
||||
"integrity": "sha512-aBXPT3bmtLryXaoJLyYPXPlSD4p1ld9aYeR+sJNOZjJJGiOpb+fKfh3NkcCu7J54nUJwCERPBExCCpyCOHnu/w=="
|
||||
},
|
||||
"@babel/helper-simple-access": {
|
||||
"version": "7.18.6",
|
||||
@@ -5813,17 +5965,17 @@
|
||||
"peer": true
|
||||
},
|
||||
"@babel/plugin-syntax-jsx": {
|
||||
"version": "7.14.5",
|
||||
"resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.14.5.tgz",
|
||||
"integrity": "sha512-ohuFIsOMXJnbOMRfX7/w7LocdR6R7whhuRD4ax8IipLcLPlZGJKkBxgHp++U4N/vKyU16/YDQr2f5seajD3jIw==",
|
||||
"version": "7.18.6",
|
||||
"resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.18.6.tgz",
|
||||
"integrity": "sha512-6mmljtAedFGTWu2p/8WIORGwy+61PLgOMPOdazc7YoJ9ZCWUyFy3A6CpPkRKLKD1ToAesxX8KGEViAiLo9N+7Q==",
|
||||
"requires": {
|
||||
"@babel/helper-plugin-utils": "^7.14.5"
|
||||
"@babel/helper-plugin-utils": "^7.18.6"
|
||||
}
|
||||
},
|
||||
"@babel/runtime": {
|
||||
"version": "7.15.4",
|
||||
"resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.15.4.tgz",
|
||||
"integrity": "sha512-99catp6bHCaxr4sJ/DbTGgHS4+Rs2RVd2g7iOap6SLGPDknRK9ztKNsE/Fg6QhSeh1FGE5f6gHGQmvvn3I3xhw==",
|
||||
"version": "7.18.9",
|
||||
"resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.18.9.tgz",
|
||||
"integrity": "sha512-lkqXDcvlFT5rvEjiu6+QYO+1GXrEHRo2LOtS7E4GtX5ESIZOgepqsZBVIj6Pv+a6zqsya9VCgiK1KAK4BvJDAw==",
|
||||
"requires": {
|
||||
"regenerator-runtime": "^0.13.4"
|
||||
}
|
||||
@@ -5914,18 +6066,81 @@
|
||||
"@cspotcode/source-map-consumer": "0.8.0"
|
||||
}
|
||||
},
|
||||
"@emotion/babel-plugin": {
|
||||
"version": "11.7.1",
|
||||
"resolved": "https://registry.npmjs.org/@emotion/babel-plugin/-/babel-plugin-11.7.1.tgz",
|
||||
"integrity": "sha512-K3/6Y+J/sIAjplf3uIteWLhPuOyuMNnE+iyYnTF/m294vc6IL90kTHp7y8ldZYbpKlP17rpOWDKM9DvTcrOmNQ==",
|
||||
"@dnd-kit/accessibility": {
|
||||
"version": "3.0.1",
|
||||
"resolved": "https://registry.npmjs.org/@dnd-kit/accessibility/-/accessibility-3.0.1.tgz",
|
||||
"integrity": "sha512-HXRrwS9YUYQO9lFRc/49uO/VICbM+O+ZRpFDe9Pd1rwVv2PCNkRiTZRdxrDgng/UkvdC3Re9r2vwPpXXrWeFzg==",
|
||||
"requires": {
|
||||
"@babel/helper-module-imports": "^7.12.13",
|
||||
"@babel/plugin-syntax-jsx": "^7.12.13",
|
||||
"@babel/runtime": "^7.13.10",
|
||||
"@emotion/hash": "^0.8.0",
|
||||
"@emotion/memoize": "^0.7.5",
|
||||
"@emotion/serialize": "^1.0.2",
|
||||
"babel-plugin-macros": "^2.6.1",
|
||||
"tslib": "^2.0.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"tslib": {
|
||||
"version": "2.4.0",
|
||||
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz",
|
||||
"integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ=="
|
||||
}
|
||||
}
|
||||
},
|
||||
"@dnd-kit/core": {
|
||||
"version": "6.0.5",
|
||||
"resolved": "https://registry.npmjs.org/@dnd-kit/core/-/core-6.0.5.tgz",
|
||||
"integrity": "sha512-3nL+Zy5cT+1XwsWdlXIvGIFvbuocMyB4NBxTN74DeBaBqeWdH9JsnKwQv7buZQgAHmAH+eIENfS1ginkvW6bCw==",
|
||||
"requires": {
|
||||
"@dnd-kit/accessibility": "^3.0.0",
|
||||
"@dnd-kit/utilities": "^3.2.0",
|
||||
"tslib": "^2.0.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"tslib": {
|
||||
"version": "2.4.0",
|
||||
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz",
|
||||
"integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ=="
|
||||
}
|
||||
}
|
||||
},
|
||||
"@dnd-kit/sortable": {
|
||||
"version": "7.0.1",
|
||||
"resolved": "https://registry.npmjs.org/@dnd-kit/sortable/-/sortable-7.0.1.tgz",
|
||||
"integrity": "sha512-n77qAzJQtMMywu25sJzhz3gsHnDOUlEjTtnRl8A87rWIhnu32zuP+7zmFjwGgvqfXmRufqiHOSlH7JPC/tnJ8Q==",
|
||||
"requires": {
|
||||
"@dnd-kit/utilities": "^3.2.0",
|
||||
"tslib": "^2.0.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"tslib": {
|
||||
"version": "2.4.0",
|
||||
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz",
|
||||
"integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ=="
|
||||
}
|
||||
}
|
||||
},
|
||||
"@dnd-kit/utilities": {
|
||||
"version": "3.2.0",
|
||||
"resolved": "https://registry.npmjs.org/@dnd-kit/utilities/-/utilities-3.2.0.tgz",
|
||||
"integrity": "sha512-h65/pn2IPCCIWwdlR2BMLqRkDxpTEONA+HQW3n765HBijLYGyrnTCLa2YQt8VVjjSQD6EfFlTE6aS2Q/b6nb2g==",
|
||||
"requires": {
|
||||
"tslib": "^2.0.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"tslib": {
|
||||
"version": "2.4.0",
|
||||
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz",
|
||||
"integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ=="
|
||||
}
|
||||
}
|
||||
},
|
||||
"@emotion/babel-plugin": {
|
||||
"version": "11.10.2",
|
||||
"resolved": "https://registry.npmjs.org/@emotion/babel-plugin/-/babel-plugin-11.10.2.tgz",
|
||||
"integrity": "sha512-xNQ57njWTFVfPAc3cjfuaPdsgLp5QOSuRsj9MA6ndEhH/AzuZM86qIQzt6rq+aGBwj3n5/TkLmU5lhAfdRmogA==",
|
||||
"requires": {
|
||||
"@babel/helper-module-imports": "^7.16.7",
|
||||
"@babel/plugin-syntax-jsx": "^7.17.12",
|
||||
"@babel/runtime": "^7.18.3",
|
||||
"@emotion/hash": "^0.9.0",
|
||||
"@emotion/memoize": "^0.8.0",
|
||||
"@emotion/serialize": "^1.1.0",
|
||||
"babel-plugin-macros": "^3.1.0",
|
||||
"convert-source-map": "^1.5.0",
|
||||
"escape-string-regexp": "^4.0.0",
|
||||
"find-root": "^1.1.0",
|
||||
@@ -5933,6 +6148,11 @@
|
||||
"stylis": "4.0.13"
|
||||
},
|
||||
"dependencies": {
|
||||
"@emotion/memoize": {
|
||||
"version": "0.8.0",
|
||||
"resolved": "https://registry.npmjs.org/@emotion/memoize/-/memoize-0.8.0.tgz",
|
||||
"integrity": "sha512-G/YwXTkv7Den9mXDO7AhLWkE3q+I92B+VqAE+dYG4NGPaHZGvt3G8Q0p9vmE+sq7rTGphUbAvmQ9YpbfMQGGlA=="
|
||||
},
|
||||
"escape-string-regexp": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz",
|
||||
@@ -5951,17 +6171,22 @@
|
||||
}
|
||||
},
|
||||
"@emotion/cache": {
|
||||
"version": "11.7.1",
|
||||
"resolved": "https://registry.npmjs.org/@emotion/cache/-/cache-11.7.1.tgz",
|
||||
"integrity": "sha512-r65Zy4Iljb8oyjtLeCuBH8Qjiy107dOYC6SJq7g7GV5UCQWMObY4SJDPGFjiiVpPrOJ2hmJOoBiYTC7hwx9E2A==",
|
||||
"version": "11.10.3",
|
||||
"resolved": "https://registry.npmjs.org/@emotion/cache/-/cache-11.10.3.tgz",
|
||||
"integrity": "sha512-Psmp/7ovAa8appWh3g51goxu/z3iVms7JXOreq136D8Bbn6dYraPnmL6mdM8GThEx9vwSn92Fz+mGSjBzN8UPQ==",
|
||||
"requires": {
|
||||
"@emotion/memoize": "^0.7.4",
|
||||
"@emotion/sheet": "^1.1.0",
|
||||
"@emotion/utils": "^1.0.0",
|
||||
"@emotion/weak-memoize": "^0.2.5",
|
||||
"@emotion/memoize": "^0.8.0",
|
||||
"@emotion/sheet": "^1.2.0",
|
||||
"@emotion/utils": "^1.2.0",
|
||||
"@emotion/weak-memoize": "^0.3.0",
|
||||
"stylis": "4.0.13"
|
||||
},
|
||||
"dependencies": {
|
||||
"@emotion/memoize": {
|
||||
"version": "0.8.0",
|
||||
"resolved": "https://registry.npmjs.org/@emotion/memoize/-/memoize-0.8.0.tgz",
|
||||
"integrity": "sha512-G/YwXTkv7Den9mXDO7AhLWkE3q+I92B+VqAE+dYG4NGPaHZGvt3G8Q0p9vmE+sq7rTGphUbAvmQ9YpbfMQGGlA=="
|
||||
},
|
||||
"stylis": {
|
||||
"version": "4.0.13",
|
||||
"resolved": "https://registry.npmjs.org/stylis/-/stylis-4.0.13.tgz",
|
||||
@@ -5970,9 +6195,9 @@
|
||||
}
|
||||
},
|
||||
"@emotion/hash": {
|
||||
"version": "0.8.0",
|
||||
"resolved": "https://registry.npmjs.org/@emotion/hash/-/hash-0.8.0.tgz",
|
||||
"integrity": "sha512-kBJtf7PH6aWwZ6fka3zQ0p6SBYzx4fl1LoZXE2RrnYST9Xljm7WfKJrU4g/Xr3Beg72MLrp1AWNUmuYJTL7Cow=="
|
||||
"version": "0.9.0",
|
||||
"resolved": "https://registry.npmjs.org/@emotion/hash/-/hash-0.9.0.tgz",
|
||||
"integrity": "sha512-14FtKiHhy2QoPIzdTcvh//8OyBlknNs2nXRwIhG904opCby3l+9Xaf/wuPvICBF0rc1ZCNBd3nKe9cd2mecVkQ=="
|
||||
},
|
||||
"@emotion/is-prop-valid": {
|
||||
"version": "1.1.1",
|
||||
@@ -5988,35 +6213,42 @@
|
||||
"integrity": "sha512-igX9a37DR2ZPGYtV6suZ6whr8pTFtyHL3K/oLUotxpSVO2ASaprmAe2Dkq7tBo7CRY7MMDrAa9nuQP9/YG8FxQ=="
|
||||
},
|
||||
"@emotion/react": {
|
||||
"version": "11.7.1",
|
||||
"resolved": "https://registry.npmjs.org/@emotion/react/-/react-11.7.1.tgz",
|
||||
"integrity": "sha512-DV2Xe3yhkF1yT4uAUoJcYL1AmrnO5SVsdfvu+fBuS7IbByDeTVx9+wFmvx9Idzv7/78+9Mgx2Hcmr7Fex3tIyw==",
|
||||
"version": "11.10.0",
|
||||
"resolved": "https://registry.npmjs.org/@emotion/react/-/react-11.10.0.tgz",
|
||||
"integrity": "sha512-K6z9zlHxxBXwN8TcpwBKcEsBsOw4JWCCmR+BeeOWgqp8GIU1yA2Odd41bwdAAr0ssbQrbJbVnndvv7oiv1bZeQ==",
|
||||
"requires": {
|
||||
"@babel/runtime": "^7.13.10",
|
||||
"@emotion/cache": "^11.7.1",
|
||||
"@emotion/serialize": "^1.0.2",
|
||||
"@emotion/sheet": "^1.1.0",
|
||||
"@emotion/utils": "^1.0.0",
|
||||
"@emotion/weak-memoize": "^0.2.5",
|
||||
"@babel/runtime": "^7.18.3",
|
||||
"@emotion/babel-plugin": "^11.10.0",
|
||||
"@emotion/cache": "^11.10.0",
|
||||
"@emotion/serialize": "^1.1.0",
|
||||
"@emotion/utils": "^1.2.0",
|
||||
"@emotion/weak-memoize": "^0.3.0",
|
||||
"hoist-non-react-statics": "^3.3.1"
|
||||
}
|
||||
},
|
||||
"@emotion/serialize": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/@emotion/serialize/-/serialize-1.0.2.tgz",
|
||||
"integrity": "sha512-95MgNJ9+/ajxU7QIAruiOAdYNjxZX7G2mhgrtDWswA21VviYIRP1R5QilZ/bDY42xiKsaktP4egJb3QdYQZi1A==",
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/@emotion/serialize/-/serialize-1.1.0.tgz",
|
||||
"integrity": "sha512-F1ZZZW51T/fx+wKbVlwsfchr5q97iW8brAnXmsskz4d0hVB4O3M/SiA3SaeH06x02lSNzkkQv+n3AX3kCXKSFA==",
|
||||
"requires": {
|
||||
"@emotion/hash": "^0.8.0",
|
||||
"@emotion/memoize": "^0.7.4",
|
||||
"@emotion/unitless": "^0.7.5",
|
||||
"@emotion/utils": "^1.0.0",
|
||||
"@emotion/hash": "^0.9.0",
|
||||
"@emotion/memoize": "^0.8.0",
|
||||
"@emotion/unitless": "^0.8.0",
|
||||
"@emotion/utils": "^1.2.0",
|
||||
"csstype": "^3.0.2"
|
||||
},
|
||||
"dependencies": {
|
||||
"@emotion/memoize": {
|
||||
"version": "0.8.0",
|
||||
"resolved": "https://registry.npmjs.org/@emotion/memoize/-/memoize-0.8.0.tgz",
|
||||
"integrity": "sha512-G/YwXTkv7Den9mXDO7AhLWkE3q+I92B+VqAE+dYG4NGPaHZGvt3G8Q0p9vmE+sq7rTGphUbAvmQ9YpbfMQGGlA=="
|
||||
}
|
||||
}
|
||||
},
|
||||
"@emotion/sheet": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/@emotion/sheet/-/sheet-1.1.0.tgz",
|
||||
"integrity": "sha512-u0AX4aSo25sMAygCuQTzS+HsImZFuS8llY8O7b9MDRzbJM0kVJlAz6KNDqcG7pOuQZJmj/8X/rAW+66kMnMW+g=="
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/@emotion/sheet/-/sheet-1.2.0.tgz",
|
||||
"integrity": "sha512-OiTkRgpxescko+M51tZsMq7Puu/KP55wMT8BgpcXVG2hqXc0Vo0mfymJ/Uj24Hp0i083ji/o0aLddh08UEjq8w=="
|
||||
},
|
||||
"@emotion/styled": {
|
||||
"version": "11.6.0",
|
||||
@@ -6031,19 +6263,19 @@
|
||||
}
|
||||
},
|
||||
"@emotion/unitless": {
|
||||
"version": "0.7.5",
|
||||
"resolved": "https://registry.npmjs.org/@emotion/unitless/-/unitless-0.7.5.tgz",
|
||||
"integrity": "sha512-OWORNpfjMsSSUBVrRBVGECkhWcULOAJz9ZW8uK9qgxD+87M7jHRcvh/A96XXNhXTLmKcoYSQtBEX7lHMO7YRwg=="
|
||||
"version": "0.8.0",
|
||||
"resolved": "https://registry.npmjs.org/@emotion/unitless/-/unitless-0.8.0.tgz",
|
||||
"integrity": "sha512-VINS5vEYAscRl2ZUDiT3uMPlrFQupiKgHz5AA4bCH1miKBg4qtwkim1qPmJj/4WG6TreYMY111rEFsjupcOKHw=="
|
||||
},
|
||||
"@emotion/utils": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@emotion/utils/-/utils-1.0.0.tgz",
|
||||
"integrity": "sha512-mQC2b3XLDs6QCW+pDQDiyO/EdGZYOygE8s5N5rrzjSI4M3IejPE/JPndCBwRT9z982aqQNi6beWs1UeayrQxxA=="
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/@emotion/utils/-/utils-1.2.0.tgz",
|
||||
"integrity": "sha512-sn3WH53Kzpw8oQ5mgMmIzzyAaH2ZqFEbozVVBSYp538E06OSE6ytOp7pRAjNQR+Q/orwqdQYJSe2m3hCOeznkw=="
|
||||
},
|
||||
"@emotion/weak-memoize": {
|
||||
"version": "0.2.5",
|
||||
"resolved": "https://registry.npmjs.org/@emotion/weak-memoize/-/weak-memoize-0.2.5.tgz",
|
||||
"integrity": "sha512-6U71C2Wp7r5XtFtQzYrW5iKFT67OixrSxjI4MptCHzdSVlgabczzqLe0ZSgnub/5Kp4hSbpDB1tMytZY9pwxxA=="
|
||||
"version": "0.3.0",
|
||||
"resolved": "https://registry.npmjs.org/@emotion/weak-memoize/-/weak-memoize-0.3.0.tgz",
|
||||
"integrity": "sha512-AHPmaAx+RYfZz0eYu6Gviiagpmiyw98ySSlQvCUhVGDRtDFe4DBS0x1bSjdF3gqUDYOczB+yYvBTtEylYSdRhg=="
|
||||
},
|
||||
"@eslint/eslintrc": {
|
||||
"version": "1.0.5",
|
||||
@@ -6532,6 +6764,11 @@
|
||||
"integrity": "sha512-eZxlbI8GZscaGS7kkc/trHTT5xgrjH3/1n2JDwusC9iahPKWMRvRjJSAN5mCXviuTGQ/lHnhvv8Q1YTpnfz9gA==",
|
||||
"dev": true
|
||||
},
|
||||
"@types/file-saver": {
|
||||
"version": "2.0.5",
|
||||
"resolved": "https://registry.npmjs.org/@types/file-saver/-/file-saver-2.0.5.tgz",
|
||||
"integrity": "sha512-zv9kNf3keYegP5oThGLaPk8E081DFDuwfqjtiTzm6PoxChdJ1raSuADf2YGCVIyrSynLrgc8JWv296s7Q7pQSQ=="
|
||||
},
|
||||
"@types/hoist-non-react-statics": {
|
||||
"version": "3.3.1",
|
||||
"resolved": "https://registry.npmjs.org/@types/hoist-non-react-statics/-/hoist-non-react-statics-3.3.1.tgz",
|
||||
@@ -6598,6 +6835,14 @@
|
||||
"csstype": "^3.0.2"
|
||||
}
|
||||
},
|
||||
"@types/react-transition-group": {
|
||||
"version": "4.4.5",
|
||||
"resolved": "https://registry.npmjs.org/@types/react-transition-group/-/react-transition-group-4.4.5.tgz",
|
||||
"integrity": "sha512-juKD/eiSM3/xZYzjuzH6ZwpP+/lejltmiS3QEzV/vmb/Q8+HfDmxu+Baga8UEMGBqV88Nbg4l2hY/K2DkyaLLA==",
|
||||
"requires": {
|
||||
"@types/react": "*"
|
||||
}
|
||||
},
|
||||
"@types/scheduler": {
|
||||
"version": "0.16.2",
|
||||
"resolved": "https://registry.npmjs.org/@types/scheduler/-/scheduler-0.16.2.tgz",
|
||||
@@ -6855,13 +7100,13 @@
|
||||
"dev": true
|
||||
},
|
||||
"babel-plugin-macros": {
|
||||
"version": "2.8.0",
|
||||
"resolved": "https://registry.npmjs.org/babel-plugin-macros/-/babel-plugin-macros-2.8.0.tgz",
|
||||
"integrity": "sha512-SEP5kJpfGYqYKpBrj5XU3ahw5p5GOHJ0U5ssOSQ/WBVdwkD2Dzlce95exQTs3jOVWPPKLBN2rlEWkCK7dSmLvg==",
|
||||
"version": "3.1.0",
|
||||
"resolved": "https://registry.npmjs.org/babel-plugin-macros/-/babel-plugin-macros-3.1.0.tgz",
|
||||
"integrity": "sha512-Cg7TFGpIr01vOQNODXOOaGz2NpCU5gl8x1qJFbb6hbZxR7XrcE2vtbAsTAbJ7/xwJtUuJEw8K8Zr/AE0LHlesg==",
|
||||
"requires": {
|
||||
"@babel/runtime": "^7.7.2",
|
||||
"cosmiconfig": "^6.0.0",
|
||||
"resolve": "^1.12.0"
|
||||
"@babel/runtime": "^7.12.5",
|
||||
"cosmiconfig": "^7.0.0",
|
||||
"resolve": "^1.19.0"
|
||||
}
|
||||
},
|
||||
"balanced-match": {
|
||||
@@ -7056,15 +7301,15 @@
|
||||
"dev": true
|
||||
},
|
||||
"cosmiconfig": {
|
||||
"version": "6.0.0",
|
||||
"resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-6.0.0.tgz",
|
||||
"integrity": "sha512-xb3ZL6+L8b9JLLCx3ZdoZy4+2ECphCMo2PwqgP1tlfVq6M6YReyzBJtvWWtbDSpNr9hn96pkCiZqUcFEc+54Qg==",
|
||||
"version": "7.0.1",
|
||||
"resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-7.0.1.tgz",
|
||||
"integrity": "sha512-a1YWNUV2HwGimB7dU2s1wUMurNKjpx60HxBB6xUM8Re+2s1g1IIfJvFR0/iCF+XHdE0GMTKTuLR32UQff4TEyQ==",
|
||||
"requires": {
|
||||
"@types/parse-json": "^4.0.0",
|
||||
"import-fresh": "^3.1.0",
|
||||
"import-fresh": "^3.2.1",
|
||||
"parse-json": "^5.0.0",
|
||||
"path-type": "^4.0.0",
|
||||
"yaml": "^1.7.2"
|
||||
"yaml": "^1.10.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"yaml": {
|
||||
@@ -7190,6 +7435,15 @@
|
||||
"esutils": "^2.0.2"
|
||||
}
|
||||
},
|
||||
"dom-helpers": {
|
||||
"version": "5.2.1",
|
||||
"resolved": "https://registry.npmjs.org/dom-helpers/-/dom-helpers-5.2.1.tgz",
|
||||
"integrity": "sha512-nRCa7CK3VTrM2NmGkIy4cbK7IZlgBE/PYMn55rrXefr5xXDP0LdtfPnblFDoVdcAfslJ7or6iqAUnx0CCGIWQA==",
|
||||
"requires": {
|
||||
"@babel/runtime": "^7.8.7",
|
||||
"csstype": "^3.0.2"
|
||||
}
|
||||
},
|
||||
"dom-serializer": {
|
||||
"version": "1.4.1",
|
||||
"resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-1.4.1.tgz",
|
||||
@@ -7663,17 +7917,6 @@
|
||||
"jsx-ast-utils": "^3.2.1",
|
||||
"language-tags": "^1.0.5",
|
||||
"minimatch": "^3.0.4"
|
||||
},
|
||||
"dependencies": {
|
||||
"@babel/runtime": {
|
||||
"version": "7.16.5",
|
||||
"resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.16.5.tgz",
|
||||
"integrity": "sha512-TXWihFIS3Pyv5hzR7j6ihmeLkZfrXGxAr5UfSl8CHf+6q/wpiYDkUau0czckpYG8QmnCIuPpdLtuA9VmuGGyMA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"regenerator-runtime": "^0.13.4"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"eslint-plugin-react": {
|
||||
@@ -7863,6 +8106,12 @@
|
||||
"flat-cache": "^3.0.4"
|
||||
}
|
||||
},
|
||||
"file-saver": {
|
||||
"version": "2.0.5",
|
||||
"resolved": "https://registry.npmjs.org/file-saver/-/file-saver-2.0.5.tgz",
|
||||
"integrity": "sha512-P9bmyZ3h/PRG+Nzga+rbdI4OEpNDzAVyy74uVO9ATgzLK6VtAsYybF/+TOCvrc0MO793d6+42lLyZTw7/ArVzA==",
|
||||
"dev": true
|
||||
},
|
||||
"filename-reserved-regex": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/filename-reserved-regex/-/filename-reserved-regex-2.0.0.tgz",
|
||||
@@ -8122,6 +8371,11 @@
|
||||
"void-elements": "3.1.0"
|
||||
}
|
||||
},
|
||||
"html-to-image": {
|
||||
"version": "1.10.6",
|
||||
"resolved": "https://registry.npmjs.org/html-to-image/-/html-to-image-1.10.6.tgz",
|
||||
"integrity": "sha512-+iFUWRJDmRRB92IxEAVoiuYQQXRp91yuI4Om7+lswwL3OOzoQ+H7laGLuZFK6ks2Z6Nz0wYm0UzahIO+D1Zxag=="
|
||||
},
|
||||
"htmlparser2": {
|
||||
"version": "6.1.0",
|
||||
"resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-6.1.0.tgz",
|
||||
@@ -8576,6 +8830,11 @@
|
||||
"integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==",
|
||||
"dev": true
|
||||
},
|
||||
"memoize-one": {
|
||||
"version": "5.2.1",
|
||||
"resolved": "https://registry.npmjs.org/memoize-one/-/memoize-one-5.2.1.tgz",
|
||||
"integrity": "sha512-zYiwtZUcYyXKo/np96AGZAckk+FWWsUdJ3cHGGmld7+AhvcWmQyGCYUh1hc4Q/pkOhb65dQR/pqCyK0cOaHz4Q=="
|
||||
},
|
||||
"memorystream": {
|
||||
"version": "0.3.1",
|
||||
"resolved": "https://registry.npmjs.org/memorystream/-/memorystream-0.3.1.tgz",
|
||||
@@ -9083,7 +9342,6 @@
|
||||
"version": "15.7.2",
|
||||
"resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.7.2.tgz",
|
||||
"integrity": "sha512-8QQikdH7//R2vurIJSutZ1smHYTcLpRWEOlHnzcWHmBYrOGUysKwSsrC89BCiFj3CbrfJ/nXFdJepOVrY1GCHQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"loose-envify": "^1.4.0",
|
||||
"object-assign": "^4.1.1",
|
||||
@@ -9093,8 +9351,7 @@
|
||||
"react-is": {
|
||||
"version": "16.13.1",
|
||||
"resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz",
|
||||
"integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==",
|
||||
"dev": true
|
||||
"integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ=="
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -9163,6 +9420,31 @@
|
||||
"easy-bem": "^1.1.1"
|
||||
}
|
||||
},
|
||||
"react-select": {
|
||||
"version": "5.4.0",
|
||||
"resolved": "https://registry.npmjs.org/react-select/-/react-select-5.4.0.tgz",
|
||||
"integrity": "sha512-CjE9RFLUvChd5SdlfG4vqxZd55AZJRrLrHzkQyTYeHlpOztqcgnyftYAolJ0SGsBev6zAs6qFrjm6KU3eo2hzg==",
|
||||
"requires": {
|
||||
"@babel/runtime": "^7.12.0",
|
||||
"@emotion/cache": "^11.4.0",
|
||||
"@emotion/react": "^11.8.1",
|
||||
"@types/react-transition-group": "^4.4.0",
|
||||
"memoize-one": "^5.0.0",
|
||||
"prop-types": "^15.6.0",
|
||||
"react-transition-group": "^4.3.0"
|
||||
}
|
||||
},
|
||||
"react-transition-group": {
|
||||
"version": "4.4.5",
|
||||
"resolved": "https://registry.npmjs.org/react-transition-group/-/react-transition-group-4.4.5.tgz",
|
||||
"integrity": "sha512-pZcd1MCJoiKiBR2NRxeCRg13uCXbydPnmB4EOeRrY7480qNWO8IIgQG6zlDkm6uRMsURXPuKq0GWtiM59a5Q6g==",
|
||||
"requires": {
|
||||
"@babel/runtime": "^7.5.5",
|
||||
"dom-helpers": "^5.0.1",
|
||||
"loose-envify": "^1.4.0",
|
||||
"prop-types": "^15.6.2"
|
||||
}
|
||||
},
|
||||
"read-pkg": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-3.0.0.tgz",
|
||||
|
||||
+8
-1
@@ -4,9 +4,14 @@
|
||||
"description": "",
|
||||
"main": "index.js",
|
||||
"dependencies": {
|
||||
"@dnd-kit/core": "^6.0.5",
|
||||
"@dnd-kit/sortable": "^7.0.1",
|
||||
"@dnd-kit/utilities": "^3.2.0",
|
||||
"@mdi/js": "^6.5.95",
|
||||
"@mdi/react": "^1.5.0",
|
||||
"@types/file-saver": "^2.0.5",
|
||||
"date-fns": "^2.27.0",
|
||||
"html-to-image": "^1.10.6",
|
||||
"next": "^12.1.6",
|
||||
"next-i18next": "^10.1.0",
|
||||
"nprogress": "^0.2.0",
|
||||
@@ -15,6 +20,7 @@
|
||||
"react": "^17.0.2",
|
||||
"react-dom": "^17.0.2",
|
||||
"react-indiana-drag-scroll": "^2.1.0",
|
||||
"react-select": "^5.4.0",
|
||||
"theme-ui": "^0.12.1",
|
||||
"yaml": "^2.1.1"
|
||||
},
|
||||
@@ -26,6 +32,7 @@
|
||||
"cheerio": "^1.0.0-rc.10",
|
||||
"eslint": "8.5.0",
|
||||
"eslint-config-next": "12.0.7",
|
||||
"file-saver": "^2.0.5",
|
||||
"filenamify": "^4.3.0",
|
||||
"http-server": "^14.1.0",
|
||||
"node-fetch": "^2.6.7",
|
||||
@@ -37,7 +44,7 @@
|
||||
"scripts": {
|
||||
"dev": "run-p dev:web dev:assets",
|
||||
"dev:web": "next dev -p 4000",
|
||||
"dev:assets": "http-server assets -p 4001 -s",
|
||||
"dev:assets": "http-server assets -p 4001 -s --cors",
|
||||
"build": "npm run compile:novels && next build",
|
||||
"start": "next start",
|
||||
"lint": "next lint",
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 811 KiB |
@@ -0,0 +1,104 @@
|
||||
import { useMemo } from 'react'
|
||||
import ReactSelect, { components } from 'react-select'
|
||||
import { Flex, Image } from 'theme-ui'
|
||||
import { assetsBucketBaseUrl } from '../../../lib/consts'
|
||||
import { BattlesuitData } from '../../../lib/honkai3rd/battlesuits'
|
||||
|
||||
interface BattlesuitSelectProps {
|
||||
instanceId: string
|
||||
value: string
|
||||
optionIds: string[]
|
||||
battlesuits: BattlesuitData[]
|
||||
onChange: (newValue: string) => void
|
||||
}
|
||||
|
||||
const BattlesuitSelect = ({
|
||||
instanceId,
|
||||
optionIds,
|
||||
value,
|
||||
battlesuits,
|
||||
onChange,
|
||||
}: BattlesuitSelectProps) => {
|
||||
const battlesuitOptions = useMemo(() => {
|
||||
return optionIds.map((battlesuitId) => {
|
||||
const battlesuit = battlesuits.find((aBattlesuit) => {
|
||||
return aBattlesuit.id === battlesuitId
|
||||
})
|
||||
if (battlesuit == null) {
|
||||
return {
|
||||
value: 'unknown',
|
||||
label: 'unknown',
|
||||
}
|
||||
}
|
||||
return {
|
||||
value: battlesuit.id,
|
||||
label: battlesuit.name,
|
||||
}
|
||||
})
|
||||
}, [battlesuits, optionIds])
|
||||
|
||||
const battlesuit = battlesuits.find((battlesuit) => {
|
||||
return battlesuit.id === value
|
||||
})
|
||||
|
||||
return (
|
||||
<ReactSelect
|
||||
instanceId={instanceId}
|
||||
value={
|
||||
battlesuit != null
|
||||
? {
|
||||
label: battlesuit.name,
|
||||
value: battlesuit.id,
|
||||
}
|
||||
: null
|
||||
}
|
||||
onChange={(option) => {
|
||||
if (option == null) {
|
||||
return
|
||||
}
|
||||
onChange(option.value)
|
||||
}}
|
||||
options={battlesuitOptions}
|
||||
components={{
|
||||
SingleValue: (props) => {
|
||||
return (
|
||||
<>
|
||||
<components.SingleValue {...props}>
|
||||
<Flex sx={{ alignItems: 'center', color: 'black' }}>
|
||||
<Image
|
||||
width={20}
|
||||
height={20}
|
||||
alt={props.data.label}
|
||||
src={`${assetsBucketBaseUrl}/honkai3rd/battlesuits/portrait-${props.data.value}.png`}
|
||||
sx={{ flexShrink: 0, mr: 2 }}
|
||||
/>
|
||||
{props.children}
|
||||
</Flex>
|
||||
</components.SingleValue>
|
||||
</>
|
||||
)
|
||||
},
|
||||
Option: (props) => {
|
||||
return (
|
||||
<>
|
||||
<components.Option {...props}>
|
||||
<Flex sx={{ alignItems: 'center', color: 'black' }}>
|
||||
<Image
|
||||
width={20}
|
||||
height={20}
|
||||
alt={props.data.label}
|
||||
src={`${assetsBucketBaseUrl}/honkai3rd/battlesuits/portrait-${props.data.value}.png`}
|
||||
sx={{ mr: 2, flexShrink: 0 }}
|
||||
/>
|
||||
{props.children}
|
||||
</Flex>
|
||||
</components.Option>
|
||||
</>
|
||||
)
|
||||
},
|
||||
}}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
export default BattlesuitSelect
|
||||
@@ -0,0 +1,509 @@
|
||||
import { Box, Button, Flex, Input, Label, Select, Textarea } from 'theme-ui'
|
||||
import { ERGGData, ERGGDataUpdater, ERGGExSignetType } from './types'
|
||||
import {
|
||||
erVersions,
|
||||
isGeneralSigil,
|
||||
PopulatedSignetGroup,
|
||||
RemembranceSigil,
|
||||
remembranceSigilIds,
|
||||
supportBattlesuitIds,
|
||||
} from '../../../lib/honkai3rd/elysianRealm'
|
||||
import {
|
||||
DndContext,
|
||||
closestCenter,
|
||||
KeyboardSensor,
|
||||
PointerSensor,
|
||||
useSensor,
|
||||
useSensors,
|
||||
} from '@dnd-kit/core'
|
||||
import {
|
||||
arrayMove,
|
||||
SortableContext,
|
||||
sortableKeyboardCoordinates,
|
||||
useSortable,
|
||||
verticalListSortingStrategy,
|
||||
} from '@dnd-kit/sortable'
|
||||
import { CSS } from '@dnd-kit/utilities'
|
||||
import { BattlesuitData } from '../../../lib/honkai3rd/battlesuits'
|
||||
import DifficultySelect from './DifficultySelect'
|
||||
import { getExSignetLabel } from './utils'
|
||||
import BattlesuitSelect from './BattlesuitSelect'
|
||||
import SigilSelect from './SigilSelect'
|
||||
import { WeaponData } from '../../../lib/honkai3rd/weapons'
|
||||
import { StigmataData } from '../../../lib/honkai3rd/stigmata'
|
||||
import { useMemo } from 'react'
|
||||
import EquipmentSetControl from './EquipmentSetControl'
|
||||
import SignetGroupSelect from './SignetGroupSelect'
|
||||
|
||||
interface DataFormProps {
|
||||
updateData: ERGGDataUpdater
|
||||
data: ERGGData
|
||||
battlesuits: BattlesuitData[]
|
||||
exSignetGroup: PopulatedSignetGroup
|
||||
sigils: RemembranceSigil[]
|
||||
weapons: WeaponData[]
|
||||
stigmata: StigmataData[]
|
||||
}
|
||||
|
||||
const DataForm = ({
|
||||
updateData,
|
||||
data,
|
||||
battlesuits,
|
||||
exSignetGroup,
|
||||
sigils,
|
||||
weapons,
|
||||
stigmata,
|
||||
}: DataFormProps) => {
|
||||
const sensors = useSensors(
|
||||
useSensor(PointerSensor),
|
||||
useSensor(KeyboardSensor, {
|
||||
coordinateGetter: sortableKeyboardCoordinates,
|
||||
})
|
||||
)
|
||||
|
||||
const { topStigmaIds, midStigmaIds, botStigmaIds } = useMemo(() => {
|
||||
return stigmata.reduce(
|
||||
(map, stigma) => {
|
||||
switch (stigma.type) {
|
||||
case 'top':
|
||||
map.topStigmaIds.push(stigma.id)
|
||||
break
|
||||
case 'mid':
|
||||
map.midStigmaIds.push(stigma.id)
|
||||
break
|
||||
case 'bot':
|
||||
map.botStigmaIds.push(stigma.id)
|
||||
break
|
||||
}
|
||||
return map
|
||||
},
|
||||
{
|
||||
topStigmaIds: [] as string[],
|
||||
midStigmaIds: [] as string[],
|
||||
botStigmaIds: [] as string[],
|
||||
}
|
||||
)
|
||||
}, [stigmata])
|
||||
|
||||
return (
|
||||
<Box sx={{ maxWidth: 960 }}>
|
||||
<Flex>
|
||||
<Box sx={{ flex: 1, p: 2 }}>
|
||||
<Box>
|
||||
<Label>서명</Label>
|
||||
<Textarea
|
||||
value={data.signature}
|
||||
placeholder='서명...'
|
||||
onChange={(event) => {
|
||||
updateData('signature', event.target.value)
|
||||
}}
|
||||
sx={{ resize: 'vertical', minHeight: 100 }}
|
||||
/>
|
||||
</Box>
|
||||
<Box>
|
||||
<Label>랭크</Label>
|
||||
<Select
|
||||
value={data.rank || 'na'}
|
||||
onChange={(event) => {
|
||||
switch (event.target.value) {
|
||||
case 'na':
|
||||
updateData('rank', undefined)
|
||||
break
|
||||
default:
|
||||
updateData('rank', event.target.value)
|
||||
}
|
||||
}}
|
||||
>
|
||||
<option value='na'>N/A</option>
|
||||
<option value='s'>s</option>
|
||||
<option value='s1'>s1</option>
|
||||
<option value='s2'>s2</option>
|
||||
<option value='s3'>s3</option>
|
||||
<option value='ss'>ss</option>
|
||||
<option value='ss1'>ss1</option>
|
||||
<option value='ss2'>ss2</option>
|
||||
<option value='ss3'>ss3</option>
|
||||
<option value='sss'>sss</option>
|
||||
<option value='a'>a</option>
|
||||
</Select>
|
||||
</Box>
|
||||
<Box>
|
||||
<Label>태그</Label>
|
||||
<Input
|
||||
value={data.tag}
|
||||
placeholder='태그...(필살기, 평타)'
|
||||
onChange={(event) => {
|
||||
updateData('tag', event.target.value)
|
||||
}}
|
||||
/>
|
||||
</Box>
|
||||
<Box>
|
||||
<Label>난이도</Label>
|
||||
<DifficultySelect
|
||||
onChange={(newValue) => updateData('difficulty', newValue)}
|
||||
value={data.difficulty}
|
||||
/>
|
||||
</Box>
|
||||
<Box>
|
||||
<Label>발키리</Label>
|
||||
<BattlesuitSelect
|
||||
instanceId='battlesuit-select'
|
||||
battlesuits={battlesuits}
|
||||
optionIds={erVersions.reduce<string[]>(
|
||||
(battlesuitIds, version) => {
|
||||
return [...battlesuitIds, ...version.battlesuits]
|
||||
},
|
||||
[]
|
||||
)}
|
||||
value={data.battlesuitId}
|
||||
onChange={(newValue) => {
|
||||
updateData('battlesuitId', newValue)
|
||||
const exSignetSet = exSignetGroup.sets.find((signetSet) => {
|
||||
return signetSet.id === `elysia-${newValue}`
|
||||
})
|
||||
if (exSignetSet != null) {
|
||||
updateData(
|
||||
'exSignets',
|
||||
exSignetSet.signets.map((signet, index) => {
|
||||
return {
|
||||
type:
|
||||
data.exSignets[index] != null
|
||||
? data.exSignets[index].type
|
||||
: 'na',
|
||||
name: signet.name,
|
||||
}
|
||||
})
|
||||
)
|
||||
}
|
||||
}}
|
||||
/>
|
||||
</Box>
|
||||
<Box>
|
||||
<Label>전용 각인</Label>
|
||||
<Flex>
|
||||
<Box>
|
||||
{data.exSignets.map((signet, index) => {
|
||||
return (
|
||||
<Flex
|
||||
key={index}
|
||||
sx={{ p: 1, height: 40, alignItems: 'center', mb: 2 }}
|
||||
>
|
||||
<Select
|
||||
value={signet.type}
|
||||
sx={{ height: 40, width: 80, mr: 1, p: 2 }}
|
||||
onChange={(event) => {
|
||||
const newExSignets = data.exSignets.slice()
|
||||
newExSignets[index] = {
|
||||
...data.exSignets[index],
|
||||
type: event.target.value as ERGGExSignetType,
|
||||
}
|
||||
updateData('exSignets', newExSignets)
|
||||
}}
|
||||
>
|
||||
<option value='start'>시작</option>
|
||||
<option value='1st'>우선</option>
|
||||
<option value='2nd'>차선</option>
|
||||
<option value='backup'>땜빵</option>
|
||||
<option value='na'>미선택</option>
|
||||
</Select>
|
||||
</Flex>
|
||||
)
|
||||
})}
|
||||
</Box>
|
||||
<Box sx={{ flex: 1 }}>
|
||||
<DndContext
|
||||
id='exSignetOrdering'
|
||||
sensors={sensors}
|
||||
collisionDetection={closestCenter}
|
||||
onDragEnd={(event) => {
|
||||
const { active, over } = event
|
||||
if (over == null) {
|
||||
return
|
||||
}
|
||||
|
||||
if (active.id !== over.id) {
|
||||
const nameArray = data.exSignets.map(
|
||||
(signet) => signet.name
|
||||
)
|
||||
const oldIndex = nameArray.indexOf(active.id as string)
|
||||
const newIndex = nameArray.indexOf(over.id as string)
|
||||
const newNameArray = arrayMove(
|
||||
nameArray,
|
||||
oldIndex,
|
||||
newIndex
|
||||
)
|
||||
const newExSignets = data.exSignets.map(
|
||||
(signet, index) => {
|
||||
return {
|
||||
...signet,
|
||||
name: newNameArray[index],
|
||||
}
|
||||
}
|
||||
)
|
||||
updateData('exSignets', newExSignets)
|
||||
}
|
||||
}}
|
||||
>
|
||||
<SortableContext
|
||||
items={data.exSignets.map((signet) => ({
|
||||
id: signet.name,
|
||||
}))}
|
||||
strategy={verticalListSortingStrategy}
|
||||
>
|
||||
{data.exSignets.map((signet) => (
|
||||
<SortableItem key={signet.name} name={signet.name} />
|
||||
))}
|
||||
</SortableContext>
|
||||
</DndContext>
|
||||
</Box>
|
||||
</Flex>
|
||||
</Box>
|
||||
</Box>
|
||||
<Box sx={{ flex: 1, p: 2 }}>
|
||||
<Box>
|
||||
{data.signets.map((signet, index) => {
|
||||
return (
|
||||
<Box key={index}>
|
||||
<Label>{index + 1} 번째 각인</Label>
|
||||
<Flex sx={{ alignItems: 'center', p: 1 }}>
|
||||
<Box sx={{ flex: 1, flexShrink: 0, mr: 1 }}>
|
||||
<SignetGroupSelect
|
||||
value={signet.group}
|
||||
onChange={(newValue) => {
|
||||
const newSignets = data.signets.slice()
|
||||
newSignets[index] = {
|
||||
...signet,
|
||||
group: newValue as any,
|
||||
}
|
||||
updateData('signets', newSignets)
|
||||
}}
|
||||
instanceId={`signet-select-${index}`}
|
||||
/>
|
||||
</Box>
|
||||
<Box>
|
||||
<Button
|
||||
onClick={() => {
|
||||
const newSignets = data.signets.slice()
|
||||
newSignets[index] = {
|
||||
...signet,
|
||||
nexus: signet.nexus === 1 ? 2 : 1,
|
||||
}
|
||||
updateData('signets', newSignets)
|
||||
}}
|
||||
sx={{ mr: 1, width: 40 }}
|
||||
>
|
||||
{signet.nexus === 1 ? 'I' : 'II'}
|
||||
</Button>
|
||||
</Box>
|
||||
|
||||
<Box sx={{ width: 60 }}>
|
||||
<Select
|
||||
value={signet.type}
|
||||
onChange={(event) => {
|
||||
const newSignets = data.signets.slice()
|
||||
newSignets[index] = {
|
||||
...signet,
|
||||
type: event.target.value as any,
|
||||
}
|
||||
updateData('signets', newSignets)
|
||||
}}
|
||||
>
|
||||
<option value='start'>과도</option>
|
||||
<option value='core'>핵심</option>
|
||||
<option value='sub'>보조</option>
|
||||
</Select>
|
||||
</Box>
|
||||
</Flex>
|
||||
<Box sx={{ p: 1 }}>
|
||||
<Textarea
|
||||
value={signet.description}
|
||||
onChange={(event) => {
|
||||
const newSignets = data.signets.slice()
|
||||
newSignets[index] = {
|
||||
...signet,
|
||||
description: event.target.value,
|
||||
}
|
||||
updateData('signets', newSignets)
|
||||
}}
|
||||
placeholder='각인 설명...'
|
||||
sx={{ resize: 'vertical' }}
|
||||
/>
|
||||
</Box>
|
||||
</Box>
|
||||
)
|
||||
})}
|
||||
</Box>
|
||||
</Box>
|
||||
<Box sx={{ flex: 1, p: 2 }}>
|
||||
<Box>
|
||||
<Label>서포트 발키리</Label>
|
||||
{data.supportSets.map((supportSet, index) => {
|
||||
return (
|
||||
<Box key={index}>
|
||||
<Box>{supportSet.type === 'util' ? '유틸' : '딜링'}</Box>
|
||||
<Flex>
|
||||
<Box sx={{ flex: 1, mr: 1 }}>
|
||||
<BattlesuitSelect
|
||||
instanceId={`battlesuit-support-select-${index}-1`}
|
||||
value={supportSet.battlesuitIds[0]}
|
||||
optionIds={supportBattlesuitIds}
|
||||
battlesuits={battlesuits}
|
||||
onChange={(newValue) => {
|
||||
const newSupportSets = data.supportSets.slice()
|
||||
newSupportSets[index] = {
|
||||
...newSupportSets[index],
|
||||
battlesuitIds: [
|
||||
...newSupportSets[index].battlesuitIds,
|
||||
],
|
||||
}
|
||||
newSupportSets[index].battlesuitIds[0] = newValue
|
||||
if (
|
||||
data.supportSets[index].battlesuitIds[1] ===
|
||||
newValue
|
||||
) {
|
||||
newSupportSets[index].battlesuitIds[1] =
|
||||
data.supportSets[index].battlesuitIds[0]
|
||||
}
|
||||
updateData('supportSets', newSupportSets)
|
||||
}}
|
||||
/>
|
||||
</Box>
|
||||
<Box sx={{ flex: 1 }}>
|
||||
<BattlesuitSelect
|
||||
instanceId={`battlesuit-support-select-${index}-2`}
|
||||
value={supportSet.battlesuitIds[1]}
|
||||
optionIds={supportBattlesuitIds}
|
||||
battlesuits={battlesuits}
|
||||
onChange={(newValue) => {
|
||||
const newSupportSets = data.supportSets.slice()
|
||||
newSupportSets[index] = {
|
||||
...newSupportSets[index],
|
||||
battlesuitIds: [
|
||||
...newSupportSets[index].battlesuitIds,
|
||||
],
|
||||
}
|
||||
newSupportSets[index].battlesuitIds[1] = newValue
|
||||
if (
|
||||
data.supportSets[index].battlesuitIds[0] ===
|
||||
newValue
|
||||
) {
|
||||
newSupportSets[index].battlesuitIds[0] =
|
||||
data.supportSets[index].battlesuitIds[1]
|
||||
}
|
||||
updateData('supportSets', newSupportSets)
|
||||
}}
|
||||
/>
|
||||
</Box>
|
||||
</Flex>
|
||||
</Box>
|
||||
)
|
||||
})}
|
||||
</Box>
|
||||
<Box sx={{ flex: 1 }}>
|
||||
{data.sigilSets.map((sigilSet, index) => {
|
||||
return (
|
||||
<Box key={index}>
|
||||
<Box>
|
||||
{sigilSet.type === 'start'
|
||||
? '초반'
|
||||
: sigilSet.type === 'mid'
|
||||
? '중반'
|
||||
: '후반'}{' '}
|
||||
증명
|
||||
</Box>
|
||||
<Flex>
|
||||
<Box sx={{ flex: 1, mr: 1 }}>
|
||||
<SigilSelect
|
||||
instanceId={`sigil-select-${index}-general`}
|
||||
value={sigilSet.sigilIds[0]}
|
||||
optionIds={remembranceSigilIds.filter(isGeneralSigil)}
|
||||
sigils={sigils}
|
||||
onChange={(newValue) => {
|
||||
const newSigilSets = data.sigilSets.slice()
|
||||
newSigilSets[index] = {
|
||||
...newSigilSets[index],
|
||||
sigilIds: [
|
||||
newValue,
|
||||
newSigilSets[index].sigilIds[1],
|
||||
],
|
||||
}
|
||||
updateData('sigilSets', newSigilSets)
|
||||
}}
|
||||
/>
|
||||
</Box>
|
||||
<Box>
|
||||
<SigilSelect
|
||||
instanceId={`sigil-select-${index}-support`}
|
||||
value={sigilSet.sigilIds[1]}
|
||||
optionIds={remembranceSigilIds.filter(
|
||||
(sigilId) => !isGeneralSigil(sigilId)
|
||||
)}
|
||||
sigils={sigils}
|
||||
onChange={(newValue) => {
|
||||
const newSigilSets = data.sigilSets.slice()
|
||||
newSigilSets[index] = {
|
||||
...newSigilSets[index],
|
||||
sigilIds: [
|
||||
newSigilSets[index].sigilIds[0],
|
||||
newValue,
|
||||
],
|
||||
}
|
||||
updateData('sigilSets', newSigilSets)
|
||||
}}
|
||||
/>
|
||||
</Box>
|
||||
</Flex>
|
||||
</Box>
|
||||
)
|
||||
})}
|
||||
</Box>
|
||||
<Box>
|
||||
{data.equipmentSets.map((equipmentSet, index) => {
|
||||
return (
|
||||
<EquipmentSetControl
|
||||
key={index}
|
||||
equipmentSet={equipmentSet}
|
||||
weapons={weapons}
|
||||
stigmata={stigmata}
|
||||
topStigmaIds={topStigmaIds}
|
||||
midStigmaIds={midStigmaIds}
|
||||
botStigmaIds={botStigmaIds}
|
||||
index={index}
|
||||
updateData={updateData}
|
||||
/>
|
||||
)
|
||||
})}
|
||||
</Box>
|
||||
</Box>
|
||||
</Flex>
|
||||
</Box>
|
||||
)
|
||||
}
|
||||
|
||||
export default DataForm
|
||||
|
||||
export function SortableItem(props: { name: string }) {
|
||||
const { attributes, listeners, setNodeRef, transform, transition } =
|
||||
useSortable({ id: props.name })
|
||||
|
||||
const style = {
|
||||
transform: CSS.Transform.toString(transform),
|
||||
transition,
|
||||
}
|
||||
|
||||
return (
|
||||
<div ref={setNodeRef} style={style} {...attributes} {...listeners}>
|
||||
<Flex
|
||||
sx={{
|
||||
height: 40,
|
||||
mb: 2,
|
||||
cursor: 'ns-resize',
|
||||
alignItems: 'center',
|
||||
p: 1,
|
||||
}}
|
||||
>
|
||||
{getExSignetLabel(props.name)}
|
||||
</Flex>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,83 @@
|
||||
import { Box } from 'theme-ui'
|
||||
import { colors } from './styles'
|
||||
|
||||
interface DifficultyBoxProps {
|
||||
difficulty: 'abstinence' | 'corruption' | 'inferno'
|
||||
}
|
||||
|
||||
const DifficultyBox = ({ difficulty }: DifficultyBoxProps) => {
|
||||
return (
|
||||
<Box
|
||||
sx={{
|
||||
position: 'absolute',
|
||||
left: 15,
|
||||
width: 60,
|
||||
height: 105,
|
||||
backgroundColor:
|
||||
difficulty === 'corruption'
|
||||
? colors.corruptionDifficultyColor
|
||||
: difficulty === 'abstinence'
|
||||
? colors.abstinenceDifficultyColor
|
||||
: colors.infernoDifficultyColor,
|
||||
padding: '5px',
|
||||
borderBottomLeftRadius: 10,
|
||||
borderBottomRightRadius: 10,
|
||||
boxShadow: '5px 5px 10px rgba(0,0,0,0.5)',
|
||||
}}
|
||||
className='difficultyLabel'
|
||||
>
|
||||
<Box
|
||||
sx={{
|
||||
color: colors.backgroundColor,
|
||||
fontWeight: 'bold',
|
||||
textAlign: 'center',
|
||||
fontSize: 16,
|
||||
}}
|
||||
>
|
||||
난이도
|
||||
</Box>
|
||||
<Box
|
||||
sx={{
|
||||
borderColor: colors.backgroundColor,
|
||||
borderWidth: '1px 0 1px',
|
||||
borderStyle: 'dashed',
|
||||
width: '100%',
|
||||
}}
|
||||
/>
|
||||
<Box
|
||||
sx={{
|
||||
color: colors.backgroundColor,
|
||||
fontWeight: 'bold',
|
||||
fontSize: 25,
|
||||
textAlign: 'center',
|
||||
}}
|
||||
>
|
||||
{difficulty === 'corruption'
|
||||
? '침식'
|
||||
: difficulty === 'abstinence'
|
||||
? '제약'
|
||||
: '겁화'}
|
||||
</Box>
|
||||
<Box
|
||||
sx={{
|
||||
borderColor: colors.backgroundColor,
|
||||
borderWidth: '1px 0 1px',
|
||||
borderStyle: 'dashed',
|
||||
width: '100%',
|
||||
}}
|
||||
/>
|
||||
<Box
|
||||
sx={{
|
||||
color: colors.backgroundColor,
|
||||
fontWeight: 'bold',
|
||||
textAlign: 'center',
|
||||
fontSize: 16,
|
||||
}}
|
||||
>
|
||||
추천
|
||||
</Box>
|
||||
</Box>
|
||||
)
|
||||
}
|
||||
|
||||
export default DifficultyBox
|
||||
@@ -0,0 +1,30 @@
|
||||
import { Select } from 'theme-ui'
|
||||
import { ERGGDifficulty } from './types'
|
||||
|
||||
interface DifficultySelectProps {
|
||||
onChange: (newValue: ERGGDifficulty) => void
|
||||
value: ERGGDifficulty
|
||||
}
|
||||
|
||||
const DifficultySelect = ({ onChange, value }: DifficultySelectProps) => {
|
||||
return (
|
||||
<Select
|
||||
onChange={(event) => {
|
||||
switch (event.target.value) {
|
||||
case 'abstinence':
|
||||
case 'corruption':
|
||||
case 'inferno':
|
||||
onChange(event.target.value)
|
||||
break
|
||||
}
|
||||
}}
|
||||
value={value}
|
||||
>
|
||||
<option value='corruption'>침식</option>
|
||||
<option value='abstinence'>제약</option>
|
||||
<option value='inferno'>겁화</option>
|
||||
</Select>
|
||||
)
|
||||
}
|
||||
|
||||
export default DifficultySelect
|
||||
@@ -0,0 +1,444 @@
|
||||
/* eslint-disable @next/next/no-page-custom-font */
|
||||
import { useCallback, useEffect, useRef, useState } from 'react'
|
||||
import {
|
||||
Box,
|
||||
Button,
|
||||
Flex,
|
||||
Heading,
|
||||
Image,
|
||||
Input,
|
||||
Label,
|
||||
Text,
|
||||
Textarea,
|
||||
} from 'theme-ui'
|
||||
import { BattlesuitData } from '../../../lib/honkai3rd/battlesuits'
|
||||
import { WeaponData } from '../../../lib/honkai3rd/weapons'
|
||||
import DifficultyBox from './DifficultyBox'
|
||||
import SignetBox from './SignetBox'
|
||||
import { colors } from './styles'
|
||||
import ValkBox from './ValkBox'
|
||||
import {
|
||||
PopulatedSignetGroup,
|
||||
RemembranceSigil,
|
||||
} from '../../../lib/honkai3rd/elysianRealm'
|
||||
import SigilBox from './SigilBox'
|
||||
import SupportBox from './SupportBox'
|
||||
import DataForm from './DataForm'
|
||||
import EquipmentBox from './EquipmentBox'
|
||||
import { ERGGData, ERGGDataUpdater, ERGGExSignetType } from './types'
|
||||
import { StigmataData } from '../../../lib/honkai3rd/stigmata'
|
||||
import { saveAs } from 'file-saver'
|
||||
import { toBlob } from 'html-to-image'
|
||||
import { assetsBucketBaseUrl } from '../../../lib/consts'
|
||||
|
||||
interface ERGuideGeneratorProps {
|
||||
weapons: WeaponData[]
|
||||
stigmata: StigmataData[]
|
||||
battlesuits: BattlesuitData[]
|
||||
exSignetGroup: PopulatedSignetGroup
|
||||
sigils: RemembranceSigil[]
|
||||
}
|
||||
|
||||
const exSignetTypes: ERGGExSignetType[] = [
|
||||
'start',
|
||||
'1st',
|
||||
'2nd',
|
||||
'backup',
|
||||
'na',
|
||||
]
|
||||
|
||||
const ERGuideGenerator = ({
|
||||
weapons,
|
||||
stigmata,
|
||||
battlesuits,
|
||||
exSignetGroup,
|
||||
sigils,
|
||||
}: ERGuideGeneratorProps) => {
|
||||
const [data, setData] = useState<ERGGData>({
|
||||
tag: '',
|
||||
signature:
|
||||
'작성자 : XXX\nAbyss Lab에서 생성됨\nhttps://abyss-lab.app/honkai3rd',
|
||||
battlesuitId: 'vill-v',
|
||||
difficulty: 'corruption',
|
||||
exSignets:
|
||||
exSignetGroup.sets
|
||||
.find((set) => set.id === 'elysia-vill-v')
|
||||
?.signets.map((signet, index) => {
|
||||
return {
|
||||
type: exSignetTypes[index],
|
||||
name: signet.name,
|
||||
}
|
||||
}) || [],
|
||||
supportSets: [
|
||||
{ type: 'util', battlesuitIds: ['le', 'ae'] },
|
||||
{ type: 'dps', battlesuitIds: ['br', 'ae'] },
|
||||
],
|
||||
sigilSets: [
|
||||
{
|
||||
type: 'start',
|
||||
sigilIds: ['burden', 'it-will-be-written'],
|
||||
},
|
||||
{
|
||||
type: 'mid',
|
||||
sigilIds: ['burden', 'it-will-be-written'],
|
||||
},
|
||||
{
|
||||
type: 'end',
|
||||
sigilIds: ['burden', 'it-will-be-written'],
|
||||
},
|
||||
],
|
||||
equipmentSets: [
|
||||
{
|
||||
type: 'best',
|
||||
weapon: 'vill-v-pri-weapon',
|
||||
top: 'carlo-collodi-top',
|
||||
mid: 'carlo-collodi-mid',
|
||||
bot: 'carlo-collodi-bot',
|
||||
},
|
||||
{
|
||||
type: 'alt',
|
||||
weapon: 'vill-v-pri-weapon',
|
||||
top: 'carlo-collodi-top',
|
||||
mid: 'carlo-collodi-mid',
|
||||
bot: 'carlo-collodi-bot',
|
||||
},
|
||||
],
|
||||
signets: [
|
||||
{
|
||||
type: 'core',
|
||||
group: 'vill-v',
|
||||
nexus: 2,
|
||||
description: '',
|
||||
},
|
||||
{
|
||||
type: 'core',
|
||||
group: 'vill-v',
|
||||
nexus: 2,
|
||||
description: '',
|
||||
},
|
||||
{
|
||||
type: 'sub',
|
||||
group: 'vill-v',
|
||||
nexus: 2,
|
||||
description: '',
|
||||
},
|
||||
{
|
||||
type: 'sub',
|
||||
group: 'vill-v',
|
||||
nexus: 2,
|
||||
description: '',
|
||||
},
|
||||
{
|
||||
type: 'sub',
|
||||
group: 'vill-v',
|
||||
nexus: 2,
|
||||
description: '',
|
||||
},
|
||||
],
|
||||
})
|
||||
const [fileName, setFileName] = useState('guide')
|
||||
|
||||
const guideRef = useRef(null)
|
||||
|
||||
const updateData = useCallback<ERGGDataUpdater>(
|
||||
(key, value) => {
|
||||
setData((previousData) => {
|
||||
const newData = {
|
||||
...previousData,
|
||||
[key]: typeof value === 'function' ? value(previousData[key]) : value,
|
||||
}
|
||||
|
||||
return newData
|
||||
})
|
||||
},
|
||||
[setData]
|
||||
)
|
||||
|
||||
const [customStyle, setCustomStyle] = useState('')
|
||||
const loadedRef = useRef(false)
|
||||
useEffect(() => {
|
||||
if (loadedRef.current) {
|
||||
localStorage.setItem('ergg:customStyle', customStyle)
|
||||
} else {
|
||||
setCustomStyle(localStorage.getItem('ergg:customStyle') || '')
|
||||
loadedRef.current = true
|
||||
}
|
||||
}, [customStyle])
|
||||
|
||||
return (
|
||||
<Box
|
||||
onDragOver={(event) => {
|
||||
event.preventDefault()
|
||||
}}
|
||||
onDrop={async (event) => {
|
||||
event.preventDefault()
|
||||
|
||||
const result = await new Promise<string>((resolve, reject) => {
|
||||
const file = event.dataTransfer.files[0]
|
||||
const reader = new FileReader()
|
||||
reader.addEventListener(
|
||||
'load',
|
||||
() => {
|
||||
resolve(reader.result as string)
|
||||
},
|
||||
{ once: true }
|
||||
)
|
||||
reader.addEventListener(
|
||||
'error',
|
||||
(error) => {
|
||||
reject(error)
|
||||
},
|
||||
{ once: true }
|
||||
)
|
||||
reader.readAsText(file)
|
||||
})
|
||||
|
||||
const parsedResult = JSON.parse(result)
|
||||
setData(parsedResult)
|
||||
}}
|
||||
>
|
||||
<Box sx={{ width: 960 }}>
|
||||
<Box
|
||||
ref={guideRef}
|
||||
sx={{
|
||||
width: 960,
|
||||
height: 660,
|
||||
position: 'relative',
|
||||
backgroundColor: colors.backgroundColor,
|
||||
color: '#FFF',
|
||||
fontFamily: `'NanumSquare', sans-serif`,
|
||||
}}
|
||||
>
|
||||
<style
|
||||
dangerouslySetInnerHTML={{
|
||||
__html: `@font-face {
|
||||
font-family: 'GyeonggiTitleM';
|
||||
src: url('https://cdn.jsdelivr.net/gh/projectnoonnu/noonfonts_one@1.0/GyeonggiTitleM.woff') format('woff');
|
||||
font-weight: normal;
|
||||
font-style: normal;
|
||||
}
|
||||
@font-face {
|
||||
font-family: 'YdestreetB';
|
||||
src: url('https://cdn.jsdelivr.net/gh/projectnoonnu/noonfonts_2110@1.0/YdestreetB.woff2') format('woff2');
|
||||
font-weight: normal;
|
||||
font-style: normal;
|
||||
}
|
||||
@import url('https://cdn.rawgit.com/moonspam/NanumSquare/master/nanumsquare.css');
|
||||
@font-face {
|
||||
font-family: 'ghanachoco';
|
||||
src: url('https://cdn.jsdelivr.net/gh/projectnoonnu/noonfonts_20-04@1.0/ghanachoco.woff') format('woff');
|
||||
font-weight: normal;
|
||||
font-style: normal;
|
||||
}
|
||||
|
||||
|
||||
.exSignetLabel {
|
||||
font-family: 'ghanachoco';
|
||||
}
|
||||
.difficultyLabel {
|
||||
font-family: 'YdestreetB';
|
||||
}
|
||||
.signetTypeLabel {
|
||||
font-family: 'YdestreetB';
|
||||
}
|
||||
.signetDescription {
|
||||
font-family: 'GyeonggiTitleM';
|
||||
}
|
||||
.signetGroupLabel {
|
||||
font-family: 'YdestreetB';
|
||||
}
|
||||
.tagLabel {
|
||||
font-family: 'YdestreetB';
|
||||
}
|
||||
`,
|
||||
}}
|
||||
/>
|
||||
<Box
|
||||
sx={{
|
||||
position: 'absolute',
|
||||
top: 0,
|
||||
left: 0,
|
||||
width: 960,
|
||||
height: 660,
|
||||
opacity: 0.15,
|
||||
backgroundImage: `url('/assets/erbg.png')`,
|
||||
backgroundSize: 1300,
|
||||
backgroundPositionY: -55,
|
||||
backgroundPositionX: -30,
|
||||
}}
|
||||
></Box>
|
||||
<style
|
||||
dangerouslySetInnerHTML={{
|
||||
__html: customStyle,
|
||||
}}
|
||||
/>
|
||||
<Flex
|
||||
sx={{
|
||||
position: 'absolute',
|
||||
top: 15,
|
||||
left: 85,
|
||||
}}
|
||||
>
|
||||
{data.rank && (
|
||||
<Image
|
||||
alt={data.rank}
|
||||
width={40}
|
||||
height={40}
|
||||
src={`${assetsBucketBaseUrl}/honkai3rd/rank-icons/${data.rank}-rank.png`}
|
||||
sx={{ mr: '5px' }}
|
||||
/>
|
||||
)}
|
||||
{data.tag && (
|
||||
<Box
|
||||
sx={{
|
||||
padding: '5px',
|
||||
border: 'solid 1px gray',
|
||||
boxSizing: 'border-box',
|
||||
backgroundColor: '#181614',
|
||||
boxShadow: '5px 5px 10px rgba(0,0,0,0.5)',
|
||||
}}
|
||||
className='tagLabel'
|
||||
>
|
||||
{data.tag}
|
||||
</Box>
|
||||
)}
|
||||
</Flex>
|
||||
<Flex
|
||||
sx={{
|
||||
position: 'absolute',
|
||||
right: 10,
|
||||
padding: '5px 10px',
|
||||
boxSizing: 'border-box',
|
||||
bottom: 15,
|
||||
maxWidth: 460,
|
||||
alignItems: 'center',
|
||||
whiteSpace: 'pre-wrap',
|
||||
color: '#A59A9B',
|
||||
fontStyle: 'italic',
|
||||
textAlign: 'right',
|
||||
}}
|
||||
>
|
||||
<Text>{data.signature}</Text>
|
||||
</Flex>
|
||||
<SignetBox signets={data.signets} />
|
||||
<DifficultyBox difficulty={data.difficulty} />
|
||||
|
||||
<ValkBox
|
||||
battlesuitId={data.battlesuitId}
|
||||
exSignets={data.exSignets}
|
||||
/>
|
||||
<Box
|
||||
sx={{
|
||||
position: 'absolute',
|
||||
bottom: 15 + (87 + 10) * 2,
|
||||
left: 15,
|
||||
}}
|
||||
>
|
||||
<SupportBox supportSets={data.supportSets} />
|
||||
</Box>
|
||||
<Box
|
||||
sx={{
|
||||
position: 'absolute',
|
||||
bottom: 15 + 87 + 10,
|
||||
left: 15,
|
||||
}}
|
||||
>
|
||||
<SigilBox sigilSets={data.sigilSets} sigils={sigils} />
|
||||
</Box>
|
||||
<Box
|
||||
sx={{
|
||||
position: 'absolute',
|
||||
bottom: '15px',
|
||||
left: 15,
|
||||
}}
|
||||
>
|
||||
<EquipmentBox
|
||||
equipmentSets={data.equipmentSets}
|
||||
weapons={weapons}
|
||||
stigmata={stigmata}
|
||||
/>
|
||||
</Box>
|
||||
</Box>
|
||||
</Box>
|
||||
|
||||
<Box sx={{ m: 2 }}>
|
||||
<Flex sx={{ alignItems: 'center' }}>
|
||||
<Box sx={{ mr: 1 }}>
|
||||
<Label>File Name</Label>
|
||||
</Box>
|
||||
<Box sx={{ mr: 1 }}>
|
||||
<Input
|
||||
value={fileName}
|
||||
onChange={(event) => {
|
||||
setFileName(event.target.value)
|
||||
}}
|
||||
/>
|
||||
</Box>
|
||||
<Button
|
||||
sx={{ mr: 1 }}
|
||||
onClick={async () => {
|
||||
if (guideRef.current == null) {
|
||||
return
|
||||
}
|
||||
|
||||
const blob = await toBlob(guideRef.current)
|
||||
|
||||
if (blob == null) {
|
||||
return
|
||||
}
|
||||
saveAs(blob, `${fileName}.png`)
|
||||
}}
|
||||
>
|
||||
Download Image ({fileName}.png)
|
||||
</Button>
|
||||
<Button
|
||||
onClick={() => {
|
||||
console.log(JSON.stringify(data))
|
||||
saveAs(new Blob([JSON.stringify(data)]), `${fileName}.json`)
|
||||
}}
|
||||
>
|
||||
Download JSON Data ({fileName}.json)
|
||||
</Button>
|
||||
</Flex>
|
||||
</Box>
|
||||
|
||||
<DataForm
|
||||
exSignetGroup={exSignetGroup}
|
||||
battlesuits={battlesuits}
|
||||
updateData={updateData}
|
||||
data={data}
|
||||
sigils={sigils}
|
||||
weapons={weapons}
|
||||
stigmata={stigmata}
|
||||
/>
|
||||
<hr />
|
||||
<Box sx={{ p: 2 }}>
|
||||
<Heading as='h3'>사용된 폰트</Heading>
|
||||
<Box as='ul'>
|
||||
<Box as='li'>
|
||||
Y이드스트릿체 https://www.yspotlight.co.kr/brand/font?tabNo=1
|
||||
</Box>
|
||||
<Box as='li'>나눔스퀘어 https://hangeul.naver.com/2017/nanum</Box>
|
||||
<Box as='li'>
|
||||
경기천년제목
|
||||
https://www.gg.go.kr/contents/contents.do?ciIdx=679&menuId=2457
|
||||
</Box>
|
||||
<Box as='li'>
|
||||
가나초콜릿 hhttps://www.lotteconf.co.kr/prcenter/gana
|
||||
</Box>
|
||||
</Box>
|
||||
<Box sx={{ display: 'none' }}>
|
||||
<Label>Custom Style(Don't paste any suspicious scripts!!)</Label>
|
||||
<Textarea
|
||||
value={customStyle}
|
||||
onChange={(event) => {
|
||||
setCustomStyle(event.target.value)
|
||||
}}
|
||||
/>
|
||||
</Box>
|
||||
</Box>
|
||||
</Box>
|
||||
)
|
||||
}
|
||||
|
||||
export default ERGuideGenerator
|
||||
@@ -0,0 +1,136 @@
|
||||
import { Box, Flex, Image } from 'theme-ui'
|
||||
import { assetsBucketBaseUrl } from '../../../lib/consts'
|
||||
import { StigmataData } from '../../../lib/honkai3rd/stigmata'
|
||||
import { WeaponData } from '../../../lib/honkai3rd/weapons'
|
||||
import { ERGGEquipmentSet } from './types'
|
||||
|
||||
interface EquipmentBoxProps {
|
||||
equipmentSets: ERGGEquipmentSet[]
|
||||
weapons: WeaponData[]
|
||||
stigmata: StigmataData[]
|
||||
}
|
||||
|
||||
const EquipmentBox = ({
|
||||
equipmentSets,
|
||||
weapons,
|
||||
stigmata,
|
||||
}: EquipmentBoxProps) => {
|
||||
return (
|
||||
<Box
|
||||
sx={{
|
||||
padding: '5px',
|
||||
border: 'solid 1px gray',
|
||||
boxSizing: 'border-box',
|
||||
backgroundColor: '#181614',
|
||||
boxShadow: '5px 5px 10px rgba(0,0,0,0.5)',
|
||||
}}
|
||||
>
|
||||
<Flex>
|
||||
<Box
|
||||
sx={{
|
||||
backgroundColor: '#8E5B45',
|
||||
p: '5px',
|
||||
textAlign: 'center',
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
justifyContent: 'center',
|
||||
mr: '5px',
|
||||
width: 55,
|
||||
}}
|
||||
>
|
||||
<Box>추천</Box>
|
||||
<Box>장비</Box>
|
||||
</Box>
|
||||
{equipmentSets.map((equipmentSet, index) => {
|
||||
return (
|
||||
<Box
|
||||
key={index}
|
||||
sx={{
|
||||
backgroundColor: '#615559',
|
||||
p: '15px 5px 0',
|
||||
borderRadius: '5px',
|
||||
position: 'relative',
|
||||
mr: '5px',
|
||||
'&:last-child': {
|
||||
mr: 0,
|
||||
},
|
||||
}}
|
||||
>
|
||||
<Box
|
||||
sx={{
|
||||
position: 'absolute',
|
||||
top: 0,
|
||||
left: 0,
|
||||
backgroundColor:
|
||||
equipmentSet.type === 'best' ? '#EE4E2C' : '#9082BD',
|
||||
borderTopLeftRadius: '5px',
|
||||
borderBottomRightRadius: '5px',
|
||||
p: '0 7px',
|
||||
fontSize: 12,
|
||||
}}
|
||||
>
|
||||
{equipmentSet.type === 'best' ? '베스트' : '대체'}
|
||||
</Box>
|
||||
<Box sx={{ height: 40 }}>
|
||||
<Image
|
||||
alt=''
|
||||
src={`${assetsBucketBaseUrl}/honkai3rd/weapons/${equipmentSet.weapon}.png`}
|
||||
width={40}
|
||||
height={40}
|
||||
sx={{ borderRadius: '5px', mr: '5px' }}
|
||||
/>
|
||||
<Image
|
||||
alt=''
|
||||
src={`${assetsBucketBaseUrl}/honkai3rd/stigmata/icon-${equipmentSet.top}.png`}
|
||||
width={40}
|
||||
height={40}
|
||||
sx={{ borderRadius: '5px', mr: '5px' }}
|
||||
/>
|
||||
<Image
|
||||
alt=''
|
||||
src={`${assetsBucketBaseUrl}/honkai3rd/stigmata/icon-${equipmentSet.mid}.png`}
|
||||
width={40}
|
||||
height={40}
|
||||
sx={{ borderRadius: '5px', mr: '5px' }}
|
||||
/>
|
||||
<Image
|
||||
alt=''
|
||||
src={`${assetsBucketBaseUrl}/honkai3rd/stigmata/icon-${equipmentSet.bot}.png`}
|
||||
width={40}
|
||||
height={40}
|
||||
sx={{ borderRadius: '5px' }}
|
||||
/>
|
||||
</Box>
|
||||
<Flex
|
||||
sx={{
|
||||
height: 20,
|
||||
fontSize: 12,
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
}}
|
||||
>
|
||||
{getWeaponName(equipmentSet.weapon)}+
|
||||
{getStigmataName(equipmentSet.top)}/
|
||||
{getStigmataName(equipmentSet.mid)}/
|
||||
{getStigmataName(equipmentSet.bot)}
|
||||
</Flex>
|
||||
</Box>
|
||||
)
|
||||
})}
|
||||
</Flex>
|
||||
</Box>
|
||||
)
|
||||
|
||||
function getWeaponName(id: string) {
|
||||
return weapons
|
||||
.find((weapon) => weapon.id === id)
|
||||
?.name.split(' ')[0]
|
||||
.slice(0, 4)
|
||||
.trim()
|
||||
}
|
||||
function getStigmataName(id: string) {
|
||||
return stigmata.find((stigma) => stigma.id === id)?.name.slice(0, 3)
|
||||
}
|
||||
}
|
||||
|
||||
export default EquipmentBox
|
||||
@@ -0,0 +1,150 @@
|
||||
import { useCallback, useMemo } from 'react'
|
||||
import { Box, Flex, Label } from 'theme-ui'
|
||||
import { StigmataData } from '../../../lib/honkai3rd/stigmata'
|
||||
import { WeaponData } from '../../../lib/honkai3rd/weapons'
|
||||
import StigmaSelect from './StigmaSelect'
|
||||
import { ERGGDataUpdater, ERGGEquipmentSet } from './types'
|
||||
import WeaponSelect from './WeaponSelect'
|
||||
|
||||
interface EquipmentSetControlProps {
|
||||
index: number
|
||||
equipmentSet: ERGGEquipmentSet
|
||||
updateData: ERGGDataUpdater
|
||||
weapons: WeaponData[]
|
||||
stigmata: StigmataData[]
|
||||
topStigmaIds: string[]
|
||||
midStigmaIds: string[]
|
||||
botStigmaIds: string[]
|
||||
}
|
||||
|
||||
const EquipmentSetControl = ({
|
||||
index,
|
||||
equipmentSet,
|
||||
updateData,
|
||||
weapons,
|
||||
stigmata,
|
||||
topStigmaIds,
|
||||
midStigmaIds,
|
||||
botStigmaIds,
|
||||
}: EquipmentSetControlProps) => {
|
||||
const handleWeaponChange = useCallback(
|
||||
(newValue: string) => {
|
||||
updateData('equipmentSets', (previousEquipmentSets) => {
|
||||
const newEquipmentSets = previousEquipmentSets.slice()
|
||||
newEquipmentSets[index] = {
|
||||
...newEquipmentSets[index],
|
||||
weapon: newValue,
|
||||
}
|
||||
return newEquipmentSets
|
||||
})
|
||||
},
|
||||
[index, updateData]
|
||||
)
|
||||
const weaponIds = useMemo(() => weapons.map((weapon) => weapon.id), [weapons])
|
||||
|
||||
const handleTopStigmaChange = useCallback(
|
||||
(newValue: string) => {
|
||||
updateData('equipmentSets', (previousEquipmentSets) => {
|
||||
const newEquipmentSets = previousEquipmentSets.slice()
|
||||
newEquipmentSets[index] = {
|
||||
...newEquipmentSets[index],
|
||||
top: newValue,
|
||||
}
|
||||
return newEquipmentSets
|
||||
})
|
||||
},
|
||||
[index, updateData]
|
||||
)
|
||||
|
||||
const handleMidStigmaChange = useCallback(
|
||||
(newValue: string) => {
|
||||
updateData('equipmentSets', (previousEquipmentSets) => {
|
||||
const newEquipmentSets = previousEquipmentSets.slice()
|
||||
newEquipmentSets[index] = {
|
||||
...newEquipmentSets[index],
|
||||
mid: newValue,
|
||||
}
|
||||
return newEquipmentSets
|
||||
})
|
||||
},
|
||||
[index, updateData]
|
||||
)
|
||||
|
||||
const handleBotStigmaChange = useCallback(
|
||||
(newValue: string) => {
|
||||
updateData('equipmentSets', (previousEquipmentSets) => {
|
||||
const newEquipmentSets = previousEquipmentSets.slice()
|
||||
newEquipmentSets[index] = {
|
||||
...newEquipmentSets[index],
|
||||
bot: newValue,
|
||||
}
|
||||
return newEquipmentSets
|
||||
})
|
||||
},
|
||||
[index, updateData]
|
||||
)
|
||||
|
||||
return (
|
||||
<Box>
|
||||
<Box>{equipmentSet.type === 'best' ? '베스트' : '대체'}</Box>
|
||||
<Flex sx={{ alignItems: 'center' }}>
|
||||
<Box sx={{ mr: 2 }}>
|
||||
<Label>무기</Label>
|
||||
</Box>
|
||||
<Box sx={{ flexShrink: 0, flex: 1 }}>
|
||||
<WeaponSelect
|
||||
instanceId={`equipment-${index}-weapon`}
|
||||
value={equipmentSet.weapon}
|
||||
onChange={handleWeaponChange}
|
||||
weapons={weapons}
|
||||
optionIds={weaponIds}
|
||||
/>
|
||||
</Box>
|
||||
</Flex>
|
||||
<Flex sx={{ alignItems: 'center' }}>
|
||||
<Box sx={{ mr: 2 }}>
|
||||
<Label>상단</Label>
|
||||
</Box>
|
||||
<Box sx={{ flexShrink: 0, flex: 1 }}>
|
||||
<StigmaSelect
|
||||
instanceId={`equipment-${index}-top`}
|
||||
value={equipmentSet.top}
|
||||
onChange={handleTopStigmaChange}
|
||||
stigmata={stigmata}
|
||||
optionIds={topStigmaIds}
|
||||
/>
|
||||
</Box>
|
||||
</Flex>
|
||||
<Flex sx={{ alignItems: 'center' }}>
|
||||
<Box sx={{ mr: 2 }}>
|
||||
<Label>중단</Label>
|
||||
</Box>
|
||||
<Box sx={{ flexShrink: 0, flex: 1 }}>
|
||||
<StigmaSelect
|
||||
instanceId={`equipment-${index}-mid`}
|
||||
value={equipmentSet.mid}
|
||||
onChange={handleMidStigmaChange}
|
||||
stigmata={stigmata}
|
||||
optionIds={midStigmaIds}
|
||||
/>
|
||||
</Box>
|
||||
</Flex>
|
||||
<Flex sx={{ alignItems: 'center' }}>
|
||||
<Box sx={{ mr: 2 }}>
|
||||
<Label>하단</Label>
|
||||
</Box>
|
||||
<Box sx={{ flexShrink: 0, flex: 1 }}>
|
||||
<StigmaSelect
|
||||
instanceId={`equipment-${index}-bot`}
|
||||
value={equipmentSet.bot}
|
||||
onChange={handleBotStigmaChange}
|
||||
stigmata={stigmata}
|
||||
optionIds={botStigmaIds}
|
||||
/>
|
||||
</Box>
|
||||
</Flex>
|
||||
</Box>
|
||||
)
|
||||
}
|
||||
|
||||
export default EquipmentSetControl
|
||||
@@ -0,0 +1,116 @@
|
||||
import { memo } from 'react'
|
||||
import { Box, Flex, Image } from 'theme-ui'
|
||||
import { assetsBucketBaseUrl } from '../../../lib/consts'
|
||||
import { RemembranceSigil } from '../../../lib/honkai3rd/elysianRealm'
|
||||
import { ERGGSigilSet } from './types'
|
||||
|
||||
interface SigilBoxProps {
|
||||
sigilSets: ERGGSigilSet[]
|
||||
sigils: RemembranceSigil[]
|
||||
}
|
||||
|
||||
const SigilBox = ({ sigilSets, sigils }: SigilBoxProps) => {
|
||||
return (
|
||||
<Box
|
||||
sx={{
|
||||
padding: '5px',
|
||||
border: 'solid 1px gray',
|
||||
boxSizing: 'border-box',
|
||||
backgroundColor: 'rgba(0,0,0,0.5)',
|
||||
boxShadow: '5px 5px 10px rgba(0,0,0,0.5)',
|
||||
}}
|
||||
>
|
||||
<Flex>
|
||||
<Box
|
||||
sx={{
|
||||
backgroundColor: '#8E5B45',
|
||||
p: '5px',
|
||||
textAlign: 'center',
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
justifyContent: 'center',
|
||||
mr: '5px',
|
||||
width: 55,
|
||||
}}
|
||||
>
|
||||
<Box>회상의</Box>
|
||||
<Box>증명</Box>
|
||||
</Box>
|
||||
{sigilSets.map((sigilSet, index) => {
|
||||
return (
|
||||
<Box
|
||||
key={index}
|
||||
sx={{
|
||||
backgroundColor: '#615559',
|
||||
p: '15px 5px 0',
|
||||
borderRadius: '5px',
|
||||
position: 'relative',
|
||||
mr: '5px',
|
||||
'&:last-child': {
|
||||
mr: 0,
|
||||
},
|
||||
}}
|
||||
>
|
||||
<Box
|
||||
sx={{
|
||||
position: 'absolute',
|
||||
top: 0,
|
||||
left: 0,
|
||||
backgroundColor:
|
||||
sigilSet.type === 'start'
|
||||
? '#666480'
|
||||
: sigilSet.type === 'mid'
|
||||
? '#8A6A5C'
|
||||
: '#C06848',
|
||||
borderTopLeftRadius: '5px',
|
||||
borderBottomRightRadius: '5px',
|
||||
p: '0 7px',
|
||||
fontSize: 12,
|
||||
}}
|
||||
>
|
||||
{sigilSet.type === 'start'
|
||||
? '초반'
|
||||
: sigilSet.type === 'mid'
|
||||
? '중반'
|
||||
: '후반'}
|
||||
</Box>
|
||||
<Box sx={{ height: 40 }}>
|
||||
<Image
|
||||
alt=''
|
||||
src={`${assetsBucketBaseUrl}/honkai3rd/elysian-realm/remembrance-sigils/${sigilSet.sigilIds[0]}.png`}
|
||||
width={40}
|
||||
height={40}
|
||||
sx={{ mr: '5px', borderRadius: 5 }}
|
||||
/>
|
||||
<Image
|
||||
alt=''
|
||||
src={`${assetsBucketBaseUrl}/honkai3rd/elysian-realm/remembrance-sigils/${sigilSet.sigilIds[1]}.png`}
|
||||
width={40}
|
||||
height={40}
|
||||
sx={{ borderRadius: 5 }}
|
||||
/>
|
||||
</Box>
|
||||
<Flex
|
||||
sx={{
|
||||
height: 20,
|
||||
fontSize: 12,
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
}}
|
||||
>
|
||||
{getSigilName(sigilSet.sigilIds[0])}+
|
||||
{getSigilName(sigilSet.sigilIds[1])}
|
||||
</Flex>
|
||||
</Box>
|
||||
)
|
||||
})}
|
||||
</Flex>
|
||||
</Box>
|
||||
)
|
||||
|
||||
function getSigilName(id: string) {
|
||||
return sigils.find((sigil) => sigil.id === id)?.name.slice(0, 3)
|
||||
}
|
||||
}
|
||||
|
||||
export default memo(SigilBox)
|
||||
@@ -0,0 +1,108 @@
|
||||
import { RemembranceSigil } from '../../../lib/honkai3rd/elysianRealm'
|
||||
import ReactSelect, { components } from 'react-select'
|
||||
import { Flex, Image } from 'theme-ui'
|
||||
import { memo, useMemo } from 'react'
|
||||
import { assetsBucketBaseUrl } from '../../../lib/consts'
|
||||
|
||||
interface SigilSelectProps {
|
||||
instanceId: string
|
||||
value: string
|
||||
optionIds: string[]
|
||||
sigils: RemembranceSigil[]
|
||||
onChange: (newValue: string) => void
|
||||
}
|
||||
|
||||
const SigilSelect = ({
|
||||
instanceId,
|
||||
optionIds,
|
||||
sigils,
|
||||
onChange,
|
||||
value,
|
||||
}: SigilSelectProps) => {
|
||||
const sigilOptions = useMemo(() => {
|
||||
return optionIds.map((sigilId) => {
|
||||
const sigil = sigils.find((aSigil) => {
|
||||
return aSigil.id === sigilId
|
||||
})
|
||||
if (sigil == null) {
|
||||
return {
|
||||
value: 'unknown',
|
||||
label: 'unknown',
|
||||
}
|
||||
}
|
||||
return {
|
||||
value: sigil.id,
|
||||
label: sigil.name,
|
||||
}
|
||||
})
|
||||
}, [optionIds, sigils])
|
||||
|
||||
const sigil = useMemo(
|
||||
() =>
|
||||
sigils.find((sigil) => {
|
||||
return sigil.id === value
|
||||
}),
|
||||
[sigils, value]
|
||||
)
|
||||
|
||||
return (
|
||||
<ReactSelect
|
||||
instanceId={instanceId}
|
||||
value={
|
||||
sigil != null
|
||||
? {
|
||||
label: sigil.name,
|
||||
value: sigil.id,
|
||||
}
|
||||
: null
|
||||
}
|
||||
onChange={(option) => {
|
||||
if (option == null) {
|
||||
return
|
||||
}
|
||||
onChange(option.value)
|
||||
}}
|
||||
options={sigilOptions}
|
||||
components={{
|
||||
SingleValue: (props) => {
|
||||
return (
|
||||
<>
|
||||
<components.SingleValue {...props}>
|
||||
<Flex sx={{ alignItems: 'center', color: 'black' }}>
|
||||
<Image
|
||||
width={20}
|
||||
height={20}
|
||||
alt={props.data.label}
|
||||
src={`${assetsBucketBaseUrl}/honkai3rd/elysian-realm/remembrance-sigils/${props.data.value}.png`}
|
||||
mr={2}
|
||||
/>
|
||||
{props.children}
|
||||
</Flex>
|
||||
</components.SingleValue>
|
||||
</>
|
||||
)
|
||||
},
|
||||
Option: (props) => {
|
||||
return (
|
||||
<>
|
||||
<components.Option {...props}>
|
||||
<Flex sx={{ alignItems: 'center', color: 'black' }}>
|
||||
<Image
|
||||
width={20}
|
||||
height={20}
|
||||
alt={props.data.label}
|
||||
src={`${assetsBucketBaseUrl}/honkai3rd/elysian-realm/remembrance-sigils/${props.data.value}.png`}
|
||||
mr={2}
|
||||
/>
|
||||
{props.children}
|
||||
</Flex>
|
||||
</components.Option>
|
||||
</>
|
||||
)
|
||||
},
|
||||
}}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
export default memo(SigilSelect)
|
||||
@@ -0,0 +1,156 @@
|
||||
import React from 'react'
|
||||
import { Box, Flex, Image, Paragraph } from 'theme-ui'
|
||||
import { assetsBucketBaseUrl } from '../../../lib/consts'
|
||||
import { signetGroupMap } from '../../../lib/honkai3rd/elysianRealm'
|
||||
import { ERGGSignet } from './types'
|
||||
|
||||
interface SignetBoxProps {
|
||||
signets: ERGGSignet[]
|
||||
}
|
||||
|
||||
const SignetBox = ({ signets }: SignetBoxProps) => {
|
||||
return (
|
||||
<>
|
||||
{signets.map((signet, index) => {
|
||||
const dia = 460
|
||||
const radius = dia / 2
|
||||
const margin = 30
|
||||
const descriptionTop = 40 + margin + ((dia - margin * 2) / 4) * index
|
||||
const top =
|
||||
40 + radius + radius * Math.sin((30 / 180) * Math.PI * (index - 2))
|
||||
const angle = Math.asin((radius - (top - 40)) / radius)
|
||||
const left = Math.cos(angle) * radius + 100 + radius
|
||||
|
||||
const signetRadius = 45
|
||||
return (
|
||||
<React.Fragment key={index}>
|
||||
<Flex
|
||||
sx={{
|
||||
position: 'absolute',
|
||||
zIndex: 1,
|
||||
top: `${top - signetRadius}px`,
|
||||
left: `${left - signetRadius}px`,
|
||||
backgroundColor: '#10131C',
|
||||
height: signetRadius * 2,
|
||||
width: signetRadius * 2,
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center',
|
||||
borderRadius: signetRadius,
|
||||
border: '1px solid gray',
|
||||
boxShadow: '5px 5px 10px rgba(0,0,0,0.5)',
|
||||
flexDirection: 'column',
|
||||
}}
|
||||
>
|
||||
<Image
|
||||
alt=''
|
||||
src={`${assetsBucketBaseUrl}/honkai3rd/elysian-realm/signets/${signet.group}.png`}
|
||||
width={45}
|
||||
height={45}
|
||||
/>
|
||||
<Box
|
||||
className='signetGroupLabel'
|
||||
sx={{
|
||||
transform: 'translateX(-3px)',
|
||||
fontSize: 18,
|
||||
}}
|
||||
>
|
||||
{getSignetAltName(signet.group)}
|
||||
</Box>
|
||||
<Box
|
||||
sx={{
|
||||
backgroundColor: 'black',
|
||||
border: '1px solid gray',
|
||||
width: 20,
|
||||
height: 20,
|
||||
textAlign: 'center',
|
||||
borderRadius: 4,
|
||||
position: 'absolute',
|
||||
bottom: '12px',
|
||||
fontSize: 16,
|
||||
lineHeight: '20px',
|
||||
right: `${5}px`,
|
||||
}}
|
||||
>
|
||||
{signet.nexus === 1 ? 'I' : 'II'}
|
||||
</Box>
|
||||
</Flex>
|
||||
<Box
|
||||
sx={{
|
||||
position: 'absolute',
|
||||
borderBottom: '2px dashed gray',
|
||||
height: 0,
|
||||
top: `${top}px`,
|
||||
left: `${left}px`,
|
||||
right: 340,
|
||||
}}
|
||||
/>
|
||||
<Flex
|
||||
sx={{
|
||||
top: `${descriptionTop - 40}px`,
|
||||
height: 80,
|
||||
border: 'solid 1px gray',
|
||||
boxSizing: 'border-box',
|
||||
backgroundColor: 'rgba(0,0,0,0.5)',
|
||||
boxShadow: '5px 5px 10px rgba(0,0,0,0.5)',
|
||||
width: 330,
|
||||
position: 'absolute',
|
||||
right: 10,
|
||||
alignItems: 'center',
|
||||
}}
|
||||
>
|
||||
<Flex
|
||||
sx={{
|
||||
width: 80,
|
||||
height: 60,
|
||||
borderRight: 'solid 1px gray',
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center',
|
||||
mr: '5px',
|
||||
flexShrink: 0,
|
||||
}}
|
||||
>
|
||||
<Box
|
||||
sx={{
|
||||
fontSize: 4,
|
||||
lineHeight: 1.3,
|
||||
fontWeight: 'bold',
|
||||
color:
|
||||
signet.type === 'core'
|
||||
? '#E39070'
|
||||
: signet.type === 'start'
|
||||
? '#FEDEC2'
|
||||
: '#A59A9B',
|
||||
}}
|
||||
className='signetTypeLabel'
|
||||
>
|
||||
<Box>
|
||||
<Box>
|
||||
{signet.type === 'core'
|
||||
? '핵심'
|
||||
: signet.type === 'start'
|
||||
? '과도'
|
||||
: '보조'}
|
||||
</Box>
|
||||
<Box>각인</Box>
|
||||
</Box>
|
||||
</Box>
|
||||
</Flex>
|
||||
<Paragraph
|
||||
className='signetDescription'
|
||||
sx={{ padding: '5px', whiteSpace: 'pre-wrap' }}
|
||||
>
|
||||
{signet.description}
|
||||
</Paragraph>
|
||||
</Flex>
|
||||
</React.Fragment>
|
||||
)
|
||||
})}
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
export default SignetBox
|
||||
|
||||
function getSignetAltName(id: string) {
|
||||
return signetGroupMap.get(id)?.krAltName
|
||||
}
|
||||
@@ -0,0 +1,82 @@
|
||||
import { useMemo } from 'react'
|
||||
import ReactSelect, { components } from 'react-select'
|
||||
import { Flex, Image } from 'theme-ui'
|
||||
import { assetsBucketBaseUrl } from '../../../lib/consts'
|
||||
import { signetGroups } from '../../../lib/honkai3rd/elysianRealm'
|
||||
|
||||
interface SignetGroupSelectProps {
|
||||
instanceId: string
|
||||
value: string
|
||||
onChange: (newValue: string) => void
|
||||
}
|
||||
|
||||
const SignetGroupSelect = ({
|
||||
instanceId,
|
||||
value,
|
||||
onChange,
|
||||
}: SignetGroupSelectProps) => {
|
||||
const options = useMemo(() => {
|
||||
return signetGroups.slice(1).map((signetGroup) => {
|
||||
return {
|
||||
value: signetGroup.id,
|
||||
label: signetGroup.krAltName,
|
||||
}
|
||||
})
|
||||
}, [])
|
||||
|
||||
const currentOption = options.find((option) => option.value === value)
|
||||
|
||||
return (
|
||||
<ReactSelect
|
||||
instanceId={instanceId}
|
||||
value={currentOption}
|
||||
onChange={(option) => {
|
||||
if (option == null) {
|
||||
return
|
||||
}
|
||||
onChange(option.value)
|
||||
}}
|
||||
options={options}
|
||||
components={{
|
||||
SingleValue: (props) => {
|
||||
return (
|
||||
<>
|
||||
<components.SingleValue {...props}>
|
||||
<Flex sx={{ alignItems: 'center', color: 'black' }}>
|
||||
<Image
|
||||
width={20}
|
||||
height={20}
|
||||
alt={props.data.label}
|
||||
src={`${assetsBucketBaseUrl}/honkai3rd/elysian-realm/signets/${props.data.value}.png`}
|
||||
sx={{ flexShrink: 0, mr: 2 }}
|
||||
/>
|
||||
{props.children}
|
||||
</Flex>
|
||||
</components.SingleValue>
|
||||
</>
|
||||
)
|
||||
},
|
||||
Option: (props) => {
|
||||
return (
|
||||
<>
|
||||
<components.Option {...props}>
|
||||
<Flex sx={{ alignItems: 'center', color: 'black' }}>
|
||||
<Image
|
||||
width={20}
|
||||
height={20}
|
||||
alt={props.data.label}
|
||||
src={`${assetsBucketBaseUrl}/honkai3rd/elysian-realm/signets/${props.data.value}.png`}
|
||||
sx={{ mr: 2, flexShrink: 0 }}
|
||||
/>
|
||||
{props.children}
|
||||
</Flex>
|
||||
</components.Option>
|
||||
</>
|
||||
)
|
||||
},
|
||||
}}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
export default SignetGroupSelect
|
||||
@@ -0,0 +1,108 @@
|
||||
import ReactSelect, { components } from 'react-select'
|
||||
import { Flex, Image } from 'theme-ui'
|
||||
import { memo, useMemo } from 'react'
|
||||
import { assetsBucketBaseUrl } from '../../../lib/consts'
|
||||
import { StigmataData } from '../../../lib/honkai3rd/stigmata'
|
||||
|
||||
interface StigmaSelectProps {
|
||||
instanceId: string
|
||||
value: string
|
||||
optionIds: string[]
|
||||
stigmata: StigmataData[]
|
||||
onChange: (newValue: string) => void
|
||||
}
|
||||
|
||||
const StigmaSelect = ({
|
||||
instanceId,
|
||||
optionIds,
|
||||
stigmata,
|
||||
onChange,
|
||||
value,
|
||||
}: StigmaSelectProps) => {
|
||||
const stigmaOptions = useMemo(() => {
|
||||
return optionIds.map((stigmaId) => {
|
||||
const stigma = stigmata.find((aStigma) => {
|
||||
return aStigma.id === stigmaId
|
||||
})
|
||||
if (stigma == null) {
|
||||
return {
|
||||
value: 'unknown',
|
||||
label: 'unknown',
|
||||
}
|
||||
}
|
||||
return {
|
||||
value: stigma.id,
|
||||
label: stigma.name,
|
||||
}
|
||||
})
|
||||
}, [optionIds, stigmata])
|
||||
|
||||
const stigma = useMemo(
|
||||
() =>
|
||||
stigmata.find((aStigma) => {
|
||||
return aStigma.id === value
|
||||
}),
|
||||
[value, stigmata]
|
||||
)
|
||||
|
||||
return (
|
||||
<ReactSelect
|
||||
instanceId={instanceId}
|
||||
value={
|
||||
stigma != null
|
||||
? {
|
||||
label: stigma.name,
|
||||
value: stigma.id,
|
||||
}
|
||||
: null
|
||||
}
|
||||
onChange={(option) => {
|
||||
if (option == null) {
|
||||
return
|
||||
}
|
||||
onChange(option.value)
|
||||
}}
|
||||
options={stigmaOptions}
|
||||
components={{
|
||||
SingleValue: (props) => {
|
||||
return (
|
||||
<>
|
||||
<components.SingleValue {...props}>
|
||||
<Flex sx={{ alignItems: 'center', color: 'black' }}>
|
||||
<Image
|
||||
width={20}
|
||||
height={20}
|
||||
alt={props.data.label}
|
||||
src={`${assetsBucketBaseUrl}/honkai3rd/stigmata/icon-${props.data.value}.png`}
|
||||
sx={{ mr: 2, flexShrink: 0 }}
|
||||
/>
|
||||
{props.children}
|
||||
</Flex>
|
||||
</components.SingleValue>
|
||||
</>
|
||||
)
|
||||
},
|
||||
Option: (props) => {
|
||||
return (
|
||||
<>
|
||||
<components.Option {...props}>
|
||||
<Flex sx={{ alignItems: 'center', color: 'black' }}>
|
||||
<Image
|
||||
width={20}
|
||||
height={20}
|
||||
alt={props.data.label}
|
||||
src={`${assetsBucketBaseUrl}/honkai3rd/stigmata/icon-${props.data.value}.png`}
|
||||
sx={{ mr: 2, flexShrink: 0 }}
|
||||
/>
|
||||
{props.children}
|
||||
</Flex>
|
||||
</components.Option>
|
||||
</>
|
||||
)
|
||||
},
|
||||
}}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
export default memo(StigmaSelect)
|
||||
@@ -0,0 +1,132 @@
|
||||
import { Box, Flex, Image } from 'theme-ui'
|
||||
import { assetsBucketBaseUrl } from '../../../lib/consts'
|
||||
import { ERGGSupportSet } from './types'
|
||||
|
||||
interface SupportBoxProps {
|
||||
supportSets: ERGGSupportSet[]
|
||||
}
|
||||
|
||||
const SupportBox = ({ supportSets }: SupportBoxProps) => {
|
||||
return (
|
||||
<Box
|
||||
sx={{
|
||||
padding: '5px',
|
||||
border: 'solid 1px gray',
|
||||
boxSizing: 'border-box',
|
||||
backgroundColor: 'rgba(0,0,0,0.5)',
|
||||
boxShadow: '5px 5px 10px rgba(0,0,0,0.5)',
|
||||
}}
|
||||
>
|
||||
<Flex>
|
||||
<Box
|
||||
sx={{
|
||||
backgroundColor: '#8E5B45',
|
||||
p: '5px',
|
||||
textAlign: 'center',
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
justifyContent: 'center',
|
||||
width: 55,
|
||||
mr: '5px',
|
||||
}}
|
||||
>
|
||||
<Box>지원</Box>
|
||||
<Box>발키리</Box>
|
||||
</Box>
|
||||
{supportSets.map((supportSet, index) => {
|
||||
return (
|
||||
<Box
|
||||
key={index}
|
||||
sx={{
|
||||
backgroundColor: '#615559',
|
||||
p: '15px 5px 0',
|
||||
borderRadius: '5px',
|
||||
position: 'relative',
|
||||
mr: '5px',
|
||||
'&:last-child': {
|
||||
mr: 0,
|
||||
},
|
||||
}}
|
||||
>
|
||||
<Box
|
||||
sx={{
|
||||
position: 'absolute',
|
||||
top: 0,
|
||||
left: 0,
|
||||
backgroundColor:
|
||||
supportSet.type === 'util' ? '#356D7E' : '#EE4D2A',
|
||||
borderTopLeftRadius: '5px',
|
||||
borderBottomRightRadius: '5px',
|
||||
p: '0 7px',
|
||||
fontSize: 12,
|
||||
}}
|
||||
>
|
||||
{supportSet.type === 'util' ? '유틸' : '딜링'}
|
||||
</Box>
|
||||
<Box sx={{ height: 40 }}>
|
||||
{supportSet.battlesuitIds.map((battlesuitId) => {
|
||||
return (
|
||||
<Image
|
||||
key={battlesuitId}
|
||||
alt=''
|
||||
src={`${assetsBucketBaseUrl}/honkai3rd/battlesuits/portrait-${battlesuitId}.png`}
|
||||
width={40}
|
||||
height={40}
|
||||
sx={{
|
||||
borderRadius: '5px',
|
||||
mr: '5px',
|
||||
'&:last-child': { mr: 0 },
|
||||
}}
|
||||
/>
|
||||
)
|
||||
})}
|
||||
</Box>
|
||||
<Flex
|
||||
sx={{
|
||||
height: 20,
|
||||
fontSize: 12,
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
}}
|
||||
>
|
||||
{getSupportName(supportSet.battlesuitIds[0])}+
|
||||
{getSupportName(supportSet.battlesuitIds[1])}
|
||||
</Flex>
|
||||
</Box>
|
||||
)
|
||||
})}
|
||||
</Flex>
|
||||
</Box>
|
||||
)
|
||||
}
|
||||
|
||||
export default SupportBox
|
||||
|
||||
function getSupportName(id: string) {
|
||||
switch (id) {
|
||||
case 'le':
|
||||
return '귀메'
|
||||
case 'vc':
|
||||
return '삐로냐'
|
||||
case 'ss':
|
||||
return '빙로냐'
|
||||
case 'sn':
|
||||
return '쩨레'
|
||||
case 'br':
|
||||
return '스메코'
|
||||
case 'ae':
|
||||
return '선인'
|
||||
case 'hb':
|
||||
return '브로니'
|
||||
case 'ma':
|
||||
return '레이븐'
|
||||
case 'dp':
|
||||
return '성녀'
|
||||
case 'bke':
|
||||
return '월백'
|
||||
case 'rc':
|
||||
return '파르도'
|
||||
case 'sa':
|
||||
return '테갈'
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,149 @@
|
||||
import { Box, Flex, Text } from 'theme-ui'
|
||||
import { assetsBucketBaseUrl } from '../../../lib/consts'
|
||||
import { colors } from './styles'
|
||||
import { ERGGExSignet, ERGGExSignetType } from './types'
|
||||
import { getExSignetLabel } from './utils'
|
||||
|
||||
interface ValkBoxProps {
|
||||
battlesuitId: string
|
||||
exSignets: ERGGExSignet[]
|
||||
}
|
||||
|
||||
const ValkBox = ({ battlesuitId, exSignets }: ValkBoxProps) => {
|
||||
return (
|
||||
<Box
|
||||
sx={{
|
||||
position: 'absolute',
|
||||
left: 100,
|
||||
top: 40,
|
||||
width: 460,
|
||||
height: 460,
|
||||
}}
|
||||
>
|
||||
{exSignets.map(({ type, name }, index) => {
|
||||
return (
|
||||
<ValkExSignetBox key={index} index={index} type={type} name={name} />
|
||||
)
|
||||
})}
|
||||
|
||||
<Box
|
||||
sx={{
|
||||
borderRadius: '50%',
|
||||
border: 'solid 1px gray',
|
||||
boxShadow: '5px 5px 10px rgba(0,0,0,0.5)',
|
||||
width: 460,
|
||||
height: 460,
|
||||
backgroundImage: `url('${assetsBucketBaseUrl}/honkai3rd/battlesuits/${battlesuitId}.png')`,
|
||||
backgroundSize: 'cover',
|
||||
backgroundPosition: getBattlesuitImagePosition(battlesuitId),
|
||||
backgroundRepeat: 'no-repeat',
|
||||
backgroundColor: 'rgba(0,0,0,0.2)',
|
||||
}}
|
||||
></Box>
|
||||
</Box>
|
||||
)
|
||||
}
|
||||
|
||||
function getBattlesuitImagePosition(battlesuitId: string) {
|
||||
switch (battlesuitId) {
|
||||
case 'meme':
|
||||
return '0 10px'
|
||||
default:
|
||||
return 'center'
|
||||
}
|
||||
}
|
||||
|
||||
const ValkExSignetBox = ({
|
||||
index,
|
||||
type,
|
||||
name,
|
||||
}: {
|
||||
index: number
|
||||
type: ERGGExSignetType
|
||||
name: string
|
||||
}) => {
|
||||
const label = getExSignetLabel(name)
|
||||
const intervalAngle = 15
|
||||
const angle = -intervalAngle * (index + 1) - 24
|
||||
return (
|
||||
<Box
|
||||
sx={{
|
||||
position: 'absolute',
|
||||
top: 230 - 230 * Math.cos((angle / 180) * Math.PI) - 25,
|
||||
left: 230 + 230 * Math.sin((angle / 180) * Math.PI) - 25,
|
||||
width: 50,
|
||||
height: 50,
|
||||
}}
|
||||
>
|
||||
<Box
|
||||
sx={{
|
||||
position: 'absolute',
|
||||
backgroundColor:
|
||||
type === 'start'
|
||||
? '#C52CC5'
|
||||
: type === '1st'
|
||||
? '#EE4D2A'
|
||||
: type === '2nd'
|
||||
? '#9082BD'
|
||||
: type === 'backup'
|
||||
? '#C4C4C4'
|
||||
: 'transparent',
|
||||
borderWidth: 1,
|
||||
borderStyle: 'solid',
|
||||
color: type === 'backup' ? 'black' : '#fff',
|
||||
borderColor: type === 'na' ? '#AA9FA3' : 'transparent',
|
||||
top: '5px',
|
||||
right: 25,
|
||||
whiteSpace: 'nowrap',
|
||||
paddingRight: '30px',
|
||||
paddingLeft: '10px',
|
||||
textAlign: 'right',
|
||||
lineHeight: 1.3,
|
||||
zIndex: 1,
|
||||
borderTopLeftRadius: '4px',
|
||||
borderBottomLeftRadius: '4px',
|
||||
}}
|
||||
>
|
||||
{type === 'start'
|
||||
? '시작'
|
||||
: type === '1st'
|
||||
? '우선'
|
||||
: type === '2nd'
|
||||
? '차선'
|
||||
: type === 'backup'
|
||||
? '땜빵'
|
||||
: '미선택'}
|
||||
</Box>
|
||||
<Flex
|
||||
sx={{
|
||||
position: 'absolute',
|
||||
zIndex: 2,
|
||||
border: 'solid 1px gray',
|
||||
borderRadius: '50%',
|
||||
backgroundColor: colors.backgroundColor,
|
||||
boxShadow: '5px 5px 10px rgba(0,0,0,0.5)',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
fontSize:
|
||||
label.length > 3
|
||||
? label.indexOf('\n') >= 0
|
||||
? '14px'
|
||||
: '11px'
|
||||
: label.length > 2
|
||||
? 16
|
||||
: 20,
|
||||
width: 50,
|
||||
height: 50,
|
||||
lineHeight: 1.2,
|
||||
textAlign: 'center',
|
||||
whiteSpace: 'pre',
|
||||
}}
|
||||
className='exSignetLabel'
|
||||
>
|
||||
<Text>{label}</Text>
|
||||
</Flex>
|
||||
</Box>
|
||||
)
|
||||
}
|
||||
|
||||
export default ValkBox
|
||||
@@ -0,0 +1,105 @@
|
||||
import ReactSelect, { components } from 'react-select'
|
||||
import { Flex, Image } from 'theme-ui'
|
||||
import { memo, useMemo } from 'react'
|
||||
import { assetsBucketBaseUrl } from '../../../lib/consts'
|
||||
import { WeaponData } from '../../../lib/honkai3rd/weapons'
|
||||
|
||||
interface WeaponSelectProps {
|
||||
instanceId: string
|
||||
value: string
|
||||
optionIds: string[]
|
||||
weapons: WeaponData[]
|
||||
onChange: (newValue: string) => void
|
||||
}
|
||||
|
||||
const WeaponSelect = ({
|
||||
instanceId,
|
||||
optionIds,
|
||||
weapons,
|
||||
onChange,
|
||||
value,
|
||||
}: WeaponSelectProps) => {
|
||||
const weaponOptions = useMemo(() => {
|
||||
return optionIds.map((weaponId) => {
|
||||
const weapon = weapons.find((aWeapon) => {
|
||||
return aWeapon.id === weaponId
|
||||
})
|
||||
if (weapon == null) {
|
||||
return {
|
||||
value: 'unknown',
|
||||
label: 'unknown',
|
||||
}
|
||||
}
|
||||
return {
|
||||
value: weapon.id,
|
||||
label: weapon.name,
|
||||
}
|
||||
})
|
||||
}, [optionIds, weapons])
|
||||
|
||||
const weaponValue = useMemo(() => {
|
||||
const weapon = weapons.find((aWeapon) => {
|
||||
return aWeapon.id === value
|
||||
})
|
||||
return weapon != null
|
||||
? {
|
||||
label: weapon.name,
|
||||
value: weapon.id,
|
||||
}
|
||||
: null
|
||||
}, [value, weapons])
|
||||
|
||||
return (
|
||||
<ReactSelect
|
||||
instanceId={instanceId}
|
||||
value={weaponValue}
|
||||
onChange={(option) => {
|
||||
if (option == null) {
|
||||
return
|
||||
}
|
||||
onChange(option.value)
|
||||
}}
|
||||
options={weaponOptions}
|
||||
components={{
|
||||
SingleValue: (props) => {
|
||||
return (
|
||||
<>
|
||||
<components.SingleValue {...props}>
|
||||
<Flex sx={{ alignItems: 'center', color: 'black' }}>
|
||||
<Image
|
||||
width={20}
|
||||
height={20}
|
||||
alt={props.data.label}
|
||||
src={`${assetsBucketBaseUrl}/honkai3rd/weapons/${props.data.value}.png`}
|
||||
sx={{ mr: 2, flexShrink: 0 }}
|
||||
/>
|
||||
{props.children}
|
||||
</Flex>
|
||||
</components.SingleValue>
|
||||
</>
|
||||
)
|
||||
},
|
||||
Option: (props) => {
|
||||
return (
|
||||
<>
|
||||
<components.Option {...props}>
|
||||
<Flex sx={{ alignItems: 'center', color: 'black' }}>
|
||||
<Image
|
||||
width={20}
|
||||
height={20}
|
||||
alt={props.data.label}
|
||||
src={`${assetsBucketBaseUrl}/honkai3rd/weapons/${props.data.value}.png`}
|
||||
sx={{ mr: 2, flexShrink: 0 }}
|
||||
/>
|
||||
{props.children}
|
||||
</Flex>
|
||||
</components.Option>
|
||||
</>
|
||||
)
|
||||
},
|
||||
}}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
export default memo(WeaponSelect)
|
||||
@@ -0,0 +1,6 @@
|
||||
export const colors = {
|
||||
backgroundColor: '#311E22',
|
||||
abstinenceDifficultyColor: '#F09F85',
|
||||
corruptionDifficultyColor: '#EE4E2C',
|
||||
infernoDifficultyColor: '#9DA3D3',
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
export type ERGGExSignetType = 'start' | '1st' | '2nd' | 'backup' | 'na'
|
||||
|
||||
export interface ERGGExSignet {
|
||||
type: ERGGExSignetType
|
||||
name: string
|
||||
}
|
||||
|
||||
export type ERGGDataUpdater = <T extends keyof ERGGData>(
|
||||
key: T,
|
||||
value: ERGGData[T] | ((previousData: ERGGData[T]) => ERGGData[T])
|
||||
) => void
|
||||
|
||||
export interface ERGGSupportSet {
|
||||
type: 'util' | 'dps'
|
||||
battlesuitIds: [string, string]
|
||||
}
|
||||
|
||||
export interface ERGGSigilSet {
|
||||
type: 'start' | 'mid' | 'end'
|
||||
sigilIds: [string, string]
|
||||
}
|
||||
|
||||
export type ERGGDifficulty = 'abstinence' | 'corruption' | 'inferno'
|
||||
|
||||
export interface ERGGEquipmentSet {
|
||||
type: 'best' | 'alt'
|
||||
weapon: string
|
||||
top: string
|
||||
mid: string
|
||||
bot: string
|
||||
}
|
||||
|
||||
export interface ERGGSignet {
|
||||
group: string
|
||||
type: 'core' | 'start' | 'sub'
|
||||
nexus: 1 | 2
|
||||
description: string
|
||||
}
|
||||
|
||||
export type ERGGData = {
|
||||
rank?: string
|
||||
tag: string
|
||||
signature: string
|
||||
battlesuitId: string
|
||||
difficulty: ERGGDifficulty
|
||||
exSignets: ERGGExSignet[]
|
||||
supportSets: ERGGSupportSet[]
|
||||
sigilSets: ERGGSigilSet[]
|
||||
equipmentSets: ERGGEquipmentSet[]
|
||||
signets: ERGGSignet[]
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
export function getExSignetLabel(name: string) {
|
||||
return name
|
||||
.replace('의 축복', '')
|
||||
.replace(/\s/g, '\n')
|
||||
.replace(/[\[\]]/g, '')
|
||||
}
|
||||
@@ -113,6 +113,26 @@ export const remembranceSigilIds = [
|
||||
'key-to-the-deep',
|
||||
]
|
||||
|
||||
export function isGeneralSigil(sigilId: string) {
|
||||
switch (sigilId) {
|
||||
case 'it-will-be-written':
|
||||
case 'dreamful-gold':
|
||||
case 'an-old-pal-s-legacy':
|
||||
case 'empty-like-shala':
|
||||
case 'tsukimi-himiko':
|
||||
case 'boundless-logos':
|
||||
case 'hometown':
|
||||
case 'because-of-you':
|
||||
case 'boundless-feeling':
|
||||
case 'falling-in-past-light':
|
||||
case 'out-of-reach':
|
||||
case 'the-lonely-moon':
|
||||
case 'awakening':
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
export interface SignetData {
|
||||
id: string
|
||||
name: string
|
||||
@@ -127,6 +147,8 @@ export interface SignetGroup {
|
||||
id: string
|
||||
name: string
|
||||
krName: string
|
||||
altName: string
|
||||
krAltName: string
|
||||
setIds: string[]
|
||||
}
|
||||
|
||||
|
||||
@@ -121,6 +121,11 @@ export const theme: Theme = {
|
||||
lineHeight: 'heading',
|
||||
},
|
||||
},
|
||||
forms: {
|
||||
checkbox: {
|
||||
color: 'border',
|
||||
},
|
||||
},
|
||||
buttons: {
|
||||
primary: {
|
||||
color: 'primary',
|
||||
@@ -144,6 +149,9 @@ export const theme: Theme = {
|
||||
'&.hidden': {
|
||||
display: 'none',
|
||||
},
|
||||
'&:disabled': {
|
||||
opacity: 0.5,
|
||||
},
|
||||
},
|
||||
secondary: {
|
||||
color: 'background',
|
||||
|
||||
@@ -4,7 +4,6 @@ import Breadcrumb from '../../../components/organisms/Breadcrumb'
|
||||
import { getBattlesuitMapByIds } from '../../../server/data/honkai3rd/battlesuits'
|
||||
import { BattlesuitData } from '../../../lib/honkai3rd/battlesuits'
|
||||
import BattlesuitCard from '../../../components/molecules/BattlesuitCard'
|
||||
|
||||
import { NextPageContext } from 'next'
|
||||
import { getI18NProps } from '../../../server/i18n'
|
||||
import { useTranslation } from '../../../lib/i18n'
|
||||
@@ -19,6 +18,7 @@ import {
|
||||
getRemembranceSigils as getRemembranceSigils,
|
||||
getSupportBattlesuits,
|
||||
} from '../../../server/data/honkai3rd/elysianRealm'
|
||||
import Link from 'next/link'
|
||||
|
||||
type BattlesuitListItemData = Pick<
|
||||
BattlesuitData,
|
||||
@@ -152,6 +152,11 @@ const ElysianRealmIndexPage = ({
|
||||
})}
|
||||
</Flex>
|
||||
</Box>
|
||||
<Box>
|
||||
<Link href='/honkai3rd/elysian-realm/utils/gen-guide'>
|
||||
Guide Generator (KR Only)
|
||||
</Link>
|
||||
</Box>
|
||||
</Box>
|
||||
</Honkai3rdLayout>
|
||||
)
|
||||
@@ -180,6 +185,7 @@ export async function getStaticProps({ locale }: NextPageContext) {
|
||||
name,
|
||||
}
|
||||
})
|
||||
|
||||
return {
|
||||
props: {
|
||||
battlesuitMap: getBattlesuitMapByIds(erBattlesuitIds, locale),
|
||||
|
||||
@@ -0,0 +1,88 @@
|
||||
/* eslint-disable @next/next/no-page-custom-font */
|
||||
import { NextPageContext } from 'next'
|
||||
import { useRouter } from 'next/router'
|
||||
import { pick } from 'ramda'
|
||||
import { Box, Button, Flex, Heading } from 'theme-ui'
|
||||
import ERGuideGenerator from '../../../../components/organisms/ERGuideGenerator/ERGuideGenerator'
|
||||
import { BattlesuitData } from '../../../../lib/honkai3rd/battlesuits'
|
||||
import {
|
||||
PopulatedSignetGroup,
|
||||
RemembranceSigil,
|
||||
} from '../../../../lib/honkai3rd/elysianRealm'
|
||||
import { WeaponData } from '../../../../lib/honkai3rd/weapons'
|
||||
import { StigmataData } from '../../../../lib/honkai3rd/stigmata'
|
||||
import { listBattlesuits } from '../../../../server/data/honkai3rd/battlesuits'
|
||||
import {
|
||||
getRemembranceSigils,
|
||||
getSignetGroupById,
|
||||
} from '../../../../server/data/honkai3rd/elysianRealm'
|
||||
import { listStigmata } from '../../../../server/data/honkai3rd/stigmata'
|
||||
import { listWeapons } from '../../../../server/data/honkai3rd/weapons'
|
||||
import { getI18NProps } from '../../../../server/i18n'
|
||||
|
||||
interface GenerateGuidePageProps {
|
||||
weapons: WeaponData[]
|
||||
stigmata: StigmataData[]
|
||||
battlesuits: BattlesuitData[]
|
||||
exSignetGroup: PopulatedSignetGroup
|
||||
sigils: RemembranceSigil[]
|
||||
}
|
||||
|
||||
const GenerateGuidePage = ({
|
||||
weapons,
|
||||
stigmata,
|
||||
battlesuits,
|
||||
exSignetGroup,
|
||||
sigils,
|
||||
}: GenerateGuidePageProps) => {
|
||||
const router = useRouter()
|
||||
|
||||
return (
|
||||
<Box>
|
||||
<Flex m={2} sx={{ alignItems: 'center' }}>
|
||||
<Button
|
||||
onClick={() => {
|
||||
router.push('/honkai3rd')
|
||||
}}
|
||||
mr={2}
|
||||
>
|
||||
Back
|
||||
</Button>
|
||||
<Heading>ER Guide Generator</Heading>
|
||||
</Flex>
|
||||
<ERGuideGenerator
|
||||
weapons={weapons}
|
||||
stigmata={stigmata}
|
||||
battlesuits={battlesuits}
|
||||
exSignetGroup={exSignetGroup}
|
||||
sigils={sigils}
|
||||
/>
|
||||
</Box>
|
||||
)
|
||||
}
|
||||
|
||||
export default GenerateGuidePage
|
||||
|
||||
export async function getStaticProps({ locale }: NextPageContext) {
|
||||
return {
|
||||
props: {
|
||||
weapons: listWeapons('ko-KR').map((weapon) => {
|
||||
return pick(['name', 'id', 'rarity', 'category'], weapon)
|
||||
}),
|
||||
stigmata: listStigmata('ko-KR').map((stigmata) => {
|
||||
return pick(['name', 'id', 'type'], stigmata)
|
||||
}),
|
||||
battlesuits: listBattlesuits('ko-KR').map((battlesuit) => {
|
||||
return {
|
||||
id: battlesuit.id,
|
||||
name: battlesuit.name,
|
||||
type: battlesuit.type,
|
||||
valkyrie: battlesuit.valkyrie,
|
||||
}
|
||||
}),
|
||||
exSignetGroup: getSignetGroupById('elysia', 'ko-KR'),
|
||||
sigils: getRemembranceSigils('ko-KR'),
|
||||
...(await getI18NProps('ko-KR')),
|
||||
},
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user