Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add mantine theme #1287

Draft
wants to merge 10 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from 8 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions docs/installation.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ Now the schema package.
{ name: 'Bootstrap3' },
{ name: 'Bootstrap4' },
{ name: 'Bootstrap5' },
{ name: 'Mantine' },
{ name: 'AntD' },
{ name: 'Unstyled' },
]}
Expand Down
791 changes: 655 additions & 136 deletions package-lock.json

Large diffs are not rendered by default.

6 changes: 6 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,9 @@
"@docusaurus/preset-classic": "2.1.0",
"@emotion/react": "11.7.1",
"@emotion/styled": "11.6.0",
"@mantine/core": "7.8.0",
"@mantine/dates": "7.8.0",
"@tabler/icons-react": "3.2.0",
"@material-ui/core": "4.11.2",
"@material-ui/icons": "4.11.2",
"@mui/material": "5.4.1",
Expand Down Expand Up @@ -77,5 +80,8 @@
},
"engines": {
"npm": ">=7.0.0"
},
"devDependencies": {
"process": "^0.11.10"
}
}
11 changes: 11 additions & 0 deletions packages/uniforms-mantine/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# uniforms-mantine

> Mantine components for `uniforms`.

## Install

```sh
$ npm install uniforms-unstyled
wadamek65 marked this conversation as resolved.
Show resolved Hide resolved
```

