dirk-cfx-react 1.1.1 → 1.1.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -2,67 +2,18 @@
2
2
 
3
3
  require('@mantine/core/styles.css');
4
4
  require('@mantine/notifications/styles.css');
5
- require('./styles/notify.css');
6
- require('./styles/fonts.css');
7
- require('./styles/scrollBar.css');
8
- require('./styles/tornEdge.css');
9
- var fontawesomeSvgCore = require('@fortawesome/fontawesome-svg-core');
10
- var freeBrandsSvgIcons = require('@fortawesome/free-brands-svg-icons');
11
- var freeRegularSvgIcons = require('@fortawesome/free-regular-svg-icons');
12
- var freeSolidSvgIcons = require('@fortawesome/free-solid-svg-icons');
13
5
  var core = require('@mantine/core');
14
- var react = require('react');
6
+ var React = require('react');
15
7
  var zustand = require('zustand');
16
8
  var jsxRuntime = require('react/jsx-runtime');
17
9
 
18
- // src/providers/DirkProvider.tsx
10
+ function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
19
11
 
20
- // src/utils/misc.ts
21
- var isEnvBrowser = () => !window.invokeNative;
12
+ var React__default = /*#__PURE__*/_interopDefault(React);
22
13
 
23
- // src/utils/fetchNui.ts
24
- async function fetchNui(eventName, data, mockData) {
25
- const options = {
26
- method: "post",
27
- headers: {
28
- "Content-Type": "application/json; charset=UTF-8"
29
- },
30
- body: JSON.stringify(data)
31
- };
32
- if (isEnvBrowser() && mockData) return mockData;
33
- if (isEnvBrowser() && mockData === void 0) {
34
- console.warn(
35
- `[fetchNui] Called fetchNui for event "${eventName}" in browser environment without mockData. Returning empty object.`
36
- );
37
- return {};
38
- }
39
- const resourceName = window.GetParentResourceName ? window.GetParentResourceName() : "nui-frame-app";
40
- const resp = await fetch(`https://${resourceName}/${eventName}`, options);
41
- return await resp.json();
42
- }
43
- var initialFetches = {};
44
- async function registerInitialFetch(eventName, data, mockData) {
45
- const fetcher = () => fetchNui(eventName, data, mockData);
46
- initialFetches[eventName] = fetcher;
47
- return fetcher();
48
- }
49
- async function runFetches() {
50
- return Promise.all(
51
- Object.entries(initialFetches).map(async ([eventName, fetcher]) => {
52
- const data = await fetcher();
53
- return { eventName, data };
54
- })
55
- );
56
- }
57
- var useAutoFetcher = () => {
58
- react.useEffect(() => {
59
- if (isEnvBrowser()) return;
60
- const run = async () => {
61
- await runFetches();
62
- };
63
- run();
64
- }, []);
65
- };
14
+ var __defProp = Object.defineProperty;
15
+ var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
16
+ var __publicField = (obj, key, value) => __defNormalProp(obj, key + "" , value);
66
17
  var label = {
67
18
  fontSize: "var(--mantine-font-size-xs)",
68
19
  fontFamily: "Akrobat Bold",
@@ -222,73 +173,126 @@ var theme = core.createTheme({
222
173
  }
223
174
  });
224
175
  var theme_default = theme;
