Skip to content

Commit

Permalink
feat: Create Daisy UI v5 equivalent custom widgets
Browse files Browse the repository at this point in the history
  • Loading branch information
inchoate committed Jan 31, 2025
1 parent b121756 commit 371946c
Show file tree
Hide file tree
Showing 87 changed files with 14,016 additions and 7,863 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -140,3 +140,4 @@ out/

# typescript tsbuildinfo
*.tsbuildinfo
.aider*
20,008 changes: 12,381 additions & 7,627 deletions package-lock.json

Large diffs are not rendered by default.

6 changes: 5 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@
"packages/bootstrap-4",
"packages/chakra-ui",
"packages/core",
"packages/daisy-ui",
"packages/docs",
"packages/fluent-ui",
"packages/fluentui-rc",
Expand All @@ -80,5 +81,8 @@
"packages/validator-ajv8",
"packages/snapshot-tests"
],
"packageManager": "[email protected]+sha512.a6b2f7906b721bba3d67d4aff083df04dad64c399707841b7acf00f6b133b7ac24255f2652fa22ae3534329dc6180534e98d17432037ff6fd140556e2bb3137e"
"packageManager": "[email protected]+sha512.a6b2f7906b721bba3d67d4aff083df04dad64c399707841b7acf00f6b133b7ac24255f2652fa22ae3534329dc6180534e98d17432037ff6fd140556e2bb3137e",
"dependencies": {
"tailwindcss": "^4.0.1"
}
}
18 changes: 18 additions & 0 deletions packages/daisy-ui/.eslintrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
{
"extends": ["eslint:recommended", "plugin:react/recommended", "plugin:@typescript-eslint/recommended"],
"parser": "@typescript-eslint/parser",
"plugins": ["@typescript-eslint", "react"],
"env": {
"browser": true,
"es2021": true
},
"settings": {
"react": {
"version": "detect"
}
},
"rules": {
"react/prop-types": "off",
"@typescript-eslint/explicit-module-boundary-types": "off"
}
}
40 changes: 40 additions & 0 deletions packages/daisy-ui/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
# @rjsf/daisy-ui

This package provides Daisy UI components for use with `react-jsonschema-form`. It includes a set of custom widgets and templates styled with Daisy UI.

## Installation

Since this package is not published to npm, you can use it locally by linking it in your project.

## Usage

Import the `DaisyForm` component and use it in your application:

```jsx
import { DaisyForm } from '@rjsf/daisy-ui';

function App() {
return (
<DaisyForm schema={yourSchema} uiSchema={yourUiSchema} formData={yourFormData} />
);
}
```

## Development

To develop and test this package locally, use the following commands:

```bash
# Build the package
npm run build

# Link the package locally
npm link

# In your application directory
npm link @rjsf/daisy-ui
```

## License

This project is licensed under the Apache-2.0 License.
11 changes: 11 additions & 0 deletions packages/daisy-ui/babel.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
module.exports = {
presets: [
'@babel/preset-env',
'@babel/preset-react',
'@babel/preset-typescript'
],
plugins: [
'@babel/plugin-proposal-class-properties',
'@babel/plugin-proposal-object-rest-spread'
]
};
33 changes: 33 additions & 0 deletions packages/daisy-ui/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
{
"name": "@rjsf/daisy-ui",
"version": "0.1.0",
"description": "Daisy UI components for react-jsonschema-form",
"main": "src/index.ts",
"types": "src/index.ts",
"scripts": {
"build": "tsc -b",
"build:cjs": "esbuild ./src/index.ts --bundle --outfile=dist/index.js --sourcemap --packages=external --format=cjs",
"build:esm": "esbuild ./src/index.ts --bundle --outfile=dist/daisy-ui.esm.js --sourcemap --packages=external --format=esm",
"build:umd": "rollup dist/daisy-ui.esm.js --format=umd --file=dist/daisy-ui.umd.js --name=@rjsf/daisy-ui"
},
"dependencies": {
"@rjsf/core": "^5.24.2",
"@rjsf/utils": "^5.24.2",
"react": "^18.2.0",
"daisyui": "^5.0.0-beta.5"
},
"peerDependencies": {
"react": "^18.2.0"
},
"devDependencies": {
"typescript": "^4.9.5",
"esbuild": "^0.14.0",
"rollup": "^2.70.0"
},
"repository": {
"type": "git",
"url": "git+https://github.com/rjsf-team/react-jsonschema-form.git"
},
"author": "Your Name <[email protected]>",
"license": "Apache-2.0"
}
12 changes: 12 additions & 0 deletions packages/daisy-ui/src/AddButton/AddButton.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { DaisyProps } from '../types/DaisyProps';
import { IconButtonProps, StrictRJSFSchema, RJSFSchema, FormContextType } from '@rjsf/utils';

