mirror of
https://github.com/placeholder-soft/storytime.git
synced 2026-01-12 15:24:45 +08:00
Merge branch 'main' of github.com:placeholder-soft/storytime
This commit is contained in:
@@ -5,7 +5,7 @@
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
"build": "tsc && vite build",
|
||||
"build": "vite build",
|
||||
"lint": "eslint . --ext ts,tsx --report-unused-disable-directives --max-warnings 0",
|
||||
"preview": "vite preview"
|
||||
},
|
||||
@@ -46,8 +46,10 @@
|
||||
"eslint": "^8.53.0",
|
||||
"eslint-plugin-react-hooks": "^4.6.0",
|
||||
"eslint-plugin-react-refresh": "^0.4.4",
|
||||
"prettier": "^3.1.1",
|
||||
"typescript": "^5.2.2",
|
||||
"vite": "^5.0.0",
|
||||
"vite-plugin-pages": "^0.32.0"
|
||||
"vite-plugin-pages": "^0.32.0",
|
||||
"vite-plugin-svgr": "^4.2.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
606
app/pnpm-lock.yaml
generated
606
app/pnpm-lock.yaml
generated
@@ -109,6 +109,9 @@ devDependencies:
|
||||
eslint-plugin-react-refresh:
|
||||
specifier: ^0.4.4
|
||||
version: 0.4.5(eslint@8.55.0)
|
||||
prettier:
|
||||
specifier: ^3.1.1
|
||||
version: 3.1.1
|
||||
typescript:
|
||||
specifier: ^5.2.2
|
||||
version: 5.3.3
|
||||
@@ -118,6 +121,9 @@ devDependencies:
|
||||
vite-plugin-pages:
|
||||
specifier: ^0.32.0
|
||||
version: 0.32.0(vite@5.0.7)
|
||||
vite-plugin-svgr:
|
||||
specifier: ^4.2.0
|
||||
version: 4.2.0(typescript@5.3.3)(vite@5.0.7)
|
||||
|
||||
packages:
|
||||
|
||||
@@ -126,6 +132,169 @@ packages:
|
||||
engines: {node: '>=0.10.0'}
|
||||
dev: true
|
||||
|
||||
/@ampproject/remapping@2.2.1:
|
||||
resolution: {integrity: sha512-lFMjJTrFL3j7L9yBxwYfCq2k6qqwHyzuUl/XBnif78PWTJYyL/dfowQHWE3sp6U6ZzqWiiIZnpTMO96zhkjwtg==}
|
||||
engines: {node: '>=6.0.0'}
|
||||
dependencies:
|
||||
'@jridgewell/gen-mapping': 0.3.3
|
||||
'@jridgewell/trace-mapping': 0.3.20
|
||||
dev: true
|
||||
|
||||
/@babel/code-frame@7.23.5:
|
||||
resolution: {integrity: sha512-CgH3s1a96LipHCmSUmYFPwY7MNx8C3avkq7i4Wl3cfa662ldtUe4VM1TPXX70pfmrlWTb6jLqTYrZyT2ZTJBgA==}
|
||||
engines: {node: '>=6.9.0'}
|
||||
dependencies:
|
||||
'@babel/highlight': 7.23.4
|
||||
chalk: 2.4.2
|
||||
dev: true
|
||||
|
||||
/@babel/compat-data@7.23.5:
|
||||
resolution: {integrity: sha512-uU27kfDRlhfKl+w1U6vp16IuvSLtjAxdArVXPa9BvLkrr7CYIsxH5adpHObeAGY/41+syctUWOZ140a2Rvkgjw==}
|
||||
engines: {node: '>=6.9.0'}
|
||||
dev: true
|
||||
|
||||
/@babel/core@7.23.6:
|
||||
resolution: {integrity: sha512-FxpRyGjrMJXh7X3wGLGhNDCRiwpWEF74sKjTLDJSG5Kyvow3QZaG0Adbqzi9ZrVjTWpsX+2cxWXD71NMg93kdw==}
|
||||
engines: {node: '>=6.9.0'}
|
||||
dependencies:
|
||||
'@ampproject/remapping': 2.2.1
|
||||
'@babel/code-frame': 7.23.5
|
||||
'@babel/generator': 7.23.6
|
||||
'@babel/helper-compilation-targets': 7.23.6
|
||||
'@babel/helper-module-transforms': 7.23.3(@babel/core@7.23.6)
|
||||
'@babel/helpers': 7.23.6
|
||||
'@babel/parser': 7.23.6
|
||||
'@babel/template': 7.22.15
|
||||
'@babel/traverse': 7.23.6
|
||||
'@babel/types': 7.23.6
|
||||
convert-source-map: 2.0.0
|
||||
debug: 4.3.4
|
||||
gensync: 1.0.0-beta.2
|
||||
json5: 2.2.3
|
||||
semver: 6.3.1
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
dev: true
|
||||
|
||||
/@babel/generator@7.23.6:
|
||||
resolution: {integrity: sha512-qrSfCYxYQB5owCmGLbl8XRpX1ytXlpueOb0N0UmQwA073KZxejgQTzAmJezxvpwQD9uGtK2shHdi55QT+MbjIw==}
|
||||
engines: {node: '>=6.9.0'}
|
||||
dependencies:
|
||||
'@babel/types': 7.23.6
|
||||
'@jridgewell/gen-mapping': 0.3.3
|
||||
'@jridgewell/trace-mapping': 0.3.20
|
||||
jsesc: 2.5.2
|
||||
dev: true
|
||||
|
||||
/@babel/helper-compilation-targets@7.23.6:
|
||||
resolution: {integrity: sha512-9JB548GZoQVmzrFgp8o7KxdgkTGm6xs9DW0o/Pim72UDjzr5ObUQ6ZzYPqA+g9OTS2bBQoctLJrky0RDCAWRgQ==}
|
||||
engines: {node: '>=6.9.0'}
|
||||
dependencies:
|
||||
'@babel/compat-data': 7.23.5
|
||||
'@babel/helper-validator-option': 7.23.5
|
||||
browserslist: 4.22.2
|
||||
lru-cache: 5.1.1
|
||||
semver: 6.3.1
|
||||
dev: true
|
||||
|
||||
/@babel/helper-environment-visitor@7.22.20:
|
||||
resolution: {integrity: sha512-zfedSIzFhat/gFhWfHtgWvlec0nqB9YEIVrpuwjruLlXfUSnA8cJB0miHKwqDnQ7d32aKo2xt88/xZptwxbfhA==}
|
||||
engines: {node: '>=6.9.0'}
|
||||
dev: true
|
||||
|
||||
/@babel/helper-function-name@7.23.0:
|
||||
resolution: {integrity: sha512-OErEqsrxjZTJciZ4Oo+eoZqeW9UIiOcuYKRJA4ZAgV9myA+pOXhhmpfNCKjEH/auVfEYVFJ6y1Tc4r0eIApqiw==}
|
||||
engines: {node: '>=6.9.0'}
|
||||
dependencies:
|
||||
'@babel/template': 7.22.15
|
||||
'@babel/types': 7.23.6
|
||||
dev: true
|
||||
|
||||
/@babel/helper-hoist-variables@7.22.5:
|
||||
resolution: {integrity: sha512-wGjk9QZVzvknA6yKIUURb8zY3grXCcOZt+/7Wcy8O2uctxhplmUPkOdlgoNhmdVee2c92JXbf1xpMtVNbfoxRw==}
|
||||
engines: {node: '>=6.9.0'}
|
||||
dependencies:
|
||||
'@babel/types': 7.23.6
|
||||
dev: true
|
||||
|
||||
/@babel/helper-module-imports@7.22.15:
|
||||
resolution: {integrity: sha512-0pYVBnDKZO2fnSPCrgM/6WMc7eS20Fbok+0r88fp+YtWVLZrp4CkafFGIp+W0VKw4a22sgebPT99y+FDNMdP4w==}
|
||||
engines: {node: '>=6.9.0'}
|
||||
dependencies:
|
||||
'@babel/types': 7.23.6
|
||||
dev: true
|
||||
|
||||
/@babel/helper-module-transforms@7.23.3(@babel/core@7.23.6):
|
||||
resolution: {integrity: sha512-7bBs4ED9OmswdfDzpz4MpWgSrV7FXlc3zIagvLFjS5H+Mk7Snr21vQ6QwrsoCGMfNC4e4LQPdoULEt4ykz0SRQ==}
|
||||
engines: {node: '>=6.9.0'}
|
||||
peerDependencies:
|
||||
'@babel/core': ^7.0.0
|
||||
dependencies:
|
||||
'@babel/core': 7.23.6
|
||||
'@babel/helper-environment-visitor': 7.22.20
|
||||
'@babel/helper-module-imports': 7.22.15
|
||||
'@babel/helper-simple-access': 7.22.5
|
||||
'@babel/helper-split-export-declaration': 7.22.6
|
||||
'@babel/helper-validator-identifier': 7.22.20
|
||||
dev: true
|
||||
|
||||
/@babel/helper-simple-access@7.22.5:
|
||||
resolution: {integrity: sha512-n0H99E/K+Bika3++WNL17POvo4rKWZ7lZEp1Q+fStVbUi8nxPQEBOlTmCOxW/0JsS56SKKQ+ojAe2pHKJHN35w==}
|
||||
engines: {node: '>=6.9.0'}
|
||||
dependencies:
|
||||
'@babel/types': 7.23.6
|
||||
dev: true
|
||||
|
||||
/@babel/helper-split-export-declaration@7.22.6:
|
||||
resolution: {integrity: sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g==}
|
||||
engines: {node: '>=6.9.0'}
|
||||
dependencies:
|
||||
'@babel/types': 7.23.6
|
||||
dev: true
|
||||
|
||||
/@babel/helper-string-parser@7.23.4:
|
||||
resolution: {integrity: sha512-803gmbQdqwdf4olxrX4AJyFBV/RTr3rSmOj0rKwesmzlfhYNDEs+/iOcznzpNWlJlIlTJC2QfPFcHB6DlzdVLQ==}
|
||||
engines: {node: '>=6.9.0'}
|
||||
dev: true
|
||||
|
||||
/@babel/helper-validator-identifier@7.22.20:
|
||||
resolution: {integrity: sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A==}
|
||||
engines: {node: '>=6.9.0'}
|
||||
dev: true
|
||||
|
||||
/@babel/helper-validator-option@7.23.5:
|
||||
resolution: {integrity: sha512-85ttAOMLsr53VgXkTbkx8oA6YTfT4q7/HzXSLEYmjcSTJPMPQtvq1BD79Byep5xMUYbGRzEpDsjUf3dyp54IKw==}
|
||||
engines: {node: '>=6.9.0'}
|
||||
dev: true
|
||||
|
||||
/@babel/helpers@7.23.6:
|
||||
resolution: {integrity: sha512-wCfsbN4nBidDRhpDhvcKlzHWCTlgJYUUdSJfzXb2NuBssDSIjc3xcb+znA7l+zYsFljAcGM0aFkN40cR3lXiGA==}
|
||||
engines: {node: '>=6.9.0'}
|
||||
dependencies:
|
||||
'@babel/template': 7.22.15
|
||||
'@babel/traverse': 7.23.6
|
||||
'@babel/types': 7.23.6
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
dev: true
|
||||
|
||||
/@babel/highlight@7.23.4:
|
||||
resolution: {integrity: sha512-acGdbYSfp2WheJoJm/EBBBLh/ID8KDc64ISZ9DYtBmC8/Q204PZJLHyzeB5qMzJ5trcOkybd78M4x2KWsUq++A==}
|
||||
engines: {node: '>=6.9.0'}
|
||||
dependencies:
|
||||
'@babel/helper-validator-identifier': 7.22.20
|
||||
chalk: 2.4.2
|
||||
js-tokens: 4.0.0
|
||||
dev: true
|
||||
|
||||
/@babel/parser@7.23.6:
|
||||
resolution: {integrity: sha512-Z2uID7YJ7oNvAI20O9X0bblw7Qqs8Q2hFy0R9tAfnfLkp5MW0UH9eUvnDSnFwKZ0AvgS1ucqR4KzvVHgnke1VQ==}
|
||||
engines: {node: '>=6.0.0'}
|
||||
hasBin: true
|
||||
dependencies:
|
||||
'@babel/types': 7.23.6
|
||||
dev: true
|
||||
|
||||
/@babel/runtime@7.23.5:
|
||||
resolution: {integrity: sha512-NdUTHcPe4C99WxPub+K9l9tK5/lV4UXIoaHSYgzco9BCyjKAAwzdBI+wWtYqHt7LJdbo74ZjRPJgzVweq1sz0w==}
|
||||
engines: {node: '>=6.9.0'}
|
||||
@@ -133,6 +302,42 @@ packages:
|
||||
regenerator-runtime: 0.14.0
|
||||
dev: false
|
||||
|
||||
/@babel/template@7.22.15:
|
||||
resolution: {integrity: sha512-QPErUVm4uyJa60rkI73qneDacvdvzxshT3kksGqlGWYdOTIUOwJ7RDUL8sGqslY1uXWSL6xMFKEXDS3ox2uF0w==}
|
||||
engines: {node: '>=6.9.0'}
|
||||
dependencies:
|
||||
'@babel/code-frame': 7.23.5
|
||||
'@babel/parser': 7.23.6
|
||||
'@babel/types': 7.23.6
|
||||
dev: true
|
||||
|
||||
/@babel/traverse@7.23.6:
|
||||
resolution: {integrity: sha512-czastdK1e8YByZqezMPFiZ8ahwVMh/ESl9vPgvgdB9AmFMGP5jfpFax74AQgl5zj4XHzqeYAg2l8PuUeRS1MgQ==}
|
||||
engines: {node: '>=6.9.0'}
|
||||
dependencies:
|
||||
'@babel/code-frame': 7.23.5
|
||||
'@babel/generator': 7.23.6
|
||||
'@babel/helper-environment-visitor': 7.22.20
|
||||
'@babel/helper-function-name': 7.23.0
|
||||
'@babel/helper-hoist-variables': 7.22.5
|
||||
'@babel/helper-split-export-declaration': 7.22.6
|
||||
'@babel/parser': 7.23.6
|
||||
'@babel/types': 7.23.6
|
||||
debug: 4.3.4
|
||||
globals: 11.12.0
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
dev: true
|
||||
|
||||
/@babel/types@7.23.6:
|
||||
resolution: {integrity: sha512-+uarb83brBzPKN38NX1MkB6vb6+mwvR6amUulqAE7ccQw1pEl+bCia9TbdG1lsnFP7lZySvUn37CHyXQdfTwzg==}
|
||||
engines: {node: '>=6.9.0'}
|
||||
dependencies:
|
||||
'@babel/helper-string-parser': 7.23.4
|
||||
'@babel/helper-validator-identifier': 7.22.20
|
||||
to-fast-properties: 2.0.0
|
||||
dev: true
|
||||
|
||||
/@emotion/hash@0.9.1:
|
||||
resolution: {integrity: sha512-gJB6HLm5rYwSLI6PQa+X1t5CFGrv1J1TWG+sOyMCeKz2ojaj6Fnl/rZEspogG+cvqbt4AE/2eIyD2QfLKTBNlQ==}
|
||||
dev: false
|
||||
@@ -901,6 +1106,36 @@ packages:
|
||||
resolution: {integrity: sha512-dvuCeX5fC9dXgJn9t+X5atfmgQAzUOWqS1254Gh0m6i8wKd10ebXkfNKiRK+1GWi/yTvvLDHpoxLr0xxxeslWw==}
|
||||
dev: true
|
||||
|
||||
/@jridgewell/gen-mapping@0.3.3:
|
||||
resolution: {integrity: sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ==}
|
||||
engines: {node: '>=6.0.0'}
|
||||
dependencies:
|
||||
'@jridgewell/set-array': 1.1.2
|
||||
'@jridgewell/sourcemap-codec': 1.4.15
|
||||
'@jridgewell/trace-mapping': 0.3.20
|
||||
dev: true
|
||||
|
||||
/@jridgewell/resolve-uri@3.1.1:
|
||||
resolution: {integrity: sha512-dSYZh7HhCDtCKm4QakX0xFpsRDqjjtZf/kjI/v3T3Nwt5r8/qz/M19F9ySyOqU94SXBmeG9ttTul+YnR4LOxFA==}
|
||||
engines: {node: '>=6.0.0'}
|
||||
dev: true
|
||||
|
||||
/@jridgewell/set-array@1.1.2:
|
||||
resolution: {integrity: sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==}
|
||||
engines: {node: '>=6.0.0'}
|
||||
dev: true
|
||||
|
||||
/@jridgewell/sourcemap-codec@1.4.15:
|
||||
resolution: {integrity: sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==}
|
||||
dev: true
|
||||
|
||||
/@jridgewell/trace-mapping@0.3.20:
|
||||
resolution: {integrity: sha512-R8LcPeWZol2zR8mmH3JeKQ6QRCFb7XgUhV9ZlGhHLGyg4wpPiPZNQOOWhFZhxKw8u//yTbNGI42Bx/3paXEQ+Q==}
|
||||
dependencies:
|
||||
'@jridgewell/resolve-uri': 3.1.1
|
||||
'@jridgewell/sourcemap-codec': 1.4.15
|
||||
dev: true
|
||||
|
||||
/@mapbox/node-pre-gyp@1.0.11:
|
||||
resolution: {integrity: sha512-Yhlar6v9WQgUp/He7BdgzOz8lqMQ8sU+jkCq7Wx8Myc5YFJLbEe7lgui/V7G1qB1DJykHSGwreceSaD60Y0PUQ==}
|
||||
hasBin: true
|
||||
@@ -2216,6 +2451,20 @@ packages:
|
||||
engines: {node: '>=14.0.0'}
|
||||
dev: false
|
||||
|
||||
/@rollup/pluginutils@5.1.0:
|
||||
resolution: {integrity: sha512-XTIWOPPcpvyKI6L1NHo0lFlCyznUEyPmPY1mc3KpPVDYulHSTvyeLNVW00QTLIAFNhR3kYnJTQHeGqU4M3n09g==}
|
||||
engines: {node: '>=14.0.0'}
|
||||
peerDependencies:
|
||||
rollup: ^1.20.0||^2.0.0||^3.0.0||^4.0.0
|
||||
peerDependenciesMeta:
|
||||
rollup:
|
||||
optional: true
|
||||
dependencies:
|
||||
'@types/estree': 1.0.5
|
||||
estree-walker: 2.0.2
|
||||
picomatch: 2.3.1
|
||||
dev: true
|
||||
|
||||
/@rollup/rollup-android-arm-eabi@4.7.0:
|
||||
resolution: {integrity: sha512-rGku10pL1StFlFvXX5pEv88KdGW6DHUghsxyP/aRYb9eH+74jTGJ3U0S/rtlsQ4yYq1Hcc7AMkoJOb1xu29Fxw==}
|
||||
cpu: [arm]
|
||||
@@ -2343,6 +2592,132 @@ packages:
|
||||
resolution: {integrity: sha512-bprE8+K5V+DPX7q2e2K57ImqNBdfGHDIWaGI5xHxZoxbKOuQZn4wzPiUxOAHnsUr3w3xHrWXwN7gnG/iIuEMIg==}
|
||||
dev: false
|
||||
|
||||
/@svgr/babel-plugin-add-jsx-attribute@8.0.0(@babel/core@7.23.6):
|
||||
resolution: {integrity: sha512-b9MIk7yhdS1pMCZM8VeNfUlSKVRhsHZNMl5O9SfaX0l0t5wjdgu4IDzGB8bpnGBBOjGST3rRFVsaaEtI4W6f7g==}
|
||||
engines: {node: '>=14'}
|
||||
peerDependencies:
|
||||
'@babel/core': ^7.0.0-0
|
||||
dependencies:
|
||||
'@babel/core': 7.23.6
|
||||
dev: true
|
||||
|
||||
/@svgr/babel-plugin-remove-jsx-attribute@8.0.0(@babel/core@7.23.6):
|
||||
resolution: {integrity: sha512-BcCkm/STipKvbCl6b7QFrMh/vx00vIP63k2eM66MfHJzPr6O2U0jYEViXkHJWqXqQYjdeA9cuCl5KWmlwjDvbA==}
|
||||
engines: {node: '>=14'}
|
||||
peerDependencies:
|
||||
'@babel/core': ^7.0.0-0
|
||||
dependencies:
|
||||
'@babel/core': 7.23.6
|
||||
dev: true
|
||||
|
||||
/@svgr/babel-plugin-remove-jsx-empty-expression@8.0.0(@babel/core@7.23.6):
|
||||
resolution: {integrity: sha512-5BcGCBfBxB5+XSDSWnhTThfI9jcO5f0Ai2V24gZpG+wXF14BzwxxdDb4g6trdOux0rhibGs385BeFMSmxtS3uA==}
|
||||
engines: {node: '>=14'}
|
||||
peerDependencies:
|
||||
'@babel/core': ^7.0.0-0
|
||||
dependencies:
|
||||
'@babel/core': 7.23.6
|
||||
dev: true
|
||||
|
||||
/@svgr/babel-plugin-replace-jsx-attribute-value@8.0.0(@babel/core@7.23.6):
|
||||
resolution: {integrity: sha512-KVQ+PtIjb1BuYT3ht8M5KbzWBhdAjjUPdlMtpuw/VjT8coTrItWX6Qafl9+ji831JaJcu6PJNKCV0bp01lBNzQ==}
|
||||
engines: {node: '>=14'}
|
||||
peerDependencies:
|
||||
'@babel/core': ^7.0.0-0
|
||||
dependencies:
|
||||
'@babel/core': 7.23.6
|
||||
dev: true
|
||||
|
||||
/@svgr/babel-plugin-svg-dynamic-title@8.0.0(@babel/core@7.23.6):
|
||||
resolution: {integrity: sha512-omNiKqwjNmOQJ2v6ge4SErBbkooV2aAWwaPFs2vUY7p7GhVkzRkJ00kILXQvRhA6miHnNpXv7MRnnSjdRjK8og==}
|
||||
engines: {node: '>=14'}
|
||||
peerDependencies:
|
||||
'@babel/core': ^7.0.0-0
|
||||
dependencies:
|
||||
'@babel/core': 7.23.6
|
||||
dev: true
|
||||
|
||||
/@svgr/babel-plugin-svg-em-dimensions@8.0.0(@babel/core@7.23.6):
|
||||
resolution: {integrity: sha512-mURHYnu6Iw3UBTbhGwE/vsngtCIbHE43xCRK7kCw4t01xyGqb2Pd+WXekRRoFOBIY29ZoOhUCTEweDMdrjfi9g==}
|
||||
engines: {node: '>=14'}
|
||||
peerDependencies:
|
||||
'@babel/core': ^7.0.0-0
|
||||
dependencies:
|
||||
'@babel/core': 7.23.6
|
||||
dev: true
|
||||
|
||||
/@svgr/babel-plugin-transform-react-native-svg@8.1.0(@babel/core@7.23.6):
|
||||
resolution: {integrity: sha512-Tx8T58CHo+7nwJ+EhUwx3LfdNSG9R2OKfaIXXs5soiy5HtgoAEkDay9LIimLOcG8dJQH1wPZp/cnAv6S9CrR1Q==}
|
||||
engines: {node: '>=14'}
|
||||
peerDependencies:
|
||||
'@babel/core': ^7.0.0-0
|
||||
dependencies:
|
||||
'@babel/core': 7.23.6
|
||||
dev: true
|
||||
|
||||
/@svgr/babel-plugin-transform-svg-component@8.0.0(@babel/core@7.23.6):
|
||||
resolution: {integrity: sha512-DFx8xa3cZXTdb/k3kfPeaixecQLgKh5NVBMwD0AQxOzcZawK4oo1Jh9LbrcACUivsCA7TLG8eeWgrDXjTMhRmw==}
|
||||
engines: {node: '>=12'}
|
||||
peerDependencies:
|
||||
'@babel/core': ^7.0.0-0
|
||||
dependencies:
|
||||
'@babel/core': 7.23.6
|
||||
dev: true
|
||||
|
||||
/@svgr/babel-preset@8.1.0(@babel/core@7.23.6):
|
||||
resolution: {integrity: sha512-7EYDbHE7MxHpv4sxvnVPngw5fuR6pw79SkcrILHJ/iMpuKySNCl5W1qcwPEpU+LgyRXOaAFgH0KhwD18wwg6ug==}
|
||||
engines: {node: '>=14'}
|
||||
peerDependencies:
|
||||
'@babel/core': ^7.0.0-0
|
||||
dependencies:
|
||||
'@babel/core': 7.23.6
|
||||
'@svgr/babel-plugin-add-jsx-attribute': 8.0.0(@babel/core@7.23.6)
|
||||
'@svgr/babel-plugin-remove-jsx-attribute': 8.0.0(@babel/core@7.23.6)
|
||||
'@svgr/babel-plugin-remove-jsx-empty-expression': 8.0.0(@babel/core@7.23.6)
|
||||
'@svgr/babel-plugin-replace-jsx-attribute-value': 8.0.0(@babel/core@7.23.6)
|
||||
'@svgr/babel-plugin-svg-dynamic-title': 8.0.0(@babel/core@7.23.6)
|
||||
'@svgr/babel-plugin-svg-em-dimensions': 8.0.0(@babel/core@7.23.6)
|
||||
'@svgr/babel-plugin-transform-react-native-svg': 8.1.0(@babel/core@7.23.6)
|
||||
'@svgr/babel-plugin-transform-svg-component': 8.0.0(@babel/core@7.23.6)
|
||||
dev: true
|
||||
|
||||
/@svgr/core@8.1.0(typescript@5.3.3):
|
||||
resolution: {integrity: sha512-8QqtOQT5ACVlmsvKOJNEaWmRPmcojMOzCz4Hs2BGG/toAp/K38LcsMRyLp349glq5AzJbCEeimEoxaX6v/fLrA==}
|
||||
engines: {node: '>=14'}
|
||||
dependencies:
|
||||
'@babel/core': 7.23.6
|
||||
'@svgr/babel-preset': 8.1.0(@babel/core@7.23.6)
|
||||
camelcase: 6.3.0
|
||||
cosmiconfig: 8.3.6(typescript@5.3.3)
|
||||
snake-case: 3.0.4
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
- typescript
|
||||
dev: true
|
||||
|
||||
/@svgr/hast-util-to-babel-ast@8.0.0:
|
||||
resolution: {integrity: sha512-EbDKwO9GpfWP4jN9sGdYwPBU0kdomaPIL2Eu4YwmgP+sJeXT+L7bMwJUBnhzfH8Q2qMBqZ4fJwpCyYsAN3mt2Q==}
|
||||
engines: {node: '>=14'}
|
||||
dependencies:
|
||||
'@babel/types': 7.23.6
|
||||
entities: 4.5.0
|
||||
dev: true
|
||||
|
||||
/@svgr/plugin-jsx@8.1.0(@svgr/core@8.1.0):
|
||||
resolution: {integrity: sha512-0xiIyBsLlr8quN+WyuxooNW9RJ0Dpr8uOnH/xrCVO8GLUcwHISwj1AG0k+LFzteTkAA0GbX0kj9q6Dk70PTiPA==}
|
||||
engines: {node: '>=14'}
|
||||
peerDependencies:
|
||||
'@svgr/core': '*'
|
||||
dependencies:
|
||||
'@babel/core': 7.23.6
|
||||
'@svgr/babel-preset': 8.1.0(@babel/core@7.23.6)
|
||||
'@svgr/core': 8.1.0(typescript@5.3.3)
|
||||
'@svgr/hast-util-to-babel-ast': 8.0.0
|
||||
svg-parser: 2.0.4
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
dev: true
|
||||
|
||||
/@swc/core-darwin-arm64@1.3.100:
|
||||
resolution: {integrity: sha512-XVWFsKe6ei+SsDbwmsuRkYck1SXRpO60Hioa4hoLwR8fxbA9eVp6enZtMxzVVMBi8ej5seZ4HZQeAWepbukiBw==}
|
||||
engines: {node: '>=10'}
|
||||
@@ -2482,6 +2857,10 @@ packages:
|
||||
'@types/ms': 0.7.34
|
||||
dev: true
|
||||
|
||||
/@types/estree@1.0.5:
|
||||
resolution: {integrity: sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==}
|
||||
dev: true
|
||||
|
||||
/@types/fabric@5.3.6:
|
||||
resolution: {integrity: sha512-nTP5I68SsGnanIHxCoBX83ghscw9M9DI27iSDcd0Z+cpiQ5cZByH0nzkm4itDR/LgAy253q7B93xHgyOh2+hFQ==}
|
||||
dev: true
|
||||
@@ -2820,6 +3199,13 @@ packages:
|
||||
resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==}
|
||||
engines: {node: '>=8'}
|
||||
|
||||
/ansi-styles@3.2.1:
|
||||
resolution: {integrity: sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==}
|
||||
engines: {node: '>=4'}
|
||||
dependencies:
|
||||
color-convert: 1.9.3
|
||||
dev: true
|
||||
|
||||
/ansi-styles@4.3.0:
|
||||
resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==}
|
||||
engines: {node: '>=8'}
|
||||
@@ -2911,6 +3297,17 @@ packages:
|
||||
dev: false
|
||||
optional: true
|
||||
|
||||
/browserslist@4.22.2:
|
||||
resolution: {integrity: sha512-0UgcrvQmBDvZHFGdYUehrCNIazki7/lUP3kkoi/r3YB2amZbFM9J43ZRkJTXBUZK4gmx56+Sqk9+Vs9mwZx9+A==}
|
||||
engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7}
|
||||
hasBin: true
|
||||
dependencies:
|
||||
caniuse-lite: 1.0.30001568
|
||||
electron-to-chromium: 1.4.610
|
||||
node-releases: 2.0.14
|
||||
update-browserslist-db: 1.0.13(browserslist@4.22.2)
|
||||
dev: true
|
||||
|
||||
/bs58@5.0.0:
|
||||
resolution: {integrity: sha512-r+ihvQJvahgYT50JD05dyJNKlmmSlMoOGwn1lCcEzanPglg7TxYjioQUYehQ9mAR/+hOSd2jRc/Z2y5UxBymvQ==}
|
||||
dependencies:
|
||||
@@ -2930,10 +3327,19 @@ packages:
|
||||
engines: {node: '>=6'}
|
||||
dev: true
|
||||
|
||||
/camelcase@6.3.0:
|
||||
resolution: {integrity: sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==}
|
||||
engines: {node: '>=10'}
|
||||
dev: true
|
||||
|
||||
/camelize@1.0.1:
|
||||
resolution: {integrity: sha512-dU+Tx2fsypxTgtLoE36npi3UqcjSSMNYfkqgmoEhtZrraP5VWq0K7FkWVTYa8eMPtnU/G2txVsfdCJTn9uzpuQ==}
|
||||
dev: false
|
||||
|
||||
/caniuse-lite@1.0.30001568:
|
||||
resolution: {integrity: sha512-vSUkH84HontZJ88MiNrOau1EBrCqEQYgkC5gIySiDlpsm8sGVrhU7Kx4V6h0tnqaHzIHZv08HlJIwPbL4XL9+A==}
|
||||
dev: true
|
||||
|
||||
/canvas@2.11.2:
|
||||
resolution: {integrity: sha512-ItanGBMrmRV7Py2Z+Xhs7cT+FNt5K0vPL4p9EZ/UX/Mu7hFbkxSjKF2KVtPwX7UYWp7dRKnrTvReflgrItJbdw==}
|
||||
engines: {node: '>=6'}
|
||||
@@ -2948,6 +3354,15 @@ packages:
|
||||
dev: false
|
||||
optional: true
|
||||
|
||||
/chalk@2.4.2:
|
||||
resolution: {integrity: sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==}
|
||||
engines: {node: '>=4'}
|
||||
dependencies:
|
||||
ansi-styles: 3.2.1
|
||||
escape-string-regexp: 1.0.5
|
||||
supports-color: 5.5.0
|
||||
dev: true
|
||||
|
||||
/chalk@4.1.2:
|
||||
resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==}
|
||||
engines: {node: '>=10'}
|
||||
@@ -2980,12 +3395,22 @@ packages:
|
||||
engines: {node: '>=6'}
|
||||
dev: false
|
||||
|
||||
/color-convert@1.9.3:
|
||||
resolution: {integrity: sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==}
|
||||
dependencies:
|
||||
color-name: 1.1.3
|
||||
dev: true
|
||||
|
||||
/color-convert@2.0.1:
|
||||
resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==}
|
||||
engines: {node: '>=7.0.0'}
|
||||
dependencies:
|
||||
color-name: 1.1.4
|
||||
|
||||
/color-name@1.1.3:
|
||||
resolution: {integrity: sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==}
|
||||
dev: true
|
||||
|
||||
/color-name@1.1.4:
|
||||
resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==}
|
||||
|
||||
@@ -3013,6 +3438,26 @@ packages:
|
||||
dev: false
|
||||
optional: true
|
||||
|
||||
/convert-source-map@2.0.0:
|
||||
resolution: {integrity: sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==}
|
||||
dev: true
|
||||
|
||||
/cosmiconfig@8.3.6(typescript@5.3.3):
|
||||
resolution: {integrity: sha512-kcZ6+W5QzcJ3P1Mt+83OUv/oHFqZHIx8DuxG6eZ5RGMERoLqp4BuGjhHLYGK+Kf5XVkQvqBSmAy/nGWN3qDgEA==}
|
||||
engines: {node: '>=14'}
|
||||
peerDependencies:
|
||||
typescript: '>=4.9.5'
|
||||
peerDependenciesMeta:
|
||||
typescript:
|
||||
optional: true
|
||||
dependencies:
|
||||
import-fresh: 3.3.0
|
||||
js-yaml: 4.1.0
|
||||
parse-json: 5.2.0
|
||||
path-type: 4.0.0
|
||||
typescript: 5.3.3
|
||||
dev: true
|
||||
|
||||
/cross-spawn@7.0.3:
|
||||
resolution: {integrity: sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==}
|
||||
engines: {node: '>= 8'}
|
||||
@@ -3220,10 +3665,32 @@ packages:
|
||||
dev: false
|
||||
optional: true
|
||||
|
||||
/dot-case@3.0.4:
|
||||
resolution: {integrity: sha512-Kv5nKlh6yRrdrGvxeJ2e5y2eRUpkUosIW4A2AS38zwSz27zu7ufDwQPi5Jhs3XAlGNetl3bmnGhQsMtkKJnj3w==}
|
||||
dependencies:
|
||||
no-case: 3.0.4
|
||||
tslib: 2.6.2
|
||||
dev: true
|
||||
|
||||
/electron-to-chromium@1.4.610:
|
||||
resolution: {integrity: sha512-mqi2oL1mfeHYtOdCxbPQYV/PL7YrQlxbvFEZ0Ee8GbDdShimqt2/S6z2RWqysuvlwdOrQdqvE0KZrBTipAeJzg==}
|
||||
dev: true
|
||||
|
||||
/emoji-regex@8.0.0:
|
||||
resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==}
|
||||
dev: false
|
||||
|
||||
/entities@4.5.0:
|
||||
resolution: {integrity: sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==}
|
||||
engines: {node: '>=0.12'}
|
||||
dev: true
|
||||
|
||||
/error-ex@1.3.2:
|
||||
resolution: {integrity: sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==}
|
||||
dependencies:
|
||||
is-arrayish: 0.2.1
|
||||
dev: true
|
||||
|
||||
/es-get-iterator@1.1.3:
|
||||
resolution: {integrity: sha512-sPZmqHBe6JIiTfN5q2pEi//TwxmAFHwj/XEuYjTuse78i8KxaqMTTzxPoFKuzRpDpTJ+0NAbpfenkmH2rePtuw==}
|
||||
dependencies:
|
||||
@@ -3271,7 +3738,11 @@ packages:
|
||||
/escalade@3.1.1:
|
||||
resolution: {integrity: sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==}
|
||||
engines: {node: '>=6'}
|
||||
dev: false
|
||||
|
||||
/escape-string-regexp@1.0.5:
|
||||
resolution: {integrity: sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==}
|
||||
engines: {node: '>=0.8.0'}
|
||||
dev: true
|
||||
|
||||
/escape-string-regexp@4.0.0:
|
||||
resolution: {integrity: sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==}
|
||||
@@ -3408,6 +3879,10 @@ packages:
|
||||
resolution: {integrity: sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==}
|
||||
engines: {node: '>=4.0'}
|
||||
|
||||
/estree-walker@2.0.2:
|
||||
resolution: {integrity: sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==}
|
||||
dev: true
|
||||
|
||||
/esutils@2.0.3:
|
||||
resolution: {integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==}
|
||||
engines: {node: '>=0.10.0'}
|
||||
@@ -3617,6 +4092,11 @@ packages:
|
||||
dev: false
|
||||
optional: true
|
||||
|
||||
/gensync@1.0.0-beta.2:
|
||||
resolution: {integrity: sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==}
|
||||
engines: {node: '>=6.9.0'}
|
||||
dev: true
|
||||
|
||||
/get-caller-file@2.0.5:
|
||||
resolution: {integrity: sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==}
|
||||
engines: {node: 6.* || 8.* || >= 10.*}
|
||||
@@ -3660,6 +4140,11 @@ packages:
|
||||
once: 1.4.0
|
||||
path-is-absolute: 1.0.1
|
||||
|
||||
/globals@11.12.0:
|
||||
resolution: {integrity: sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==}
|
||||
engines: {node: '>=4'}
|
||||
dev: true
|
||||
|
||||
/globals@13.24.0:
|
||||
resolution: {integrity: sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==}
|
||||
engines: {node: '>=8'}
|
||||
@@ -3693,6 +4178,11 @@ packages:
|
||||
resolution: {integrity: sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==}
|
||||
dev: true
|
||||
|
||||
/has-flag@3.0.0:
|
||||
resolution: {integrity: sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==}
|
||||
engines: {node: '>=4'}
|
||||
dev: true
|
||||
|
||||
/has-flag@4.0.0:
|
||||
resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==}
|
||||
engines: {node: '>=8'}
|
||||
@@ -3850,6 +4340,10 @@ packages:
|
||||
is-typed-array: 1.1.12
|
||||
dev: true
|
||||
|
||||
/is-arrayish@0.2.1:
|
||||
resolution: {integrity: sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==}
|
||||
dev: true
|
||||
|
||||
/is-bigint@1.0.4:
|
||||
resolution: {integrity: sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==}
|
||||
dependencies:
|
||||
@@ -3984,7 +4478,6 @@ packages:
|
||||
|
||||
/js-tokens@4.0.0:
|
||||
resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==}
|
||||
dev: false
|
||||
|
||||
/js-yaml@4.1.0:
|
||||
resolution: {integrity: sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==}
|
||||
@@ -4038,10 +4531,20 @@ packages:
|
||||
dev: false
|
||||
optional: true
|
||||
|
||||
/jsesc@2.5.2:
|
||||
resolution: {integrity: sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==}
|
||||
engines: {node: '>=4'}
|
||||
hasBin: true
|
||||
dev: true
|
||||
|
||||
/json-buffer@3.0.1:
|
||||
resolution: {integrity: sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==}
|
||||
dev: true
|
||||
|
||||
/json-parse-even-better-errors@2.3.1:
|
||||
resolution: {integrity: sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==}
|
||||
dev: true
|
||||
|
||||
/json-schema-traverse@0.4.1:
|
||||
resolution: {integrity: sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==}
|
||||
dev: true
|
||||
@@ -4079,6 +4582,10 @@ packages:
|
||||
type-check: 0.4.0
|
||||
dev: true
|
||||
|
||||
/lines-and-columns@1.2.4:
|
||||
resolution: {integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==}
|
||||
dev: true
|
||||
|
||||
/local-pkg@0.5.0:
|
||||
resolution: {integrity: sha512-ok6z3qlYyCDS4ZEU27HaU6x/xZa9Whf8jD4ptH5UZTQYZVYeb9bnZ3ojVhiJNLiXK1Hfc0GNbLXcmZ5plLDDBg==}
|
||||
engines: {node: '>=14'}
|
||||
@@ -4113,6 +4620,18 @@ packages:
|
||||
js-tokens: 4.0.0
|
||||
dev: false
|
||||
|
||||
/lower-case@2.0.2:
|
||||
resolution: {integrity: sha512-7fm3l3NAF9WfN6W3JOmf5drwpVqX78JtoGJ3A6W0a6ZnldM41w2fV5D490psKFTpMds8TJse/eHLFFsNHHjHgg==}
|
||||
dependencies:
|
||||
tslib: 2.6.2
|
||||
dev: true
|
||||
|
||||
/lru-cache@5.1.1:
|
||||
resolution: {integrity: sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==}
|
||||
dependencies:
|
||||
yallist: 3.1.1
|
||||
dev: true
|
||||
|
||||
/lru-cache@6.0.0:
|
||||
resolution: {integrity: sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==}
|
||||
engines: {node: '>=10'}
|
||||
@@ -4238,6 +4757,13 @@ packages:
|
||||
resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==}
|
||||
dev: true
|
||||
|
||||
/no-case@3.0.4:
|
||||
resolution: {integrity: sha512-fgAN3jGAh+RoxUGZHTSOLJIqUc2wmoBwGR4tbpNAKmmovFoWq0OdRkb0VkldReO2a2iBT/OEulG9XSUc10r3zg==}
|
||||
dependencies:
|
||||
lower-case: 2.0.2
|
||||
tslib: 2.6.2
|
||||
dev: true
|
||||
|
||||
/node-fetch@2.7.0:
|
||||
resolution: {integrity: sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==}
|
||||
engines: {node: 4.x || >=6.0.0}
|
||||
@@ -4252,6 +4778,10 @@ packages:
|
||||
dev: false
|
||||
optional: true
|
||||
|
||||
/node-releases@2.0.14:
|
||||
resolution: {integrity: sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw==}
|
||||
dev: true
|
||||
|
||||
/nopt@5.0.0:
|
||||
resolution: {integrity: sha512-Tbj67rffqceeLpcRXrT7vKAN8CwfPeIBgM7E6iBkmKLV7bEMwpGgYLGv0jACUsECaa/vuxP0IjEont6umdMgtQ==}
|
||||
engines: {node: '>=6'}
|
||||
@@ -4360,6 +4890,16 @@ packages:
|
||||
engines: {node: '>=6'}
|
||||
dev: true
|
||||
|
||||
/parse-json@5.2.0:
|
||||
resolution: {integrity: sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==}
|
||||
engines: {node: '>=8'}
|
||||
dependencies:
|
||||
'@babel/code-frame': 7.23.5
|
||||
error-ex: 1.3.2
|
||||
json-parse-even-better-errors: 2.3.1
|
||||
lines-and-columns: 1.2.4
|
||||
dev: true
|
||||
|
||||
/parse5@6.0.1:
|
||||
resolution: {integrity: sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw==}
|
||||
requiresBuild: true
|
||||
@@ -4426,6 +4966,12 @@ packages:
|
||||
engines: {node: '>= 0.8.0'}
|
||||
dev: true
|
||||
|
||||
/prettier@3.1.1:
|
||||
resolution: {integrity: sha512-22UbSzg8luF4UuZtzgiUOfcGM8s4tjBv6dJRT7j275NXsy2jb4aJa4NNveul5x4eqlF1wuhuR2RElK71RvmVaw==}
|
||||
engines: {node: '>=14'}
|
||||
hasBin: true
|
||||
dev: true
|
||||
|
||||
/protobufjs@7.2.5:
|
||||
resolution: {integrity: sha512-gGXRSXvxQ7UiPgfw8gevrfRWcTlSbOFg+p/N+JVJEK5VhueL2miT6qTymqAmjr1Q5WbOCyJbyrk6JfWKwlFn6A==}
|
||||
engines: {node: '>=12.0.0'}
|
||||
@@ -4727,8 +5273,6 @@ packages:
|
||||
resolution: {integrity: sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==}
|
||||
hasBin: true
|
||||
requiresBuild: true
|
||||
dev: false
|
||||
optional: true
|
||||
|
||||
/semver@7.5.4:
|
||||
resolution: {integrity: sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==}
|
||||
@@ -4813,6 +5357,13 @@ packages:
|
||||
engines: {node: '>=8'}
|
||||
dev: true
|
||||
|
||||
/snake-case@3.0.4:
|
||||
resolution: {integrity: sha512-LAOh4z89bGQvl9pFfNF8V146i7o7/CqFPbqzYgP+yYzDIDeS9HaNFtXABamRW+AQzEVODcvE79ljJ+8a9YSdMg==}
|
||||
dependencies:
|
||||
dot-case: 3.0.4
|
||||
tslib: 2.6.2
|
||||
dev: true
|
||||
|
||||
/source-map-js@1.0.2:
|
||||
resolution: {integrity: sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==}
|
||||
engines: {node: '>=0.10.0'}
|
||||
@@ -4901,12 +5452,23 @@ packages:
|
||||
engines: {node: '>=14.0.0'}
|
||||
dev: false
|
||||
|
||||
/supports-color@5.5.0:
|
||||
resolution: {integrity: sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==}
|
||||
engines: {node: '>=4'}
|
||||
dependencies:
|
||||
has-flag: 3.0.0
|
||||
dev: true
|
||||
|
||||
/supports-color@7.2.0:
|
||||
resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==}
|
||||
engines: {node: '>=8'}
|
||||
dependencies:
|
||||
has-flag: 4.0.0
|
||||
|
||||
/svg-parser@2.0.4:
|
||||
resolution: {integrity: sha512-e4hG1hRwoOdRb37cIMSgzNsxyzKfayW6VOflrwvR+/bzrkyxY/31WkbgnQpgtrNp1SdpJvpUAGTa/ZoiPNDuRQ==}
|
||||
dev: true
|
||||
|
||||
/symbol-tree@3.2.4:
|
||||
resolution: {integrity: sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==}
|
||||
requiresBuild: true
|
||||
@@ -4931,6 +5493,11 @@ packages:
|
||||
resolution: {integrity: sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==}
|
||||
dev: true
|
||||
|
||||
/to-fast-properties@2.0.0:
|
||||
resolution: {integrity: sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==}
|
||||
engines: {node: '>=4'}
|
||||
dev: true
|
||||
|
||||
/to-regex-range@5.0.1:
|
||||
resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==}
|
||||
engines: {node: '>=8.0'}
|
||||
@@ -4976,7 +5543,6 @@ packages:
|
||||
|
||||
/tslib@2.6.2:
|
||||
resolution: {integrity: sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==}
|
||||
dev: false
|
||||
|
||||
/tweetnacl@1.0.3:
|
||||
resolution: {integrity: sha512-6rt+RN7aOi1nGMyC4Xa5DdYiukl2UWCbcJft7YhxReBGQD7OAM8Pbxw6YMo4r2diNEA8FEmu32YOn9rhaiE5yw==}
|
||||
@@ -5038,6 +5604,17 @@ packages:
|
||||
dev: false
|
||||
optional: true
|
||||
|
||||
/update-browserslist-db@1.0.13(browserslist@4.22.2):
|
||||
resolution: {integrity: sha512-xebP81SNcPuNpPP3uzeW1NYXxI3rxyJzF3pD6sH4jE7o/IX+WtSpwnVU+qIsDPyk0d3hmFQ7mjqc6AtV604hbg==}
|
||||
hasBin: true
|
||||
peerDependencies:
|
||||
browserslist: '>= 4.21.0'
|
||||
dependencies:
|
||||
browserslist: 4.22.2
|
||||
escalade: 3.1.1
|
||||
picocolors: 1.0.0
|
||||
dev: true
|
||||
|
||||
/uri-js@4.4.1:
|
||||
resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==}
|
||||
dependencies:
|
||||
@@ -5121,6 +5698,21 @@ packages:
|
||||
- supports-color
|
||||
dev: true
|
||||
|
||||
/vite-plugin-svgr@4.2.0(typescript@5.3.3)(vite@5.0.7):
|
||||
resolution: {integrity: sha512-SC7+FfVtNQk7So0XMjrrtLAbEC8qjFPifyD7+fs/E6aaNdVde6umlVVh0QuwDLdOMu7vp5RiGFsB70nj5yo0XA==}
|
||||
peerDependencies:
|
||||
vite: ^2.6.0 || 3 || 4 || 5
|
||||
dependencies:
|
||||
'@rollup/pluginutils': 5.1.0
|
||||
'@svgr/core': 8.1.0(typescript@5.3.3)
|
||||
'@svgr/plugin-jsx': 8.1.0(@svgr/core@8.1.0)
|
||||
vite: 5.0.7
|
||||
transitivePeerDependencies:
|
||||
- rollup
|
||||
- supports-color
|
||||
- typescript
|
||||
dev: true
|
||||
|
||||
/vite@5.0.7:
|
||||
resolution: {integrity: sha512-B4T4rJCDPihrQo2B+h1MbeGL/k/GMAHzhQ8S0LjQ142s6/+l3hHTT095ORvsshj4QCkoWu3Xtmob5mazvakaOw==}
|
||||
engines: {node: ^18.0.0 || >=20.0.0}
|
||||
@@ -5337,6 +5929,10 @@ packages:
|
||||
engines: {node: '>=10'}
|
||||
dev: false
|
||||
|
||||
/yallist@3.1.1:
|
||||
resolution: {integrity: sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==}
|
||||
dev: true
|
||||
|
||||
/yallist@4.0.0:
|
||||
resolution: {integrity: sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==}
|
||||
|
||||
|
||||
23
app/src/components/Cover.tsx
Normal file
23
app/src/components/Cover.tsx
Normal file
@@ -0,0 +1,23 @@
|
||||
import { useDispatch, useSelector } from "react-redux";
|
||||
import { Container, Heading } from "@radix-ui/themes";
|
||||
import { toScene } from "../modules/story/actions";
|
||||
import { storySelector } from "../modules/story/selectors";
|
||||
|
||||
const Cover = () => {
|
||||
const { title, currentSceneIndex } = useSelector(storySelector);
|
||||
const dispatch = useDispatch();
|
||||
|
||||
const next = () => {
|
||||
dispatch(toScene({ index: currentSceneIndex + 1 }));
|
||||
// move to next scene
|
||||
};
|
||||
|
||||
return (
|
||||
<Container onClick={next}>
|
||||
<Heading>{title}</Heading>
|
||||
<Heading as="h4">image here</Heading>
|
||||
</Container>
|
||||
);
|
||||
};
|
||||
|
||||
export default Cover;
|
||||
29
app/src/components/Layout/Layout.tsx
Normal file
29
app/src/components/Layout/Layout.tsx
Normal file
@@ -0,0 +1,29 @@
|
||||
/// <reference types="vite-plugin-svgr/client" />
|
||||
import styled from "styled-components";
|
||||
import {FC} from "react";
|
||||
import LogonIcon from './_/logo.svg?react'
|
||||
|
||||
export const StyledHeader = styled.div`
|
||||
//display: flex;
|
||||
width: 100vw;
|
||||
background: #A9F868;;
|
||||
position: fixed;
|
||||
top: 0;
|
||||
padding: 29px 34px;
|
||||
`
|
||||
|
||||
export const Header: FC = () => {
|
||||
return (
|
||||
<StyledHeader>
|
||||
<LogonIcon/>
|
||||
</StyledHeader>
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
export const PageContainer = styled.div`
|
||||
background: #A9F868;
|
||||
width: 100vw;
|
||||
min-height: 100vh;
|
||||
`
|
||||
|
||||
4
app/src/components/Layout/_/logo.svg
Normal file
4
app/src/components/Layout/_/logo.svg
Normal file
@@ -0,0 +1,4 @@
|
||||
<svg width="128" height="24" viewBox="0 0 128 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<rect x="0.5" y="0.5" width="127" height="23" rx="11.5" stroke="black"/>
|
||||
<path d="M13.1 19.18C9.7 19.18 8.08 17.44 8 14.8H9.78C9.88 16.5 10.9 17.56 13.1 17.56C15.14 17.56 16.32 16.76 16.32 15.16C16.32 13.8 15.54 13.2 14.02 12.88L11.98 12.44C9.76 11.96 8.48 10.8 8.48 8.66C8.48 6.4 10.22 4.82 13.12 4.82C15.92 4.82 17.88 6.5 17.9 8.98H16.12C16.04 7.46 15.04 6.46 13.08 6.46C11.42 6.46 10.28 7.18 10.28 8.66C10.28 9.8 10.98 10.4 12.46 10.74L14.36 11.18C16.76 11.74 18.14 12.86 18.14 15.16C18.14 17.66 16.14 19.18 13.1 19.18ZM24.0661 19V6.66H19.9461V5H29.9861V6.66H25.8661V19H24.0661ZM37.1184 19.18C33.5984 19.18 31.5984 17.02 31.5984 13.2V10.8C31.5984 6.98 33.5984 4.82 37.1184 4.82C40.6384 4.82 42.6384 6.98 42.6384 10.8V13.2C42.6384 17.02 40.6384 19.18 37.1184 19.18ZM33.3984 13.2C33.3984 15.82 34.4184 17.48 37.1184 17.48C39.8184 17.48 40.8384 15.82 40.8384 13.2V10.8C40.8384 8.18 39.8184 6.52 37.1184 6.52C34.4184 6.52 33.3984 8.18 33.3984 10.8V13.2ZM45.8359 19V5H51.1759C53.7759 5 55.4159 6.38 55.4159 8.76C55.4159 11.4 53.7759 12.62 51.1759 12.62H48.1559L56.1559 19H53.2959L47.5959 14.34V19H45.8359ZM47.5959 10.98H51.0759C52.5759 10.98 53.5959 10.46 53.5959 8.78C53.5959 7.14 52.5759 6.6 51.0759 6.6H47.5959V10.98ZM61.4625 19V12.6H60.7825L56.6625 5H58.6225L62.3825 12.1L66.1225 5H68.0425L63.9425 12.6H63.2625V19H61.4625ZM73.4606 19V6.66H69.3406V5H79.3806V6.66H75.2606V19H73.4606ZM81.4859 19V17.34H84.4059V6.66H81.4859V5H89.1259V6.66H86.2059V17.34H89.1259V19H81.4859ZM97.8152 19L94.2952 5.5V19H92.5352V5H95.8752L99.5152 18.5L103.155 5H106.495V19H104.735V5.5L101.215 19H97.8152ZM110.504 19V5H119.104V6.64H112.304V10.96H118.484V12.6H112.304V17.36H119.104V19H110.504Z" fill="black"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.7 KiB |
42
app/src/components/Scene.tsx
Normal file
42
app/src/components/Scene.tsx
Normal file
@@ -0,0 +1,42 @@
|
||||
import { useDispatch, useSelector } from "react-redux";
|
||||
import { Container, Heading } from "@radix-ui/themes";
|
||||
import {
|
||||
storySelector,
|
||||
currentSceneSelector,
|
||||
} from "../modules/story/selectors";
|
||||
import { updateStory } from "../modules/story/actions";
|
||||
import { StoryProgressPromptRole } from "../types/story";
|
||||
|
||||
const Cover = () => {
|
||||
// const { currentSceneIndex } = useSelector(storySelector);
|
||||
const { sceneTitle, sceneDescription, optionPrompt, options } =
|
||||
useSelector(currentSceneSelector);
|
||||
const dispatch = useDispatch();
|
||||
|
||||
const onOptionClick = (val: string) => {
|
||||
dispatch(
|
||||
updateStory({
|
||||
message: { role: StoryProgressPromptRole.User, content: val },
|
||||
})
|
||||
);
|
||||
};
|
||||
|
||||
return (
|
||||
<Container>
|
||||
<Heading>{sceneTitle}</Heading>
|
||||
<Heading as="h4">{sceneDescription}</Heading>
|
||||
<Heading as="h4">{optionPrompt}</Heading>
|
||||
{options && options.length && (
|
||||
<ul>
|
||||
{options.map((option, oidx) => (
|
||||
<li key={oidx} onClick={() => onOptionClick(option)}>
|
||||
{option}
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
)}
|
||||
</Container>
|
||||
);
|
||||
};
|
||||
|
||||
export default Cover;
|
||||
@@ -13,7 +13,7 @@ export function protectedRoute<T extends { user: User }>(component: FC<T>) {
|
||||
return <div>Loading...</div>;
|
||||
}
|
||||
if (user == null) {
|
||||
return <Navigate to="/" />;
|
||||
return <Navigate to="/login" />;
|
||||
}
|
||||
return createElement(component, {
|
||||
...props,
|
||||
|
||||
@@ -1,7 +1,14 @@
|
||||
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||
// Import the functions you need from the SDKs you need
|
||||
import { initializeApp } from "firebase/app";
|
||||
import { getFirestore } from "firebase/firestore";
|
||||
import { getAuth } from "firebase/auth";
|
||||
import { getFirestore, connectFirestoreEmulator } from "firebase/firestore";
|
||||
import {
|
||||
getFunctions,
|
||||
httpsCallable,
|
||||
connectFunctionsEmulator,
|
||||
} from "firebase/functions";
|
||||
import { getAuth, connectAuthEmulator } from "firebase/auth";
|
||||
import { CloudFunctionsType } from "model/functions";
|
||||
|
||||
// Your web app's Firebase configuration
|
||||
const firebaseConfig = {
|
||||
@@ -16,3 +23,25 @@ const firebaseConfig = {
|
||||
export const app = initializeApp(firebaseConfig);
|
||||
export const db = getFirestore(app);
|
||||
export const auth = getAuth(app);
|
||||
export const functions = getFunctions(app);
|
||||
|
||||
export async function callFunction<Name extends keyof CloudFunctionsType>(
|
||||
name: Name,
|
||||
...args: Parameters<CloudFunctionsType[Name]>
|
||||
): Promise<ReturnType<CloudFunctionsType[Name]>> {
|
||||
return await httpsCallable(
|
||||
functions,
|
||||
"execute",
|
||||
)({
|
||||
type: name,
|
||||
args,
|
||||
}).then((a) => a.data as any);
|
||||
}
|
||||
|
||||
const useEmulator = import.meta.env.VITE_USE_EMULATOR === "true";
|
||||
|
||||
if (useEmulator) {
|
||||
connectAuthEmulator(auth, "http://localhost:9099", { disableWarnings: true });
|
||||
connectFirestoreEmulator(db, "localhost", 8080);
|
||||
connectFunctionsEmulator(functions, "localhost", 5001);
|
||||
}
|
||||
|
||||
10
app/src/global.d.ts
vendored
Normal file
10
app/src/global.d.ts
vendored
Normal file
@@ -0,0 +1,10 @@
|
||||
declare module "*.svg" {
|
||||
import * as React from "react"
|
||||
|
||||
export const ReactComponent: React.FunctionComponent<
|
||||
React.SVGProps<SVGSVGElement> & { title?: string }
|
||||
>
|
||||
|
||||
const src: string
|
||||
export default src
|
||||
}
|
||||
37
app/src/index.css
Normal file
37
app/src/index.css
Normal file
@@ -0,0 +1,37 @@
|
||||
a {
|
||||
font-weight: 500;
|
||||
color: black;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
body {
|
||||
margin: 0;
|
||||
display: flex;
|
||||
min-height: 100vh;
|
||||
}
|
||||
|
||||
h1 {
|
||||
font-size: 3.2em;
|
||||
line-height: 1.1;
|
||||
}
|
||||
|
||||
body, div, dl, dt, dd, ul, ol, li, tr, td, th,
|
||||
h1, h2, h3, h4, h5, h6, hr, br, img, table,
|
||||
input, form, a, p, textarea {
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
ul, ol, li {
|
||||
list-style: none;
|
||||
}
|
||||
|
||||
a {
|
||||
text-decoration: none;
|
||||
display: block;
|
||||
}
|
||||
|
||||
img {
|
||||
border: 0;
|
||||
display: block;
|
||||
}
|
||||
@@ -1,17 +1,17 @@
|
||||
// import React from "react";
|
||||
import ReactDOM from "react-dom/client";
|
||||
import * as ReactDOM from "react-dom/client";
|
||||
import "@mysten/dapp-kit/dist/index.css";
|
||||
import "@radix-ui/themes/styles.css";
|
||||
|
||||
import "./index.css";
|
||||
import { getFullnodeUrl } from "@mysten/sui.js/client";
|
||||
import {
|
||||
createNetworkConfig,
|
||||
SuiClientProvider,
|
||||
WalletProvider,
|
||||
createNetworkConfig,
|
||||
} from "@mysten/dapp-kit";
|
||||
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
|
||||
import { Theme } from "@radix-ui/themes";
|
||||
import App from "./App.tsx";
|
||||
import App from "./App";
|
||||
|
||||
const queryClient = new QueryClient();
|
||||
|
||||
@@ -33,6 +33,6 @@ ReactDOM.createRoot(document.getElementById("root")!).render(
|
||||
</WalletProvider>
|
||||
</SuiClientProvider>
|
||||
</QueryClientProvider>
|
||||
</Theme>
|
||||
</Theme>,
|
||||
// </React.StrictMode>
|
||||
);
|
||||
|
||||
12
app/src/mock.ts
Normal file
12
app/src/mock.ts
Normal file
@@ -0,0 +1,12 @@
|
||||
export const MOCK_STORY_INIT_RESP = `{
|
||||
"type": "story-introduction",
|
||||
"title": "The Quest of Gary the Snail",
|
||||
"character": "An adventurous and inquisitive snail named Gary with a vibrant, spiral shell painted with a mosaic of forest hues",
|
||||
"setting": "A diverse medieval realm known as Verdant Kingdom, a lush land composed of enchanted forests, majestic mountains, and serene valleys, where magical creatures coexist and ancient secrets lay hidden beneath the luscious canopy",
|
||||
"introduction": "Gary the snail, adorned with his magnificent, spiral shell, sets his tiny eyes upon the world beyond his comfortable mushroom abode. The land is alive with the murmur of the trees and the soft whispers of the wind. With a heart filled with wanderlust and antennas tuned to the pulse of adventure, Gary discovers an old scroll half-buried under a willow, sealed with the royal emblem of the long-lost Turritella dynasty. The scroll promises a quest of valor and wisdom that could lead to the fabled relic, The Amulet of Aiolos, which grants the bearer the favor of the winds. Each choice will steer Gary deeper into the heart of Verdant Kingdom's forgotten lore.",
|
||||
"sceneNumber": 1,
|
||||
"sceneTitle": "The Willow's Whisper",
|
||||
"sceneDescription": "As Gary unrolls the ancient scroll under the protective boughs of the willow, a soft glow emanates from the delicate parchment. Lines drawn with ink the color of the midnight sky reveal three distinct paths that lie ahead:\n\n1. The Glimmering Brook: A babbling waterway, lit by the dance of sunbeams piercing through the foliage, home to the wise Koi, keepers of the kingdom's history.\n\n2. The Sunstone Caves: A complex of deep caverns beneath the Amber Hills, where the ceilings glitter with mineral constellations that tell stories of old.\n\n3. The Rosewood Thicket: A dense expanse brimming with roses of various hues and fragrances, said to guard the path to the court of the fae.",
|
||||
"optionsPrompt": "Which path should Gary embark upon to unravel the mysteries of Verdant Kingdom?",
|
||||
"options": ["Brook", "Caves", "Thicket"]
|
||||
}`;
|
||||
@@ -1,24 +1,57 @@
|
||||
import { Action } from "redux";
|
||||
|
||||
// Action Types
|
||||
export const CREATE_CHARACTER = "Character/CREATE_CHARACTER";
|
||||
export const CREATE_CHARACTER_SUCCESS = "Character/CREATE_CHARACTER_SUCCESS";
|
||||
export const CREATE_CHARACTER_NAME = "Character/CREATE_CHARACTER_NAME";
|
||||
export const CREATE_CHARACTER_TYPE = "Character/CREATE_CHARACTER_TYPE";
|
||||
export const CREATE_CHARACTER_IMAGE = "Character/CREATE_CHARACTER_IMAGE";
|
||||
export const CREATE_CHARACTER_IMAGE_SUCCESS =
|
||||
"Character/CREATE_CHARACTER_IMAGE_SUCCESS";
|
||||
|
||||
// Action Creators
|
||||
type CreateCharacterBody = { sketchBlob: Blob; prompt: string };
|
||||
export type CreateCharacterAction = Action & { data: CreateCharacterBody };
|
||||
export const createCharacter = (
|
||||
data: CreateCharacterBody
|
||||
): CreateCharacterAction => ({
|
||||
type: CREATE_CHARACTER,
|
||||
type CreateCharacterNameBody = { characterName: string };
|
||||
export type CreateCharacterNameAction = Action & {
|
||||
data: CreateCharacterNameBody;
|
||||
};
|
||||
export const createCharacterName = (
|
||||
data: CreateCharacterNameBody
|
||||
): CreateCharacterNameAction => ({
|
||||
type: CREATE_CHARACTER_NAME,
|
||||
data,
|
||||
});
|
||||
|
||||
type CreateCharacterSuccessBody = { blob: Blob; characterName: string };
|
||||
export type CreateCharacterSuccessAction = Action & {
|
||||
data: CreateCharacterSuccessBody;
|
||||
type CreateCharacterTypeBody = { characterType: string };
|
||||
export type CreateCharacterTypeAction = Action & {
|
||||
data: CreateCharacterTypeBody;
|
||||
};
|
||||
export const createCharacterSuccess = (data: CreateCharacterSuccessBody) => ({
|
||||
type: CREATE_CHARACTER_SUCCESS,
|
||||
export const createCharacterType = (
|
||||
data: CreateCharacterTypeBody
|
||||
): CreateCharacterTypeAction => ({
|
||||
type: CREATE_CHARACTER_TYPE,
|
||||
data,
|
||||
});
|
||||
|
||||
type CreateCharacterImageBody = { sketchBlob: Blob; prompt: string };
|
||||
export type CreateCharacterImageAction = Action & {
|
||||
data: CreateCharacterImageBody;
|
||||
};
|
||||
export const createCharacterImage = (
|
||||
data: CreateCharacterImageBody
|
||||
): CreateCharacterImageAction => ({
|
||||
type: CREATE_CHARACTER_IMAGE,
|
||||
data,
|
||||
});
|
||||
|
||||
type CreateCharacterImageSuccessBody = { blob: Blob; characterType: string };
|
||||
export type CreateCharacterImageSuccessAction = Action & {
|
||||
data: CreateCharacterImageSuccessBody;
|
||||
};
|
||||
export const createCharacterImageSuccess = (
|
||||
data: CreateCharacterImageSuccessBody
|
||||
) => ({
|
||||
type: CREATE_CHARACTER_IMAGE_SUCCESS,
|
||||
data,
|
||||
});
|
||||
|
||||
export type CharacterAction =
|
||||
| CreateCharacterImageAction
|
||||
| CreateCharacterImageSuccessAction;
|
||||
|
||||
@@ -1,27 +1,36 @@
|
||||
import {
|
||||
CreateCharacterSuccessAction,
|
||||
CREATE_CHARACTER_SUCCESS,
|
||||
CREATE_CHARACTER_NAME,
|
||||
CREATE_CHARACTER_TYPE,
|
||||
CREATE_CHARACTER_IMAGE_SUCCESS,
|
||||
CharacterAction,
|
||||
} from "./actions";
|
||||
|
||||
// Initial State
|
||||
export type CharacterState = {
|
||||
characterName: string;
|
||||
characterType: string;
|
||||
characterImage: Blob;
|
||||
};
|
||||
const initialState: CharacterState = {
|
||||
characterName: "",
|
||||
characterType: "",
|
||||
characterImage: new Blob(),
|
||||
};
|
||||
|
||||
// Reducer
|
||||
const characterReducer = (
|
||||
state = initialState,
|
||||
action: CreateCharacterSuccessAction
|
||||
) => {
|
||||
const characterReducer = (state = initialState, action: CharacterAction) => {
|
||||
switch (action.type) {
|
||||
case CREATE_CHARACTER_SUCCESS: {
|
||||
const { blob, characterName } = action.data;
|
||||
return { ...state, characterImage: blob, characterName };
|
||||
case CREATE_CHARACTER_NAME: {
|
||||
const { characterName } = action.data;
|
||||
return { ...state, characterName };
|
||||
}
|
||||
case CREATE_CHARACTER_TYPE: {
|
||||
const { characterType } = action.data;
|
||||
return { ...state, characterType };
|
||||
}
|
||||
case CREATE_CHARACTER_IMAGE_SUCCESS: {
|
||||
const { blob, characterType } = action.data;
|
||||
return { ...state, characterImage: blob, characterType };
|
||||
}
|
||||
default:
|
||||
return state;
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
import axios from "axios";
|
||||
import { call, put, takeEvery } from "redux-saga/effects";
|
||||
import {
|
||||
CREATE_CHARACTER,
|
||||
CreateCharacterAction,
|
||||
createCharacterSuccess,
|
||||
CREATE_CHARACTER_IMAGE,
|
||||
CreateCharacterImageAction,
|
||||
createCharacterImageSuccess,
|
||||
} from "./actions";
|
||||
|
||||
// Sample worker saga
|
||||
function* createCharacter(action: CreateCharacterAction) {
|
||||
function* createCharacterImage(action: CreateCharacterImageAction) {
|
||||
const { sketchBlob, prompt } = action.data;
|
||||
const formData = new FormData();
|
||||
formData.append("sketch_file", sketchBlob);
|
||||
@@ -25,7 +25,9 @@ function* createCharacter(action: CreateCharacterAction) {
|
||||
responseType: "blob",
|
||||
}
|
||||
);
|
||||
yield put(createCharacterSuccess({ blob: data, characterName: prompt }));
|
||||
yield put(
|
||||
createCharacterImageSuccess({ blob: data, characterType: prompt })
|
||||
);
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
}
|
||||
@@ -33,5 +35,5 @@ function* createCharacter(action: CreateCharacterAction) {
|
||||
|
||||
// Combine all sagas
|
||||
export default function* characterSaga() {
|
||||
yield takeEvery(CREATE_CHARACTER, createCharacter);
|
||||
yield takeEvery(CREATE_CHARACTER_IMAGE, createCharacterImage);
|
||||
}
|
||||
|
||||
@@ -13,3 +13,8 @@ export const characterNameSelector = createSelector(
|
||||
[getCharacterBase],
|
||||
({ characterName }) => characterName
|
||||
);
|
||||
|
||||
export const characterTypeSelector = createSelector(
|
||||
[getCharacterBase],
|
||||
({ characterType }) => characterType
|
||||
);
|
||||
|
||||
@@ -2,12 +2,20 @@ import { Action } from "redux";
|
||||
import { StoryProgress } from "../../types/story";
|
||||
|
||||
// Action Types
|
||||
export const TO_SCENE = "Story/TO_SCENE";
|
||||
export const INIT_STORY = "Story/INIT_STORY";
|
||||
export const INIT_STORY_SUCCESS = "Story/INIT_STORY_SUCCESS";
|
||||
export const UPDATE_STORY = "Story/UPDATE_STORY";
|
||||
export const UPDATE_STORY_SUCCESS = "Story/UPDATE_STORY_SUCCESS";
|
||||
|
||||
// Action Creators
|
||||
type ToSceneBody = { index: number };
|
||||
export type ToSceneAction = Action & { data: ToSceneBody };
|
||||
export const toScene = (data: ToSceneBody): ToSceneAction => ({
|
||||
type: TO_SCENE,
|
||||
data,
|
||||
});
|
||||
|
||||
type InitStoryBody = { initMessage: StoryProgress };
|
||||
export type InitStoryAction = Action & { data: InitStoryBody };
|
||||
export const initStory = (data: InitStoryBody): InitStoryAction => ({
|
||||
@@ -24,10 +32,10 @@ export const initStorySuccess = (data: InitStorySuccessBody) => ({
|
||||
data,
|
||||
});
|
||||
|
||||
type UpdateStoryBody = { initMessage: StoryProgress };
|
||||
type UpdateStoryBody = { message: StoryProgress };
|
||||
export type UpdateStoryAction = Action & { data: UpdateStoryBody };
|
||||
export const UpdateStory = (data: UpdateStoryBody): UpdateStoryAction => ({
|
||||
type: INIT_STORY,
|
||||
export const updateStory = (data: UpdateStoryBody): UpdateStoryAction => ({
|
||||
type: UPDATE_STORY,
|
||||
data,
|
||||
});
|
||||
|
||||
@@ -41,6 +49,7 @@ export const updateStorySuccess = (data: InitStorySuccessBody) => ({
|
||||
});
|
||||
|
||||
export type StoryAction =
|
||||
| ToSceneAction
|
||||
| InitStoryAction
|
||||
| InitStorySuccessAction
|
||||
| UpdateStoryAction
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { StoryProgress, Scene } from "../../types/story";
|
||||
import {
|
||||
StoryAction,
|
||||
TO_SCENE,
|
||||
INIT_STORY,
|
||||
INIT_STORY_SUCCESS,
|
||||
UPDATE_STORY,
|
||||
@@ -11,22 +12,29 @@ import { parseStoryGuideline } from "./utils";
|
||||
// Initial State
|
||||
export type StoryState = {
|
||||
storyProgressPrompts: StoryProgress[];
|
||||
storyTitle: string;
|
||||
storyIntro: string;
|
||||
scene: number;
|
||||
title: string;
|
||||
introduction: string;
|
||||
currentSceneIndex: number;
|
||||
scenes: Scene[];
|
||||
};
|
||||
const initialState: StoryState = {
|
||||
scene: 0,
|
||||
currentSceneIndex: 0,
|
||||
storyProgressPrompts: [],
|
||||
storyTitle: "",
|
||||
storyIntro: "",
|
||||
title: "",
|
||||
introduction: "",
|
||||
scenes: [],
|
||||
};
|
||||
|
||||
// Reducer
|
||||
const storyReducer = (state = initialState, action: StoryAction) => {
|
||||
switch (action.type) {
|
||||
case TO_SCENE: {
|
||||
const { index } = action.data;
|
||||
return {
|
||||
...state,
|
||||
currentSceneIndex: index,
|
||||
};
|
||||
}
|
||||
case INIT_STORY: {
|
||||
const { initMessage } = action.data;
|
||||
return {
|
||||
@@ -36,22 +44,34 @@ const storyReducer = (state = initialState, action: StoryAction) => {
|
||||
}
|
||||
case INIT_STORY_SUCCESS: {
|
||||
const { progress } = action.data;
|
||||
const { title, intro, scene } = parseStoryGuideline(progress.content);
|
||||
const { title, introduction, scene } = parseStoryGuideline(
|
||||
progress.content
|
||||
);
|
||||
return {
|
||||
...state,
|
||||
storyTitle: title,
|
||||
storyIntro: intro,
|
||||
storyProgressPrompts: [...state.storyProgressPrompts, progress],
|
||||
title,
|
||||
introduction,
|
||||
scenes: [...state.scenes, scene],
|
||||
storyProgressPrompts: [...state.storyProgressPrompts, progress],
|
||||
};
|
||||
}
|
||||
case UPDATE_STORY: {
|
||||
// TODO: when users fires their prompt to open AI, add the user role prompt into prompt list
|
||||
return state;
|
||||
// when users fires their prompt to open AI, add the user role prompt into prompt list
|
||||
const { message } = action.data;
|
||||
return {
|
||||
...state,
|
||||
storyProgressPrompts: [...state.storyProgressPrompts, message],
|
||||
};
|
||||
}
|
||||
case UPDATE_STORY_SUCCESS: {
|
||||
// TODO: when user received resp from open AI, it includes assistant prompt
|
||||
return state;
|
||||
// when user received resp from open AI, it includes assistant prompt
|
||||
const { progress } = action.data;
|
||||
const { scene } = parseStoryGuideline(progress.content);
|
||||
return {
|
||||
...state,
|
||||
scenes: [...state.scenes, scene],
|
||||
storyProgressPrompts: [...state.storyProgressPrompts, progress],
|
||||
};
|
||||
}
|
||||
default:
|
||||
return state;
|
||||
|
||||
@@ -1,7 +1,15 @@
|
||||
import axios from "axios";
|
||||
import { call, put, takeEvery } from "redux-saga/effects";
|
||||
import { call, put, select, takeEvery } from "redux-saga/effects";
|
||||
import { StoryProgress } from "../../types/story";
|
||||
import { INIT_STORY, InitStoryAction, initStorySuccess } from "./actions";
|
||||
import {
|
||||
INIT_STORY,
|
||||
UPDATE_STORY,
|
||||
InitStoryAction,
|
||||
initStorySuccess,
|
||||
updateStorySuccess,
|
||||
toScene,
|
||||
} from "./actions";
|
||||
import { storyProgressSelector, storySelector } from "./selectors";
|
||||
|
||||
// Sample worker saga
|
||||
function* initStory(action: InitStoryAction) {
|
||||
@@ -9,6 +17,9 @@ function* initStory(action: InitStoryAction) {
|
||||
const payload = {
|
||||
model: "gpt-4-1106-preview",
|
||||
messages: [initMessage],
|
||||
temperature: 1,
|
||||
max_tokens: 1024,
|
||||
top_p: 1,
|
||||
};
|
||||
|
||||
try {
|
||||
@@ -29,7 +40,41 @@ function* initStory(action: InitStoryAction) {
|
||||
}
|
||||
}
|
||||
|
||||
function* updateStory(action: InitStoryAction) {
|
||||
const { message } = action.data;
|
||||
const { currentSceneIndex } = yield select(storySelector);
|
||||
const storyProgress = (yield select(
|
||||
storyProgressSelector
|
||||
)) as StoryProgress[];
|
||||
const payload = {
|
||||
model: "gpt-4-1106-preview",
|
||||
messages: [...storyProgress, message],
|
||||
temperature: 1,
|
||||
max_tokens: 1024,
|
||||
top_p: 1,
|
||||
};
|
||||
try {
|
||||
const { data } = yield call(
|
||||
axios.post,
|
||||
"https://api.openai.com/v1/chat/completions",
|
||||
payload,
|
||||
{
|
||||
headers: {
|
||||
Authorization: `Bearer ${import.meta.env.VITE_OPENAI_API_SECRET}`,
|
||||
},
|
||||
}
|
||||
);
|
||||
const progress = data.choices?.[0].message as StoryProgress;
|
||||
yield put(updateStorySuccess({ progress }));
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
} finally {
|
||||
yield put(toScene({ index: currentSceneIndex + 1 }));
|
||||
}
|
||||
}
|
||||
|
||||
// Combine all sagas
|
||||
export default function* storySaga() {
|
||||
yield takeEvery(INIT_STORY, initStory);
|
||||
yield takeEvery(UPDATE_STORY, updateStory);
|
||||
}
|
||||
|
||||
@@ -1,9 +1,25 @@
|
||||
import { Scene } from "model";
|
||||
import { createSelector } from "reselect";
|
||||
import { RootState } from "..";
|
||||
|
||||
// Assuming your state structure has a counter object
|
||||
const getStoryBase = (state: RootState) => state.story;
|
||||
|
||||
export const storySelector = createSelector(
|
||||
[getStoryBase],
|
||||
({ title, introduction, currentSceneIndex }) => ({
|
||||
title,
|
||||
introduction,
|
||||
currentSceneIndex,
|
||||
})
|
||||
);
|
||||
|
||||
export const currentSceneSelector = createSelector(
|
||||
[getStoryBase],
|
||||
({ scenes, currentSceneIndex }) =>
|
||||
currentSceneIndex > 0 ? scenes[currentSceneIndex - 1] : ({} as Scene)
|
||||
);
|
||||
|
||||
export const storyProgressSelector = createSelector(
|
||||
[getStoryBase],
|
||||
({ storyProgressPrompts }) => storyProgressPrompts
|
||||
|
||||
@@ -1,22 +1,50 @@
|
||||
export const parseScene = (content: string) => {
|
||||
import { RawScene, Scene } from "../../types/story";
|
||||
|
||||
export const parseScene = (content: string): Scene => {
|
||||
// TODO: parse `Scene` type out of AI generated content
|
||||
console.log(content);
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
let cont: any = {};
|
||||
try {
|
||||
cont = JSON.parse(content) as RawScene;
|
||||
} catch (e) {
|
||||
console.log(e);
|
||||
}
|
||||
return {
|
||||
content: "",
|
||||
options: [],
|
||||
type: cont.type,
|
||||
character: cont.character,
|
||||
setting: cont.setting,
|
||||
sceneNumber: cont.sceneNumber,
|
||||
sceneTitle: cont.sceneTitle,
|
||||
sceneDescription: cont.sceneDescription,
|
||||
optionPrompt: cont.optionPrompt,
|
||||
options: cont.options,
|
||||
};
|
||||
};
|
||||
|
||||
export const parseStoryGuideline = (content: string) => {
|
||||
export const parseStoryGuideline = (
|
||||
content: string
|
||||
): { title: string; introduction: string; scene: Scene } => {
|
||||
// TODO: parse the story title, coverImage, intro and first `Scene` type out of AI generated content
|
||||
console.log(content);
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
let cont: any = {};
|
||||
try {
|
||||
cont = JSON.parse(content) as RawScene;
|
||||
} catch (e) {
|
||||
console.log(e);
|
||||
}
|
||||
return {
|
||||
title: "",
|
||||
intro: "",
|
||||
coverImageUrl: "",
|
||||
title: cont.title,
|
||||
introduction: cont.introduction,
|
||||
// coverImageUrl: "", // TODO: get from other service
|
||||
scene: {
|
||||
content: "",
|
||||
options: [],
|
||||
type: cont.type,
|
||||
character: cont.character,
|
||||
setting: cont.setting,
|
||||
sceneNumber: cont.sceneNumber,
|
||||
sceneTitle: cont.sceneTitle,
|
||||
sceneDescription: cont.sceneDescription,
|
||||
optionPrompt: cont.optionPrompt,
|
||||
options: cont.options,
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
@@ -1,11 +1,14 @@
|
||||
import { useState } from "react";
|
||||
import { useEffect, useState } from "react";
|
||||
import { useDispatch, useSelector } from "react-redux";
|
||||
import { useNavigate } from "react-router-dom";
|
||||
import styled from "styled-components";
|
||||
import Canvas from "../components/Canvas";
|
||||
import Preview from "../components/Preview";
|
||||
import { characterImageSelector } from "../modules/character/selectors";
|
||||
import { createCharacter } from "../modules/character/actions";
|
||||
import {
|
||||
characterImageSelector,
|
||||
characterTypeSelector,
|
||||
} from "../modules/character/selectors";
|
||||
import { createCharacterImage } from "../modules/character/actions";
|
||||
|
||||
const Container = styled.div`
|
||||
display: flex;
|
||||
@@ -16,11 +19,18 @@ const CanvasPage = () => {
|
||||
const [sketchBlob, setSketchBlob] = useState<Blob>(new Blob());
|
||||
const [prompt, setPrompt] = useState("");
|
||||
const dispatch = useDispatch();
|
||||
const characterIamge = useSelector(characterImageSelector);
|
||||
const characterImage = useSelector(characterImageSelector);
|
||||
const navigate = useNavigate();
|
||||
const characterType = useSelector(characterTypeSelector);
|
||||
|
||||
useEffect(() => {
|
||||
if (characterType && !prompt) {
|
||||
setPrompt(characterType);
|
||||
}
|
||||
}, [characterType]);
|
||||
|
||||
const convert = () => {
|
||||
dispatch(createCharacter({ sketchBlob, prompt }));
|
||||
dispatch(createCharacterImage({ sketchBlob, prompt }));
|
||||
|
||||
// TODO: refactor later
|
||||
setTimeout(() => {
|
||||
@@ -39,7 +49,7 @@ const CanvasPage = () => {
|
||||
onChange={(e) => setPrompt(e.target.value)}
|
||||
/>
|
||||
</div>
|
||||
<Preview data={characterIamge} />
|
||||
<Preview data={characterImage} />
|
||||
</Container>
|
||||
<div>
|
||||
<button onClick={convert}>Convert</button>
|
||||
|
||||
38
app/src/pages/characterBase.tsx
Normal file
38
app/src/pages/characterBase.tsx
Normal file
@@ -0,0 +1,38 @@
|
||||
import { useState } from "react";
|
||||
import { useDispatch } from "react-redux";
|
||||
import { useNavigate } from "react-router-dom";
|
||||
import { Container, Heading, Button } from "@radix-ui/themes";
|
||||
import { createCharacterType } from "../modules/character/actions";
|
||||
|
||||
const CHARACTER_BASE = ["cat", "human", "bear"];
|
||||
|
||||
const CharacterBase = () => {
|
||||
const [characterBase, setCharacterBase] = useState("human");
|
||||
const navigate = useNavigate();
|
||||
const dispatch = useDispatch();
|
||||
|
||||
return (
|
||||
<Container>
|
||||
<Heading>Select Character Base</Heading>
|
||||
<ul>
|
||||
{CHARACTER_BASE.map((c) => (
|
||||
<li key={c} onClick={() => setCharacterBase(c)}>
|
||||
<img src="" alt={c} />
|
||||
<Heading as="h4">{c}</Heading>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
<Button
|
||||
onClick={() => {
|
||||
// update default character type
|
||||
dispatch(createCharacterType({ characterType: characterBase }));
|
||||
navigate("/canvas");
|
||||
}}
|
||||
>
|
||||
Select Character
|
||||
</Button>
|
||||
</Container>
|
||||
);
|
||||
};
|
||||
|
||||
export default CharacterBase;
|
||||
@@ -6,16 +6,18 @@ import {
|
||||
onSnapshot,
|
||||
QueryDocumentSnapshot,
|
||||
} from "firebase/firestore";
|
||||
import { Link } from "react-router-dom";
|
||||
import { Link, useNavigate } from "react-router-dom";
|
||||
import { User } from "firebase/auth";
|
||||
import { Container, Button } from "@radix-ui/themes";
|
||||
import { protectedRoute } from "../components/protectedRoute.tsx";
|
||||
|
||||
const DashboardPage = protectedRoute(({ user }: { user: User }) => {
|
||||
const [projects, setProjects] = useState<QueryDocumentSnapshot<Project>[]>();
|
||||
const navigate = useNavigate();
|
||||
useEffect(() => {
|
||||
onSnapshot(collection(db, `users/${user.uid}/projects`), (snapshot) => {
|
||||
setProjects(
|
||||
snapshot.docs.map((x) => x as QueryDocumentSnapshot<Project>),
|
||||
snapshot.docs.map((x) => x as QueryDocumentSnapshot<Project>)
|
||||
);
|
||||
});
|
||||
}, [user.uid]);
|
||||
@@ -24,10 +26,16 @@ const DashboardPage = protectedRoute(({ user }: { user: User }) => {
|
||||
}
|
||||
if (projects.length === 0) {
|
||||
return (
|
||||
<div>
|
||||
Start creating
|
||||
<Link to="/canvas">Create adventure</Link>
|
||||
</div>
|
||||
<Container>
|
||||
Create Your own Adventure
|
||||
<Button
|
||||
onClick={() => {
|
||||
navigate("/name");
|
||||
}}
|
||||
>
|
||||
Get Started
|
||||
</Button>
|
||||
</Container>
|
||||
);
|
||||
}
|
||||
return (
|
||||
|
||||
@@ -1,10 +1,19 @@
|
||||
import { ConnectButton } from "@mysten/dapp-kit";
|
||||
import { Box, Container, Flex, Heading } from "@radix-ui/themes";
|
||||
import { WalletStatus } from "../components/WalletStatus.tsx";
|
||||
import { callFunction } from "../firebase.ts";
|
||||
|
||||
export default function App() {
|
||||
return (
|
||||
<>
|
||||
<button
|
||||
onClick={async () => {
|
||||
const result = await callFunction("generateImage", "test");
|
||||
console.log(result);
|
||||
}}
|
||||
>
|
||||
Test Cloudfunction Call
|
||||
</button>
|
||||
<Flex
|
||||
position="sticky"
|
||||
px="4"
|
||||
|
||||
BIN
app/src/pages/home/_/step1.png
Normal file
BIN
app/src/pages/home/_/step1.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 168 KiB |
BIN
app/src/pages/home/_/step2.png
Normal file
BIN
app/src/pages/home/_/step2.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 162 KiB |
BIN
app/src/pages/home/_/step3.png
Normal file
BIN
app/src/pages/home/_/step3.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 168 KiB |
110
app/src/pages/home/index.tsx
Normal file
110
app/src/pages/home/index.tsx
Normal file
@@ -0,0 +1,110 @@
|
||||
import { FC } from "react";
|
||||
import { Header, PageContainer } from "../../components/Layout/Layout";
|
||||
import styled from "styled-components";
|
||||
import step1 from "./_/step1.png";
|
||||
import step2 from "./_/step2.png";
|
||||
import step3 from "./_/step3.png";
|
||||
import { Link } from "react-router-dom";
|
||||
|
||||
const StyledTitle = styled.h1`
|
||||
color: #000;
|
||||
font-size: 50px;
|
||||
font-weight: 600;
|
||||
line-height: 60px;
|
||||
letter-spacing: -1px;
|
||||
margin-left: 34px;
|
||||
margin-top: 72px;
|
||||
`;
|
||||
|
||||
const StyledStepContainer = styled.div`
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
gap: 20px;
|
||||
padding: 0 20px;
|
||||
`;
|
||||
|
||||
const StyledStepItem = styled.div`
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 12px;
|
||||
`;
|
||||
|
||||
const StyledStepItemTitle = styled.div`
|
||||
color: #000;
|
||||
font-size: 30px;
|
||||
font-weight: 500;
|
||||
line-height: 60px;
|
||||
`;
|
||||
|
||||
const StyledStepItemImage = styled.img`
|
||||
width: 100%;
|
||||
border-radius: 5px;
|
||||
`;
|
||||
|
||||
const StyledStepItemDescription = styled.div`
|
||||
color: #000;
|
||||
font-size: 18px;
|
||||
font-weight: 500;
|
||||
line-height: 20px;
|
||||
`;
|
||||
|
||||
const StepItem: FC<{
|
||||
title: string;
|
||||
description: string;
|
||||
image: string;
|
||||
}> = (props) => {
|
||||
return (
|
||||
<StyledStepItem>
|
||||
<StyledStepItemTitle>{props.title}</StyledStepItemTitle>
|
||||
<StyledStepItemImage src={props.image} alt="" />
|
||||
<StyledStepItemDescription>{props.description}</StyledStepItemDescription>
|
||||
</StyledStepItem>
|
||||
);
|
||||
};
|
||||
|
||||
const StyledStartButton = styled(Link)`
|
||||
padding: 4px 25px;
|
||||
border-radius: 10px;
|
||||
background: #000;
|
||||
color: #fff;
|
||||
text-align: center;
|
||||
width: fit-content;
|
||||
cursor: pointer;
|
||||
`;
|
||||
|
||||
const StyledStartButtonContainer = styled.div`
|
||||
display: flex;
|
||||
margin-top: 140px;
|
||||
justify-content: center;
|
||||
`;
|
||||
|
||||
const HomePage: FC = () => {
|
||||
return (
|
||||
<PageContainer>
|
||||
<Header />
|
||||
<StyledTitle>Create your own Adventure</StyledTitle>
|
||||
<StyledStepContainer>
|
||||
<StepItem
|
||||
title={"1.Create Character"}
|
||||
image={step1}
|
||||
description="You’ve got two images, you need two words.Start working out that big brain"
|
||||
/>
|
||||
<StepItem
|
||||
title={"2.Generate Story"}
|
||||
image={step2}
|
||||
description="You’ve got two images, you need two words.Start working out that big brain"
|
||||
/>
|
||||
<StepItem
|
||||
title={"3.Mint Your Story"}
|
||||
image={step3}
|
||||
description="You’ve got two images, you need two words.Start working out that big brain"
|
||||
/>
|
||||
</StyledStepContainer>
|
||||
<StyledStartButtonContainer>
|
||||
<StyledStartButton to="/login">Get started</StyledStartButton>
|
||||
</StyledStartButtonContainer>
|
||||
</PageContainer>
|
||||
);
|
||||
};
|
||||
|
||||
export default HomePage;
|
||||
@@ -1,36 +1,5 @@
|
||||
import { useEffect, useState } from "react";
|
||||
import { Navigate } from "react-router";
|
||||
import {
|
||||
GoogleAuthProvider,
|
||||
onAuthStateChanged,
|
||||
signInWithPopup,
|
||||
User,
|
||||
} from "firebase/auth";
|
||||
import { auth } from "../firebase.ts";
|
||||
|
||||
export default function App() {
|
||||
const [user, setUser] = useState<User | null>();
|
||||
useEffect(() => {
|
||||
onAuthStateChanged(auth, (user) => {
|
||||
setUser(user);
|
||||
});
|
||||
}, []);
|
||||
if (user === undefined) {
|
||||
return <div>Loading...</div>;
|
||||
}
|
||||
if (user != null) {
|
||||
return <Navigate to="/dashboard" />;
|
||||
}
|
||||
return (
|
||||
<div>
|
||||
<button
|
||||
onClick={async () => {
|
||||
const provider = new GoogleAuthProvider();
|
||||
await signInWithPopup(auth, provider);
|
||||
}}
|
||||
>
|
||||
Continue with Google
|
||||
</button>
|
||||
</div>
|
||||
);
|
||||
return <Navigate to="/home" />;
|
||||
}
|
||||
|
||||
110
app/src/pages/login/index.tsx
Normal file
110
app/src/pages/login/index.tsx
Normal file
@@ -0,0 +1,110 @@
|
||||
import { FC, useEffect, useState } from "react";
|
||||
import { Header, PageContainer } from "../../components/Layout/Layout";
|
||||
import styled from "styled-components";
|
||||
import {
|
||||
GoogleAuthProvider,
|
||||
onAuthStateChanged,
|
||||
signInWithPopup,
|
||||
User,
|
||||
} from "firebase/auth";
|
||||
import { auth } from "../../firebase.ts";
|
||||
import { Navigate } from "react-router";
|
||||
|
||||
export const StyledPageContainer = styled(PageContainer)`
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 100vw;
|
||||
`;
|
||||
|
||||
const StyledCard = styled.div`
|
||||
width: 353px;
|
||||
height: 433px;
|
||||
border-radius: 10px;
|
||||
background: #ddffc2;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
padding: 59px 35px;
|
||||
align-items: center;
|
||||
`;
|
||||
|
||||
const StyledCardTitle = styled.div`
|
||||
color: #000;
|
||||
font-family: N27;
|
||||
font-size: 20px;
|
||||
line-height: 24px;
|
||||
text-align: center;
|
||||
`;
|
||||
|
||||
const StyledDescritionTitle = styled.p`
|
||||
color: #000;
|
||||
text-align: center;
|
||||
font-family: Inter Tight;
|
||||
font-size: 30px;
|
||||
font-weight: 500;
|
||||
line-height: 60px;
|
||||
margin-top: 74px;
|
||||
`;
|
||||
|
||||
const StyledDescription = styled.p`
|
||||
color: #000;
|
||||
text-align: center;
|
||||
font-family: Inter Tight;
|
||||
font-size: 12px;
|
||||
font-weight: 500;
|
||||
line-height: 20px;
|
||||
width: 237px;
|
||||
`;
|
||||
|
||||
const StyleSubButton = styled.button`
|
||||
color: #fff;
|
||||
font-weight: 600;
|
||||
text-align: center;
|
||||
width: 283px;
|
||||
padding: 10px 25px;
|
||||
gap: 10px;
|
||||
border-radius: 10px;
|
||||
background: #000;
|
||||
margin-top: 80px;
|
||||
cursor: pointer;
|
||||
`;
|
||||
|
||||
const LoginPage: FC = () => {
|
||||
const [user, setUser] = useState<User | null>();
|
||||
useEffect(() => {
|
||||
onAuthStateChanged(auth, (user) => {
|
||||
setUser(user);
|
||||
});
|
||||
}, []);
|
||||
if (user === undefined) {
|
||||
return <div>Loading...</div>;
|
||||
}
|
||||
if (user != null) {
|
||||
return <Navigate to="/dashboard" />;
|
||||
}
|
||||
return (
|
||||
<>
|
||||
<Header />
|
||||
<StyledPageContainer>
|
||||
<StyledCard>
|
||||
<StyledCardTitle>STORYTIME</StyledCardTitle>
|
||||
<StyledDescritionTitle>Start Creating!</StyledDescritionTitle>
|
||||
<StyledDescription>
|
||||
You’ve got two images, you need two words. Start working out that
|
||||
big brain
|
||||
</StyledDescription>
|
||||
<StyleSubButton
|
||||
onClick={async () => {
|
||||
const provider = new GoogleAuthProvider();
|
||||
await signInWithPopup(auth, provider);
|
||||
}}
|
||||
>
|
||||
Continue with google
|
||||
</StyleSubButton>
|
||||
</StyledCard>
|
||||
</StyledPageContainer>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default LoginPage;
|
||||
BIN
app/src/pages/mint/_/story.png
Normal file
BIN
app/src/pages/mint/_/story.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 311 KiB |
60
app/src/pages/mint/index.tsx
Normal file
60
app/src/pages/mint/index.tsx
Normal file
@@ -0,0 +1,60 @@
|
||||
import { FC } from "react";
|
||||
import { Header, PageContainer } from "../../components/Layout/Layout";
|
||||
import storyImg from "./_/story.png";
|
||||
import styled from "styled-components";
|
||||
|
||||
export const StyledPageContainer = styled(PageContainer)`
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 100vw;
|
||||
`;
|
||||
|
||||
const StyledMintTitle = styled.div`
|
||||
color: #000;
|
||||
text-align: center;
|
||||
font-family: Inter;
|
||||
font-size: 60px;
|
||||
font-weight: 600;
|
||||
line-height: 60px;
|
||||
letter-spacing: -1px;
|
||||
`;
|
||||
|
||||
const StyledMintSubTitle = styled.div`
|
||||
color: #000;
|
||||
font-family: Inter;
|
||||
font-size: 25px;
|
||||
font-weight: 600;
|
||||
line-height: 24px;
|
||||
`
|
||||
|
||||
const StyledMintImg = styled.img`
|
||||
margin-top: 47px;
|
||||
margin-bottom: 29px;
|
||||
`
|
||||
const StyledMintButton = styled.div`
|
||||
padding: 4px 25px;
|
||||
border-radius: 10px;
|
||||
background: #000;
|
||||
cursor: pointer;
|
||||
color: #fff;
|
||||
margin-top: 29px;
|
||||
`
|
||||
|
||||
|
||||
const MinStoryPage: FC = () => {
|
||||
return (
|
||||
<div>
|
||||
<Header />
|
||||
<StyledPageContainer>
|
||||
<StyledMintTitle>Mint your story</StyledMintTitle>
|
||||
<StyledMintImg src={storyImg} alt="" />
|
||||
<StyledMintSubTitle>The Journey to Dragon’s Keep</StyledMintSubTitle>
|
||||
<StyledMintButton>MINT STORY</StyledMintButton>
|
||||
</StyledPageContainer>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default MinStoryPage;
|
||||
33
app/src/pages/name.tsx
Normal file
33
app/src/pages/name.tsx
Normal file
@@ -0,0 +1,33 @@
|
||||
import { useState } from "react";
|
||||
import { useNavigate } from "react-router-dom";
|
||||
import { useDispatch } from "react-redux";
|
||||
import { Container, Heading, TextField, Button } from "@radix-ui/themes";
|
||||
import { createCharacterName } from "../modules/character/actions";
|
||||
|
||||
const Name = () => {
|
||||
const [characterName, setCharacterName] = useState("");
|
||||
const navigate = useNavigate();
|
||||
const dispatch = useDispatch();
|
||||
return (
|
||||
<Container>
|
||||
<Heading>Enter Character Name</Heading>
|
||||
<TextField.Root>
|
||||
<TextField.Input
|
||||
value={characterName}
|
||||
onChange={(e) => setCharacterName(e.target.value)}
|
||||
placeholder="ENTER CHARACTER NAME"
|
||||
/>
|
||||
</TextField.Root>
|
||||
<Button
|
||||
onClick={() => {
|
||||
dispatch(createCharacterName({ characterName }));
|
||||
navigate("/characterBase");
|
||||
}}
|
||||
>
|
||||
Select Character
|
||||
</Button>
|
||||
</Container>
|
||||
);
|
||||
};
|
||||
|
||||
export default Name;
|
||||
@@ -1,31 +1,40 @@
|
||||
import { useDispatch, useSelector } from "react-redux";
|
||||
import { Container } from "@radix-ui/themes";
|
||||
import { characterNameSelector } from "../../modules/character/selectors";
|
||||
import { characterTypeSelector } from "../../modules/character/selectors";
|
||||
import { initStory } from "../../modules/story/actions";
|
||||
import { getStoryTemplate } from "../../utils";
|
||||
import { useEffect } from "react";
|
||||
import { StoryProgressPromptRole } from "../../types/story";
|
||||
import { storyProgressSelector } from "../../modules/story/selectors";
|
||||
import {
|
||||
storySelector,
|
||||
storyProgressSelector,
|
||||
} from "../../modules/story/selectors";
|
||||
import Scene from "../../components/Scene";
|
||||
import Cover from "../../components/Cover";
|
||||
|
||||
const Story: React.FC = () => {
|
||||
const characterName = useSelector(characterNameSelector);
|
||||
const template = getStoryTemplate(characterName);
|
||||
const characterType = useSelector(characterTypeSelector);
|
||||
const template = getStoryTemplate({ characterName, characterType });
|
||||
const dispatch = useDispatch();
|
||||
const { title, currentSceneIndex } = useSelector(storySelector);
|
||||
const storyProgress = useSelector(storyProgressSelector);
|
||||
console.log(storyProgress);
|
||||
|
||||
useEffect(() => {
|
||||
dispatch(
|
||||
initStory({
|
||||
initMessage: {
|
||||
role: StoryProgressPromptRole.System,
|
||||
content: template,
|
||||
},
|
||||
})
|
||||
);
|
||||
}, []);
|
||||
if (!title) {
|
||||
dispatch(
|
||||
initStory({
|
||||
initMessage: {
|
||||
role: StoryProgressPromptRole.System,
|
||||
content: template,
|
||||
},
|
||||
})
|
||||
);
|
||||
}
|
||||
}, [title]);
|
||||
|
||||
return <Container>OYOYO</Container>;
|
||||
return currentSceneIndex > 0 ? <Scene /> : <Cover />;
|
||||
};
|
||||
|
||||
export default Story;
|
||||
|
||||
@@ -8,14 +8,28 @@ export type StoryProgress = {
|
||||
content: string;
|
||||
};
|
||||
|
||||
type SceneOption = {
|
||||
content: string;
|
||||
value: string;
|
||||
export type RawScene = {
|
||||
title: string; // project
|
||||
introduction: string; // project
|
||||
type: "story-introduction" | "story-followup" | "story-ending";
|
||||
character: string;
|
||||
setting: string;
|
||||
sceneNumber: number;
|
||||
sceneTitle: string;
|
||||
sceneDescription: string;
|
||||
optionPrompt: string;
|
||||
options: string[];
|
||||
};
|
||||
|
||||
export type Scene = {
|
||||
index: number;
|
||||
content: string;
|
||||
options: SceneOption[];
|
||||
imageUrl: string;
|
||||
// title: string; // project
|
||||
// introduction: string; // project
|
||||
type: "story-introduction" | "story-followup" | "story-ending";
|
||||
character: string;
|
||||
setting: string;
|
||||
sceneNumber: number;
|
||||
sceneTitle: string;
|
||||
sceneDescription: string;
|
||||
optionPrompt: string;
|
||||
options: string[];
|
||||
};
|
||||
|
||||
@@ -1,40 +1,89 @@
|
||||
export const getStoryTemplate = (customPrompt: string) =>
|
||||
export const getStoryTemplate = ({
|
||||
characterType,
|
||||
characterName,
|
||||
}: {
|
||||
characterType: string;
|
||||
characterName: string;
|
||||
}) =>
|
||||
encodeURI(
|
||||
`Respond with markdown format and highlight list out each section.
|
||||
`Respond with JSON format, don't output any other content except the JSON, don't wrap the JSON with markdown syntax
|
||||
|
||||
Create a choose your own adventure game with 6 scenes with each scene having 3 choices for the user that are both fun and engaging.
|
||||
Create a choose-your-own adventure game that lasts 6 scenes where each scene's choice will lead to the next scene. Each scene having 3 choices for the user to choose from that is both fun and engaging. Ensure the the character aesthetic is well defined with tons of description and the setting has the scenery very detailed. Response one scene at a time.
|
||||
|
||||
Here is the structure for the storybook and an example:
|
||||
Here is the structure for the storybook (in typescript interface format) and an example:
|
||||
|
||||
Structure
|
||||
Title
|
||||
Character
|
||||
Setting
|
||||
Introduction
|
||||
Scenes description followed by user choices. (Scene should be 4-5 sentences max).
|
||||
Conclusion
|
||||
\`\`\`
|
||||
type MarkdownText = string
|
||||
type Option = string
|
||||
interface StorybookIntro extends StorybookFollowup {
|
||||
type: "story-introduction"
|
||||
title: string
|
||||
character: string
|
||||
setting: string
|
||||
introduction: string
|
||||
}
|
||||
interface StorybookFollowup {
|
||||
type: "story-followup"
|
||||
sceneNumber: number
|
||||
sceneTitle: string
|
||||
sceneDescription: MarkdownText
|
||||
optionsPrompt: string
|
||||
options: [
|
||||
Option,
|
||||
Option,
|
||||
Option,
|
||||
]
|
||||
}
|
||||
interface StorybookEnding {
|
||||
type: "story-ending"
|
||||
sceneNumber: number
|
||||
sceneTitle: string
|
||||
sceneDescription: MarkdownText
|
||||
}
|
||||
\`\`\`
|
||||
|
||||
Example:
|
||||
Title: "The Enchanted Forest Adventure"
|
||||
Example 1:
|
||||
|
||||
Character: A clever and resourceful rabbit named Remy.
|
||||
{
|
||||
"type": "story-introduction",
|
||||
"title": "The Enchanted Forest Adventure",
|
||||
"character": "A clever and resourceful rabbit named Remy with a top hat and a red bowtie",
|
||||
"setting": "A whimsical world where nature and magic intertwine, filled with talking animals, mystical plants, and hidden paths that brings about a pleasant and warm atmosphere",
|
||||
"introduction": "In a world where every leaf and stone tells a story, Remy, a clever and resourceful rabbit, is about to embark on an unexpected journey. Known for his wit and curiosity, Remy lives in a cozy burrow near the Enchanted Glade. One morning, he finds a mysterious map leading to an unknown destination. His adventure begins with a choice of where to go first.",
|
||||
"sceneNumber": 1,
|
||||
"sceneTitle": "The Mysterious Map",
|
||||
"sceneDescription": "Remy examines the map and notices three landmarks:\n\n1. The Silver Lake: A shimmering lake known for its reflective waters that show visions.\n\n2. The Whispering Woods: A dense forest where the trees are said to hold ancient wisdom.\n\n3. The Moonlit Meadow: A tranquil meadow that glows under the moon, rumored to be a place of magic.",
|
||||
"optionsPrompt": "Where should Remy start his adventure?",
|
||||
"options": ["Lake", "Woods", "Meadow"]
|
||||
}
|
||||
|
||||
Setting: A whimsical world where nature and magic intertwine, filled with talking animals, mystical plants, and hidden paths.
|
||||
---------- Example 1 end ---------
|
||||
|
||||
Introduction: "In a world where every leaf and stone tells a story, Remy, a clever and resourceful rabbit, is about to embark on an unexpected journey. Known for his wit and curiosity, Remy lives in a cozy burrow near the Enchanted Glade. One morning, he finds a mysterious map leading to an unknown destination. His adventure begins with a choice of where to go first."
|
||||
Example 2:
|
||||
|
||||
Scene 1: The Mysterious Map
|
||||
Remy examines the map and notices three landmarks:
|
||||
{
|
||||
"type": "story-followup",
|
||||
"sceneNumber": 2,
|
||||
"sceneTitle": "The Mysterious Map",
|
||||
"sceneDescription": "Remy examines the map and notices three landmarks:\n\n1. The Silver Lake: A shimmering lake known for its reflective waters that show visions.\n\n2. The Whispering Woods: A dense forest where the trees are said to hold ancient wisdom.\n\n3. The Moonlit Meadow: A tranquil meadow that glows under the moon, rumored to be a place of magic.",
|
||||
"optionsPrompt": "Where should Remy start his adventure?",
|
||||
"options": ["Lake", "Woods", "Meadow"]
|
||||
}
|
||||
|
||||
1. The Silver Lake: A shimmering lake known for its reflective waters that show visions.
|
||||
2. The Whispering Woods: A dense forest where the trees are said to hold ancient wisdom.
|
||||
3. The Moonlit Meadow: A tranquil meadow that glows under the moon, rumored to be a place of magic.
|
||||
Where should Remy start his adventure? [Type 'Lake', 'Woods', or 'Meadow']
|
||||
---------- Example 2 end ---------
|
||||
|
||||
Let me know your choice, and we'll continue the story from there!
|
||||
Example 3:
|
||||
|
||||
Stop after each scene for user to type their input. As an user, I can play the game here by responding with a choice.
|
||||
{
|
||||
"type": "story-ending",
|
||||
"sceneNumber": 5,
|
||||
"sceneTitle": "The Mysterious Map",
|
||||
"sceneDescription": "Gary, reflecting on his experiences throughout the quest, realizes that true treasure lies not in solitary glory, but in sharing triumphs with others. With care, he transports the Golden Lettuce back to his community. His return is celebrated, and the lettuce's seeds bring prosperity to the garden.\n\nGary's act of kindness becomes a tale told from one generation to the next, inspiring countless other snails to live a life of bravery, adventure, and most importantly, generosity."
|
||||
}
|
||||
|
||||
The Character is a ${customPrompt} named Gary for this new story
|
||||
`.trim()
|
||||
---------- Example 3 end ---------
|
||||
|
||||
Ensure that after each scene the user has to type their input. As a user, I can play the game here by responding with a choice.
|
||||
|
||||
The Character is a ${characterType} named ${characterName} for this new story`.trim()
|
||||
);
|
||||
|
||||
@@ -20,6 +20,6 @@
|
||||
"noUnusedParameters": true,
|
||||
"noFallthroughCasesInSwitch": true
|
||||
},
|
||||
"include": ["src"],
|
||||
"include": ["src", "src/global.d.ts"],
|
||||
"references": [{ "path": "./tsconfig.node.json" }]
|
||||
}
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
import { defineConfig } from 'vite'
|
||||
import {defineConfig} from 'vite'
|
||||
import react from '@vitejs/plugin-react-swc'
|
||||
import Pages from 'vite-plugin-pages'
|
||||
import svgr from "vite-plugin-svgr";
|
||||
|
||||
// https://vitejs.dev/config/
|
||||
export default defineConfig({
|
||||
plugins: [react(), Pages()],
|
||||
plugins: [react(), svgr(), Pages(),],
|
||||
})
|
||||
|
||||
@@ -37,5 +37,26 @@
|
||||
},
|
||||
"storage": {
|
||||
"rules": "storage.rules"
|
||||
},
|
||||
"emulators": {
|
||||
"auth": {
|
||||
"port": 9099
|
||||
},
|
||||
"functions": {
|
||||
"port": 5001
|
||||
},
|
||||
"firestore": {
|
||||
"port": 8080
|
||||
},
|
||||
"hosting": {
|
||||
"port": 5000
|
||||
},
|
||||
"storage": {
|
||||
"port": 9199
|
||||
},
|
||||
"ui": {
|
||||
"enabled": true
|
||||
},
|
||||
"singleProjectMode": true
|
||||
}
|
||||
}
|
||||
|
||||
11
functions/src/generateImage.ts
Normal file
11
functions/src/generateImage.ts
Normal file
@@ -0,0 +1,11 @@
|
||||
import { CloudFunctionsTypeWithUid } from "./handlersType";
|
||||
|
||||
export const generateImage: CloudFunctionsTypeWithUid["generateImage"] = async (
|
||||
prompt,
|
||||
uid,
|
||||
) => {
|
||||
return {
|
||||
url: "hello",
|
||||
finalPrompt: "world" + prompt,
|
||||
};
|
||||
};
|
||||
7
functions/src/handlersType.d.ts
vendored
Normal file
7
functions/src/handlersType.d.ts
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
import { CloudFunctionsType } from "model/functions";
|
||||
|
||||
export type CloudFunctionsTypeWithUid = {
|
||||
[P in keyof CloudFunctionsType]: (
|
||||
...args: [...Parameters<CloudFunctionsType[P]>, string | undefined]
|
||||
) => ReturnType<CloudFunctionsType[P]>;
|
||||
};
|
||||
@@ -7,7 +7,7 @@
|
||||
* See a full list of supported triggers at https://firebase.google.com/docs/functions
|
||||
*/
|
||||
|
||||
import { onCall, onRequest, Request } from "firebase-functions/v2/https";
|
||||
import { onCall, onRequest, Request, HttpsError } from "firebase-functions/v2/https";
|
||||
import * as logger from "firebase-functions/logger";
|
||||
import { OpenAI } from "openai";
|
||||
import * as express from "express";
|
||||
@@ -26,10 +26,15 @@ admin.initializeApp({
|
||||
// https://firebase.google.com/docs/functions/typescript
|
||||
|
||||
export const execute = onCall({ region: "asia-east1" }, (request) => {
|
||||
logger.info("Hello logs!", { structuredData: true });
|
||||
return {
|
||||
data: "Hello from Firebase!",
|
||||
};
|
||||
const uid = auth?.uid;
|
||||
logger.info(data, { context: uid });
|
||||
if (!(data.type in handlers)) {
|
||||
throw new HttpsError(
|
||||
"invalid-argument",
|
||||
`Function ${data.type} does not exist`,
|
||||
);
|
||||
}
|
||||
return await (handlers as any)[data.type](...data.args, uid);
|
||||
});
|
||||
const openai = new OpenAI({
|
||||
apiKey: "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",
|
||||
|
||||
3
model/functions.d.ts
vendored
Normal file
3
model/functions.d.ts
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
export type CloudFunctionsType = {
|
||||
generateImage(prompt: string): Promise<{ url: string; finalPrompt: string }>;
|
||||
};
|
||||
15
model/model.d.ts
vendored
15
model/model.d.ts
vendored
@@ -40,9 +40,14 @@ export type SceneOption = { content: string; value: string };
|
||||
export type Scene = {
|
||||
id: string;
|
||||
projectId: string;
|
||||
imageUrl: string;
|
||||
index: number;
|
||||
content: string;
|
||||
options: SceneOption[];
|
||||
imageUrl: string;
|
||||
title: string; // project
|
||||
introduction: string; // project
|
||||
type: "story-introduction" | "story-followup" | "story-ending";
|
||||
character: string;
|
||||
setting: string;
|
||||
sceneNumber: number;
|
||||
sceneTitle: string;
|
||||
sceneDescription: string;
|
||||
optionPrompt: string;
|
||||
options: string[];
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user