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 2 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,022 changes: 902 additions & 120 deletions package-lock.json

Large diffs are not rendered by default.

2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,11 @@
"@docusaurus/preset-classic": "2.1.0",
"@emotion/react": "11.7.1",
"@emotion/styled": "11.6.0",
"@mantine/core": "^6.0.17",
wadamek65 marked this conversation as resolved.
Show resolved Hide resolved
"@material-ui/core": "4.11.2",
"@material-ui/icons": "4.11.2",
"@mui/material": "5.4.1",
"@tabler/icons-react": "^2.24.0",
"@testing-library/jest-dom": "5.16.5",
"@testing-library/react": "12.1.5",
"@testing-library/user-event": "14.4.3",
Expand Down
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) });
}
14 changes: 14 additions & 0 deletions packages/uniforms-mantine/__tests__/_mount.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import { mount as enzyme } from 'enzyme';
import { context } from 'uniforms';

function mount(node: any, options: any) {
if (options === undefined) {
return enzyme(node);
}
return enzyme(node, {
wrappingComponent: context.Provider,
wrappingComponentProps: { value: options.context },
});
}

export default mount as typeof enzyme;
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.24.0",
wadamek65 marked this conversation as resolved.
Show resolved Hide resolved
"@material-ui/core": "^6.0.17",
"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 '/client/components/uniforms/base/BoolField';

Check failure on line 5 in packages/uniforms-mantine/src/AutoField.tsx

View workflow job for this annotation

GitHub Actions / CI (14.x)

Cannot find module '/client/components/uniforms/base/BoolField' or its corresponding type declarations.

Check failure on line 5 in packages/uniforms-mantine/src/AutoField.tsx

View workflow job for this annotation

GitHub Actions / CI (18.x)

Cannot find module '/client/components/uniforms/base/BoolField' or its corresponding type declarations.
wadamek65 marked this conversation as resolved.
Show resolved Hide resolved
import ListField from '/client/components/uniforms/base/ListField';

Check failure on line 6 in packages/uniforms-mantine/src/AutoField.tsx

View workflow job for this annotation

GitHub Actions / CI (14.x)

Cannot find module '/client/components/uniforms/base/ListField' or its corresponding type declarations.

Check failure on line 6 in packages/uniforms-mantine/src/AutoField.tsx

View workflow job for this annotation

GitHub Actions / CI (18.x)

Cannot find module '/client/components/uniforms/base/ListField' or its corresponding type declarations.
import NestField from '/client/components/uniforms/base/NestField';

Check failure on line 7 in packages/uniforms-mantine/src/AutoField.tsx

View workflow job for this annotation

GitHub Actions / CI (14.x)

Cannot find module '/client/components/uniforms/base/NestField' or its corresponding type declarations.

Check failure on line 7 in packages/uniforms-mantine/src/AutoField.tsx

View workflow job for this annotation

GitHub Actions / CI (18.x)

Cannot find module '/client/components/uniforms/base/NestField' or its corresponding type declarations.
import NumField from '/client/components/uniforms/base/NumField';

Check failure on line 8 in packages/uniforms-mantine/src/AutoField.tsx

View workflow job for this annotation

GitHub Actions / CI (14.x)

Cannot find module '/client/components/uniforms/base/NumField' or its corresponding type declarations.

Check failure on line 8 in packages/uniforms-mantine/src/AutoField.tsx

View workflow job for this annotation

GitHub Actions / CI (18.x)

Cannot find module '/client/components/uniforms/base/NumField' or its corresponding type declarations.
import SelectField from '/client/components/uniforms/base/SelectField';

Check failure on line 9 in packages/uniforms-mantine/src/AutoField.tsx

View workflow job for this annotation

GitHub Actions / CI (14.x)

Cannot find module '/client/components/uniforms/base/SelectField' or its corresponding type declarations.

Check failure on line 9 in packages/uniforms-mantine/src/AutoField.tsx

View workflow job for this annotation

GitHub Actions / CI (18.x)

Cannot find module '/client/components/uniforms/base/SelectField' or its corresponding type declarations.
import TextField from '/client/components/uniforms/base/TextField';

Check failure on line 10 in packages/uniforms-mantine/src/AutoField.tsx

View workflow job for this annotation

GitHub Actions / CI (14.x)

Cannot find module '/client/components/uniforms/base/TextField' or its corresponding type declarations.

Check failure on line 10 in packages/uniforms-mantine/src/AutoField.tsx

View workflow job for this annotation

GitHub Actions / CI (18.x)

Cannot find module '/client/components/uniforms/base/TextField' or its corresponding type declarations.

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 '/client/components/uniforms/base/AutoField';

Check failure on line 4 in packages/uniforms-mantine/src/AutoFields.tsx

View workflow job for this annotation

GitHub Actions / CI (14.x)

Cannot find module '/client/components/uniforms/base/AutoField' or its corresponding type declarations.

Check failure on line 4 in packages/uniforms-mantine/src/AutoFields.tsx

View workflow job for this annotation

GitHub Actions / CI (18.x)

Cannot find module '/client/components/uniforms/base/AutoField' or its corresponding type declarations.

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 '/client/components/uniforms/base/ValidatedQuickForm';

Check failure on line 3 in packages/uniforms-mantine/src/AutoForm.tsx

View workflow job for this annotation

GitHub Actions / CI (14.x)

Cannot find module '/client/components/uniforms/base/ValidatedQuickForm' or its corresponding type declarations.

Check failure on line 3 in packages/uniforms-mantine/src/AutoForm.tsx

View workflow job for this annotation

GitHub Actions / CI (18.x)

Cannot find module '/client/components/uniforms/base/ValidatedQuickForm' or its corresponding type declarations.

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);
37 changes: 37 additions & 0 deletions packages/uniforms-mantine/src/BoolField.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import { Checkbox, CheckboxProps } from '@mantine/core';
import React, { Ref } from 'react';
import { connectField, FieldProps, filterDOMProps } from 'uniforms';

export type BoolFieldProps = FieldProps<
boolean,
CheckboxProps,
{ inputRef?: Ref<typeof Checkbox | any> }
>;

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

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

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

/* istanbul ignore next */
const DateConstructor = (typeof global === 'object' ? global : window).Date;
const dateFormat = (value?: Date, type: DateFieldType = 'datetime-local') =>
value?.toISOString().slice(0, type === 'datetime-local' ? -8 : -14);

export type DateFieldProps = HTMLFieldProps<
Date,
HTMLDivElement,
{
inputRef?: Ref<HTMLInputElement>;
max?: Date;
min?: Date;
type?: DateFieldType;
}
>;

function Date({
disabled,
id,
inputRef,
label,
max,
min,
name,
onChange,
placeholder,
readOnly,
value,
type = 'datetime-local',
...props
}: DateFieldProps) {
return (
<div {...filterDOMProps(props)}>
{label && <label htmlFor={id}>{label}</label>}

<input
disabled={disabled}
id={id}
max={dateFormat(max)}
min={dateFormat(min)}
name={name}
onChange={event => {
const date = new DateConstructor(event.target.valueAsNumber);
if (date.getFullYear() < 10000) {
onChange(date);
} else if (isNaN(event.target.valueAsNumber)) {
onChange(undefined);
}
}}
placeholder={placeholder}
readOnly={readOnly}
ref={inputRef}
type={type}
value={dateFormat(value, type) ?? ''}
/>
</div>
);
}

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