For more in depth documentation see [uniforms.tools](https://uniforms.tools).
38 changes: 38 additions & 0 deletions packages/uniforms-mantine/__tests__/_createContext.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import { SimpleSchemaDefinition } from 'simpl-schema';
import { Context, UnknownObject, randomIds, ChangedMap } from 'uniforms';

import createSchema from './_createSchema';

const randomId = randomIds();

export default function createContext<Model extends UnknownObject>(
schema?: SimpleSchemaDefinition,
context?: Partial<Context<Model>>,
model = {} as Model,
): { context: Context<Model> } {
return {
context: {
changed: false,
changedMap: {} as ChangedMap<Model>,
error: null,
model,
name: [],
onChange() {},
onSubmit() {},
randomId,
submitted: false,
submitting: false,
validating: false,
...context,
schema: createSchema(schema),
state: {
disabled: false,
readOnly: false,
showInlineError: false,
...context?.state,
},
// @ts-expect-error We don't have a true ref in tests.
formRef: null,
},
};
}
6 changes: 6 additions & 0 deletions packages/uniforms-mantine/__tests__/_createSchema.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import SimpleSchema, { SimpleSchemaDefinition } from 'simpl-schema';
import { SimpleSchema2Bridge } from 'uniforms-bridge-simple-schema-2';

export default function createSchema(schema: SimpleSchemaDefinition = {}) {
return new SimpleSchema2Bridge({ schema: new SimpleSchema(schema) });
}
63 changes: 63 additions & 0 deletions packages/uniforms-mantine/__tests__/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
import * as theme from 'uniforms-unstyled';
wadamek65 marked this conversation as resolved.
Show resolved Hide resolved
import * as suites from 'uniforms/__suites__';

it('exports everything', () => {
expect(theme).toEqual({
AutoFields: expect.any(Function),
AutoField: expect.any(Function),
AutoForm: expect.any(Function),
BaseForm: expect.any(Function),
BoolField: expect.any(Function),
DateField: expect.any(Function),
ErrorField: expect.any(Function),
ErrorsField: expect.any(Function),
HiddenField: expect.any(Function),
ListAddField: expect.any(Function),
ListDelField: expect.any(Function),
ListField: expect.any(Function),
ListItemField: expect.any(Function),
LongTextField: expect.any(Function),
NestField: expect.any(Function),
NumField: expect.any(Function),
QuickForm: expect.any(Function),
RadioField: expect.any(Function),
SelectField: expect.any(Function),
SubmitField: expect.any(Function),
TextField: expect.any(Function),
ValidatedForm: expect.any(Function),
ValidatedQuickForm: expect.any(Function),
});
});

describe('@RTL', () => {
suites.testAutoField(theme.AutoField, {
getDateField: screen => screen.getByLabelText('X'),
getSelectField: screen => screen.getByRole('combobox'),
});
suites.testAutoForm(theme.AutoForm);
suites.testBaseForm(theme.BaseForm);
suites.testBoolField(theme.BoolField);
suites.testDateField(theme.DateField);
suites.testErrorField(theme.ErrorField);
suites.testErrorsField(theme.ErrorsField);
suites.testHiddenField(theme.HiddenField);
suites.testListAddField(theme.ListAddField);
suites.testListDelField(theme.ListDelField);
suites.testListField(theme.ListField, {
getListAddField: screen => screen.getByRole('button'),
});
suites.testLongTextField(theme.LongTextField, {
skipShowInlineErrorTests: true,
});
suites.testNestField(theme.NestField, {
skipShowInlineErrorTests: true,
skipErrorMessageTests: true,
});
suites.testNumField(theme.NumField);
suites.testQuickForm(theme.QuickForm);
suites.testRadioField(theme.RadioField);
suites.testSubmitField(theme.SubmitField);
suites.testTextField(theme.TextField);
suites.testValidatedForm(theme.ValidatedForm);
suites.testValidatedQuickForm(theme.ValidatedQuickForm);
});
40 changes: 40 additions & 0 deletions packages/uniforms-mantine/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
{
"name": "uniforms-mantine",
"version": "4.0.0-alpha.5",
"license": "MIT",
"main": "./cjs/index.js",
"module": "./esm/index.js",
"sideEffects": false,
"description": "Mantine components for uniforms.",
"repository": "https://github.com/vazco/uniforms/tree/master/packages/uniforms-mantine",
"bugs": "https://github.com/vazco/uniforms/issues",
"funding": "https://github.com/vazco/uniforms?sponsor=1",
"keywords": [
"form",
"forms",
"meteor",
"react",
"react-component",
"schema",
"validation"
],
"files": [
"cjs/*.d.ts",
"cjs/*.js",
"esm/*.d.ts",
"esm/*.js",
"src/*.ts",
"src/*.tsx"
],
"peerDependencies": {
"@tabler/icons-react": "^2.0.0",
"@mantine/core": "^7.0.0",
"react": "^18.0.0 || ^17.0.0 || ^16.8.0"
},
"dependencies": {
"invariant": "^2.0.0",
"lodash": "^4.0.0",
"tslib": "^2.2.0",
"uniforms": "^4.0.0-alpha.5"
}
}
33 changes: 33 additions & 0 deletions packages/uniforms-mantine/src/AutoField.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import invariant from 'invariant';
import { createAutoField } from 'uniforms';
export { AutoFieldProps } from 'uniforms';

import BoolField from './BoolField';
import ListField from './ListField';
import NestField from './NestField';
import NumField from './NumField';
import SelectField from './SelectField';
import TextField from './TextField';

const AutoField = createAutoField(props => {
if (props.allowedValues) {
return SelectField;
}

switch (props.fieldType) {
case Array:
return ListField;
case Boolean:
return BoolField;
case Number:
return NumField;
case Object:
return NestField;
case String:
return TextField;
}

return invariant(false, 'Unsupported field type: %s', props.fieldType);
});

export default AutoField;
29 changes: 29 additions & 0 deletions packages/uniforms-mantine/src/AutoFields.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import { ComponentType, createElement } from 'react';
import { useForm } from 'uniforms';

import AutoField from './AutoField';

export type AutoFieldsProps = {
autoField?: ComponentType<{ name: string }>;
element?: ComponentType | string;
fields?: string[];
omitFields?: string[];
};

export default function AutoFields({
autoField = AutoField,
element = 'div',
fields,
omitFields = [],
...props
}: AutoFieldsProps) {
const { schema } = useForm();

return createElement(
element,
props,
(fields ?? schema.getSubfields())
.filter(field => !omitFields.includes(field))
.map(field => createElement(autoField, { key: field, name: field })),
);
}
13 changes: 13 additions & 0 deletions packages/uniforms-mantine/src/AutoForm.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { AutoForm } from 'uniforms';

import ValidatedQuickForm from './ValidatedQuickForm';

function Auto(parent: any) {
class _ extends AutoForm.Auto(parent) {
static Auto = Auto;
}

return _ as unknown as AutoForm;
}

export default Auto(ValidatedQuickForm);
14 changes: 14 additions & 0 deletions packages/uniforms-mantine/src/BaseForm.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import { BaseForm } from 'uniforms';

function Mantine(parent: any) {
class _ extends parent {
static Mantine = Mantine;

// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access, @typescript-eslint/restrict-template-expressions -- comes from uniform's core
piotrpospiech marked this conversation as resolved.
Show resolved Hide resolved
static displayName = `Mantine${parent.displayName}`;
}

return _ as unknown as typeof BaseForm;
}

export default Mantine(BaseForm);
39 changes: 39 additions & 0 deletions packages/uniforms-mantine/src/BoolField.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import React, { Ref } from 'react';
import { connectField, filterDOMProps, FieldProps } from 'uniforms';
import { Checkbox, CheckboxProps } from '@mantine/core';

export type BoolFieldProps = FieldProps<
boolean,
CheckboxProps,
{ inputRef?: Ref<HTMLInputElement> }
>;

function Bool({
disabled,
showInlineError,
error,
errorMessage,
inputRef,
name,
onChange,
readOnly,
value,
label,
...props
}: BoolFieldProps) {
return (
<Checkbox
mb="xs"
checked={value || false}
disabled={disabled}
error={showInlineError && !!error && errorMessage}
name={name}
onChange={() => (readOnly ? undefined : onChange(!value))}
ref={inputRef}
label={label}
{...filterDOMProps(props)}
/>
);
}

export default connectField<BoolFieldProps>(Bool, { kind: 'leaf' });
75 changes: 75 additions & 0 deletions packages/uniforms-mantine/src/DateField.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
import { DateInput, DateTimePicker, DateInputProps } from '@mantine/dates';
import React, { RefObject } from 'react';
import { connectField, filterDOMProps, FieldProps } from 'uniforms';

type DateFieldType = 'date' | 'datetime-local';

type DateFieldInputProps = Omit<DateInputProps, 'onCopy'> & {
inputRef?: RefObject<HTMLInputElement | HTMLButtonElement>;
max?: Date;
min?: Date;
type?: DateFieldType;
};

type DateFieldProps = FieldProps<Date, DateFieldInputProps>;

function Date({
disabled,
inputRef,
label,
max,
min,
name,
onChange,
placeholder,
readOnly,
value,
type = 'datetime-local',
...props
}: DateFieldProps) {
if (type === 'date') {
return (
<DateInput
mb="xs"
disabled={disabled}
label={label}
name={name}
maxDate={max}
minDate={min}
onChange={(date: Date) =>
readOnly
? undefined
: date === null
? onChange(undefined)
: onChange(date)
}
placeholder={placeholder}
ref={inputRef as RefObject<HTMLInputElement>}
value={value}
{...filterDOMProps(props)}
/>
);
}

return (
<DateTimePicker
disabled={disabled}
label={label}
name={name}
maxDate={max}
minDate={min}
placeholder={placeholder}
ref={inputRef as RefObject<HTMLButtonElement>}
value={value}
onChange={(date: Date) =>
readOnly
? undefined
: date === null
? onChange(undefined)
: onChange(date)
}
/>
);
}

export default connectField<DateFieldProps>(Date, { kind: 'leaf' });
Loading
Loading