225
- fontawesomeSvgCore.library.add(freeSolidSvgIcons.fas, freeRegularSvgIcons.far, freeBrandsSvgIcons.fab);
226
- var useSettings = zustand.create((set) => ({
176
+
177
+ // src/utils/misc.ts
178
+ var isEnvBrowser = () => !window.invokeNative;
179
+
180
+ // src/utils/fetchNui.ts
181
+ async function fetchNui(eventName, data, mockData) {
182
+ const options = {
183
+ method: "post",
184
+ headers: {
185
+ "Content-Type": "application/json; charset=UTF-8"
186
+ },
187
+ body: JSON.stringify(data)
188
+ };
189
+ if (isEnvBrowser() && mockData === void 0) {
190
+ console.warn(
191
+ `[fetchNui] Called fetchNui for event "${eventName}" in browser environment without mockData. Returning empty object.`
192
+ );
193
+ return {};
194
+ }
195
+ const resourceName = window.GetParentResourceName ? window.GetParentResourceName() : "nui-frame-app";
196
+ const resp = await fetch(`https://${resourceName}/${eventName}`, options);
197
+ return await resp.json();
198
+ }
199
+ async function registerInitialFetch(eventName, data, mockData) {
200
+ const fetcher = () => fetchNui(eventName, data, mockData);
201
+ return fetcher();
202
+ }
203
+
204
+ // src/utils/useSettings.ts
205
+ var useSettings = zustand.create(() => ({
206
+ hydrated: false,
227
207
  game: "fivem",
228
208
  primaryColor: "dirk",
229
209
  primaryShade: 9,
230
- itemImgPath: "https://assets.dirkcfx.com/items/",
210
+ itemImgPath: "",
231
211
  customTheme: {}
232
212
  }));
233
- registerInitialFetch("GET_SETTINGS", void 0, {
234
- game: "fivem",
235
- primaryColor: "dirk",
236
- primaryShade: 9,
237
- itemImgPath: "https://assets.dirkcfx.com/items/",
238
- customTheme: {}
239
- }).then((data) => {
213
+ registerInitialFetch("GET_SETTINGS").then((data) => {
240
214
  useSettings.setState({
241
- ...data
215
+ ...data,
216
+ hydrated: true
242
217
  });
218
+ }).catch(() => {
219
+ useSettings.setState({ hydrated: true });
243
220
  });
244
- function DirkProvider(props) {
245
- const primaryColor = useSettings((data) => data.primaryColor);
246
- const primaryShade = useSettings((data) => data.primaryShade);
247
- const customTheme = useSettings((data) => data.customTheme);
248
- const game = useSettings((data) => data.game);
249
- const mergedTheme = react.useMemo(() => ({
250
- ...theme_default,
221
+
222
+ // src/utils/mergeMantineTheme.ts
223
+ var isValidColorScale = (v) => Array.isArray(v) && v.length >= 5 && v.every((c) => typeof c === "string");
224
+ function mergeMantineThemeSafe(base, custom, override) {
225
+ const colors = { ...base.colors };
226
+ for (const [key, value] of Object.entries(custom ?? {})) {
227
+ if (isValidColorScale(value)) {
228
+ colors[key] = value;
229
+ } else {
230
+ console.warn(`[theme] invalid color ignored: ${key}`, value);
231
+ }
232
+ }
233
+ return {
234
+ ...base,
235
+ ...override,
236
+ colors: {
237
+ ...colors,
238
+ ...override?.colors ?? {}
239
+ }
240
+ };
241
+ }
242
+ var DirkErrorBoundary = class extends React__default.default.Component {
243
+ constructor() {
244
+ super(...arguments);
245
+ __publicField(this, "state", { error: null });
246
+ }
247
+ static getDerivedStateFromError(error2) {
248
+ return { error: error2 };
249
+ }
250
+ componentDidCatch(error2, info) {
251
+ console.group("\u{1F525} Dirk UI Crash");
252
+ console.error(error2);
253
+ console.error(info.componentStack);
254
+ console.groupEnd();
255
+ }
256
+ render() {
257
+ if (!this.state.error) return this.props.children;
258
+ return /* @__PURE__ */ jsxRuntime.jsxs(core.Box, { p: "md", bg: "dark.8", children: [
259
+ /* @__PURE__ */ jsxRuntime.jsx(core.Text, { c: "red", fw: 600, children: "UI crashed" }),
260
+ /* @__PURE__ */ jsxRuntime.jsx(core.Code, { block: true, mt: "sm", children: this.state.error.message })
261
+ ] });
262
+ }
263
+ };
264
+ function DirkProvider({ children, themeOverride }) {
265
+ const {
266
+ hydrated,
251
267
  primaryColor,
252
268
  primaryShade,
253
- colors: {
254
- ...theme_default.colors,
255
- ...customTheme,
256
- // Custom theme colors will override/extend base colors
257
- ...props.themeOverride?.colors
258
- // Props theme colors will override/extend previous colors
259
- },
260
- ...props.themeOverride
261
- // Props theme will override/extend the entire theme
262
- }), [primaryColor, primaryShade, customTheme, props.themeOverride]);
263
- console.log("created merged theme:");
264
- console.log(mergedTheme);
265
- react.useEffect(() => {
266
- document.fonts.ready.then(() => {
267
- document.body.style.fontFamily = game === "rdr3" ? '"Red Dead", sans-serif' : game === "fivem" ? '"Akrobat Regular", sans-serif' : "sans-serif";
268
- });
269
+ customTheme,
270
+ game
271
+ } = useSettings();
272
+ if (!hydrated) return null;
273
+ const mergedTheme = React.useMemo(
274
+ () => mergeMantineThemeSafe(
275
+ { ...theme_default, primaryColor, primaryShade },
276
+ customTheme,
277
+ themeOverride
278
+ ),
279
+ [primaryColor, primaryShade, customTheme, themeOverride]
280
+ );
281
+ React.useEffect(() => {
282
+ document.body.style.fontFamily = game === "rdr3" ? '"Red Dead", sans-serif' : '"Akrobat Regular", sans-serif';
269
283
  }, [game]);
270
- react.useEffect(() => {
271
- fetchNui("NUI_READY");
272
- }, []);
273
- useAutoFetcher();
274
- return /* @__PURE__ */ jsxRuntime.jsx(core.MantineProvider, { theme: mergedTheme, defaultColorScheme: "dark", children: /* @__PURE__ */ jsxRuntime.jsx(Wrapper, { children: props.children }) });
275
- }
276
- function Wrapper({ children }) {
277
- const game = useSettings((data) => data.game);
278
- if (!isEnvBrowser()) return /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children });
279
- return /* @__PURE__ */ jsxRuntime.jsx(
284
+ const content = isEnvBrowser() ? /* @__PURE__ */ jsxRuntime.jsx(
280
285
  core.BackgroundImage,
281
286
  {
282
287
  w: "100vw",
283
288
  h: "100vh",
284
- style: { overflow: "hidden", backgroundColor: "transparent" },
285
289
  src: game === "fivem" ? "https://i.ytimg.com/vi/TOxuNbXrO28/maxresdefault.jpg" : "https://raw.githubusercontent.com/Jump-On-Studios/RedM-jo_libs/refs/heads/main/source-repositories/Menu/public/assets/images/background_dev.jpg",
286
290
  children
287
291
  }
288
- );
292
+ ) : children;
293
+ return /* @__PURE__ */ jsxRuntime.jsx(DirkErrorBoundary, { children: /* @__PURE__ */ jsxRuntime.jsx(core.MantineProvider, { theme: mergedTheme, defaultColorScheme: "dark", children: content }) });
289
294
  }
290
295
 
291
296
  exports.DirkProvider = DirkProvider;
292
- exports.useSettings = useSettings;
293
297
  //# sourceMappingURL=index.cjs.map
294
298
  //# sourceMappingURL=index.cjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/utils/misc.ts","../../src/utils/fetchNui.ts","../../src/theme.ts","../../src/providers/DirkProvider.tsx"],"names":["useEffect","createTheme","theme","library","fas","far","fab","create","useMemo","jsx","MantineProvider","BackgroundImage"],"mappings":"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","file":"index.cjs","sourcesContent":["export const isEnvBrowser = (): boolean => !(window as any).invokeNative;\r\n\r\n// Basic no operation function\r\nexport const noop = () => {};\r\n\r\nexport const splitFAString = (faString:string) => {\r\n const [prefix, newIcon] = faString.split('-');\r\n if (!prefix || !newIcon) return {prefix: 'fas', newIcon: 'question'};\r\n return {prefix, newIcon};\r\n}\r\n\r\nexport const numberToRoman = (num:number) => {\r\n const romanNumerals = ['I', 'II', 'III', 'IV', 'V', 'VI', 'VII', 'VIII', 'IX', 'X', 'XI', 'XII', 'XIII', 'XIV', 'XV', 'XVI', 'XVII', 'XVIII', 'XIX', 'XX'] \r\n return romanNumerals[num]\r\n}\r\n\r\nexport const copyToClipboard = (text:string) => {\r\n const el = document.createElement('textarea');\r\n el.value = text;\r\n document.body.appendChild(el);\r\n el.select();\r\n document.execCommand('copy');\r\n document.body.removeChild(el);\r\n}\r\n\r\nexport const openLink = (url:string) => {\r\n if (isEnvBrowser()) {\r\n window.open(url, '_blank');\r\n } else {\r\n // @ts-expect-error -- invokeNative exists in NUI\r\n window.invokeNative('openLink', url);\r\n } \r\n}","import { useEffect } from \"react\";\r\nimport { isEnvBrowser } from \"./misc\";\r\n\r\n/**\r\n * Simple wrapper around fetch API tailored for CEF/NUI use.\r\n */\r\nexport async function fetchNui<T = unknown>(\r\n eventName: string,\r\n data?: unknown,\r\n mockData?: T,\r\n): Promise<T> {\r\n const options = {\r\n method: \"post\",\r\n headers: {\r\n \"Content-Type\": \"application/json; charset=UTF-8\",\r\n },\r\n body: JSON.stringify(data),\r\n };\r\n\r\n if (isEnvBrowser() && mockData) return mockData;\r\n if (isEnvBrowser() && mockData === undefined) {\r\n console.warn(\r\n `[fetchNui] Called fetchNui for event \"${eventName}\" in browser environment without mockData. Returning empty object.`,\r\n );\r\n return {} as T;\r\n }\r\n\r\n const resourceName = (window as any).GetParentResourceName\r\n ? (window as any).GetParentResourceName()\r\n : \"nui-frame-app\";\r\n\r\n const resp = await fetch(`https://${resourceName}/${eventName}`, options);\r\n return await resp.json();\r\n}\r\n\r\n// -----------------------------\r\n// Initial fetch registration\r\n// -----------------------------\r\nexport type InitialFetch<T> = () => Promise<T>;\r\nexport const initialFetches: Record<string, InitialFetch<unknown>> = {};\r\n\r\n/**\r\n * Registers an initial fetch that automatically uses fetchNui.\r\n * Works like:\r\n * ```ts\r\n * registerInitialFetch<{ name: string }>(\"MY_EVENT_NAME\", undefined, { name: \"Mocky\" });\r\n * ```\r\n * and returns a Promise resolving to the same type as fetchNui.\r\n */\r\nexport async function registerInitialFetch<T = unknown>(\r\n eventName: string,\r\n data?: unknown,\r\n mockData?: T,\r\n): Promise<T> {\r\n const fetcher = () => fetchNui<T>(eventName, data, mockData);\r\n initialFetches[eventName] = fetcher;\r\n return fetcher(); // run immediately if needed\r\n}\r\n\r\n/**\r\n * Runs all registered initial fetches in parallel.\r\n */\r\nexport async function runFetches() {\r\n return Promise.all(\r\n Object.entries(initialFetches).map(async ([eventName, fetcher]) => {\r\n const data = await fetcher();\r\n return { eventName, data };\r\n }),\r\n );\r\n}\r\n\r\n/**\r\n * React hook to automatically run all registered fetches on mount.\r\n */\r\nexport const useAutoFetcher = () => {\r\n useEffect(() => {\r\n if (isEnvBrowser()) return;\r\n const run = async () => {\r\n const results = await runFetches();\r\n };\r\n run();\r\n }, []);\r\n};\r\n","import { createTheme, MantineTheme, NumberInput } from \"@mantine/core\";\r\n\r\nexport const label = {\r\n fontSize: 'var(--mantine-font-size-xs)',\r\n fontFamily: 'Akrobat Bold',\r\n letterSpacing: '0.05em',\r\n textTransform: 'uppercase', \r\n};\r\nexport const error = {\r\n fontSize: 'var(--mantine-font-size-xs)',\r\n fontFamily: 'Akrobat Regular',\r\n};\r\n\r\nconst theme = createTheme({\r\n primaryColor: \"dirk\",\r\n primaryShade: 9,\r\n defaultRadius: \"xs\",\r\n fontFamily: \"Akrobat Regular, sans-serif\",\r\n\r\n radius:{\r\n xxs: '0.3vh',\r\n xs: '0.5vh',\r\n sm: '0.75vh',\r\n md: '1vh',\r\n lg: '1.5vh',\r\n xl: '2vh',\r\n xxl: '3vh',\r\n },\r\n\r\n fontSizes: {\r\n xxs: '1.2vh',\r\n xs: '1.5vh',\r\n sm: '1.8vh',\r\n md: '2.2vh',\r\n lg: '2.8vh',\r\n xl: '3.3vh',\r\n xxl: '3.8vh',\r\n },\r\n\r\n lineHeights: {\r\n xxs: '1.4vh',\r\n xs: '1.8vh',\r\n sm: '2.2vh',\r\n md: '2.8vh',\r\n lg: '3.3vh',\r\n xl: '3.8vh',\r\n },\r\n\r\n spacing:{\r\n xxs: '0.5vh',\r\n xs: '0.75vh',\r\n sm: '1.5vh',\r\n md: '2vh',\r\n lg: '3vh',\r\n xl: '4vh',\r\n xxl: '5vh',\r\n },\r\n\r\n components:{\r\n Progress:{\r\n styles:{\r\n label: {\r\n fontFamily: 'Akrobat Bold',\r\n letterSpacing: '0.05em',\r\n textTransform: 'uppercase', \r\n \r\n },\r\n root:{\r\n backgroundColor: 'rgba(77, 77, 77, 0.4)',\r\n },\r\n \r\n }\r\n },\r\n Textarea: {\r\n styles:{\r\n label: label,\r\n error: error,\r\n },\r\n },\r\n\r\n Button:{\r\n styles:{\r\n root:{\r\n fontSize: 'var(--mantine-font-size-xs)',\r\n },\r\n },\r\n },\r\n\r\n Select:{\r\n styles:{\r\n label: label,\r\n input:{\r\n padding: 'var(--mantine-spacing-sm)',\r\n },\r\n }\r\n },\r\n\r\n Pill: {\r\n styles: (theme: MantineTheme) => ({\r\n root: {\r\n display: 'inline-flex',\r\n alignItems: 'center',\r\n justifyContent: 'space-between',\r\n backgroundColor: 'rgba(76, 76, 76, 0.3)',\r\n height: 'fit-content',\r\n textTransform: 'uppercase',\r\n letterSpacing: '0.05em',\r\n fontFamily: 'Akrobat Bold',\r\n fontSize: theme.fontSizes.xs,\r\n borderRadius: theme.defaultRadius,\r\n padding: `${theme.spacing.xs} ${theme.spacing.sm}`,\r\n }\r\n })\r\n },\r\n\r\n Input:{\r\n styles: {\r\n label: label,\r\n error: error,\r\n\r\n input:{\r\n padding: 'var(--mantine-spacing-sm)',\r\n backgroundColor: 'rgba(76, 76, 76, 0.3)', \r\n },\r\n },\r\n },\r\n ColorInput:{\r\n styles: {\r\n label: label,\r\n input:{\r\n padding: 'var(--mantine-spacing-sm)',\r\n },\r\n },\r\n },\r\n TextInput:{\r\n styles:{\r\n label: label,\r\n wrapper:{\r\n \r\n },\r\n section:{\r\n marginRight: '0.2vh',\r\n },\r\n\r\n input:{\r\n padding: 'var(--mantine-spacing-sm)',\r\n \r\n \r\n },\r\n }\r\n },\r\n NumberInput:{\r\n \r\n styles:{\r\n label: label,\r\n input:{\r\n padding: 'var(--mantine-spacing-sm)',\r\n },\r\n section:{\r\n pointerEvents: 'all',\r\n },\r\n }\r\n }\r\n },\r\n\r\n colors: {\r\n\r\n dirk:[\r\n \"#ffffff\",\r\n \"#f3fce9\",\r\n \"#dbf5bd\",\r\n \"#c3ee91\",\r\n \"#ace765\",\r\n \"#94e039\",\r\n \"#7ac61f\",\r\n \"#5f9a18\",\r\n \"#29420a\",\r\n \"#446e11\",\r\n ],\r\n },\r\n});\r\n\r\n\r\nexport default theme;","import '@mantine/core/styles.css';\r\nimport '@mantine/notifications/styles.css';\r\nimport './styles/notify.css';\r\nimport './styles/fonts.css';\r\nimport './styles/scrollBar.css';\r\nimport './styles/tornEdge.css';\r\n\r\n\r\nimport { library } from \"@fortawesome/fontawesome-svg-core\";\r\nimport { fab } from \"@fortawesome/free-brands-svg-icons\";\r\nimport { far } from \"@fortawesome/free-regular-svg-icons\";\r\nimport { fas } from \"@fortawesome/free-solid-svg-icons\";\r\nimport { BackgroundImage, MantineColorShade, MantineProvider, MantineThemeOverride } from '@mantine/core';\r\nimport { fetchNui, isEnvBrowser, registerInitialFetch, useAutoFetcher } from '@/utils';\r\nimport { create } from 'zustand';\r\nimport theme from '@/theme';\r\nimport { useEffect, useMemo } from 'react';\r\nlibrary.add(fas, far, fab);\r\n\r\nexport type DirkProviderProps = {\r\n fakeBackground?: boolean;\r\n children: React.ReactNode;\r\n themeOverride?: MantineThemeOverride;\r\n}\r\n\r\ntype SettingsProps = {\r\n game: 'rdr3' | 'fivem';\r\n primaryColor: string;\r\n primaryShade: number;\r\n itemImgPath: string;\r\n customTheme: Record<string, string[]>;\r\n}\r\n\r\nexport const useSettings = create<SettingsProps>((set) => ({\r\n game: 'fivem',\r\n primaryColor: 'dirk',\r\n primaryShade: 9,\r\n itemImgPath: 'https://assets.dirkcfx.com/items/',\r\n customTheme: {},\r\n}));\r\n\r\n\r\nregisterInitialFetch<Partial<SettingsProps>>(\"GET_SETTINGS\", undefined, {\r\n game: 'fivem',\r\n primaryColor: 'dirk',\r\n primaryShade: 9,\r\n itemImgPath: 'https://assets.dirkcfx.com/items/',\r\n customTheme: {},\r\n}).then((data) => {\r\n useSettings.setState({\r\n ...data,\r\n });\r\n});\r\n\r\nexport function DirkProvider(props: DirkProviderProps) {\r\n const primaryColor = useSettings((data) => data.primaryColor);\r\n const primaryShade = useSettings((data) => data.primaryShade);\r\n const customTheme = useSettings((data) => data.customTheme);\r\n const game = useSettings((data) => data.game);\r\n // Memoize the merged theme to avoid unnecessary recalculations\r\n const mergedTheme = useMemo<MantineThemeOverride>(() => ({\r\n ...theme,\r\n primaryColor: primaryColor,\r\n primaryShade: primaryShade as MantineColorShade,\r\n colors: {\r\n ...theme.colors,\r\n ...customTheme, // Custom theme colors will override/extend base colors\r\n ...props.themeOverride?.colors, // Props theme colors will override/extend previous colors\r\n },\r\n ...props.themeOverride, // Props theme will override/extend the entire theme\r\n }), [primaryColor, primaryShade, customTheme, props.themeOverride]);\r\n console.log('created merged theme:');\r\n console.log(mergedTheme)\r\n useEffect(() => {\r\n document.fonts.ready.then(() => {\r\n document.body.style.fontFamily = \r\n game === 'rdr3' ? '\"Red Dead\", sans-serif' :\r\n game === 'fivem' ? '\"Akrobat Regular\", sans-serif' :\r\n 'sans-serif';\r\n });\r\n }, [game]);\r\n\r\n useEffect(() => {\r\n fetchNui('NUI_READY')\r\n }, []);\r\n\r\n useAutoFetcher();\r\n \r\n \r\n return (\r\n <MantineProvider theme={mergedTheme} defaultColorScheme='dark'>\r\n <Wrapper>\r\n {props.children}\r\n </Wrapper>\r\n </MantineProvider>\r\n );\r\n}\r\n\r\nfunction Wrapper({ children }: { children: React.ReactNode }) {\r\n const game = useSettings((data) => data.game);\r\n if (!isEnvBrowser()) return <>{children}</>;\r\n return (\r\n <BackgroundImage\r\n w=\"100vw\"\r\n h=\"100vh\"\r\n style={{ overflow: 'hidden', backgroundColor: 'transparent' }}\r\n src={game === 'fivem'\r\n ? 'https://i.ytimg.com/vi/TOxuNbXrO28/maxresdefault.jpg'\r\n : 'https://raw.githubusercontent.com/Jump-On-Studios/RedM-jo_libs/refs/heads/main/source-repositories/Menu/public/assets/images/background_dev.jpg'}\r\n >\r\n {children}\r\n </BackgroundImage>\r\n );\r\n}\r\n\r\n"]}
1
+ {"version":3,"sources":["../../src/theme.ts","../../src/utils/misc.ts","../../src/utils/fetchNui.ts","../../src/utils/useSettings.ts","../../src/utils/mergeMantineTheme.ts","../../src/providers/DirkErrorBoundary.tsx","../../src/providers/DirkProvider.tsx"],"names":["createTheme","theme","create","React","error","jsxs","Box","jsx","Text","Code","useMemo","useEffect","BackgroundImage","MantineProvider"],"mappings":"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","file":"index.cjs","sourcesContent":["import { createTheme, MantineTheme, NumberInput } from \"@mantine/core\";\r\n\r\nexport const label = {\r\n fontSize: 'var(--mantine-font-size-xs)',\r\n fontFamily: 'Akrobat Bold',\r\n letterSpacing: '0.05em',\r\n textTransform: 'uppercase', \r\n};\r\nexport const error = {\r\n fontSize: 'var(--mantine-font-size-xs)',\r\n fontFamily: 'Akrobat Regular',\r\n};\r\n\r\nconst theme = createTheme({\r\n primaryColor: \"dirk\",\r\n primaryShade: 9,\r\n defaultRadius: \"xs\",\r\n fontFamily: \"Akrobat Regular, sans-serif\",\r\n\r\n radius:{\r\n xxs: '0.3vh',\r\n xs: '0.5vh',\r\n sm: '0.75vh',\r\n md: '1vh',\r\n lg: '1.5vh',\r\n xl: '2vh',\r\n xxl: '3vh',\r\n },\r\n\r\n fontSizes: {\r\n xxs: '1.2vh',\r\n xs: '1.5vh',\r\n sm: '1.8vh',\r\n md: '2.2vh',\r\n lg: '2.8vh',\r\n xl: '3.3vh',\r\n xxl: '3.8vh',\r\n },\r\n\r\n lineHeights: {\r\n xxs: '1.4vh',\r\n xs: '1.8vh',\r\n sm: '2.2vh',\r\n md: '2.8vh',\r\n lg: '3.3vh',\r\n xl: '3.8vh',\r\n },\r\n\r\n spacing:{\r\n xxs: '0.5vh',\r\n xs: '0.75vh',\r\n sm: '1.5vh',\r\n md: '2vh',\r\n lg: '3vh',\r\n xl: '4vh',\r\n xxl: '5vh',\r\n },\r\n\r\n components:{\r\n Progress:{\r\n styles:{\r\n label: {\r\n fontFamily: 'Akrobat Bold',\r\n letterSpacing: '0.05em',\r\n textTransform: 'uppercase', \r\n \r\n },\r\n root:{\r\n backgroundColor: 'rgba(77, 77, 77, 0.4)',\r\n },\r\n \r\n }\r\n },\r\n Textarea: {\r\n styles:{\r\n label: label,\r\n error: error,\r\n },\r\n },\r\n\r\n Button:{\r\n styles:{\r\n root:{\r\n fontSize: 'var(--mantine-font-size-xs)',\r\n },\r\n },\r\n },\r\n\r\n Select:{\r\n styles:{\r\n label: label,\r\n input:{\r\n padding: 'var(--mantine-spacing-sm)',\r\n },\r\n }\r\n },\r\n\r\n Pill: {\r\n styles: (theme: MantineTheme) => ({\r\n root: {\r\n display: 'inline-flex',\r\n alignItems: 'center',\r\n justifyContent: 'space-between',\r\n backgroundColor: 'rgba(76, 76, 76, 0.3)',\r\n height: 'fit-content',\r\n textTransform: 'uppercase',\r\n letterSpacing: '0.05em',\r\n fontFamily: 'Akrobat Bold',\r\n fontSize: theme.fontSizes.xs,\r\n borderRadius: theme.defaultRadius,\r\n padding: `${theme.spacing.xs} ${theme.spacing.sm}`,\r\n }\r\n })\r\n },\r\n\r\n Input:{\r\n styles: {\r\n label: label,\r\n error: error,\r\n\r\n input:{\r\n padding: 'var(--mantine-spacing-sm)',\r\n backgroundColor: 'rgba(76, 76, 76, 0.3)', \r\n },\r\n },\r\n },\r\n ColorInput:{\r\n styles: {\r\n label: label,\r\n input:{\r\n padding: 'var(--mantine-spacing-sm)',\r\n },\r\n },\r\n },\r\n TextInput:{\r\n styles:{\r\n label: label,\r\n wrapper:{\r\n \r\n },\r\n section:{\r\n marginRight: '0.2vh',\r\n },\r\n\r\n input:{\r\n padding: 'var(--mantine-spacing-sm)',\r\n \r\n \r\n },\r\n }\r\n },\r\n NumberInput:{\r\n \r\n styles:{\r\n label: label,\r\n input:{\r\n padding: 'var(--mantine-spacing-sm)',\r\n },\r\n section:{\r\n pointerEvents: 'all',\r\n },\r\n }\r\n }\r\n },\r\n\r\n colors: {\r\n\r\n dirk:[\r\n \"#ffffff\",\r\n \"#f3fce9\",\r\n \"#dbf5bd\",\r\n \"#c3ee91\",\r\n \"#ace765\",\r\n \"#94e039\",\r\n \"#7ac61f\",\r\n \"#5f9a18\",\r\n \"#29420a\",\r\n \"#446e11\",\r\n ],\r\n },\r\n});\r\n\r\n\r\nexport default theme;","export const isEnvBrowser = (): boolean => !(window as any).invokeNative;\r\n\r\n// Basic no operation function\r\nexport const noop = () => {};\r\n\r\nexport const splitFAString = (faString:string) => {\r\n const [prefix, newIcon] = faString.split('-');\r\n if (!prefix || !newIcon) return {prefix: 'fas', newIcon: 'question'};\r\n return {prefix, newIcon};\r\n}\r\n\r\nexport const numberToRoman = (num:number) => {\r\n const romanNumerals = ['I', 'II', 'III', 'IV', 'V', 'VI', 'VII', 'VIII', 'IX', 'X', 'XI', 'XII', 'XIII', 'XIV', 'XV', 'XVI', 'XVII', 'XVIII', 'XIX', 'XX'] \r\n return romanNumerals[num]\r\n}\r\n\r\nexport const copyToClipboard = (text:string) => {\r\n const el = document.createElement('textarea');\r\n el.value = text;\r\n document.body.appendChild(el);\r\n el.select();\r\n document.execCommand('copy');\r\n document.body.removeChild(el);\r\n}\r\n\r\nexport const openLink = (url:string) => {\r\n if (isEnvBrowser()) {\r\n window.open(url, '_blank');\r\n } else {\r\n // @ts-expect-error -- invokeNative exists in NUI\r\n window.invokeNative('openLink', url);\r\n } \r\n}","import { useEffect } from \"react\";\r\nimport { isEnvBrowser } from \"./misc\";\r\n\r\n/**\r\n * Simple wrapper around fetch API tailored for CEF/NUI use.\r\n */\r\nexport async function fetchNui<T = unknown>(\r\n eventName: string,\r\n data?: unknown,\r\n mockData?: T,\r\n): Promise<T> {\r\n const options = {\r\n method: \"post\",\r\n headers: {\r\n \"Content-Type\": \"application/json; charset=UTF-8\",\r\n },\r\n body: JSON.stringify(data),\r\n };\r\n\r\n if (isEnvBrowser() && mockData) return mockData;\r\n if (isEnvBrowser() && mockData === undefined) {\r\n console.warn(\r\n `[fetchNui] Called fetchNui for event \"${eventName}\" in browser environment without mockData. Returning empty object.`,\r\n );\r\n return {} as T;\r\n }\r\n\r\n const resourceName = (window as any).GetParentResourceName\r\n ? (window as any).GetParentResourceName()\r\n : \"nui-frame-app\";\r\n\r\n const resp = await fetch(`https://${resourceName}/${eventName}`, options);\r\n return await resp.json();\r\n}\r\n\r\n// -----------------------------\r\n// Initial fetch registration\r\n// -----------------------------\r\nexport type InitialFetch<T> = () => Promise<T>;\r\nexport const initialFetches: Record<string, InitialFetch<unknown>> = {};\r\n\r\n/**\r\n * Registers an initial fetch that automatically uses fetchNui.\r\n * Works like:\r\n * ```ts\r\n * registerInitialFetch<{ name: string }>(\"MY_EVENT_NAME\", undefined, { name: \"Mocky\" });\r\n * ```\r\n * and returns a Promise resolving to the same type as fetchNui.\r\n */\r\nexport async function registerInitialFetch<T = unknown>(\r\n eventName: string,\r\n data?: unknown,\r\n mockData?: T,\r\n): Promise<T> {\r\n const fetcher = () => fetchNui<T>(eventName, data, mockData);\r\n initialFetches[eventName] = fetcher;\r\n return fetcher(); // run immediately if needed\r\n}\r\n\r\n/**\r\n * Runs all registered initial fetches in parallel.\r\n */\r\nexport async function runFetches() {\r\n return Promise.all(\r\n Object.entries(initialFetches).map(async ([eventName, fetcher]) => {\r\n const data = await fetcher();\r\n return { eventName, data };\r\n }),\r\n );\r\n}\r\n\r\n/**\r\n * React hook to automatically run all registered fetches on mount.\r\n */\r\nexport const useAutoFetcher = () => {\r\n useEffect(() => {\r\n if (isEnvBrowser()) return;\r\n const run = async () => {\r\n const results = await runFetches();\r\n };\r\n run();\r\n }, []);\r\n};\r\n","import { create } from \"zustand\";\r\nimport { registerInitialFetch } from \"./fetchNui\";\r\n\r\nexport type SettingsState = {\r\n hydrated: boolean;\r\n game: \"fivem\" | \"rdr3\";\r\n primaryColor: string;\r\n primaryShade: number;\r\n itemImgPath: string;\r\n customTheme: Record<string, string[]>;\r\n};\r\n\r\nexport const useSettings = create<SettingsState>(() => ({\r\n hydrated: false,\r\n game: \"fivem\",\r\n primaryColor: \"dirk\",\r\n primaryShade: 9,\r\n itemImgPath: \"\",\r\n customTheme: {},\r\n}));\r\n\r\n\r\nregisterInitialFetch<Partial<SettingsState>>(\"GET_SETTINGS\")\r\n .then((data) => {\r\n useSettings.setState({\r\n ...data,\r\n hydrated: true,\r\n });\r\n })\r\n .catch(() => {\r\n useSettings.setState({ hydrated: true });\r\n });\r\n","import type { MantineThemeOverride } from \"@mantine/core\";\r\n\r\nconst isValidColorScale = (v: unknown): v is string[] =>\r\n Array.isArray(v) && v.length >= 5 && v.every(c => typeof c === \"string\");\r\n\r\nexport function mergeMantineThemeSafe(\r\n base: MantineThemeOverride,\r\n custom?: Record<string, string[]>,\r\n override?: MantineThemeOverride\r\n): MantineThemeOverride {\r\n const colors = { ...base.colors };\r\n\r\n for (const [key, value] of Object.entries(custom ?? {})) {\r\n if (isValidColorScale(value)) {\r\n colors[key] = value as [string, string, string, string, string, string, string, string, string, string, ...string[]];\r\n } else {\r\n console.warn(`[theme] invalid color ignored: ${key}`, value);\r\n }\r\n }\r\n\r\n return {\r\n ...base,\r\n ...override,\r\n colors: {\r\n ...colors,\r\n ...(override?.colors ?? {}),\r\n },\r\n };\r\n}\r\n","\"use client\";\r\n\r\nimport React from \"react\";\r\nimport { Box, Code, Text } from \"@mantine/core\";\r\n\r\nexport class DirkErrorBoundary extends React.Component<\r\n { children: React.ReactNode },\r\n { error: Error | null }\r\n> {\r\n state: { error: Error | null } = { error: null };\r\n\r\n static getDerivedStateFromError(error: Error) {\r\n return { error };\r\n }\r\n\r\n componentDidCatch(error: Error, info: React.ErrorInfo) {\r\n console.group(\"🔥 Dirk UI Crash\");\r\n console.error(error);\r\n console.error(info.componentStack);\r\n console.groupEnd();\r\n }\r\n\r\n render() {\r\n if (!this.state.error) return this.props.children;\r\n\r\n return (\r\n <Box p=\"md\" bg=\"dark.8\">\r\n <Text c=\"red\" fw={600}>UI crashed</Text>\r\n <Code block mt=\"sm\">{this.state.error.message}</Code>\r\n </Box>\r\n );\r\n }\r\n}\r\n","\"use client\";\r\n\r\nimport \"@mantine/core/styles.css\";\r\nimport \"@mantine/notifications/styles.css\";\r\n\r\nimport { MantineProvider, BackgroundImage, MantineColorShade } from \"@mantine/core\";\r\nimport { useMemo, useEffect } from \"react\";\r\nimport theme from \"@/theme\";\r\n\r\nimport { useSettings } from \"@/utils/useSettings\";\r\nimport { mergeMantineThemeSafe } from \"@/utils/mergeMantineTheme\";\r\nimport { DirkErrorBoundary } from \"./DirkErrorBoundary\";\r\nimport { isEnvBrowser } from \"@/utils\";\r\n\r\nexport type DirkProviderProps = {\r\n children: React.ReactNode;\r\n themeOverride?: any;\r\n};\r\n\r\nexport function DirkProvider({ children, themeOverride }: DirkProviderProps) {\r\n const {\r\n hydrated,\r\n primaryColor,\r\n primaryShade,\r\n customTheme,\r\n game,\r\n } = useSettings();\r\n\r\n // 🚫 do not render until state is stable\r\n if (!hydrated) return null;\r\n\r\n const mergedTheme = useMemo(\r\n () =>\r\n mergeMantineThemeSafe(\r\n { ...theme, primaryColor, primaryShade: primaryShade as MantineColorShade },\r\n customTheme,\r\n themeOverride\r\n ),\r\n [primaryColor, primaryShade, customTheme, themeOverride]\r\n );\r\n\r\n useEffect(() => {\r\n document.body.style.fontFamily =\r\n game === \"rdr3\"\r\n ? '\"Red Dead\", sans-serif'\r\n : '\"Akrobat Regular\", sans-serif';\r\n }, [game]);\r\n\r\n const content = isEnvBrowser() ? (\r\n <BackgroundImage\r\n w=\"100vw\"\r\n h=\"100vh\"\r\n src={game === \"fivem\"\r\n ? \"https://i.ytimg.com/vi/TOxuNbXrO28/maxresdefault.jpg\"\r\n : \"https://raw.githubusercontent.com/Jump-On-Studios/RedM-jo_libs/refs/heads/main/source-repositories/Menu/public/assets/images/background_dev.jpg\"}\r\n >\r\n {children}\r\n </BackgroundImage>\r\n ) : (\r\n children\r\n );\r\n\r\n return (\r\n <DirkErrorBoundary>\r\n <MantineProvider theme={mergedTheme} defaultColorScheme=\"dark\">\r\n {content}\r\n </MantineProvider>\r\n </DirkErrorBoundary>\r\n );\r\n}\r\n"]}
@@ -1,20 +1,9 @@
1
1
  import * as react_jsx_runtime from 'react/jsx-runtime';
2
- import * as zustand from 'zustand';
3
- import { MantineThemeOverride } from '@mantine/core';
4
2
 
5
3
  type DirkProviderProps = {
6
- fakeBackground?: boolean;
7
4
  children: React.ReactNode;
8
- themeOverride?: MantineThemeOverride;
5
+ themeOverride?: any;
9
6
  };
10
- type SettingsProps = {
11
- game: 'rdr3' | 'fivem';
12
- primaryColor: string;
13
- primaryShade: number;
14
- itemImgPath: string;
15
- customTheme: Record<string, string[]>;
16
- };
17
- declare const useSettings: zustand.UseBoundStore<zustand.StoreApi<SettingsProps>>;
18
- declare function DirkProvider(props: DirkProviderProps): react_jsx_runtime.JSX.Element;
7
+ declare function DirkProvider({ children, themeOverride }: DirkProviderProps): react_jsx_runtime.JSX.Element | null;
19
8
 
20
- export { DirkProvider, type DirkProviderProps, useSettings };
9
+ export { DirkProvider, type DirkProviderProps };
@@ -1,20 +1,9 @@
1
1
  import * as react_jsx_runtime from 'react/jsx-runtime';
2
- import * as zustand from 'zustand';
3
- import { MantineThemeOverride } from '@mantine/core';
4
2
 
5
3
  type DirkProviderProps = {
6
- fakeBackground?: boolean;
7
4
  children: React.ReactNode;
8
- themeOverride?: MantineThemeOverride;
5
+ themeOverride?: any;
9
6
  };
10
- type SettingsProps = {
11
- game: 'rdr3' | 'fivem';
12
- primaryColor: string;
13
- primaryShade: number;
14
- itemImgPath: string;
15
- customTheme: Record<string, string[]>;
16
- };
17
- declare const useSettings: zustand.UseBoundStore<zustand.StoreApi<SettingsProps>>;
18
- declare function DirkProvider(props: DirkProviderProps): react_jsx_runtime.JSX.Element;
7
+ declare function DirkProvider({ children, themeOverride }: DirkProviderProps): react_jsx_runtime.JSX.Element | null;
19
8
 
20
- export { DirkProvider, type DirkProviderProps, useSettings };
9
+ export { DirkProvider, type DirkProviderProps };
@@ -1,66 +1,13 @@
1
1
  import '@mantine/core/styles.css';
2
2
  import '@mantine/notifications/styles.css';
3
- import './styles/notify.css';
4
- import './styles/fonts.css';
5
- import './styles/scrollBar.css';
6
- import './styles/tornEdge.css';
7
- import { library } from '@fortawesome/fontawesome-svg-core';
8
- import { fab } from '@fortawesome/free-brands-svg-icons';
9
- import { far } from '@fortawesome/free-regular-svg-icons';
10
- import { fas } from '@fortawesome/free-solid-svg-icons';
11
- import { createTheme, MantineProvider, BackgroundImage } from '@mantine/core';
12
- import { useMemo, useEffect } from 'react';
3
+ import { createTheme, Box, Text, Code, MantineProvider, BackgroundImage } from '@mantine/core';
4
+ import React, { useMemo, useEffect } from 'react';
13
5
  import { create } from 'zustand';
14
- import { jsx, Fragment } from 'react/jsx-runtime';
6
+ import { jsxs, jsx } from 'react/jsx-runtime';
15
7
 
16
- // src/providers/DirkProvider.tsx
17
-
18
- // src/utils/misc.ts
19
- var isEnvBrowser = () => !window.invokeNative;
20
-
21
- // src/utils/fetchNui.ts
22
- async function fetchNui(eventName, data, mockData) {
23
- const options = {
24
- method: "post",
25
- headers: {
26
- "Content-Type": "application/json; charset=UTF-8"
27
- },
28
- body: JSON.stringify(data)
29
- };
30
- if (isEnvBrowser() && mockData) return mockData;
31
- if (isEnvBrowser() && mockData === void 0) {
32
- console.warn(
33
- `[fetchNui] Called fetchNui for event "${eventName}" in browser environment without mockData. Returning empty object.`
34
- );
35
- return {};
36
- }
37
- const resourceName = window.GetParentResourceName ? window.GetParentResourceName() : "nui-frame-app";
38
- const resp = await fetch(`https://${resourceName}/${eventName}`, options);
39
- return await resp.json();
40
- }
41
- var initialFetches = {};
42
- async function registerInitialFetch(eventName, data, mockData) {
43
- const fetcher = () => fetchNui(eventName, data, mockData);
44
- initialFetches[eventName] = fetcher;
45
- return fetcher();
46
- }
47
- async function runFetches() {
48
- return Promise.all(
49
- Object.entries(initialFetches).map(async ([eventName, fetcher]) => {
50
- const data = await fetcher();
51
- return { eventName, data };
52
- })
53
- );
54
- }
55
- var useAutoFetcher = () => {
56
- useEffect(() => {
57
- if (isEnvBrowser()) return;
58
- const run = async () => {
59
- await runFetches();
60
- };
61
- run();
62
- }, []);
63
- };
8
+ var __defProp = Object.defineProperty;
9
+ var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
10
+ var __publicField = (obj, key, value) => __defNormalProp(obj, key + "" , value);
64
11
  var label = {
65
12
  fontSize: "var(--mantine-font-size-xs)",
66
13
  fontFamily: "Akrobat Bold",
@@ -220,72 +167,126 @@ var theme = createTheme({
220
167
  }
221
168
  });
222
169
  var theme_default = theme;
223
- library.add(fas, far, fab);
224
- var useSettings = create((set) => ({
170
+
171
+ // src/utils/misc.ts
172
+ var isEnvBrowser = () => !window.invokeNative;
173
+
174
+ // src/utils/fetchNui.ts
175
+ async function fetchNui(eventName, data, mockData) {
176
+ const options = {
177
+ method: "post",
178
+ headers: {
179
+ "Content-Type": "application/json; charset=UTF-8"
180
+ },
181
+ body: JSON.stringify(data)
182
+ };
183
+ if (isEnvBrowser() && mockData === void 0) {
184
+ console.warn(
185
+ `[fetchNui] Called fetchNui for event "${eventName}" in browser environment without mockData. Returning empty object.`
186
+ );
187
+ return {};
188
+ }
189
+ const resourceName = window.GetParentResourceName ? window.GetParentResourceName() : "nui-frame-app";
190
+ const resp = await fetch(`https://${resourceName}/${eventName}`, options);
191
+ return await resp.json();
192
+ }
193
+ async function registerInitialFetch(eventName, data, mockData) {
194
+ const fetcher = () => fetchNui(eventName, data, mockData);
195
+ return fetcher();
196
+ }
197
+
198
+ // src/utils/useSettings.ts
199
+ var useSettings = create(() => ({
200
+ hydrated: false,
225
201
  game: "fivem",
226
202
  primaryColor: "dirk",
227
203
  primaryShade: 9,
228
- itemImgPath: "https://assets.dirkcfx.com/items/",
204
+ itemImgPath: "",
229
205
  customTheme: {}
230
206
  }));
231
- registerInitialFetch("GET_SETTINGS", void 0, {
232
- game: "fivem",
233
- primaryColor: "dirk",
234
- primaryShade: 9,
235
- itemImgPath: "https://assets.dirkcfx.com/items/",
236
- customTheme: {}
237
- }).then((data) => {
207
+ registerInitialFetch("GET_SETTINGS").then((data) => {
238
208
  useSettings.setState({
239
- ...data
209
+ ...data,
210
+ hydrated: true
240
211
  });
212
+ }).catch(() => {
213
+ useSettings.setState({ hydrated: true });
241
214
  });
242
- function DirkProvider(props) {
243
- const primaryColor = useSettings((data) => data.primaryColor);
244
- const primaryShade = useSettings((data) => data.primaryShade);
245
- const customTheme = useSettings((data) => data.customTheme);
246
- const game = useSettings((data) => data.game);
247
- const mergedTheme = useMemo(() => ({
248
- ...theme_default,
215
+
216
+ // src/utils/mergeMantineTheme.ts
217
+ var isValidColorScale = (v) => Array.isArray(v) && v.length >= 5 && v.every((c) => typeof c === "string");
218
+ function mergeMantineThemeSafe(base, custom, override) {
219
+ const colors = { ...base.colors };
220
+ for (const [key, value] of Object.entries(custom ?? {})) {
221
+ if (isValidColorScale(value)) {
222
+ colors[key] = value;
223
+ } else {
224
+ console.warn(`[theme] invalid color ignored: ${key}`, value);
225
+ }
226
+ }
227
+ return {
228
+ ...base,
229
+ ...override,
230
+ colors: {
231
+ ...colors,
232
+ ...override?.colors ?? {}
233
+ }
234
+ };
235
+ }
236
+ var DirkErrorBoundary = class extends React.Component {
237
+ constructor() {
238
+ super(...arguments);
239
+ __publicField(this, "state", { error: null });
240
+ }
241
+ static getDerivedStateFromError(error2) {
242
+ return { error: error2 };
243
+ }
244
+ componentDidCatch(error2, info) {
245
+ console.group("\u{1F525} Dirk UI Crash");
246
+ console.error(error2);
247
+ console.error(info.componentStack);
248
+ console.groupEnd();
249
+ }
250
+ render() {
251
+ if (!this.state.error) return this.props.children;
252
+ return /* @__PURE__ */ jsxs(Box, { p: "md", bg: "dark.8", children: [
253
+ /* @__PURE__ */ jsx(Text, { c: "red", fw: 600, children: "UI crashed" }),
254
+ /* @__PURE__ */ jsx(Code, { block: true, mt: "sm", children: this.state.error.message })
255
+ ] });
256
+ }
257
+ };
258
+ function DirkProvider({ children, themeOverride }) {
259
+ const {
260
+ hydrated,
249
261
  primaryColor,
250
262
  primaryShade,
251
- colors: {
252
- ...theme_default.colors,
253
- ...customTheme,
254
- // Custom theme colors will override/extend base colors
255
- ...props.themeOverride?.colors
256
- // Props theme colors will override/extend previous colors
257
- },
258
- ...props.themeOverride
259
- // Props theme will override/extend the entire theme
260
- }), [primaryColor, primaryShade, customTheme, props.themeOverride]);
261
- console.log("created merged theme:");
262
- console.log(mergedTheme);
263
+ customTheme,
264
+ game
265
+ } = useSettings();
266
+ if (!hydrated) return null;
267
+ const mergedTheme = useMemo(
268
+ () => mergeMantineThemeSafe(
269
+ { ...theme_default, primaryColor, primaryShade },
270
+ customTheme,
271
+ themeOverride
272
+ ),
273
+ [primaryColor, primaryShade, customTheme, themeOverride]
274
+ );
263
275
  useEffect(() => {
264
- document.fonts.ready.then(() => {
265
- document.body.style.fontFamily = game === "rdr3" ? '"Red Dead", sans-serif' : game === "fivem" ? '"Akrobat Regular", sans-serif' : "sans-serif";
266
- });
276
+ document.body.style.fontFamily = game === "rdr3" ? '"Red Dead", sans-serif' : '"Akrobat Regular", sans-serif';
267
277
  }, [game]);
268
- useEffect(() => {
269
- fetchNui("NUI_READY");
270
- }, []);
271
- useAutoFetcher();
272
- return /* @__PURE__ */ jsx(MantineProvider, { theme: mergedTheme, defaultColorScheme: "dark", children: /* @__PURE__ */ jsx(Wrapper, { children: props.children }) });
273
- }
274
- function Wrapper({ children }) {
275
- const game = useSettings((data) => data.game);
276
- if (!isEnvBrowser()) return /* @__PURE__ */ jsx(Fragment, { children });
277
- return /* @__PURE__ */ jsx(
278
+ const content = isEnvBrowser() ? /* @__PURE__ */ jsx(
278
279
  BackgroundImage,
279
280
  {
280
281
  w: "100vw",
281
282
  h: "100vh",
282
- style: { overflow: "hidden", backgroundColor: "transparent" },
283
283
  src: game === "fivem" ? "https://i.ytimg.com/vi/TOxuNbXrO28/maxresdefault.jpg" : "https://raw.githubusercontent.com/Jump-On-Studios/RedM-jo_libs/refs/heads/main/source-repositories/Menu/public/assets/images/background_dev.jpg",
284
284
  children
285
285
  }
286
- );
286
+ ) : children;
287
+ return /* @__PURE__ */ jsx(DirkErrorBoundary, { children: /* @__PURE__ */ jsx(MantineProvider, { theme: mergedTheme, defaultColorScheme: "dark", children: content }) });
287
288
  }
288
289
 
289
- export { DirkProvider, useSettings };
290
+ export { DirkProvider };
290
291
  //# sourceMappingURL=index.js.map
291
292
  //# sourceMappingURL=index.js.map