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

Docs landing page #1383

Merged
merged 15 commits into from
Nov 18, 2024
Merged
330 changes: 183 additions & 147 deletions pnpm-lock.yaml

Large diffs are not rendered by default.

12 changes: 9 additions & 3 deletions website/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,22 +4,28 @@ This website is built using [Docusaurus](https://docusaurus.io/), a modern stati

### Installation

In the root directory of the project, run:

```
$ yarn
$ pnpm install
```

### Local Development

In the root directory of the project, run:

```
$ yarn start
$ pnpm -filter=website run start
```

This command starts a local development server and opens up a browser window. Most changes are reflected live without having to restart the server.

### Build

In the root directory of the project, run:

```
$ yarn build
$ pnpm -filter=website run build
```

This command generates static content into the `build` directory and can be served using any static contents hosting service.
Expand Down
8 changes: 8 additions & 0 deletions website/docs/compare-matrix-landing.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
| Feature | [uniforms](https://github.com/vazco/uniforms) | [Formik](https://github.com/jaredpalmer/formik) | [redux-form](https://github.com/erikras/redux-form) | [React Final Form](https://github.com/final-form/react-final-form) | [react-hook-form](https://github.com/react-hook-form/react-hook-form) |
| :----------------------------------------------------------------------------- | :---------------------------------------------------------------------------------: | :---------------------------------------------------------------------------------: | :---------------------------------------------------------------------------------: | :---------------------------------------------------------------------------------: | ----------------------------------------------------------------------------------- |
| Automatic form layout | ![supported](https://github.githubassets.com/images/icons/emoji/unicode/2714.png) | ![unsupported](https://github.githubassets.com/images/icons/emoji/unicode/2716.png) | ![unsupported](https://github.githubassets.com/images/icons/emoji/unicode/2716.png) | ![unsupported](https://github.githubassets.com/images/icons/emoji/unicode/2716.png) | ![unsupported](https://github.githubassets.com/images/icons/emoji/unicode/2716.png) |
| Manual state management | ![supported](https://github.githubassets.com/images/icons/emoji/unicode/2714.png) | ![unsupported](https://github.githubassets.com/images/icons/emoji/unicode/2716.png) | ![supported](https://github.githubassets.com/images/icons/emoji/unicode/2714.png) | ![unsupported](https://github.githubassets.com/images/icons/emoji/unicode/2716.png) | ![supported](https://github.githubassets.com/images/icons/emoji/unicode/2714.png) |
| Manually trigger validation | ![supported](https://github.githubassets.com/images/icons/emoji/unicode/2714.png) | ![supported](https://github.githubassets.com/images/icons/emoji/unicode/2714.png) | ![unsupported](https://github.githubassets.com/images/icons/emoji/unicode/2716.png) | ![unsupported](https://github.githubassets.com/images/icons/emoji/unicode/2716.png) | ![supported](https://github.githubassets.com/images/icons/emoji/unicode/2714.png) |
| AntD, Bootstrap 3, Bootstrap 4, Bootstrap 5, Material, MUI, Semantic UI themes | ![supported](https://github.githubassets.com/images/icons/emoji/unicode/2714.png) | ![unsupported](https://github.githubassets.com/images/icons/emoji/unicode/2716.png) | ![unsupported](https://github.githubassets.com/images/icons/emoji/unicode/2716.png) | ![unsupported](https://github.githubassets.com/images/icons/emoji/unicode/2716.png) | ![unsupported](https://github.githubassets.com/images/icons/emoji/unicode/2716.png) |
| JSON, GraphQL, SimpleSchema, Zod and custom schema support | ![supported](https://github.githubassets.com/images/icons/emoji/unicode/2714.png) | ![unsupported](https://github.githubassets.com/images/icons/emoji/unicode/2716.png) | ![unsupported](https://github.githubassets.com/images/icons/emoji/unicode/2716.png) | ![unsupported](https://github.githubassets.com/images/icons/emoji/unicode/2716.png) | ![unsupported](https://github.githubassets.com/images/icons/emoji/unicode/2716.png) |
| Field level validation | ![unsupported](https://github.githubassets.com/images/icons/emoji/unicode/2716.png) | ![supported](https://github.githubassets.com/images/icons/emoji/unicode/2714.png) | ![supported](https://github.githubassets.com/images/icons/emoji/unicode/2714.png) | ![supported](https://github.githubassets.com/images/icons/emoji/unicode/2714.png) | ![supported](https://github.githubassets.com/images/icons/emoji/unicode/2714.png) |
58 changes: 58 additions & 0 deletions website/docusaurus.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,49 @@ const config: Config = {
],
],

customFields: {
email: '[email protected]',
companies: [
{ url: 'https://www.deskpro.com/', image: 'deskpro.png', alt: 'Deskpro' },
{ url: 'https://www.nokia.com/', image: 'nokia.png', alt: 'Nokia' },
{
url: 'https://github.com/react-page/react-page/tree/master/packages/plugins/createPluginMaterialUi',
image: 'react-page.png',
alt: 'React Page',
},
{
url: 'https://graphback.dev',
image: 'graphback.png',
alt: 'Graphback',
},
{
url: 'https://www.onyx-one.com/',
image: 'onyx-one.png',
alt: 'Onyx one',
},
{ url: 'https://aerogear.org', image: 'aerogear.png', alt: 'Aerogear' },
{
url: 'https://cleverbeagle.com/together',
image: 'cleverbeagle.png',
alt: 'Clever Beagle',
},
{ url: 'http://www.orionjs.org', image: 'orionjs.png', alt: 'Orion.js' },
{
url: 'https://boulder.care',
image: 'boulder.svg',
alt: 'Boulder Care',
},
],
},

themeConfig: {
algolia: {
apiKey: '9bab87682792c2bd77ec707a56669e29',
appId: 'WWWW16GKXU',
contextualSearch: false,
indexName: 'uniforms',
searchPagePath: false,
},
navbar: {
logo: { alt: 'uniforms logo', src: 'img/uniforms.svg' },
items: [
Expand All @@ -46,11 +88,27 @@ const config: Config = {
position: 'left',
label: 'Docs',
},
{
label: 'Tutorial',
to: '/docs/tutorials-basic-uniforms-usage',
position: 'left',
},
{ label: 'Playground', to: '/playground', position: 'left' },
{
href: 'https://github.com/vazco/uniforms',
label: 'GitHub',
position: 'left',
},
{
label: 'Enterprise',
href: 'https://forminer.com/?utm_source=uniforms&utm_medium=Menu_CTA&utm_campaign=Forminer_uniforms_menu_CTA&utm_id=Forminer_uniforms_menu',
position: 'left',
},
{
label: 'Custom solutions',
href: 'https://www.vazco.eu/',
position: 'left',
},
],
},
prism: {
Expand Down
17 changes: 15 additions & 2 deletions website/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,17 +20,30 @@
"@docusaurus/core": "3.5.2",
"@docusaurus/preset-classic": "3.5.2",
"@mdx-js/react": "^3.0.0",
"ajv": "8.17.1",
"antd": "5.21.5",
"classnames": "^2.0.0",
"clsx": "^2.0.0",
"lodash": "^4.0.0",
"lz-string": "1.5.0",
"message-box": "0.2.7",
"prism-react-renderer": "^2.3.0",
"raw-loader": "4.0.2",
"react": "^18.0.0",
"react-dom": "^18.0.0"
"react-dom": "^18.0.0",
"react-feather": "2.0.10",
"react-frame-component": "5.2.7",
"zod": "3.23.8"
},
"devDependencies": {
"@docusaurus/module-type-aliases": "3.5.2",
"@docusaurus/theme-classic": "3.5.2",
"@docusaurus/tsconfig": "3.5.2",
"@docusaurus/types": "3.5.2",
"typescript": "~5.5.2"
"@types/simpl-schema": "1.12.8",
"simpl-schema": "1.13.1",
"typescript": "~5.5.2",
"uniforms": "workspace:*"
},
piotrpospiech marked this conversation as resolved.
Show resolved Hide resolved
"browserslist": {
"production": [
Expand Down
45 changes: 45 additions & 0 deletions website/src/components/Badge.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import Link from '@docusaurus/Link';
import classNames from 'classnames';
import React, { ComponentType } from 'react';

import styles from '../css/index.module.css';
import { Oval } from './Oval';

export type BadgeProps = {
border: number;
color: string;
icon: ComponentType<{ color?: string }>;
number?: string;
text: string;
to: string;
};

export function Badge({
border,
color,
icon: Icon,
number,
text,
to,
}: BadgeProps) {
return (
<Link to={to} className={classNames(styles.badge)}>
<img
className={styles['badge-image']}
src={`img/border-0${border}.svg`}
alt=""
/>
{Icon && (
<Oval className={styles['top-right-corner']}>
<Icon color={color} />
</Oval>
)}
<div className={classNames(styles['badge-centered'], styles.centered)}>
<div style={{ color }} className={styles['badge-number']}>
{number}
</div>
<p className={styles.text}>{text}</p>
</div>
</Link>
);
}
24 changes: 24 additions & 0 deletions website/src/components/Button.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import Link from '@docusaurus/Link';
import classNames from 'classnames';
import React from 'react';

import styles from '../css/index.module.css';

export type ButtonProps = JSX.IntrinsicElements['button'] & { to: string };

export function Button({ children, className, to, ...props }: ButtonProps) {
return (
<Link to={to}>
<button
{...props}
className={classNames(
'button button--lg button--primary',
styles['call-to-action'],
className,
)}
>
{children}
</button>
</Link>
);
}
66 changes: 66 additions & 0 deletions website/src/components/CodeSection.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
import components from '@theme/MDXComponents';
import React from 'react';

export type CodeSectionProps = {
language: string;
replace?: Record<string, string>;
section?: string;
source: string | { default: string };
};

export function CodeSection({
language,
replace,
section,
source,
}: CodeSectionProps) {
// Unwrap ES module.
if (typeof source === 'object' && 'default' in source) {
source = source.default;
}

// Cut out only desired section.
if (section) {
const pattern = new RegExp(
`// <${section}>\\s([\\s\\S]*?)\\s// </${section}>\\s`,
'g',
);

source = source
.split(pattern)
.reduce(
(source, part, index) =>
index % 2 === 0 ? source : `${source}\n\n${part}`,
'',
);
}

// Remove remaining section tags.
source = source.replace(/\/\/ <.*?\n/g, '');

// Replace all mapped things.
if (replace) {
for (const [pattern, value] of Object.entries(replace)) {
source = source.replace(new RegExp(pattern, 'gs'), value);
}
}

// At least one newline is required for non-inline view.
source = source.trim();
if (!source.includes('\n')) {
source += '\n';
}

return (
<components.pre>
<components.code
children={source}
className={`language-${language}`}
//@ts-expect-error: Property 'mdxType' does not exist on type 'IntrinsicAttributes & Props'.
mdxType="code"
originalType="code"
parentName="pre"
/>
</components.pre>
);
}
63 changes: 63 additions & 0 deletions website/src/components/ExampleCustomizer.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
import React, { ComponentType } from 'react';
import { Box, Code, Database } from 'react-feather';

import { themeContext } from '../lib/universal';
import { CodeSection } from './CodeSection';
import { FormWrapper } from './FormWrapper';
import { TogglerTabs } from './TogglerTabs';

const tabs = [
{ name: 'Semantic', value: 'semantic' as const },
{ name: 'MUI', value: 'mui' as const },
{ name: 'Bootstrap4', value: 'bootstrap4' as const },
{ name: 'Bootstrap5', value: 'bootstrap5' as const },
{ name: 'AntD', value: 'antd' as const },
{ name: 'Unstyled', value: 'unstyled' as const },
];

const toggles = [
{ icon: <Box />, name: 'Example', tooltipText: 'Show example' },
{ icon: <Code />, name: 'Code', tooltipText: 'Show source code' },
{ icon: <Database />, name: 'Schema', tooltipText: 'Show schema' },
];

export type ExampleCustomizerProps = {
code: { default: string };
example: ComponentType;
schema: { default: string };
};

export function ExampleCustomizer({
code: { default: code },
example: Example,
schema: { default: schema },
}: ExampleCustomizerProps) {
return (
<TogglerTabs group="examples" tabsItems={tabs} togglerItems={toggles}>
{({ tab: { value: theme }, toggle: { name } }) => {
switch (name) {
case 'Code':
return (
<CodeSection
language="tsx"
replace={{ "'[^']*?/universal'": `'uniforms-${theme}'` }}
source={code}
/>
);
case 'Example':
return (
<themeContext.Provider value={theme}>
<FormWrapper>
<Example />
</FormWrapper>
</themeContext.Provider>
);
case 'Schema':
return <CodeSection language="tsx" source={schema} />;
default:
return null;
}
}}
</TogglerTabs>
);
}
21 changes: 21 additions & 0 deletions website/src/components/FormWrapper.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import React, { ReactNode, useContext } from 'react';

import styles from '../css/index.module.css';
import { useFrameAutoResize } from '../lib/autoresize';
import { themeContext } from '../lib/universal';
import { PlaygroundWrap } from './Playground';

export type FormWrapperProps = {
children: ReactNode;
};

export function FormWrapper(props: FormWrapperProps) {
const theme = useContext(themeContext);
const frameProps = useFrameAutoResize([props.children]);

return (
<div className={styles['form-wrapper']}>
<PlaygroundWrap frameProps={frameProps} theme={theme} {...props} />
</div>
);
}
14 changes: 14 additions & 0 deletions website/src/components/Heading.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import classNames from 'classnames';
import React from 'react';

import styles from '../css/index.module.css';

export type HeadingProps = JSX.IntrinsicElements['h1'];

export function Heading({ children, className, ...props }: HeadingProps) {
return (
<h2 {...props} className={classNames(styles.heading, className)}>
{children}
</h2>
);
}
Loading
Loading