export default function AddButton<T = any, S extends StrictRJSFSchema = RJSFSchema, F extends FormContextType = any>(
props: IconButtonProps<T, S, F> & DaisyProps
) {
return (
<button className='btn btn-primary' {...props}>
<span className='icon'>+</span> Add Item
</button>
);
}
2 changes: 2 additions & 0 deletions packages/daisy-ui/src/AddButton/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export { default } from './AddButton';
export * from './AddButton';
14 changes: 14 additions & 0 deletions packages/daisy-ui/src/DaisyForm/DaisyForm.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import { ComponentType } from 'react';
import { withTheme, FormProps } from '@rjsf/core';
import { generateTheme } from '../Theme';
import { FormContextType, RJSFSchema, StrictRJSFSchema } from '@rjsf/utils';

export function generateForm<
T = any,
S extends StrictRJSFSchema = RJSFSchema,
F extends FormContextType = any
>(): ComponentType<FormProps<T, S, F>> {
return withTheme<T, S, F>(generateTheme<T, S, F>());
}

export default generateForm();
2 changes: 2 additions & 0 deletions packages/daisy-ui/src/DaisyForm/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export { default } from './DaisyForm';
export * from './DaisyForm';
47 changes: 47 additions & 0 deletions packages/daisy-ui/src/DaisyUIFrameProvider.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
/**
* __createDaisyUIFrameProvider is used to ensure that DaisyUI styles
* can be rendered within an iframe without affecting the parent page.
* Required for using DaisyUI in the playground.
*
* NOTE: This is an internal component only used by @rjsf/playground
*/

interface DaisyUIFrameProviderProps {
children: React.ReactNode;
subtheme?: { dataTheme?: string } | null;
}

export const __createDaisyUIFrameProvider =
(props: DaisyUIFrameProviderProps) =>
({ document }: { document?: Document }) => {
if (document) {
// Add Tailwind script
const tailwindScript = document.createElement('script');
tailwindScript.src = 'https://cdn.tailwindcss.com';
document.head.appendChild(tailwindScript);

// Configure Tailwind with DaisyUI
const tailwindConfig = document.createElement('script');
tailwindConfig.textContent = `
tailwind.config = {
plugins: [require("daisyui")],
daisyui: {
themes: true
},
}
`;
document.head.appendChild(tailwindConfig);

// Add DaisyUI
const daisyLink = document.createElement('link');
daisyLink.rel = 'stylesheet';
daisyLink.href = 'https://cdn.jsdelivr.net/npm/daisyui@latest/dist/full.css';
document.head.appendChild(daisyLink);
}
console.log('Theme: ', props.subtheme?.dataTheme);
return (
<div data-theme={props.subtheme?.dataTheme || 'light'} className='daisy-ui-theme'>
{props.children}
</div>
);
};
12 changes: 12 additions & 0 deletions packages/daisy-ui/src/FieldError/FieldError.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@

const FieldError = ({ errors }: { errors: string[] }) => (
<div className="field-error text-red-600">
{errors.map((error, index) => (
<p key={index} className="text-sm">
{error}
</p>
))}
</div>
);

export default FieldError;
2 changes: 2 additions & 0 deletions packages/daisy-ui/src/FieldError/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export { default } from './FieldError';
export * from './FieldError';
8 changes: 8 additions & 0 deletions packages/daisy-ui/src/FieldHelp/FieldHelp.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@

const FieldHelp = ({ help }: { help: string }) => (
<div className="field-help text-gray-500 text-sm">
<p>{help}</p>
</div>
);

export default FieldHelp;
2 changes: 2 additions & 0 deletions packages/daisy-ui/src/FieldHelp/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export { default } from './FieldHelp';
export * from './FieldHelp';
13 changes: 13 additions & 0 deletions packages/daisy-ui/src/IconButton/IconButton.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { DaisyProps } from '../types/DaisyProps';
import { IconButtonProps, StrictRJSFSchema, RJSFSchema, FormContextType } from '@rjsf/utils';

export default function IconButton<T = any, S extends StrictRJSFSchema = RJSFSchema, F extends FormContextType = any>(
props: IconButtonProps<T, S, F> & DaisyProps
) {
const { icon, title, ...otherProps } = props;
return (
<button className='btn btn-icon' title={title} {...otherProps}>
<span className={`icon-${icon}`} />
</button>
);
}
2 changes: 2 additions & 0 deletions packages/daisy-ui/src/IconButton/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export { default } from './IconButton';
export * from './IconButton';
8 changes: 8 additions & 0 deletions packages/daisy-ui/src/SubmitButton/SubmitButton.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@

