Skip to content

Commit e2cfd48

Browse files
Vojtěch Václav Portešvojtechportes
authored andcommitted
feat: Added Mantine adapter
- Added Mantine adapter - Updated tsconfig - Migrated the library website from React 18 to React 19 - Updated Documentation, API and Demo sections on the library website - Updated README
1 parent 7dc761a commit e2cfd48

23 files changed

Lines changed: 1818 additions & 50 deletions

README.md

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,8 @@ subpath exports:
109109
- `@vojtechportes/react-query-builder/mui/v7` for applications still on MUI 7
110110
- `@vojtechportes/react-query-builder/antd/v6` for new Ant Design projects
111111
- `@vojtechportes/react-query-builder/antd/v5` for applications still on Ant Design 5
112+
- `@vojtechportes/react-query-builder/mantine/v9` for new Mantine projects
113+
- `@vojtechportes/react-query-builder/mantine/v8` for applications still on Mantine 8
112114
- `@vojtechportes/react-query-builder/fluentui/v8` for Fluent UI React 8 projects
113115

114116
Install the peer dependencies that match the adapter you want to use and pass
@@ -160,6 +162,33 @@ export const MyAntdBuilder = () => {
160162
};
161163
```
162164

165+
Mantine example:
166+
167+
```bash
168+
npm install @mantine/core@^9.0.0 @mantine/hooks@^9.0.0
169+
```
170+
171+
```tsx
172+
import React from 'react';
173+
import '@mantine/core/styles.css';
174+
import { MantineProvider } from '@mantine/core';
175+
import { Builder } from '@vojtechportes/react-query-builder';
176+
import { components } from '@vojtechportes/react-query-builder/mantine/v9';
177+
178+
export const MyMantineBuilder = () => {
179+
return (
180+
<MantineProvider>
181+
<Builder
182+
fields={fields}
183+
data={data}
184+
components={components}
185+
onChange={setData}
186+
/>
187+
</MantineProvider>
188+
);
189+
};
190+
```
191+
163192
Fluent UI example:
164193

165194
```bash
@@ -184,7 +213,7 @@ export const MyFluentUiBuilder = () => {
184213
```
185214

186215
`ThemeProvider` customizes the built-in default component set. It does not
187-
theme the MUI, ANTD, or Fluent UI adapters, which keep their styling in their host UI
216+
theme the MUI, ANTD, Mantine, or Fluent UI adapters, which keep their styling in their host UI
188217
libraries.
189218

190219
More adapter details:

example/package.json

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,20 +12,22 @@
1212
"@emotion/react": "^11.14.0",
1313
"@emotion/styled": "^11.14.1",
1414
"@fluentui/react": "^8.125.6",
15+
"@mantine/core": "^9.2.2",
16+
"@mantine/hooks": "^9.2.2",
1517
"@mui/icons-material": "^9.0.1",
1618
"@mui/material": "^9.0.1",
1719
"antd": "^6.0.0",
1820
"minisearch": "^7.2.0",
1921
"prism-react-renderer": "^2.4.1",
20-
"react": "^18.3.1",
21-
"react-dom": "^18.3.1",
22+
"react": "^19.2.6",
23+
"react-dom": "^19.2.6",
2224
"react-router-dom": "^7.15.1",
2325
"styled-components": "^6.4.2"
2426
},
2527
"devDependencies": {
2628
"@types/node": "^22.13.1",
27-
"@types/react": "^18.3.12",
28-
"@types/react-dom": "^18.3.1",
29+
"@types/react": "^19.2.15",
30+
"@types/react-dom": "^19.2.3",
2931
"@types/styled-components": "^5.1.34",
3032
"@vitejs/plugin-react": "^4.3.4",
3133
"typescript": "^5.6.3",

example/public/sitemap.xml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,9 @@
4242
<url>
4343
<loc>https://vojtechportes.github.io/react-query-builder/documentation/adapters/antd</loc>
4444
</url>
45+
<url>
46+
<loc>https://vojtechportes.github.io/react-query-builder/documentation/adapters/mantine</loc>
47+
</url>
4548
<url>
4649
<loc>https://vojtechportes.github.io/react-query-builder/documentation/adapters/fluentui</loc>
4750
</url>
@@ -75,6 +78,9 @@
7578
<url>
7679
<loc>https://vojtechportes.github.io/react-query-builder/api/adapters/antd</loc>
7780
</url>
81+
<url>
82+
<loc>https://vojtechportes.github.io/react-query-builder/api/adapters/mantine</loc>
83+
</url>
7884
<url>
7985
<loc>https://vojtechportes.github.io/react-query-builder/api/adapters/fluentui</loc>
8086
</url>

example/src/app/app.tsx

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ export const App: React.FC = () => (
4545
<Route path="/api/adapters" element={<ApiPage />} />
4646
<Route path="/api/adapters/mui" element={<ApiPage />} />
4747
<Route path="/api/adapters/antd" element={<ApiPage />} />
48+
<Route path="/api/adapters/mantine" element={<ApiPage />} />
4849
<Route path="/api/adapters/fluentui" element={<ApiPage />} />
4950
<Route path="/api/theming" element={<ApiPage />} />
5051
<Route path="/api/format-query" element={<ApiPage />} />
@@ -65,6 +66,10 @@ export const App: React.FC = () => (
6566
<Route path="/documentation/adapters" element={<DocumentationPage />} />
6667
<Route path="/documentation/adapters/mui" element={<DocumentationPage />} />
6768
<Route path="/documentation/adapters/antd" element={<DocumentationPage />} />
69+
<Route
70+
path="/documentation/adapters/mantine"
71+
element={<DocumentationPage />}
72+
/>
6873
<Route
6974
path="/documentation/adapters/fluentui"
7075
element={<DocumentationPage />}

example/src/components/demo-playground.tsx

Lines changed: 120 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,9 @@ import {
66
} from '@vojtechportes/react-query-builder';
77
import { components as antdComponents } from '@vojtechportes/react-query-builder/antd/v6';
88
import { components as fluentUiComponents } from '@vojtechportes/react-query-builder/fluentui/v8';
9+
import mantineStyles from '@mantine/core/styles.css?inline';
10+
import { MantineProvider } from '@mantine/core';
11+
import { components as mantineComponents } from '@vojtechportes/react-query-builder/mantine/v9';
912
import { createMonacoComponents } from '@vojtechportes/react-query-builder/monaco';
1013
import { components as muiComponents } from '@vojtechportes/react-query-builder/mui/v9';
1114
import type { IColors } from '../../../src/constants/colors';
@@ -180,13 +183,71 @@ const SourceButton = styled.button`
180183
}
181184
`;
182185

186+
const mantineScopeClassName = 'mantine-demo-scope';
187+
188+
const scopedMantineStyles = mantineStyles
189+
.replace(
190+
/:root,\s*:host/g,
191+
`.${mantineScopeClassName}`
192+
)
193+
.replace(
194+
/body,\s*:host/g,
195+
`.${mantineScopeClassName}`
196+
)
197+
.replace(
198+
/:root\[data-mantine-color-scheme='dark'\],\s*:host\(\[data-mantine-color-scheme='dark'\]\)/g,
199+
`.${mantineScopeClassName}[data-mantine-color-scheme='dark']`
200+
)
201+
.replace(
202+
/:root\[data-mantine-color-scheme='light'\],\s*:host\(\[data-mantine-color-scheme='light'\]\)/g,
203+
`.${mantineScopeClassName}[data-mantine-color-scheme='light']`
204+
)
205+
.replace(
206+
/\*,\s*\*::before,\s*\*::after/g,
207+
`.${mantineScopeClassName}, .${mantineScopeClassName} *, .${mantineScopeClassName} *::before, .${mantineScopeClassName} *::after`
208+
)
209+
.replace(
210+
/input,\s*button,\s*textarea,\s*select/g,
211+
`.${mantineScopeClassName} input, .${mantineScopeClassName} button, .${mantineScopeClassName} textarea, .${mantineScopeClassName} select`
212+
)
213+
.replace(
214+
/button,\s*select/g,
215+
`.${mantineScopeClassName} button, .${mantineScopeClassName} select`
216+
)
217+
.replace(
218+
/fieldset:disabled \.mantine-active:active/g,
219+
`.${mantineScopeClassName} fieldset:disabled .mantine-active:active`
220+
);
221+
222+
const scopedMantineDemoOverrides = `
223+
.${mantineScopeClassName} .mantine-Button-root,
224+
.${mantineScopeClassName} .mantine-UnstyledButton-root,
225+
.${mantineScopeClassName} .mantine-ActionIcon-root {
226+
font-size: 14px !important;
227+
}
228+
229+
.${mantineScopeClassName} .mantine-Button-root,
230+
.${mantineScopeClassName} .mantine-UnstyledButton-root {
231+
min-height: 34px;
232+
}
233+
234+
.${mantineScopeClassName} .mantine-Input-input,
235+
.${mantineScopeClassName} .mantine-Select-input,
236+
.${mantineScopeClassName} .mantine-MultiSelect-input,
237+
.${mantineScopeClassName} .mantine-Combobox-option,
238+
.${mantineScopeClassName} .mantine-PillsInput-input {
239+
font-size: 14px !important;
240+
}
241+
`;
242+
183243
export interface IDemoPlaygroundProps {
184244
initialData?: DenormalizedQuery;
185245
}
186246

187247
export const DemoPlayground: React.FC<IDemoPlaygroundProps> = ({
188248
initialData = initialQueryTree,
189249
}) => {
250+
const mantineRootRef = React.useRef<HTMLDivElement>(null);
190251
const [data, setData] = React.useState<DenormalizedQuery>(initialData);
191252
const [outputFormat, setOutputFormat] = React.useState<OutputFormat>('Native');
192253
const [readOnly, setReadOnly] = React.useState(false);
@@ -212,8 +273,10 @@ export const DemoPlayground: React.FC<IDemoPlaygroundProps> = ({
212273
const [showSourceCode, setShowSourceCode] = React.useState(false);
213274
const isMuiMode = customizationMode === 'mui';
214275
const isAntdMode = customizationMode === 'antd';
276+
const isMantineMode = customizationMode === 'mantine';
215277
const isFluentUiMode = customizationMode === 'fluentui';
216-
const usesAdapterMode = isMuiMode || isAntdMode || isFluentUiMode;
278+
const usesAdapterMode =
279+
isMuiMode || isAntdMode || isMantineMode || isFluentUiMode;
217280

218281
React.useEffect(() => {
219282
if (!singleRootGroup && textMode) {
@@ -227,6 +290,8 @@ export const DemoPlayground: React.FC<IDemoPlaygroundProps> = ({
227290
? muiComponents
228291
: customizationMode === 'antd'
229292
? antdComponents
293+
: customizationMode === 'mantine'
294+
? mantineComponents
230295
: customizationMode === 'fluentui'
231296
? fluentUiComponents
232297
: undefined;
@@ -483,6 +548,16 @@ export const DemoPlayground: React.FC<IDemoPlaygroundProps> = ({
483548
/>
484549
<span>Fluent UI adapter</span>
485550
</ToggleRow>
551+
552+
<ToggleRow>
553+
<Toggle
554+
type="radio"
555+
name="customization-mode"
556+
checked={customizationMode === 'mantine'}
557+
onChange={() => setCustomizationMode('mantine')}
558+
/>
559+
<span>Mantine adapter</span>
560+
</ToggleRow>
486561
</ChoiceGroup>
487562
</Panel>
488563

@@ -495,6 +570,8 @@ export const DemoPlayground: React.FC<IDemoPlaygroundProps> = ({
495570
usesAdapterMode
496571
? isMuiMode
497572
? 'ThemeProvider colors style the default builder components only. The MUI adapter uses Material UI styling instead.'
573+
: isMantineMode
574+
? 'ThemeProvider colors style the default builder components only. The Mantine adapter uses Mantine styling instead.'
498575
: isFluentUiMode
499576
? 'ThemeProvider colors style the default builder components only. The Fluent UI adapter uses Fluent UI styling instead.'
500577
: 'ThemeProvider colors style the default builder components only. The ANTD adapter uses Ant Design styling instead.'
@@ -522,19 +599,49 @@ export const DemoPlayground: React.FC<IDemoPlaygroundProps> = ({
522599
</OutputCard>
523600

524601
<BuilderCard>
525-
<BuilderSurface>
526-
{isMuiMode ? (
527-
<Builder {...builderProps} />
528-
) : isFluentUiMode ? (
529-
<Builder {...builderProps} />
530-
) : isAntdMode ? (
531-
<Builder {...builderProps} />
532-
) : (
533-
<ThemeProvider colors={themeColors}>
602+
{isMantineMode ? (
603+
<>
604+
<style>{scopedMantineStyles}</style>
605+
<style>{scopedMantineDemoOverrides}</style>
606+
<BuilderSurface
607+
ref={mantineRootRef}
608+
className={mantineScopeClassName}
609+
style={
610+
{
611+
fontSize: '14px',
612+
lineHeight: 1.5,
613+
'--mantine-font-size-xs': '0.75rem',
614+
'--mantine-font-size-sm': '0.8125rem',
615+
'--mantine-font-size-md': '0.875rem',
616+
'--mantine-font-size-lg': '1rem',
617+
'--mantine-font-size-xl': '1.125rem',
618+
} as React.CSSProperties
619+
}
620+
>
621+
<MantineProvider
622+
cssVariablesSelector={`.${mantineScopeClassName}`}
623+
getRootElement={() => mantineRootRef.current ?? undefined}
624+
withGlobalClasses={false}
625+
>
626+
<Builder {...builderProps} />
627+
</MantineProvider>
628+
</BuilderSurface>
629+
</>
630+
) : (
631+
<BuilderSurface>
632+
{isMuiMode ? (
633+
<Builder {...builderProps} />
634+
) : isFluentUiMode ? (
635+
<Builder {...builderProps} />
636+
) : isAntdMode ? (
534637
<Builder {...builderProps} />
535-
</ThemeProvider>
536-
)}
537-
</BuilderSurface>
638+
) : (
639+
<ThemeProvider colors={themeColors}>
640+
<Builder {...builderProps} />
641+
</ThemeProvider>
642+
)}
643+
</BuilderSurface>
644+
)}
538645
</BuilderCard>
539646

540647
<OutputCard>

example/src/components/site-shell.tsx

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,12 @@ const GlobalStyle = createGlobalStyle`
2929
body {
3030
margin: 0;
3131
min-width: 320px;
32-
font: inherit;
32+
font-family: "Segoe UI", "Inter", sans-serif;
33+
line-height: 1.5;
34+
color: #0f172a;
35+
background:
36+
radial-gradient(circle at top left, ${siteTheme.pageGlow}, transparent 32%),
37+
linear-gradient(180deg, #f8fbff 0%, #eef4fb 100%);
3338
}
3439
3540
a {

0 commit comments

Comments
 (0)