Skip to content
Closed
Show file tree
Hide file tree
Changes from 4 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
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,9 @@ coverage
# Dependency directories
node_modules/

# Optional npm cache directory
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is already in the .gitignore on the head of main which you are not on yet

.nx/cache/

# Optional npm cache directory
.npm

Expand Down
688 changes: 401 additions & 287 deletions package-lock.json

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@
"packages/mui",
"packages/playground",
"packages/semantic-ui",
"packages/uswds",
"packages/utils",
"packages/validator-ajv6",
"packages/validator-ajv8",
Expand Down
2 changes: 2 additions & 0 deletions packages/playground/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@
"@rjsf/material-ui": "^5.24.8",
"@rjsf/mui": "^5.24.8",
"@rjsf/semantic-ui": "^5.24.8",
"@rjsf/uswds": "^6.0.0",
"@rjsf/utils": "^5.24.8",
"@rjsf/validator-ajv6": "^5.24.8",
"@rjsf/validator-ajv8": "^5.24.8",
Expand All @@ -64,6 +65,7 @@
"dayjs": "^1.11.10",
"deep-freeze-es6": "^1.4.1",
"framer-motion": "^5.6.0",
"husky": "^9.1.7",
"jss": "^10.10.0",
"lodash": "^4.17.21",
"monaco-editor": "^0.38.0",
Expand Down
5 changes: 5 additions & 0 deletions packages/playground/src/app.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { Theme as SuiTheme } from '@rjsf/semantic-ui';
import { Theme as AntdTheme } from '@rjsf/antd';
import { Theme as Bootstrap4Theme } from '@rjsf/bootstrap-4';
import { Theme as ChakraUITheme } from '@rjsf/chakra-ui';
import { Theme as UswdsTheme } from '@rjsf/uswds';
import v8Validator, { customizeValidator } from '@rjsf/validator-ajv8';
import v6Validator from '@rjsf/validator-ajv6';
import localize_es from 'ajv-i18n/localize/es';
Expand Down Expand Up @@ -125,6 +126,10 @@ const themes: PlaygroundProps['themes'] = {
stylesheet: '//cdn.jsdelivr.net/npm/[email protected]/dist/semantic.min.css',
theme: SuiTheme,
},
uswds: {
stylesheet: 'https://cdn.jsdelivr.net/npm/uswds/dist/css/uswds.min.css',
theme: UswdsTheme,
},
};

export default function App() {
Expand Down
5 changes: 3 additions & 2 deletions packages/playground/vite.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,13 +24,14 @@ export default defineConfig({
'@rjsf/material-ui': path.resolve(__dirname, '../material-ui/src'),
'@rjsf/mui': path.resolve(__dirname, '../mui/src'),
'@rjsf/semantic-ui': path.resolve(__dirname, '../semantic-ui/src'),
'@rjsf/uswds': path.resolve(__dirname, '../uswds/src'),
'@rjsf/utils': path.resolve(__dirname, '../utils/src'),
'@rjsf/validator-ajv8': path.resolve(__dirname, '../validator-ajv8/src'),
// validator-ajv6 can not be mapped directly to the sources, because that causes wrong ajv version resolution
// which looks related to: https://github.com/vitejs/vite/issues/12618
//
// the difference when mapping directly vs mapping to src folder - @vitejs/plugin-react can not be applied in the 2nd case
'@rjsf/validator-ajv6': '@rjsf/validator-ajv6/src',
},
},
},
});
});
Comment on lines +35 to +37
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you revert these changes?

