forked from Simnation/Main
edit
This commit is contained in:
parent
be02d05ba8
commit
fc7ea910e9
35 changed files with 11992 additions and 1 deletions
1
resources/[tools]/mt_lib/web/.gitignore
vendored
Normal file
1
resources/[tools]/mt_lib/web/.gitignore
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
/node_modules
|
849
resources/[tools]/mt_lib/web/build/assets/index-C92XYwCx.js
Normal file
849
resources/[tools]/mt_lib/web/build/assets/index-C92XYwCx.js
Normal file
File diff suppressed because one or more lines are too long
849
resources/[tools]/mt_lib/web/build/assets/index-DMZM_8V6.js
Normal file
849
resources/[tools]/mt_lib/web/build/assets/index-DMZM_8V6.js
Normal file
File diff suppressed because one or more lines are too long
13
resources/[tools]/mt_lib/web/build/index.html
Normal file
13
resources/[tools]/mt_lib/web/build/index.html
Normal file
|
@ -0,0 +1,13 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<link rel="icon" type="image/svg+xml" href="/src/favicon.svg" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>NUI React Boilerplate</title>
|
||||
<script type="module" crossorigin src="./assets/index-DMZM_8V6.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<div id="root"></div>
|
||||
</body>
|
||||
</html>
|
13
resources/[tools]/mt_lib/web/index.html
Normal file
13
resources/[tools]/mt_lib/web/index.html
Normal file
|
@ -0,0 +1,13 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<link rel="icon" type="image/svg+xml" href="/src/favicon.svg" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>NUI React Boilerplate</title>
|
||||
</head>
|
||||
<body>
|
||||
<div id="root"></div>
|
||||
<script type="module" src="/src/main.tsx"></script>
|
||||
</body>
|
||||
</html>
|
4533
resources/[tools]/mt_lib/web/package-lock.json
generated
Normal file
4533
resources/[tools]/mt_lib/web/package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load diff
50
resources/[tools]/mt_lib/web/package.json
Normal file
50
resources/[tools]/mt_lib/web/package.json
Normal file
|
@ -0,0 +1,50 @@
|
|||
{
|
||||
"name": "web",
|
||||
"homepage": "web/build",
|
||||
"private": true,
|
||||
"type": "module",
|
||||
"version": "0.1.0",
|
||||
"scripts": {
|
||||
"start": "vite",
|
||||
"start:game": "vite build --watch",
|
||||
"build": "tsc && vite build",
|
||||
"preview": "vite preview"
|
||||
},
|
||||
"dependencies": {
|
||||
"@emotion/react": "^11.11.4",
|
||||
"@fortawesome/fontawesome-svg-core": "^6.5.2",
|
||||
"@fortawesome/free-solid-svg-icons": "^6.5.2",
|
||||
"@fortawesome/react-fontawesome": "^0.2.2",
|
||||
"@mantine/core": "^6.0.21",
|
||||
"@mantine/dates": "^6.0.21",
|
||||
"@mantine/form": "^7.10.1",
|
||||
"@mantine/hooks": "^6.0.21",
|
||||
"@mantine/modals": "^6.0.21",
|
||||
"@mantine/styles": "^6.0.21",
|
||||
"@tabler/icons-react": "^2.47.0",
|
||||
"html2canvas": "^1.4.1",
|
||||
"react": "^18.3.1",
|
||||
"react-dom": "^18.3.1",
|
||||
"react-icons": "^5.2.1",
|
||||
"react-markdown": "^9.0.1",
|
||||
"remark-gfm": "^4.0.0",
|
||||
"sass": "^1.77.4",
|
||||
"styled-components": "^6.1.11"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/node": "^20.14.2",
|
||||
"@types/react": "^18.3.3",
|
||||
"@types/react-dom": "^18.3.0",
|
||||
"@typescript-eslint/eslint-plugin": "^6.21.0",
|
||||
"@typescript-eslint/parser": "^6.21.0",
|
||||
"@vitejs/plugin-react": "^4.3.0",
|
||||
"eslint": "^8.57.0",
|
||||
"eslint-plugin-react-hooks": "^4.6.2",
|
||||
"eslint-plugin-react-refresh": "^0.4.7",
|
||||
"postcss": "^8.4.38",
|
||||
"postcss-preset-mantine": "^1.15.0",
|
||||
"postcss-simple-vars": "^7.0.1",
|
||||
"typescript": "^5.4.5",
|
||||
"vite": "^5.2.13"
|
||||
}
|
||||
}
|
4165
resources/[tools]/mt_lib/web/pnpm-lock.yaml
generated
Normal file
4165
resources/[tools]/mt_lib/web/pnpm-lock.yaml
generated
Normal file
File diff suppressed because it is too large
Load diff
73
resources/[tools]/mt_lib/web/src/components/Dialogue.tsx
Normal file
73
resources/[tools]/mt_lib/web/src/components/Dialogue.tsx
Normal file
|
@ -0,0 +1,73 @@
|
|||
import React, { useState, useRef } from "react"
|
||||
import { DEFAULT_THEME, Paper, Text, Divider, Stack, Button } from '@mantine/core'
|
||||
import { fetchNui } from "../utils/fetchNui"
|
||||
import { useNuiEvent } from "../hooks/useNuiEvent"
|
||||
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
|
||||
import * as Icons from '@fortawesome/free-solid-svg-icons'
|
||||
import { IconProp } from '@fortawesome/fontawesome-svg-core'
|
||||
|
||||
const Dialogue: React.FC = () => {
|
||||
const theme = DEFAULT_THEME
|
||||
const [options, setOptions] = useState([])
|
||||
const [label, setLabel] = useState('')
|
||||
const [speech, setSpeech] = useState('')
|
||||
|
||||
useNuiEvent<any>('dialogue', (data) => {
|
||||
setOptions(data.options)
|
||||
setLabel(data.label)
|
||||
setSpeech(data.speech)
|
||||
})
|
||||
|
||||
const getIconByName = (iconName: string) => {
|
||||
const formattedName = `fa${iconName.charAt(0).toUpperCase() + iconName.slice(1).replace(/-./g, (m) => m[1].toUpperCase())}`
|
||||
return Icons[formattedName as keyof typeof Icons] || Icons.faQuestionCircle
|
||||
}
|
||||
|
||||
return (
|
||||
<div
|
||||
style={{
|
||||
width: '100%',
|
||||
height: '100%',
|
||||
margin: -8,
|
||||
position: 'fixed',
|
||||
display: 'flex',
|
||||
justifyContent: 'center',
|
||||
alignItems: 'flex-end',
|
||||
background: `linear-gradient(180deg, rgba(255, 255, 255, 0) 75%, rgba(0, 0, 0, 0.80) 100%)`
|
||||
}}
|
||||
>
|
||||
<Stack miw={500} maw={1000} m={50} spacing={5}>
|
||||
<Text size="xl" fw={700} color="white">{label}</Text>
|
||||
<Paper withBorder p={5} pl={10}>
|
||||
<Text color="white" size="lg" fw={500}>{speech}</Text>
|
||||
</Paper>
|
||||
<Divider />
|
||||
<div
|
||||
style={{
|
||||
display: 'flex',
|
||||
flexDirection: 'row',
|
||||
justifyContent: 'center',
|
||||
flexWrap: 'wrap',
|
||||
gap: 10
|
||||
}}
|
||||
>
|
||||
{options.length > 0 && options.map(({ label, icon, id, close, canInteract }) => (
|
||||
canInteract && <Button
|
||||
color="gray"
|
||||
bg={theme.colors.dark[7]}
|
||||
leftIcon={<FontAwesomeIcon icon={getIconByName(icon) as IconProp} />}
|
||||
style={{
|
||||
border: `1px solid ${theme.colors.dark[4]}`
|
||||
}}
|
||||
onClick={() => fetchNui('executeAction', { id, options, close })}
|
||||
>
|
||||
{label}
|
||||
</Button>
|
||||
))}
|
||||
</div>
|
||||
</Stack>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default Dialogue
|
|
@ -0,0 +1,62 @@
|
|||
import React, { useState } from "react"
|
||||
import { DEFAULT_THEME, Paper, Text, Divider, TypographyStylesProvider } from '@mantine/core'
|
||||
import { useNuiEvent } from "../hooks/useNuiEvent"
|
||||
|
||||
const MissionStatus: React.FC = () => {
|
||||
const theme = DEFAULT_THEME
|
||||
const [title, setTitle] = useState('')
|
||||
const [text, setText] = useState('')
|
||||
|
||||
useNuiEvent<any>('missionStatus', (data) => {
|
||||
setTitle(data.title)
|
||||
setText(data.text)
|
||||
})
|
||||
|
||||
return (
|
||||
<div
|
||||
style={{
|
||||
width: '100%',
|
||||
height: '100%',
|
||||
margin: -8,
|
||||
position: 'fixed',
|
||||
display: 'flex',
|
||||
alignItems: 'center'
|
||||
}}
|
||||
>
|
||||
<div
|
||||
style={{
|
||||
maxWidth: 400,
|
||||
position: 'absolute',
|
||||
left: 20,
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
justifyContent: 'center',
|
||||
textAlign: 'center',
|
||||
gap: 5
|
||||
}}
|
||||
>
|
||||
<Text size="xl" color="white" fw={700}>{title}</Text>
|
||||
<Divider
|
||||
color="dark.0"
|
||||
size="lg"
|
||||
style={{
|
||||
borderRadius: theme.radius.md
|
||||
}}
|
||||
/>
|
||||
<Paper p={10} withBorder radius="sm">
|
||||
<TypographyStylesProvider
|
||||
style={{
|
||||
textAlign: 'left'
|
||||
}}
|
||||
>
|
||||
<div
|
||||
dangerouslySetInnerHTML={{ __html: text }}
|
||||
/>
|
||||
</TypographyStylesProvider>
|
||||
</Paper>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default MissionStatus
|
64
resources/[tools]/mt_lib/web/src/components/TextUI.tsx
Normal file
64
resources/[tools]/mt_lib/web/src/components/TextUI.tsx
Normal file
|
@ -0,0 +1,64 @@
|
|||
import React, { useState } from "react"
|
||||
import { DEFAULT_THEME, Paper, Text, Kbd } from '@mantine/core'
|
||||
import { useNuiEvent } from "../hooks/useNuiEvent"
|
||||
|
||||
const TextUI: React.FC = () => {
|
||||
const theme = DEFAULT_THEME
|
||||
const [key, setKey] = useState('')
|
||||
const [label, setLabel] = useState('')
|
||||
const [position, setPosition] = useState('')
|
||||
|
||||
useNuiEvent<any>('textUI', (data) => {
|
||||
setKey(data.key)
|
||||
setLabel(data.label)
|
||||
setPosition(data.position)
|
||||
})
|
||||
|
||||
return (
|
||||
<div
|
||||
style={{
|
||||
width: '100%',
|
||||
height: '100%',
|
||||
margin: -8,
|
||||
position: 'fixed',
|
||||
display: 'flex',
|
||||
justifyContent: ((position == 'bottom' || position == 'top') ? 'center' : ''),
|
||||
alignItems: ((position == 'right' || position == 'left') ? 'center' : '')
|
||||
}}
|
||||
>
|
||||
<div
|
||||
style={{
|
||||
maxWidth: 400,
|
||||
position: 'absolute',
|
||||
bottom: (position == 'bottom' ? 20 : 'auto'),
|
||||
top: (position == 'top' ? 20 : 'auto'),
|
||||
right: (position == 'right' ? 20 : 'auto'),
|
||||
left: (position == 'left' ? 20 : 'auto'),
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
justifyContent: 'center',
|
||||
textAlign: 'center',
|
||||
gap: 5
|
||||
}}
|
||||
>
|
||||
<Paper
|
||||
withBorder
|
||||
radius="sm"
|
||||
p={5}
|
||||
style={{
|
||||
display: 'flex',
|
||||
flexDirection: 'row',
|
||||
justifyContent: 'flex-start',
|
||||
alignItems: 'flex-start',
|
||||
gap: 5
|
||||
}}
|
||||
>
|
||||
<Kbd>{key}</Kbd>
|
||||
<Text fw={700}>{label}</Text>
|
||||
</Paper>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default TextUI
|
74
resources/[tools]/mt_lib/web/src/components/Timer.tsx
Normal file
74
resources/[tools]/mt_lib/web/src/components/Timer.tsx
Normal file
|
@ -0,0 +1,74 @@
|
|||
import React, { useState, useEffect } from "react"
|
||||
import { DEFAULT_THEME, Paper, Text, Progress } from '@mantine/core'
|
||||
import { fetchNui } from "../utils/fetchNui"
|
||||
import { useNuiEvent } from "../hooks/useNuiEvent"
|
||||
|
||||
const Timer: React.FC = () => {
|
||||
const theme = DEFAULT_THEME
|
||||
const [time, setTime] = useState(0)
|
||||
const [maxTime, setMaxTime] = useState(60)
|
||||
const [position, setPosition] = useState('')
|
||||
const [label, setLabel] = useState('')
|
||||
|
||||
useNuiEvent<any>('timer', (data) => {
|
||||
setLabel(data.label)
|
||||
setTime(data.time)
|
||||
setMaxTime(data.time)
|
||||
setPosition(data.position)
|
||||
})
|
||||
|
||||
useEffect(() => {
|
||||
if (time > 0) {
|
||||
const timerInterval = setInterval(() => {
|
||||
setTime((prevTime) => {
|
||||
if (prevTime <= 1) {
|
||||
clearInterval(timerInterval)
|
||||
fetchNui('finishTimer')
|
||||
return 0
|
||||
}
|
||||
return prevTime - 1
|
||||
})
|
||||
}, 1000)
|
||||
|
||||
return () => clearInterval(timerInterval)
|
||||
}
|
||||
}, [time])
|
||||
|
||||
return (
|
||||
<div
|
||||
style={{
|
||||
width: '100%',
|
||||
height: '100%',
|
||||
margin: -8,
|
||||
position: 'fixed',
|
||||
display: 'flex',
|
||||
justifyContent: ((position == 'bottom' || position == 'top') ? 'center' : ''),
|
||||
alignItems: ((position == 'right' || position == 'left') ? 'center' : '')
|
||||
}}
|
||||
>
|
||||
<Paper
|
||||
withBorder
|
||||
radius="sm"
|
||||
p={10}
|
||||
style={{
|
||||
maxWidth: 400,
|
||||
position: 'absolute',
|
||||
bottom: (position == 'bottom' ? 20 : 'auto'),
|
||||
top: (position == 'top' ? 20 : 'auto'),
|
||||
right: (position == 'right' ? 20 : 'auto'),
|
||||
left: (position == 'left' ? 20 : 'auto'),
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
justifyContent: 'center',
|
||||
textAlign: 'center',
|
||||
gap: 5
|
||||
}}
|
||||
>
|
||||
<Text fw={700}>{label}: {time}s</Text>
|
||||
<Progress w="100%" value={(time / maxTime) * 100} />
|
||||
</Paper>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default Timer
|
35
resources/[tools]/mt_lib/web/src/hooks/useNuiEvent.ts
Normal file
35
resources/[tools]/mt_lib/web/src/hooks/useNuiEvent.ts
Normal file
|
@ -0,0 +1,35 @@
|
|||
import { MutableRefObject, useEffect, useRef } from "react";
|
||||
import { noop } from "../utils/misc";
|
||||
|
||||
interface NuiMessageData<T = unknown> {
|
||||
action: string;
|
||||
data: T;
|
||||
}
|
||||
|
||||
type NuiHandlerSignature<T> = (data: T) => void;
|
||||
|
||||
export const useNuiEvent = <T = unknown>(
|
||||
action: string,
|
||||
handler: (data: T) => void,
|
||||
) => {
|
||||
const savedHandler: MutableRefObject<NuiHandlerSignature<T>> = useRef(noop);
|
||||
|
||||
useEffect(() => {
|
||||
savedHandler.current = handler;
|
||||
}, [handler]);
|
||||
|
||||
useEffect(() => {
|
||||
const eventListener = (event: MessageEvent<NuiMessageData<T>>) => {
|
||||
const { action: eventAction, data } = event.data;
|
||||
|
||||
if (savedHandler.current) {
|
||||
if (eventAction === action) {
|
||||
savedHandler.current(data);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
window.addEventListener("message", eventListener);
|
||||
return () => window.removeEventListener("message", eventListener);
|
||||
}, [action]);
|
||||
};
|
31
resources/[tools]/mt_lib/web/src/main.tsx
Normal file
31
resources/[tools]/mt_lib/web/src/main.tsx
Normal file
|
@ -0,0 +1,31 @@
|
|||
import React from 'react'
|
||||
import ReactDOM from 'react-dom/client'
|
||||
import { VisibilityProvider } from './providers/VisibilityProvider'
|
||||
import { MantineProvider } from '@mantine/core'
|
||||
import { ModalsProvider } from '@mantine/modals'
|
||||
import { DatesProvider } from '@mantine/dates'
|
||||
import Dialogue from './components/Dialogue'
|
||||
import MissionStatus from './components/MissionStatus'
|
||||
import Timer from './components/Timer'
|
||||
import TextUI from './components/TextUI'
|
||||
|
||||
ReactDOM.createRoot(document.getElementById('root')!).render(
|
||||
<React.StrictMode>
|
||||
<MantineProvider theme={{ colorScheme:'dark' }}>
|
||||
<ModalsProvider>
|
||||
<VisibilityProvider componentName="Dialogue">
|
||||
<Dialogue />
|
||||
</VisibilityProvider>
|
||||
<VisibilityProvider componentName="MissionStatus">
|
||||
<MissionStatus />
|
||||
</VisibilityProvider>
|
||||
<VisibilityProvider componentName="Timer">
|
||||
<Timer />
|
||||
</VisibilityProvider>
|
||||
<VisibilityProvider componentName="TextUI">
|
||||
<TextUI />
|
||||
</VisibilityProvider>
|
||||
</ModalsProvider>
|
||||
</MantineProvider>
|
||||
</React.StrictMode>
|
||||
)
|
|
@ -0,0 +1,47 @@
|
|||
import React, { createContext, useContext, useEffect, useState } from "react";
|
||||
import { useNuiEvent } from "../hooks/useNuiEvent";
|
||||
import { fetchNui } from "../utils/fetchNui";
|
||||
import { isEnvBrowser } from "../utils/misc";
|
||||
|
||||
|
||||
const VisibilityCtx = createContext<VisibilityProviderValue | null>(null);
|
||||
|
||||
|
||||
interface VisibilityProviderValue {
|
||||
setVisible: (visible: boolean) => void;
|
||||
visible: boolean;
|
||||
}
|
||||
|
||||
export const VisibilityProvider: React.FC<{
|
||||
children: React.ReactNode;
|
||||
componentName: string;
|
||||
}> = ({ children, componentName }) => {
|
||||
const [visible, setVisible] = useState(false);
|
||||
|
||||
useNuiEvent<boolean>(`setVisible${componentName}`, setVisible);
|
||||
|
||||
useEffect(() => {
|
||||
const keyHandler = (e: KeyboardEvent) => {
|
||||
if (visible && componentName !== 'TextUI' && componentName !== 'Timer' && componentName !== 'MissionStatus' && e.code === "Escape") {
|
||||
if (!isEnvBrowser()) fetchNui("hideFrame", { name: `setVisible${componentName}` });
|
||||
else setVisible(false);
|
||||
}
|
||||
};
|
||||
window.addEventListener("keydown", keyHandler);
|
||||
|
||||
return () => window.removeEventListener("keydown", keyHandler);
|
||||
}, [visible, componentName]);
|
||||
|
||||
return (
|
||||
<VisibilityCtx.Provider value={{ visible, setVisible }}>
|
||||
<div style={{ visibility: visible ? "visible" : "hidden" }}>
|
||||
{children}
|
||||
</div>
|
||||
</VisibilityCtx.Provider>
|
||||
);
|
||||
};
|
||||
|
||||
export const useVisibility = () =>
|
||||
useContext<VisibilityProviderValue>(
|
||||
VisibilityCtx as React.Context<VisibilityProviderValue>
|
||||
);
|
30
resources/[tools]/mt_lib/web/src/utils/debugData.ts
Normal file
30
resources/[tools]/mt_lib/web/src/utils/debugData.ts
Normal file
|
@ -0,0 +1,30 @@
|
|||
import { isEnvBrowser } from "./misc";
|
||||
|
||||
interface DebugEvent<T = unknown> {
|
||||
action: string;
|
||||
data: T;
|
||||
}
|
||||
|
||||
/**
|
||||
* Emulates dispatching an event using SendNuiMessage in the lua scripts.
|
||||
* This is used when developing in browser
|
||||
*
|
||||
* @param events - The event you want to cover
|
||||
* @param timer - How long until it should trigger (ms)
|
||||
*/
|
||||
export const debugData = <P>(events: DebugEvent<P>[], timer = 1000): void => {
|
||||
if (import.meta.env.MODE === "development" && isEnvBrowser()) {
|
||||
for (const event of events) {
|
||||
setTimeout(() => {
|
||||
window.dispatchEvent(
|
||||
new MessageEvent("message", {
|
||||
data: {
|
||||
action: event.action,
|
||||
data: event.data,
|
||||
},
|
||||
}),
|
||||
);
|
||||
}, timer);
|
||||
}
|
||||
}
|
||||
};
|
26
resources/[tools]/mt_lib/web/src/utils/fetchNui.ts
Normal file
26
resources/[tools]/mt_lib/web/src/utils/fetchNui.ts
Normal file
|
@ -0,0 +1,26 @@
|
|||
import { isEnvBrowser } from "./misc"
|
||||
|
||||
export async function fetchNui<T = unknown>(
|
||||
eventName: string,
|
||||
data?: unknown,
|
||||
mockData?: T,
|
||||
): Promise<T> {
|
||||
const options = {
|
||||
method: "post",
|
||||
headers: {
|
||||
"Content-Type": "application/json; charset=UTF-8",
|
||||
},
|
||||
body: JSON.stringify(data),
|
||||
};
|
||||
|
||||
if (isEnvBrowser() && mockData) return mockData
|
||||
|
||||
const resourceName = (window as any).GetParentResourceName
|
||||
? (window as any).GetParentResourceName() : "nui-frame-app"
|
||||
|
||||
const resp = await fetch(`https://${resourceName}/${eventName}`, options)
|
||||
|
||||
const respFormatted = await resp.json()
|
||||
|
||||
return respFormatted
|
||||
}
|
3
resources/[tools]/mt_lib/web/src/utils/misc.ts
Normal file
3
resources/[tools]/mt_lib/web/src/utils/misc.ts
Normal file
|
@ -0,0 +1,3 @@
|
|||
export const isEnvBrowser = (): boolean => !(window as any).invokeNative
|
||||
|
||||
export const noop = () => {}
|
1
resources/[tools]/mt_lib/web/src/vite-env.d.ts
vendored
Normal file
1
resources/[tools]/mt_lib/web/src/vite-env.d.ts
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
/// <reference types="vite/client" />
|
22
resources/[tools]/mt_lib/web/tsconfig.json
Normal file
22
resources/[tools]/mt_lib/web/tsconfig.json
Normal file
|
@ -0,0 +1,22 @@
|
|||
{
|
||||
"compilerOptions": {
|
||||
"target": "ESNext",
|
||||
"useDefineForClassFields": true,
|
||||
"lib": ["DOM", "DOM.Iterable", "ESNext"],
|
||||
"allowJs": false,
|
||||
"skipLibCheck": true,
|
||||
"esModuleInterop": false,
|
||||
"allowSyntheticDefaultImports": true,
|
||||
"strict": true,
|
||||
"forceConsistentCasingInFileNames": true,
|
||||
"module": "ESNext",
|
||||
"moduleResolution": "Node",
|
||||
"resolveJsonModule": true,
|
||||
"isolatedModules": true,
|
||||
"noEmit": true,
|
||||
"jsx": "react-jsx",
|
||||
|
||||
},
|
||||
"include": ["src"],
|
||||
"references": [{ "path": "./tsconfig.node.json" }]
|
||||
}
|
8
resources/[tools]/mt_lib/web/tsconfig.node.json
Normal file
8
resources/[tools]/mt_lib/web/tsconfig.node.json
Normal file
|
@ -0,0 +1,8 @@
|
|||
{
|
||||
"compilerOptions": {
|
||||
"composite": true,
|
||||
"module": "esnext",
|
||||
"moduleResolution": "node"
|
||||
},
|
||||
"include": ["vite.config.ts"]
|
||||
}
|
11
resources/[tools]/mt_lib/web/vite.config.ts
Normal file
11
resources/[tools]/mt_lib/web/vite.config.ts
Normal file
|
@ -0,0 +1,11 @@
|
|||
import { defineConfig } from 'vite';
|
||||
import react from '@vitejs/plugin-react';
|
||||
|
||||
export default defineConfig({
|
||||
plugins: [react()],
|
||||
base: './',
|
||||
build: {
|
||||
outDir: 'build',
|
||||
chunkSizeWarningLimit: 1000
|
||||
},
|
||||
});
|
Loading…
Add table
Add a link
Reference in a new issue