ed
This commit is contained in:
parent
510e3ffcf2
commit
f43cf424cf
305 changed files with 34683 additions and 0 deletions
21
resources/[carscripts]/community_bridge/web/.eslintrc.cjs
Normal file
21
resources/[carscripts]/community_bridge/web/.eslintrc.cjs
Normal file
|
@ -0,0 +1,21 @@
|
|||
module.exports = {
|
||||
root: true,
|
||||
env: { browser: true, es2020: true },
|
||||
extends: [
|
||||
'eslint:recommended',
|
||||
'plugin:react/recommended',
|
||||
'plugin:react/jsx-runtime',
|
||||
'plugin:react-hooks/recommended',
|
||||
],
|
||||
ignorePatterns: ['dist', '.eslintrc.cjs'],
|
||||
parserOptions: { ecmaVersion: 'latest', sourceType: 'module' },
|
||||
settings: { react: { version: '18.2' } },
|
||||
plugins: ['react-refresh'],
|
||||
rules: {
|
||||
'react/jsx-no-target-blank': 'off',
|
||||
'react-refresh/only-export-components': [
|
||||
'warn',
|
||||
{ allowConstantExport: true },
|
||||
],
|
||||
},
|
||||
}
|
23
resources/[carscripts]/community_bridge/web/.gitignore
vendored
Normal file
23
resources/[carscripts]/community_bridge/web/.gitignore
vendored
Normal file
|
@ -0,0 +1,23 @@
|
|||
# Logs
|
||||
logs
|
||||
*.log
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
pnpm-debug.log*
|
||||
lerna-debug.log*
|
||||
|
||||
node_modules
|
||||
dist-ssr
|
||||
*.local
|
||||
|
||||
# Editor directories and files
|
||||
.vscode/*
|
||||
!.vscode/extensions.json
|
||||
.idea
|
||||
.DS_Store
|
||||
*.suo
|
||||
*.ntvs*
|
||||
*.njsproj
|
||||
*.sln
|
||||
*.sw?
|
8
resources/[carscripts]/community_bridge/web/README.md
Normal file
8
resources/[carscripts]/community_bridge/web/README.md
Normal file
|
@ -0,0 +1,8 @@
|
|||
# React + Vite
|
||||
|
||||
This template provides a minimal setup to get React working in Vite with HMR and some ESLint rules.
|
||||
|
||||
Currently, two official plugins are available:
|
||||
|
||||
- [@vitejs/plugin-react](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react/README.md) uses [Babel](https://babeljs.io/) for Fast Refresh
|
||||
- [@vitejs/plugin-react-swc](https://github.com/vitejs/vite-plugin-react-swc) uses [SWC](https://swc.rs/) for Fast Refresh
|
40
resources/[carscripts]/community_bridge/web/dist/assets/index-B0fYxqh2.js
vendored
Normal file
40
resources/[carscripts]/community_bridge/web/dist/assets/index-B0fYxqh2.js
vendored
Normal file
File diff suppressed because one or more lines are too long
91
resources/[carscripts]/community_bridge/web/dist/assets/index-BEeeZu6c.css
vendored
Normal file
91
resources/[carscripts]/community_bridge/web/dist/assets/index-BEeeZu6c.css
vendored
Normal file
|
@ -0,0 +1,91 @@
|
|||
.container {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
width: 100%;
|
||||
min-height: 100vh;
|
||||
background: transparent
|
||||
}
|
||||
|
||||
.dialogue-container {
|
||||
position: fixed;
|
||||
bottom: 30px;
|
||||
width: 50%;
|
||||
background: transparent;
|
||||
padding: 15px;
|
||||
left: 50%;
|
||||
transform: translate(-50%)
|
||||
}
|
||||
|
||||
.dialogue-text {
|
||||
background: #242424;
|
||||
padding: 10px;
|
||||
border-radius: 4px;
|
||||
margin: 10px 0;
|
||||
line-height: 1.6;
|
||||
font-size: 1.1em;
|
||||
border: 0.5px dotted rgba(203, 203, 203, 0.5);
|
||||
box-shadow: 0 4px 16px #0000007e;
|
||||
|
||||
}
|
||||
|
||||
.dialogue-options {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
flex-wrap: wrap;
|
||||
gap: 6px;
|
||||
justify-content: space-between;
|
||||
margin-top: 20px;
|
||||
width: 100%
|
||||
}
|
||||
|
||||
.dialogue-button {
|
||||
background: #242424;
|
||||
border: 0.5px solid rgba(203, 203, 203, 0.5);
|
||||
color: #fff;
|
||||
padding: 12px 24px;
|
||||
border-radius: 4px;
|
||||
cursor: pointer;
|
||||
transition: all .2s ease;
|
||||
font-size: .95em;
|
||||
flex: 1;
|
||||
text-align: center;
|
||||
min-width: calc(33.333% - 8px);
|
||||
box-shadow: 0 4px 16px #0003
|
||||
}
|
||||
|
||||
.dialogue-button:hover {
|
||||
background: #3333338c;
|
||||
transform: translateY(-1px);
|
||||
box-shadow: 0 4px 16px #0000007e;
|
||||
border: 1px solid rgba(255, 255, 255, .3);
|
||||
}
|
||||
|
||||
h2 {
|
||||
color: #fff;
|
||||
margin: 0;
|
||||
font-size: 1.4em;
|
||||
font-weight: 600;
|
||||
text-shadow: 0 2px 4px rgba(0, 0, 0, .3)
|
||||
}
|
||||
|
||||
p {
|
||||
color: #fff;
|
||||
margin: 0;
|
||||
text-shadow: 0 1px 2px rgba(0, 0, 0, .2)
|
||||
}
|
||||
|
||||
* {
|
||||
font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Oxygen, Ubuntu, Cantarell, sans-serif;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale
|
||||
}
|
||||
|
||||
.hidden {
|
||||
display: none
|
||||
}
|
||||
|
||||
* {
|
||||
overflow-y: hidden;
|
||||
overflow-x: hidden
|
||||
}
|
50
resources/[carscripts]/community_bridge/web/dist/index.html
vendored
Normal file
50
resources/[carscripts]/community_bridge/web/dist/index.html
vendored
Normal file
|
@ -0,0 +1,50 @@
|
|||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>MRC Scuba</title>
|
||||
<script type="module" crossorigin src="./assets/index-B0fYxqh2.js"></script>
|
||||
<link rel="stylesheet" crossorigin href="./assets/index-BEeeZu6c.css">
|
||||
</head>
|
||||
<body>
|
||||
<div id="root"></div>
|
||||
</body>
|
||||
<script>
|
||||
// dont judge me
|
||||
|
||||
function isTableJSON(jsonString) {
|
||||
try {
|
||||
const parsed = JSON.parse(jsonString);
|
||||
return parsed;
|
||||
} catch (e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
const copyToClipboard = (str) => {
|
||||
const el = document.createElement("textarea");
|
||||
el.value = str;
|
||||
document.body.appendChild(el);
|
||||
el.select();
|
||||
document.execCommand("copy");
|
||||
document.body.removeChild(el);
|
||||
};
|
||||
|
||||
window.addEventListener("message", (event) => {
|
||||
if (event?.data?.type === "copytoclipboard") {
|
||||
var str = event.data.text;
|
||||
// str = JSON.parse(str);
|
||||
if (isTableJSON(str)) {
|
||||
str = str.replace(/\[/g, '{');
|
||||
str = str.replace(/\]/g, '}');
|
||||
// replace : with =
|
||||
str = str.replace(/:/g, '=');
|
||||
// I need all indexes with quotes to be replaced with nothing but not affect any string values
|
||||
str = str.replace(/"([^"]+)"=/g, '$1=');
|
||||
}
|
||||
copyToClipboard(str);
|
||||
}
|
||||
|
||||
});
|
||||
</script>
|
||||
</html>
|
47
resources/[carscripts]/community_bridge/web/index.html
Normal file
47
resources/[carscripts]/community_bridge/web/index.html
Normal file
|
@ -0,0 +1,47 @@
|
|||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>MRC Scuba</title>
|
||||
</head>
|
||||
<body>
|
||||
<div id="root"></div>
|
||||
<script type="module" src="./src/main.jsx"></script>
|
||||
</body>
|
||||
<script>
|
||||
// dont judge me
|
||||
|
||||
function isTableJSON(jsonString) {
|
||||
try {
|
||||
const parsed = JSON.parse(jsonString);
|
||||
return parsed;
|
||||
} catch (e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
const copyToClipboard = (str) => {
|
||||
const el = document.createElement("textarea");
|
||||
el.value = str;
|
||||
document.body.appendChild(el);
|
||||
el.select();
|
||||
document.execCommand("copy");
|
||||
document.body.removeChild(el);
|
||||
};
|
||||
|
||||
window.addEventListener("message", (event) => {
|
||||
if (event?.data?.type === "copytoclipboard") {
|
||||
var str = event.data.text;
|
||||
// str = JSON.parse(str);
|
||||
console.log("copying to clipboard", isTableJSON(str));
|
||||
if (isTableJSON(str)) {
|
||||
str = str.replace(/\[/g, '{');
|
||||
str = str.replace(/\]/g, '}');
|
||||
str = str.replace(/:/g, '=');
|
||||
str = str.replace(/"([^"]+)"=/g, '$1=');
|
||||
}
|
||||
copyToClipboard(str);
|
||||
}
|
||||
});
|
||||
</script>
|
||||
</html>
|
12078
resources/[carscripts]/community_bridge/web/package-lock.json
generated
Normal file
12078
resources/[carscripts]/community_bridge/web/package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load diff
31
resources/[carscripts]/community_bridge/web/package.json
Normal file
31
resources/[carscripts]/community_bridge/web/package.json
Normal file
|
@ -0,0 +1,31 @@
|
|||
{
|
||||
"name": "sonar-ui",
|
||||
"private": true,
|
||||
"version": "0.0.0",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
"build": "vite build --watch",
|
||||
"lint": "eslint . --ext js,jsx --report-unused-disable-directives --max-warnings 0",
|
||||
"preview": "vite preview"
|
||||
},
|
||||
"dependencies": {
|
||||
"@fortawesome/fontawesome-svg-core": "^6.7.2",
|
||||
"@fortawesome/free-solid-svg-icons": "^6.7.2",
|
||||
"@fortawesome/react-fontawesome": "^0.2.2",
|
||||
"@mantine/core": "^7.17.0",
|
||||
"@mantine/hooks": "^7.17.0",
|
||||
"react": "^18.3.1",
|
||||
"react-dom": "^18.3.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/react": "^18.3.3",
|
||||
"@types/react-dom": "^18.3.0",
|
||||
"@vitejs/plugin-react": "^4.3.1",
|
||||
"eslint": "^8.57.0",
|
||||
"eslint-plugin-react": "^7.34.2",
|
||||
"eslint-plugin-react-hooks": "^4.6.2",
|
||||
"eslint-plugin-react-refresh": "^0.4.7",
|
||||
"vite": "^5.3.1"
|
||||
}
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" class="iconify iconify--logos" width="31.88" height="32" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 257"><defs><linearGradient id="IconifyId1813088fe1fbc01fb466" x1="-.828%" x2="57.636%" y1="7.652%" y2="78.411%"><stop offset="0%" stop-color="#41D1FF"></stop><stop offset="100%" stop-color="#BD34FE"></stop></linearGradient><linearGradient id="IconifyId1813088fe1fbc01fb467" x1="43.376%" x2="50.316%" y1="2.242%" y2="89.03%"><stop offset="0%" stop-color="#FFEA83"></stop><stop offset="8.333%" stop-color="#FFDD35"></stop><stop offset="100%" stop-color="#FFA800"></stop></linearGradient></defs><path fill="url(#IconifyId1813088fe1fbc01fb466)" d="M255.153 37.938L134.897 252.976c-2.483 4.44-8.862 4.466-11.382.048L.875 37.958c-2.746-4.814 1.371-10.646 6.827-9.67l120.385 21.517a6.537 6.537 0 0 0 2.322-.004l117.867-21.483c5.438-.991 9.574 4.796 6.877 9.62Z"></path><path fill="url(#IconifyId1813088fe1fbc01fb467)" d="M185.432.063L96.44 17.501a3.268 3.268 0 0 0-2.634 3.014l-5.474 92.456a3.268 3.268 0 0 0 3.997 3.378l24.777-5.718c2.318-.535 4.413 1.507 3.936 3.838l-7.361 36.047c-.495 2.426 1.782 4.5 4.151 3.78l15.304-4.649c2.372-.72 4.652 1.36 4.15 3.788l-11.698 56.621c-.732 3.542 3.979 5.473 5.943 2.437l1.313-2.028l72.516-144.72c1.215-2.423-.88-5.186-3.54-4.672l-25.505 4.922c-2.396.462-4.435-1.77-3.759-4.114l16.646-57.705c.677-2.35-1.37-4.583-3.769-4.113Z"></path></svg>
|
After Width: | Height: | Size: 1.5 KiB |
82
resources/[carscripts]/community_bridge/web/src/dialogue.css
Normal file
82
resources/[carscripts]/community_bridge/web/src/dialogue.css
Normal file
|
@ -0,0 +1,82 @@
|
|||
.container {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
width: 100%;
|
||||
min-height: 100vh;
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
.dialogue-container {
|
||||
position: fixed;
|
||||
bottom: 30px;
|
||||
width: 50%;
|
||||
background: transparent;
|
||||
padding: 25px;
|
||||
left: 50%;
|
||||
transform: translateX(-50%);
|
||||
}
|
||||
|
||||
.dialogue-text {
|
||||
background: rgba(0, 0, 0, 0.85);
|
||||
padding: 20px;
|
||||
border-radius: 4px;
|
||||
margin: 15px 0;
|
||||
line-height: 1.6;
|
||||
font-size: 1.1em;
|
||||
border: 1px solid rgba(255, 255, 255, 0.15);
|
||||
box-shadow: 0 4px 16px rgba(0, 0, 0, 0.3);
|
||||
}
|
||||
|
||||
.dialogue-options {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
flex-wrap: wrap;
|
||||
gap: 12px;
|
||||
justify-content: space-between;
|
||||
margin-top: 20px;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.dialogue-button {
|
||||
background: rgba(0, 0, 0, 0.85);
|
||||
border: 1px solid rgba(255, 255, 255, 0.15);
|
||||
color: white;
|
||||
padding: 12px 24px;
|
||||
border-radius: 4px;
|
||||
cursor: pointer;
|
||||
transition: all 0.2s ease;
|
||||
font-size: 0.95em;
|
||||
flex: 1;
|
||||
text-align: center;
|
||||
min-width: calc(33.333% - 8px);
|
||||
box-shadow: 0 4px 16px rgba(0, 0, 0, 0.2);
|
||||
}
|
||||
|
||||
.dialogue-button:hover {
|
||||
background: rgba(51, 51, 51, 0.55);
|
||||
transform: translateY(-1px);
|
||||
box-shadow: 0 6px 20px rgba(0, 0, 0, 0.3);
|
||||
border: 1px solid rgba(255, 255, 255, 0.3);
|
||||
}
|
||||
|
||||
h2 {
|
||||
color: #ffffff;
|
||||
margin: 0;
|
||||
font-size: 1.4em;
|
||||
font-weight: 600;
|
||||
text-shadow: 0 2px 4px rgba(0, 0, 0, 0.3);
|
||||
}
|
||||
|
||||
p {
|
||||
color: #fff;
|
||||
margin: 0;
|
||||
text-shadow: 0 1px 2px rgba(0, 0, 0, 0.2);
|
||||
}
|
||||
|
||||
/* Add this for better text rendering */
|
||||
* {
|
||||
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, sans-serif;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
}
|
54
resources/[carscripts]/community_bridge/web/src/dialogue.jsx
Normal file
54
resources/[carscripts]/community_bridge/web/src/dialogue.jsx
Normal file
|
@ -0,0 +1,54 @@
|
|||
import { useState } from 'react'
|
||||
import { fetchNui } from './fetch'
|
||||
import './dialogue.css'
|
||||
|
||||
function Dialogue() {
|
||||
const [count, setCount] = useState(0)
|
||||
const [dialogueOptions, setDialogueOption] = useState([])
|
||||
const [currentText, setCurrentText] = useState("Welcome traveler! How can I help you today?")
|
||||
const [speakerName, setSpeakerName] = useState("Friendly NPC")
|
||||
|
||||
const handleMessage = (event) => {
|
||||
var data = event.data;
|
||||
|
||||
if (data !== undefined && data.type === "close") {
|
||||
document.getElementById('root').classList.add("hidden");
|
||||
}
|
||||
if (data !== undefined && data.type === "open") {
|
||||
setDialogueOption(data.options);
|
||||
setCurrentText(data.text);
|
||||
setSpeakerName(data.name);
|
||||
document.getElementById('root').classList.remove("hidden");
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
window.addEventListener("message", handleMessage);
|
||||
|
||||
return (
|
||||
<>
|
||||
<div className="container">
|
||||
{/* Dialogue System */}
|
||||
<div className="dialogue-container">
|
||||
<h2>{speakerName}</h2>
|
||||
<div className="dialogue-text">
|
||||
<p>{currentText}</p>
|
||||
</div>
|
||||
<div className="dialogue-options">
|
||||
{dialogueOptions.map((option) => (
|
||||
<button
|
||||
key={option.id}
|
||||
onClick={() => fetchNui("dialogue:SelectOption", { name: speakerName, id: option.id })}
|
||||
className="dialogue-button"
|
||||
>
|
||||
{option.label}
|
||||
</button>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
export default Dialogue
|
26
resources/[carscripts]/community_bridge/web/src/fetch.jsx
Normal file
26
resources/[carscripts]/community_bridge/web/src/fetch.jsx
Normal file
|
@ -0,0 +1,26 @@
|
|||
export const fetchNui = async (cbName, data = {}) => {
|
||||
const options = {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json; charset=UTF-8',
|
||||
},
|
||||
body: JSON.stringify(data)
|
||||
};
|
||||
|
||||
try {
|
||||
const resourceName = window.GetParentResourceName?.() || '';
|
||||
const resp = await fetch(`https://${resourceName}/${cbName}`, options);
|
||||
|
||||
if (!resp.ok) {
|
||||
throw new Error(`HTTP error! status: ${resp.status}`);
|
||||
}
|
||||
|
||||
return await resp.json();
|
||||
} catch (error) {
|
||||
console.error(`Fetch error for ${cbName}:`, error);
|
||||
if (!window.GetParentResourceName?.()) {
|
||||
console.error('Resource name is null - are you testing in browser?');
|
||||
}
|
||||
return null;
|
||||
}
|
||||
};
|
|
@ -0,0 +1,9 @@
|
|||
.hidden {
|
||||
display: none;
|
||||
|
||||
}
|
||||
|
||||
* {
|
||||
overflow-y: hidden;
|
||||
overflow-x: hidden;
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
import React from 'react';
|
||||
import ReactDOM from 'react-dom/client';
|
||||
import Dialogue from './dialogue';
|
||||
|
||||
ReactDOM.createRoot(document.getElementById('root')).render(
|
||||
<React.StrictMode>
|
||||
<Dialogue />
|
||||
</React.StrictMode>
|
||||
);
|
14
resources/[carscripts]/community_bridge/web/src/main.jsx
Normal file
14
resources/[carscripts]/community_bridge/web/src/main.jsx
Normal file
|
@ -0,0 +1,14 @@
|
|||
import React from 'react'
|
||||
import ReactDOM from 'react-dom/client'
|
||||
import Dialogue from './dialogue.jsx'
|
||||
import './index.css'
|
||||
|
||||
const root = document.getElementById('root')
|
||||
ReactDOM.createRoot(root).render(
|
||||
<React.StrictMode>
|
||||
<Dialogue />
|
||||
</React.StrictMode>,
|
||||
)
|
||||
|
||||
// add hidden to root element
|
||||
root.classList.add('hidden')
|
0
resources/[carscripts]/community_bridge/web/src/nui
Normal file
0
resources/[carscripts]/community_bridge/web/src/nui
Normal file
3
resources/[carscripts]/community_bridge/web/src/test.css
Normal file
3
resources/[carscripts]/community_bridge/web/src/test.css
Normal file
|
@ -0,0 +1,3 @@
|
|||
.hidden {
|
||||
display: none;
|
||||
}
|
32
resources/[carscripts]/community_bridge/web/src/test.jsx
Normal file
32
resources/[carscripts]/community_bridge/web/src/test.jsx
Normal file
|
@ -0,0 +1,32 @@
|
|||
import { useState } from 'react'
|
||||
import './test.css'
|
||||
|
||||
function Dialogue() {
|
||||
const [count, setCount] = useState(0)
|
||||
|
||||
const handleMessage = (event) => {
|
||||
var data = event.data;
|
||||
|
||||
if (data !== undefined && data.type === "hide") {
|
||||
document.getElementById('root').classList.add("hidden");
|
||||
}
|
||||
if (data !== undefined && data.type === "open") {
|
||||
document.getElementById('root').classList.remove("hidden");
|
||||
}
|
||||
};
|
||||
|
||||
window.addEventListener("message", handleMessage);
|
||||
|
||||
return (
|
||||
<>
|
||||
<div className="container">
|
||||
<img src= "https://dunb17ur4ymx4.cloudfront.net/wysiwyg/1364588/7b504ad7f496249800123e36ecfb3905677e337d.png"></img>
|
||||
<br></br>
|
||||
<button onClick={() => setCount(count + 1)}>Click me</button>
|
||||
<p>You clicked {count} times</p>
|
||||
</div>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
export default Dialogue
|
|
@ -0,0 +1,7 @@
|
|||
import { defineConfig } from 'vite'
|
||||
import react from '@vitejs/plugin-react'
|
||||
|
||||
// https://vitejs.dev/config/
|
||||
export default defineConfig({
|
||||
plugins: [react()],
|
||||
})
|
Loading…
Add table
Add a link
Reference in a new issue