12 changes: 12 additions & 0 deletions packages/uswds/.eslintrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"extends": [
"../../.eslintrc"
],
"rules": {
"prettier/prettier": ["error", {
"singleQuote": true,
"trailingComma": "all",
"arrowParens": "always"
}]
}
}
6 changes: 6 additions & 0 deletions packages/uswds/.prettierrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"singleQuote": true,
"trailingComma": "all",
"arrowParens": "always",
"printWidth": 100
}
102 changes: 102 additions & 0 deletions packages/uswds/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
[Github](https://github.com/uswds/uswds)
[NPM](https://www.npmjs.com/package/uswds)
[jsDeliver](https://www.jsdelivr.com/package/npm/uswds)
[Website](https://designsystem.digital.gov/)

# @rjsf/uswds

USWDS theme, fields and widgets for [`react-jsonschema-form`](https://github.com/rjsf-team/react-jsonschema-form/).

## Installation

```bash
npm install @rjsf/core @rjsf/uswds @uswds/uswds react react-dom
```
## Usage

## Prerequisites: USWDS CSS

**This package does not bundle USWDS CSS.** You must include the USWDS stylesheet in your project. Choose one method:

1. **Import CSS/Sass:**
```javascript
// In your application's entry point (e.g., index.js or App.js)
import '@uswds/uswds/dist/css/uswds.min.css';

// Or if using Sass:
// @import "~@uswds/uswds/dist/scss/uswds"; // Adjust path as needed
```

2. **Link in HTML:**
```html
<!-- In your public/index.html or equivalent -->
<link rel="stylesheet" href="/path/to/node_modules/@uswds/uswds/dist/css/uswds.min.css" />
```

### Option 1: Use the themed Form component

This is the simplest way to use the theme.

```jsx
import Form from '@rjsf/uswds';
import validator from '@rjsf/validator-ajv8'; // Or your chosen validator

const MyForm = () => {
const schema = { /* your schema */ };
const uiSchema = { /* your uiSchema */ };
const formData = { /* your data */ };

return <Form schema={schema} uiSchema={uiSchema} formData={formData} validator={validator} />;
}

// Ensure USWDS CSS is loaded as described in Prerequisites.
```

### Option 2: Use `withTheme` for customization

If you need to customize the theme with your own widgets or fields:

```jsx
import { withTheme } from '@rjsf/core';
import { Theme as UswdsTheme } from '@rjsf/uswds';
import validator from '@rjsf/validator-ajv8';

// Optional: Define custom widgets/fields
const myWidgets = {
// myCustomWidget: MyCustomWidgetComponent,
};

const myFields = {
// myCustomField: MyCustomFieldComponent,
};

// Merge customizations with the USWDS theme
const MyTheme = {
...UswdsTheme,
widgets: {
...UswdsTheme.widgets,
...myWidgets,
},
fields: {
...UswdsTheme.fields,
...myFields,
},
};

const Form = withTheme(MyTheme);

const MyForm = () => {
const schema = { /* your schema */ };
return <Form schema={schema} validator={validator} />;
}

// Ensure USWDS CSS is loaded as described in Prerequisites.
```

## Specific Options

Currently, this theme primarily focuses on applying standard USWDS classes and structure. There are no theme-specific `uiSchema` options beyond those provided by `@rjsf/core`.

## Contributing

See the [main RJSF contributing guide](https://rjsf-team.github.io/react-jsonschema-form/docs/contributing/).
3 changes: 3 additions & 0 deletions packages/uswds/babel.config.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"extends": "../../babel.config.js"
}
21 changes: 21 additions & 0 deletions packages/uswds/jest.config.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
{
"rootDir": ".",
"testEnvironment": "jsdom",
"moduleNameMapper": {
"^@rjsf/core/(.*)$": "<rootDir>/../core/src/$1",
"^@rjsf/core$": "<rootDir>/../core/src",
"^@rjsf/utils/(.*)$": "<rootDir>/../utils/src/$1",
"^@rjsf/utils$": "<rootDir>/../utils/src",
"^@rjsf/validator-ajv8/(.*)$": "<rootDir>/../validator-ajv8/src/$1",
"^@rjsf/validator-ajv8$": "<rootDir>/../validator-ajv8/src"
},
"transformIgnorePatterns": [
"/node_modules/(?!nanoid)"
],
"transform": {
"^.+\\.(js|jsx|ts|tsx)$": "babel-jest"
},
"setupFilesAfterEnv": [
"<rootDir>/src/setupTests.ts"
]
}
92 changes: 92 additions & 0 deletions packages/uswds/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
{
"name": "@rjsf/uswds",
"version": "6.0.0",
"description": "USWDS theme, fields and widgets for react-jsonschema-form",
"main": "./dist/index.js",
"module": "./lib/index.js",
"types": "./lib/index.d.ts",
"exports": {
".": {
"types": "./lib/index.d.ts",
"import": "./lib/index.js",
"require": "./dist/index.js"
}
},
"files": [
"dist",
"lib",
"src"
],
"scripts": {
"clean": "rimraf dist lib",
"build": "tsc -b tsconfig.json && tsc -p tsconfig.esm.json",
"cs-check": "prettier -l \"{src,test}/**/*.ts?(x)\"",
"cs-format": "prettier \"{src,test}/**/*.ts?(x)\" --write",
"lint": "eslint src test",
"lint:fix": "eslint src test --fix",
"prettier:fix": "prettier \"{src,test}/**/*.ts?(x)\" --write",
"test": "jest",
"test:update": "jest --u",
"test:clean": "jest --clearCache"
},
"dependencies": {
"@rjsf/utils": "^5.24.8",
"@trussworks/react-uswds": "^5.0.0 || ^6.0.0"
},
"devDependencies": {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These should be peer and dev dependencies

Suggested change
},
"dependencies": {
"@rjsf/utils": "^5.24.8",
"@trussworks/react-uswds": "^5.0.0 || ^6.0.0"
},
"devDependencies": {
},
"devDependencies": {

"@babel/core": "^7.22.8",
"@babel/preset-env": "^7.22.7",
"@babel/preset-react": "^7.22.5",
"@babel/preset-typescript": "^7.22.5",
"@rjsf/core": "^5.24.8",
"@rjsf/snapshot-tests": "^5.24.8",
"@rjsf/utils": "^5.24.8",
"@rjsf/validator-ajv8": "^5.24.8",
"@testing-library/dom": "^10.4.0",
"@testing-library/jest-dom": "^6.4.2",
"@testing-library/react": "^14.2.1",
"@testing-library/user-event": "^14.5.2",
"@types/jest": "^29.5.3",
"@types/react": "^18.2.14",
"@types/react-dom": "^18.2.6",
"@trussworks/react-uswds": "^5.0.0 || ^6.0.0",
"eslint": "^8.44.0",
"jest": "^29.7.0",
"jest-environment-jsdom": "^29.6.1",
"prettier": "^3.0.0",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-test-renderer": "^18.2.0",
"rimraf": "^5.0.5",
"tsc-alias": "^1.8.10",
"typescript": "^5.1.6",
"uswds": "^2.14.0"
},
"peerDependencies": {
"@rjsf/core": "^5.24.8",
"@rjsf/utils": "^5.24.8",
"react": "^17.0.0 || ^18.0.0",
"react-dom": "^17.0.0 || ^18.0.0"
Comment on lines +112 to +113
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
"react": "^17.0.0 || ^18.0.0",
"react-dom": "^17.0.0 || ^18.0.0"
"@trussworks/react-uswds": "^5.0.0 || ^6.0.0",
"react": ">=18",
"react-dom": ">=18",
"uswds": "^2.14.0"

},
"publishConfig": {
"access": "public"
},
"author": "John H. Jediny <[email protected]>",
"contributors": [],
"keywords": [
"react-jsonschema-form",
"jsonschema",
"json-schema",
"json",
"schema",
"form",
"react",
"uswds",
"ui"
],
"repository": {
"type": "git",
"url": "git+https://github.com/rjsf-team/react-jsonschema-form.git"
},
"license": "Apache-2.0"
}
32 changes: 32 additions & 0 deletions packages/uswds/src/Templates/AnyOfField.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import { FormContextType, RJSFSchema, StrictRJSFSchema } from '@rjsf/utils';
import { Select } from '@trussworks/react-uswds';

interface Option {
label: string;
value: string;
}

interface AnyOfFieldProps<T = any, S = RJSFSchema, F = any> {
options: Option[];
id: string;
value?: string;
onChange: (value: string) => void;
}

export default function AnyOfField<T = any, S extends StrictRJSFSchema = RJSFSchema, F extends FormContextType = any>(
props: AnyOfFieldProps<T, S, F>
) {
const { id, options = [], value, onChange } = props;

return (
<Select
id={id}
name={id}
value={value}
onChange={(e) => onChange(e.target.value)}>
{options.map((option: Option, index: number) => (
<option key={index} value={option.value}>{option.label}</option>
))}
</Select>
);
}
13 changes: 13 additions & 0 deletions packages/uswds/src/Templates/ArrayField.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { ArrayFieldTemplateProps, FormContextType, RJSFSchema, StrictRJSFSchema } from '@rjsf/utils';
import { Grid } from '@trussworks/react-uswds';

export default function ArrayFieldTemplate<T = any, S extends StrictRJSFSchema = RJSFSchema, F extends FormContextType = any>(
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you add JS Doc, feel free to copy from another theme

props: ArrayFieldTemplateProps<T, S, F>
) {
const { canAdd, className, disabled, idSchema, items, onAddClick, readonly, registry, required, schema, title, uiSchema } = props;
return (
<Grid className={className}>
{/* ...existing implementation using USWDS components... */}
</Grid>
);
}
26 changes: 26 additions & 0 deletions packages/uswds/src/Templates/ArrayFieldDescription.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@

import { ArrayFieldDescriptionProps, FormContextType, RJSFSchema, StrictRJSFSchema, descriptionId } from '@rjsf/utils';

/** The `ArrayFieldDescriptionTemplate` component renders a description for an array field
*
* @param props - The `ArrayFieldDescriptionProps` for the component
*/
export default function ArrayFieldDescriptionTemplate<
T = any,
S extends StrictRJSFSchema = RJSFSchema,
F extends FormContextType = any,
>(props: ArrayFieldDescriptionProps<T, S, F>) {
// Remove unused schema, uiSchema, registry
const { description, idSchema } = props;
const id = descriptionId<T>(idSchema);

if (!description) {
return null;
}

return (
<p id={id} className="field-description">
{description}
</p>
);
}
Loading