const SubmitButton = ({ submitText = "Submit" }: { submitText?: string }) => (
<button type="submit" className="btn btn-primary">
{submitText}
</button>
);

export default SubmitButton;
2 changes: 2 additions & 0 deletions packages/daisy-ui/src/SubmitButton/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export { default } from './SubmitButton';
export * from './SubmitButton';
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import { ArrayFieldTemplateItemType, StrictRJSFSchema, RJSFSchema, FormContextType } from '@rjsf/utils';

const ArrayFieldItemTemplate = <T = any, S extends StrictRJSFSchema = RJSFSchema, F extends FormContextType = any>(
props: ArrayFieldTemplateItemType<T, S, F>
) => {
const { children, hasMoveUp, hasMoveDown, onDropIndexClick, onReorderClick, index } = props;
return (
<div className='array-field-item'>
<div className='array-field-item-content'>{children}</div>
<div className='array-field-item-controls'>
{hasMoveUp && (
<button type='button' className='btn btn-secondary' onClick={onReorderClick(index, index - 1)}>
Move Up
</button>
)}
{hasMoveDown && (
<button type='button' className='btn btn-secondary' onClick={onReorderClick(index, index + 1)}>
Move Down
</button>
)}
<button type='button' className='btn btn-danger' onClick={onDropIndexClick(index)}>
Remove
</button>
</div>
</div>
);
};

export default ArrayFieldItemTemplate;
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export { default } from './ArrayFieldItemTemplate';
export * from './ArrayFieldItemTemplate';
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import { ArrayFieldTemplateProps, StrictRJSFSchema, RJSFSchema, FormContextType } from '@rjsf/utils';

const ArrayFieldTemplate = <T = any, S extends StrictRJSFSchema = RJSFSchema, F extends FormContextType = any>(
props: ArrayFieldTemplateProps<T, S, F>
) => {
const { items, canAdd, onAddClick, title } = props;
return (
<div className='array-field'>
<div className='array-field-title'>{title}</div>
<div className='array-field-items'>
{items.map((element) => (
<div key={element.index} className='array-field-item'>
{element.children}
</div>
))}
</div>
{canAdd && (
<button type='button' className='btn btn-primary' onClick={onAddClick}>
Add Item
</button>
)}
</div>
);
};

export default ArrayFieldTemplate;
2 changes: 2 additions & 0 deletions packages/daisy-ui/src/Templates/ArrayFieldTemplate/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export { default } from './ArrayFieldTemplate';
export * from './ArrayFieldTemplate';
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import { WidgetProps, StrictRJSFSchema, RJSFSchema, FormContextType } from '@rjsf/utils';

export default function BaseInputTemplate<
T = any,
S extends StrictRJSFSchema = RJSFSchema,
F extends FormContextType = any
>(props: WidgetProps<T, S, F>) {
const { id, value, required, disabled, readonly, onChange, label } = props;
return (
<div className='form-control'>
<label htmlFor={id} className='label hidden' style={{ display: 'none' }}>
<span className='label-text'>{label}</span>
</label>
<input
type='text'
id={id}
value={value}
required={required}
disabled={disabled || readonly}
onChange={(event) => onChange(event.target.value)}
className='input input-bordered'
/>
</div>
);
}
2 changes: 2 additions & 0 deletions packages/daisy-ui/src/Templates/BaseInputTemplate/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export { default } from './BaseInputTemplate';
export * from './BaseInputTemplate';
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { DescriptionFieldProps, StrictRJSFSchema, RJSFSchema, FormContextType } from '@rjsf/utils';

export default function DescriptionField<T = any, S extends StrictRJSFSchema = RJSFSchema, F extends FormContextType = any>(
props: DescriptionFieldProps<T, S, F>
) {
const { id, description } = props;
return (
<div id={id} className="description-field">
<p className="text-sm text-gray-600">{description}</p>
</div>
);
}
2 changes: 2 additions & 0 deletions packages/daisy-ui/src/Templates/DescriptionField/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export { default } from './DescriptionField';
export * from './DescriptionField';
16 changes: 16 additions & 0 deletions packages/daisy-ui/src/Templates/ErrorList/ErrorList.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { ErrorListProps, StrictRJSFSchema, RJSFSchema, FormContextType } from '@rjsf/utils';

export default function ErrorList<T = any, S extends StrictRJSFSchema = RJSFSchema, F extends FormContextType = any>(
props: ErrorListProps<T, S, F>
) {
const { errors } = props;
return (
<div className="error-list">
<ul className="list-disc list-inside text-red-600">
{errors.map((error, index) => (
<li key={index}>{error.stack}</li>
))}
</ul>
</div>
);
}
Loading

0 comments on commit 371946c

Please sign in to comment.