diff --git a/package-lock.json b/package-lock.json
index c546d4fd..de672d26 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -4567,107 +4567,6 @@
"win32"
]
},
- "node_modules/@mantine/core": {
- "version": "8.3.5",
- "resolved": "https://registry.npmjs.org/@mantine/core/-/core-8.3.5.tgz",
- "integrity": "sha512-PdVNLMgOS2vFhOujRi6/VC9ic8w3UDyKX7ftwDeJ7yQT8CiepUxfbWWYpVpnq23bdWh/7fIT2Pn1EY8r8GOk7g==",
- "dependencies": {
- "@floating-ui/react": "^0.27.16",
- "clsx": "^2.1.1",
- "react-number-format": "^5.4.4",
- "react-remove-scroll": "^2.7.1",
- "react-textarea-autosize": "8.5.9",
- "type-fest": "^4.41.0"
- },
- "peerDependencies": {
- "@mantine/hooks": "8.3.5",
- "react": "^18.x || ^19.x",
- "react-dom": "^18.x || ^19.x"
- }
- },
- "node_modules/@mantine/dates": {
- "version": "8.3.5",
- "resolved": "https://registry.npmjs.org/@mantine/dates/-/dates-8.3.5.tgz",
- "integrity": "sha512-LkIdC4eWPNQFv1BU1c52U3Z3RuA3yU1asvTgMEIQ/MdJsGK8GePwpgMH/jKQ8ba/AW9NfksdvtOJ6uIqPwjCkg==",
- "dependencies": {
- "clsx": "^2.1.1"
- },
- "peerDependencies": {
- "@mantine/core": "8.3.5",
- "@mantine/hooks": "8.3.5",
- "dayjs": ">=1.0.0",
- "react": "^18.x || ^19.x",
- "react-dom": "^18.x || ^19.x"
- }
- },
- "node_modules/@mantine/dropzone": {
- "version": "8.3.5",
- "resolved": "https://registry.npmjs.org/@mantine/dropzone/-/dropzone-8.3.5.tgz",
- "integrity": "sha512-8eRNoEYQzUOav8Te58osGRt2vbqJO3ZORXgKALY+FhB0YGRCZYmS/gQ2T66SpyrpovY6k6OVi1ScM3wRaJrxUg==",
- "dependencies": {
- "react-dropzone": "14.3.8"
- },
- "peerDependencies": {
- "@mantine/core": "8.3.5",
- "@mantine/hooks": "8.3.5",
- "react": "^18.x || ^19.x",
- "react-dom": "^18.x || ^19.x"
- }
- },
- "node_modules/@mantine/form": {
- "version": "8.3.5",
- "resolved": "https://registry.npmjs.org/@mantine/form/-/form-8.3.5.tgz",
- "integrity": "sha512-i9UFiHtO1dlrJXZkquyt+71YcNNxPPSkIcJCRp7k0Tif7bPqWK2xijPDEXzqvA53YvMvEMoqaQCEQLVmH7Esdg==",
- "dependencies": {
- "fast-deep-equal": "^3.1.3",
- "klona": "^2.0.6"
- },
- "peerDependencies": {
- "react": "^18.x || ^19.x"
- }
- },
- "node_modules/@mantine/hooks": {
- "version": "8.3.5",
- "resolved": "https://registry.npmjs.org/@mantine/hooks/-/hooks-8.3.5.tgz",
- "integrity": "sha512-0Wf08eWLKi3WkKlxnV1W5vfuN6wcvAV2VbhQlOy0R9nrWorGTtonQF6qqBE3PnJFYF1/ZE+HkYZQ/Dr7DmYSMQ==",
- "peerDependencies": {
- "react": "^18.x || ^19.x"
- }
- },
- "node_modules/@mantine/modals": {
- "version": "8.3.5",
- "resolved": "https://registry.npmjs.org/@mantine/modals/-/modals-8.3.5.tgz",
- "integrity": "sha512-8pEhVc2NqUcO1+mQab1J5hDwMGKbqwMWMQptF++PUI0e82BGyoxuOdYywWvvW7+UzcA1REMF7uy0mfG9RLcjew==",
- "peerDependencies": {
- "@mantine/core": "8.3.5",
- "@mantine/hooks": "8.3.5",
- "react": "^18.x || ^19.x",
- "react-dom": "^18.x || ^19.x"
- }
- },
- "node_modules/@mantine/notifications": {
- "version": "8.3.5",
- "resolved": "https://registry.npmjs.org/@mantine/notifications/-/notifications-8.3.5.tgz",
- "integrity": "sha512-8TvzrPxfdtOLGTalv7Ei1hy2F6KbR3P7/V73yw3AOKhrf1ydS89sqV2ShbsucHGJk9Pto0wjdTPd8Q7pm5MAYw==",
- "dependencies": {
- "@mantine/store": "8.3.5",
- "react-transition-group": "4.4.5"
- },
- "peerDependencies": {
- "@mantine/core": "8.3.5",
- "@mantine/hooks": "8.3.5",
- "react": "^18.x || ^19.x",
- "react-dom": "^18.x || ^19.x"
- }
- },
- "node_modules/@mantine/store": {
- "version": "8.3.5",
- "resolved": "https://registry.npmjs.org/@mantine/store/-/store-8.3.5.tgz",
- "integrity": "sha512-qN4fFsDMy86IV9oh1gZlDTv41RAsO0grjx90FGyT5QCv7NTgcavwxB74GBkhp45W8xn+Ms/awKy+6NxnmLmW1w==",
- "peerDependencies": {
- "react": "^18.x || ^19.x"
- }
- },
"node_modules/@mdx-js/loader": {
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/@mdx-js/loader/-/loader-3.1.1.tgz",
@@ -26582,6 +26481,7 @@
"version": "4.41.0",
"resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.41.0.tgz",
"integrity": "sha512-TeTSQ6H5YHvpqVwBRcnLDCBnDOHWYu7IvGbHT6N8AOymcr9PJGjc1GTtiWZTYg0NCgYwvnYWEkVChQAr9bjfwA==",
+ "dev": true,
"engines": {
"node": ">=16"
},
@@ -27989,7 +27889,7 @@
},
"src/packages/semble-pds-client": {
"name": "@cosmik.network/semble-pds-client",
- "version": "0.0.4",
+ "version": "0.0.6",
"license": "MIT",
"dependencies": {
"@atproto/api": "^0.18.0",
@@ -28038,13 +27938,14 @@
"name": "semble-webapp",
"version": "0.1.0",
"dependencies": {
- "@mantine/core": "^8.1.3",
- "@mantine/dates": "^8.1.3",
- "@mantine/dropzone": "^8.1.3",
- "@mantine/form": "^8.1.3",
- "@mantine/hooks": "^8.1.3",
- "@mantine/modals": "^8.1.3",
- "@mantine/notifications": "^8.1.3",
+ "@mantine/code-highlight": "8.3.1",
+ "@mantine/core": "8.3.1",
+ "@mantine/dates": "8.3.1",
+ "@mantine/dropzone": "8.3.1",
+ "@mantine/form": "8.3.1",
+ "@mantine/hooks": "8.3.1",
+ "@mantine/modals": "8.3.1",
+ "@mantine/notifications": "8.3.1",
"@mdx-js/loader": "^3.1.1",
"@mdx-js/react": "^3.1.1",
"@next/mdx": "^15.5.4",
@@ -28117,6 +28018,132 @@
"node": "^12.22.0 || ^14.17.0 || >=16.0.0"
}
},
+ "src/webapp/node_modules/@mantine/code-highlight": {
+ "version": "8.3.1",
+ "resolved": "https://registry.npmjs.org/@mantine/code-highlight/-/code-highlight-8.3.1.tgz",
+ "integrity": "sha512-YRjMuLGnNg8BlzYg1+Dj3ZW3sb4q0P9QBNZwGdKpe4x0dtLOPa3pVPnKWhSiD4/Y0cWUbCiyzUQ+MlzFYnAg9w==",
+ "dependencies": {
+ "clsx": "^2.1.1"
+ },
+ "peerDependencies": {
+ "@mantine/core": "8.3.1",
+ "@mantine/hooks": "8.3.1",
+ "react": "^18.x || ^19.x",
+ "react-dom": "^18.x || ^19.x"
+ }
+ },
+ "src/webapp/node_modules/@mantine/core": {
+ "version": "8.3.1",
+ "resolved": "https://registry.npmjs.org/@mantine/core/-/core-8.3.1.tgz",
+ "integrity": "sha512-OYfxn9cTv+K6RZ8+Ozn/HDQXkB8Fmn+KJJt5lxyFDP9F09EHnC59Ldadv1LyUZVBGtNqz4sn6b3vBShbxwAmYw==",
+ "dependencies": {
+ "@floating-ui/react": "^0.27.16",
+ "clsx": "^2.1.1",
+ "react-number-format": "^5.4.4",
+ "react-remove-scroll": "^2.7.1",
+ "react-textarea-autosize": "8.5.9",
+ "type-fest": "^4.41.0"
+ },
+ "peerDependencies": {
+ "@mantine/hooks": "8.3.1",
+ "react": "^18.x || ^19.x",
+ "react-dom": "^18.x || ^19.x"
+ }
+ },
+ "src/webapp/node_modules/@mantine/core/node_modules/type-fest": {
+ "version": "4.41.0",
+ "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.41.0.tgz",
+ "integrity": "sha512-TeTSQ6H5YHvpqVwBRcnLDCBnDOHWYu7IvGbHT6N8AOymcr9PJGjc1GTtiWZTYg0NCgYwvnYWEkVChQAr9bjfwA==",
+ "engines": {
+ "node": ">=16"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "src/webapp/node_modules/@mantine/dates": {
+ "version": "8.3.1",
+ "resolved": "https://registry.npmjs.org/@mantine/dates/-/dates-8.3.1.tgz",
+ "integrity": "sha512-qCGlLnrwu9eQsl+yQC/tEYgTEO8rE6hopagNpTV2/wzLBUywlL/AbtB1yHuOikQgZxXAOLfvIBWNTWUHRtTnfw==",
+ "dependencies": {
+ "clsx": "^2.1.1"
+ },
+ "peerDependencies": {
+ "@mantine/core": "8.3.1",
+ "@mantine/hooks": "8.3.1",
+ "dayjs": ">=1.0.0",
+ "react": "^18.x || ^19.x",
+ "react-dom": "^18.x || ^19.x"
+ }
+ },
+ "src/webapp/node_modules/@mantine/dropzone": {
+ "version": "8.3.1",
+ "resolved": "https://registry.npmjs.org/@mantine/dropzone/-/dropzone-8.3.1.tgz",
+ "integrity": "sha512-jsaZhX02Uu8FDWBYNk59wWEBNO0hrayuBfRGqSjY/FQwRHZXIBgfuBsE3AIBJte6ptX+gWSR0Bhwids0LicEtg==",
+ "dependencies": {
+ "react-dropzone": "14.3.8"
+ },
+ "peerDependencies": {
+ "@mantine/core": "8.3.1",
+ "@mantine/hooks": "8.3.1",
+ "react": "^18.x || ^19.x",
+ "react-dom": "^18.x || ^19.x"
+ }
+ },
+ "src/webapp/node_modules/@mantine/form": {
+ "version": "8.3.1",
+ "resolved": "https://registry.npmjs.org/@mantine/form/-/form-8.3.1.tgz",
+ "integrity": "sha512-kmnF5o0Tl/Wi+ZGdqNknoN7QDswxuRo7OlPDRwXuxv/TcazuOIwf7j0p6kFzJ0c/wuqrZfjx3vnOg4Txtmwa1g==",
+ "dependencies": {
+ "fast-deep-equal": "^3.1.3",
+ "klona": "^2.0.6"
+ },
+ "peerDependencies": {
+ "react": "^18.x || ^19.x"
+ }
+ },
+ "src/webapp/node_modules/@mantine/hooks": {
+ "version": "8.3.1",
+ "resolved": "https://registry.npmjs.org/@mantine/hooks/-/hooks-8.3.1.tgz",
+ "integrity": "sha512-lQutBS+Q0iz/cNFvdrsYassPWo3RtWcmDGJeOtKfHigLzFOhxUuLOkQgepDbMf3WcVMB/tist6Px1PQOv57JTw==",
+ "peerDependencies": {
+ "react": "^18.x || ^19.x"
+ }
+ },
+ "src/webapp/node_modules/@mantine/modals": {
+ "version": "8.3.1",
+ "resolved": "https://registry.npmjs.org/@mantine/modals/-/modals-8.3.1.tgz",
+ "integrity": "sha512-3+OL1VcrKI91eqfLR4j6gIKHxwCVINNBrBdIVKc4ozAPAF/XI5VXwhXYxV/Nd7B2lxQgsOlIK5rjEKFvTfHZBg==",
+ "peerDependencies": {
+ "@mantine/core": "8.3.1",
+ "@mantine/hooks": "8.3.1",
+ "react": "^18.x || ^19.x",
+ "react-dom": "^18.x || ^19.x"
+ }
+ },
+ "src/webapp/node_modules/@mantine/notifications": {
+ "version": "8.3.1",
+ "resolved": "https://registry.npmjs.org/@mantine/notifications/-/notifications-8.3.1.tgz",
+ "integrity": "sha512-C1Iqa4g1HNNTLv2/CxOCR1mNlYNFCNtnS0u/JsR+HvtFVrun1namxDG6e6/U0hIva2klogYdivx4cyxmjPFerg==",
+ "dependencies": {
+ "@mantine/store": "8.3.1",
+ "react-transition-group": "4.4.5"
+ },
+ "peerDependencies": {
+ "@mantine/core": "8.3.1",
+ "@mantine/hooks": "8.3.1",
+ "react": "^18.x || ^19.x",
+ "react-dom": "^18.x || ^19.x"
+ }
+ },
+ "src/webapp/node_modules/@mantine/notifications/node_modules/@mantine/store": {
+ "version": "8.3.1",
+ "resolved": "https://registry.npmjs.org/@mantine/store/-/store-8.3.1.tgz",
+ "integrity": "sha512-OZwg0YKbCEKnkFmS9oRLKA8TMriBzO1T6nUib1yfLCx0VFuznllYZiDtaSWNkEYSdnFWCv5hKh5aOD4RHUnQfQ==",
+ "peerDependencies": {
+ "react": "^18.x || ^19.x"
+ }
+ },
"src/webapp/node_modules/ansi-regex": {
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
diff --git a/src/webapp/.storybook/preview.tsx b/src/webapp/.storybook/preview.tsx
index 05689d5a..e4710f9e 100644
--- a/src/webapp/.storybook/preview.tsx
+++ b/src/webapp/.storybook/preview.tsx
@@ -1,4 +1,5 @@
import '@mantine/core/styles.css';
+import '@mantine/code-highlight/styles.css';
import React from 'react';
import { MantineProvider } from '@mantine/core';
diff --git a/src/webapp/app/(dashboard)/settings/advanced/layout.tsx b/src/webapp/app/(dashboard)/settings/advanced/layout.tsx
new file mode 100644
index 00000000..f11d9d2d
--- /dev/null
+++ b/src/webapp/app/(dashboard)/settings/advanced/layout.tsx
@@ -0,0 +1,24 @@
+import BackButton from '@/components/navigation/backButton/BackButton';
+import Header from '@/components/navigation/header/Header';
+import type { Metadata } from 'next';
+import { Fragment } from 'react';
+
+export const metadata: Metadata = {
+ title: 'Advanced',
+ description: 'Advanced',
+};
+
+interface Props {
+ children: React.ReactNode;
+}
+
+export default function Layout(props: Props) {
+ return (
+
+
+ {props.children}
+
+ );
+}
diff --git a/src/webapp/app/(dashboard)/settings/advanced/loading.tsx b/src/webapp/app/(dashboard)/settings/advanced/loading.tsx
new file mode 100644
index 00000000..3d675077
--- /dev/null
+++ b/src/webapp/app/(dashboard)/settings/advanced/loading.tsx
@@ -0,0 +1,5 @@
+import AdvancedContainerSkeleton from '@/features/settings/containers/advancedContainer/Skeleton.AdvancedContainer';
+
+export default function Loading() {
+ return ;
+}
diff --git a/src/webapp/app/(dashboard)/settings/advanced/page.tsx b/src/webapp/app/(dashboard)/settings/advanced/page.tsx
new file mode 100644
index 00000000..b84546bc
--- /dev/null
+++ b/src/webapp/app/(dashboard)/settings/advanced/page.tsx
@@ -0,0 +1,5 @@
+import AdvancedContainer from '@/features/settings/containers/advancedContainer/AdvancedContainer';
+
+export default function Page() {
+ return ;
+}
diff --git a/src/webapp/features/cards/components/urlCard/UrlCard.tsx b/src/webapp/features/cards/components/urlCard/UrlCard.tsx
index f483c851..b9c395cb 100644
--- a/src/webapp/features/cards/components/urlCard/UrlCard.tsx
+++ b/src/webapp/features/cards/components/urlCard/UrlCard.tsx
@@ -9,6 +9,8 @@ import { useRouter } from 'next/navigation';
import { isCollectionPage } from '@/lib/utils/link';
import styles from './UrlCard.module.css';
import { CardSize } from '../../types';
+import { useUserSettings } from '@/features/settings/lib/queries/useUserSettings';
+import { CodeHighlight } from '@mantine/code-highlight';
interface Props {
size?: CardSize;
@@ -26,6 +28,7 @@ interface Props {
export default function UrlCard(props: Props) {
const router = useRouter();
+ const { settings } = useUserSettings();
const handleNavigateToSemblePage = (e: MouseEvent) => {
e.stopPropagation();
@@ -50,11 +53,22 @@ export default function UrlCard(props: Props) {
onClick={handleNavigateToSemblePage}
>
-
+ {settings.tinkerMode ? (
+ e.stopPropagation()}
+ style={{ cursor: 'auto' }}
+ />
+ ) : (
+
+ )}
+
+
+
+
+
+ Tinker mode
+
+ See the Matrix (data exposed as raw JSON)
+
+
+ updateSetting('tinkerMode', event.currentTarget.checked)
+ }
+ />
+
+
+
+
+ );
+}
diff --git a/src/webapp/features/settings/containers/advancedContainer/Skeleton.AdvancedContainer.tsx b/src/webapp/features/settings/containers/advancedContainer/Skeleton.AdvancedContainer.tsx
new file mode 100644
index 00000000..1cf08ce1
--- /dev/null
+++ b/src/webapp/features/settings/containers/advancedContainer/Skeleton.AdvancedContainer.tsx
@@ -0,0 +1,14 @@
+import { Container, Stack, ButtonGroup } from '@mantine/core';
+import SettingItemSkeleton from '../../components/settingItem/Skeleton.SettingItem';
+
+export default function AdvancedContainerSkeleton() {
+ return (
+
+
+
+
+
+
+
+ );
+}
diff --git a/src/webapp/features/settings/containers/settingsContainer/SettingsContainer.tsx b/src/webapp/features/settings/containers/settingsContainer/SettingsContainer.tsx
index f6bf0e2f..ef50c48a 100644
--- a/src/webapp/features/settings/containers/settingsContainer/SettingsContainer.tsx
+++ b/src/webapp/features/settings/containers/settingsContainer/SettingsContainer.tsx
@@ -7,6 +7,7 @@ import {
IoMdInformationCircle,
} from 'react-icons/io';
import SettingLogoutItem from '../../components/settingLogoutItem/SettingLogoutItem';
+import { MdScience } from 'react-icons/md';
export default function SettingsContainer() {
return (
@@ -18,6 +19,9 @@ export default function SettingsContainer() {
Appearance
+
+ Advanced
+
Help
diff --git a/src/webapp/features/settings/lib/queries/useUserSettings.tsx b/src/webapp/features/settings/lib/queries/useUserSettings.tsx
new file mode 100644
index 00000000..ed7307ad
--- /dev/null
+++ b/src/webapp/features/settings/lib/queries/useUserSettings.tsx
@@ -0,0 +1,32 @@
+import { useLocalStorage } from '@mantine/hooks';
+
+interface UserSettings {
+ tinkerMode: boolean;
+}
+
+const defaultSettings: UserSettings = {
+ tinkerMode: false,
+};
+
+export function useUserSettings() {
+ const [settings, setSettings] = useLocalStorage({
+ key: 'user-settings',
+ defaultValue: defaultSettings,
+ });
+
+ function updateSetting(
+ key: K,
+ value: UserSettings[K],
+ ) {
+ setSettings((prev) => ({
+ ...prev,
+ [key]: value,
+ }));
+ }
+
+ return {
+ settings,
+ setSettings,
+ updateSetting,
+ };
+}
diff --git a/src/webapp/package.json b/src/webapp/package.json
index 6df1e4e0..d6f686a6 100644
--- a/src/webapp/package.json
+++ b/src/webapp/package.json
@@ -26,13 +26,14 @@
"build-storybook": "storybook build"
},
"dependencies": {
- "@mantine/core": "^8.1.3",
- "@mantine/dates": "^8.1.3",
- "@mantine/dropzone": "^8.1.3",
- "@mantine/form": "^8.1.3",
- "@mantine/hooks": "^8.1.3",
- "@mantine/modals": "^8.1.3",
- "@mantine/notifications": "^8.1.3",
+ "@mantine/code-highlight": "8.3.1",
+ "@mantine/core": "8.3.1",
+ "@mantine/dates": "8.3.1",
+ "@mantine/dropzone": "8.3.1",
+ "@mantine/form": "8.3.1",
+ "@mantine/hooks": "8.3.1",
+ "@mantine/modals": "8.3.1",
+ "@mantine/notifications": "8.3.1",
"@mdx-js/loader": "^3.1.1",
"@mdx-js/react": "^3.1.1",
"@next/mdx": "^15.5.4",
diff --git a/src/webapp/providers/index.tsx b/src/webapp/providers/index.tsx
index 63271be2..a46bcf0d 100644
--- a/src/webapp/providers/index.tsx
+++ b/src/webapp/providers/index.tsx
@@ -4,6 +4,7 @@ import { AuthProvider } from '@/hooks/useAuth';
import MantineProvider from './mantine';
import TanStackQueryProvider from './tanstack';
import { NavbarProvider } from './navbar';
+import { SettingsProvider } from './settings';
interface Props {
children: React.ReactNode;
@@ -14,7 +15,9 @@ export default function Providers(props: Props) {
- {props.children}
+
+ {props.children}
+
diff --git a/src/webapp/providers/mantine.tsx b/src/webapp/providers/mantine.tsx
index 92185508..533f620b 100644
--- a/src/webapp/providers/mantine.tsx
+++ b/src/webapp/providers/mantine.tsx
@@ -1,20 +1,41 @@
'use client';
+import '@mantine/core/styles.css';
+import '@mantine/notifications/styles.css';
+import '@mantine/code-highlight/styles.css';
import { theme } from '@/styles/theme';
import { MantineProvider as BaseProvider } from '@mantine/core';
-import '@mantine/core/styles.css';
+import {
+ CodeHighlightAdapterProvider,
+ createShikiAdapter,
+} from '@mantine/code-highlight';
+
import { Notifications } from '@mantine/notifications';
-import '@mantine/notifications/styles.css';
interface Props {
children: React.ReactNode;
}
+// Shiki requires async code to load the highlighter
+async function loadShiki() {
+ const { createHighlighter } = await import('shiki');
+ const shiki = await createHighlighter({
+ langs: ['html', 'css', 'js', 'ts', 'tsx', 'json'],
+ themes: [],
+ });
+
+ return shiki;
+}
+
+const shikiAdapter = createShikiAdapter(loadShiki);
+
export default function MantineProvider(props: Props) {
return (
-
- {props.children}
+
+
+ {props.children}
+
);
}
diff --git a/src/webapp/providers/navbar.tsx b/src/webapp/providers/navbar.tsx
index c4d432ea..1a4182bf 100644
--- a/src/webapp/providers/navbar.tsx
+++ b/src/webapp/providers/navbar.tsx
@@ -17,11 +17,11 @@ const NavbarContext = createContext({
toggleDesktop: () => {},
});
-interface ProviderProps {
+interface Props {
children: React.ReactNode;
}
-export function NavbarProvider({ children }: ProviderProps) {
+export function NavbarProvider(props: Props) {
const [mobileOpened, { toggle: toggleMobile }] = useDisclosure(false);
const [desktopOpened, { toggle: toggleDesktop }] = useDisclosure(true);
@@ -29,7 +29,7 @@ export function NavbarProvider({ children }: ProviderProps) {
- {children}
+ {props.children}
);
}
diff --git a/src/webapp/providers/settings.tsx b/src/webapp/providers/settings.tsx
new file mode 100644
index 00000000..0c420cea
--- /dev/null
+++ b/src/webapp/providers/settings.tsx
@@ -0,0 +1,25 @@
+import { useUserSettings } from '@/features/settings/lib/queries/useUserSettings';
+import { createContext, useContext } from 'react';
+
+const SettingsContext = createContext | null>(null);
+
+interface Props {
+ children: React.ReactNode;
+}
+
+export function SettingsProvider(props: Props) {
+ const settings = useUserSettings();
+ return (
+
+ {props.children}
+
+ );
+}
+
+export function useSettings() {
+ const ctx = useContext(SettingsContext);
+ if (!ctx) throw new Error('useSettings must be used inside SettingsProvider');
+ return ctx;
+}