-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Make RJSF theme with in-repo components and style
- Loading branch information
Showing
16 changed files
with
540 additions
and
98 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file was deleted.
Oops, something went wrong.
74 changes: 0 additions & 74 deletions
74
astroplant-frontend/src/rjsf-theme-semantic-ui/widgets/TimeWidget.tsx
This file was deleted.
Oops, something went wrong.
File renamed without changes.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
import { withTheme, ThemeProps } from "@rjsf/core"; | ||
|
||
// We make use of RJSF's core templates as much as possible, rather than | ||
// maintaining our own set. Those templates use Bootstrap, but we don't bundle | ||
// Bootstrap. We apply some presentational styling on the HTML tags / CSS | ||
// classes output by RJSF. It's possible for this to go out of sync when RJSF | ||
// updates, but hopefully this does not happen frequently. We can always | ||
// implement our own template set if necessary. | ||
import "./rjsf.css"; | ||
|
||
import TimeWidget from "./widgets/TimeWidget"; | ||
import CoordinateField from "./CoordinateField"; | ||
import buttonTemplates from "./templates/ButtonTemplates"; | ||
import BaseInputTemplate from "./templates/BaseInputTemplate"; | ||
import SelectWidget from "./widgets/SelectWidget"; | ||
import TextareaWidget from "./widgets/TextareaWidget"; | ||
|
||
const theme: ThemeProps = { | ||
fields: { | ||
CoordinateField: CoordinateField, | ||
}, | ||
widgets: { | ||
TextareaWidget: TextareaWidget, | ||
TimeWidget: TimeWidget, | ||
SelectWidget: SelectWidget, | ||
}, | ||
templates: { | ||
BaseInputTemplate: BaseInputTemplate, | ||
ButtonTemplates: buttonTemplates(), | ||
}, | ||
}; | ||
|
||
const Form = withTheme(theme); | ||
export default Form; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,68 @@ | ||
form.rjsf { | ||
fieldset { | ||
padding: 0; | ||
margin: 0; | ||
margin-bottom: 0.5rem; | ||
border: none; | ||
} | ||
|
||
fieldset fieldset { | ||
padding-left: 1rem; | ||
} | ||
|
||
legend { | ||
display: inline-block; | ||
width: 100%; | ||
font-weight: 600; | ||
border-bottom: 1px solid rgba(0, 0, 0, 0.1); | ||
} | ||
|
||
label { | ||
font-weight: 600; | ||
font-size: 0.85em; | ||
} | ||
|
||
label, | ||
legend { | ||
.required { | ||
color: var(--red-500); | ||
} | ||
} | ||
|
||
.field-description { | ||
margin-bottom: 0.5em; | ||
} | ||
|
||
.array-item-list { | ||
margin-top: 0.25rem; | ||
margin-bottom: 0.25rem; | ||
display: flex; | ||
flex-direction: column; | ||
gap: 0.5rem; | ||
} | ||
|
||
.array-item { | ||
display: flex; | ||
border-radius: 0.5rem; | ||
border-left: 0.2rem solid var(--gray-100); | ||
border-right: 0.2rem solid var(--gray-100); | ||
|
||
.col-xs-9 { | ||
flex: 1; | ||
} | ||
|
||
.array-item-toolbox { | ||
display: flex; | ||
align-items: center; | ||
padding: 0.25rem 1rem; | ||
} | ||
} | ||
|
||
[type="checkbox"] { | ||
margin-right: 0.5em; | ||
} | ||
|
||
select { | ||
width: 100%; | ||
} | ||
} |
115 changes: 115 additions & 0 deletions
115
astroplant-frontend/src/rjsf-theme/templates/BaseInputTemplate.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,115 @@ | ||
// Based on | ||
// https://github.com/rjsf-team/react-jsonschema-form/blob/c0265bd2e388c16b50d5c7ab1d1dafd200d5bb80/packages/core/src/components/templates/BaseInputTemplate.tsx | ||
|
||
import { ChangeEvent, FocusEvent, useCallback } from "react"; | ||
import { | ||
ariaDescribedByIds, | ||
BaseInputTemplateProps, | ||
examplesId, | ||
getInputProps, | ||
FormContextType, | ||
RJSFSchema, | ||
StrictRJSFSchema, | ||
} from "@rjsf/utils"; | ||
import { Input } from "~/Components/Input"; | ||
|
||
/** The `BaseInputTemplate` is the template to use to render the basic `<input>` component for the `core` theme. | ||
* It is used as the template for rendering many of the <input> based widgets that differ by `type` and callbacks only. | ||
* It can be customized/overridden for other themes or individual implementations as needed. | ||
* | ||
* @param props - The `WidgetProps` for this template | ||
*/ | ||
export default function BaseInputTemplate< | ||
T = any, | ||
S extends StrictRJSFSchema = RJSFSchema, | ||
F extends FormContextType = any, | ||
>(props: BaseInputTemplateProps<T, S, F>) { | ||
const { | ||
id, | ||
name, // remove this from ...rest | ||
value, | ||
readonly, | ||
disabled, | ||
autofocus, | ||
onBlur, | ||
onFocus, | ||
onChange, | ||
onChangeOverride, | ||
options, | ||
schema, | ||
uiSchema, | ||
formContext, | ||
registry, | ||
rawErrors, | ||
type, | ||
hideLabel, // remove this from ...rest | ||
hideError, // remove this from ...rest | ||
...rest | ||
} = props; | ||
|
||
// Note: since React 15.2.0 we can't forward unknown element attributes, so we | ||
// exclude the "options" and "schema" ones here. | ||
if (!id) { | ||
console.log("No id for", props); | ||
throw new Error(`no id for props ${JSON.stringify(props)}`); | ||
} | ||
const inputProps = { | ||
...rest, | ||
...getInputProps<T, S, F>(schema, type, options), | ||
}; | ||
|
||
let inputValue; | ||
if (inputProps.type === "number" || inputProps.type === "integer") { | ||
inputValue = value || value === 0 ? value : ""; | ||
} else { | ||
inputValue = value == null ? "" : value; | ||
} | ||
|
||
const _onChange = useCallback( | ||
({ target: { value } }: ChangeEvent<HTMLInputElement>) => | ||
onChange(value === "" ? options.emptyValue : value), | ||
[onChange, options], | ||
); | ||
const _onBlur = useCallback( | ||
({ target: { value } }: FocusEvent<HTMLInputElement>) => onBlur(id, value), | ||
[onBlur, id], | ||
); | ||
const _onFocus = useCallback( | ||
({ target: { value } }: FocusEvent<HTMLInputElement>) => onFocus(id, value), | ||
[onFocus, id], | ||
); | ||
|
||
return ( | ||
<> | ||
<Input | ||
id={id} | ||
name={id} | ||
className="form-control" | ||
readOnly={readonly} | ||
disabled={disabled} | ||
autoFocus={autofocus} | ||
value={inputValue} | ||
fullWidth | ||
{...inputProps} | ||
list={schema.examples ? examplesId<T>(id) : undefined} | ||
onChange={onChangeOverride || _onChange} | ||
onBlur={_onBlur} | ||
onFocus={_onFocus} | ||
aria-describedby={ariaDescribedByIds<T>(id, !!schema.examples)} | ||
/> | ||
{Array.isArray(schema.examples) && ( | ||
<datalist key={`datalist_${id}`} id={examplesId<T>(id)}> | ||
{(schema.examples as string[]) | ||
.concat( | ||
schema.default && !schema.examples.includes(schema.default) | ||
? ([schema.default] as string[]) | ||
: [], | ||
) | ||
.map((example: any) => { | ||
return <option key={example} value={example} />; | ||
})} | ||
</datalist> | ||
)} | ||
</> | ||
); | ||
} |
51 changes: 51 additions & 0 deletions
51
astroplant-frontend/src/rjsf-theme/templates/ButtonTemplates/index.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
import { | ||
FormContextType, | ||
RJSFSchema, | ||
StrictRJSFSchema, | ||
TemplatesType, | ||
} from "@rjsf/utils"; | ||
import { Icon } from "semantic-ui-react"; | ||
import { Button } from "~/Components/Button"; | ||
|
||
function buttonTemplates< | ||
T = any, | ||
S extends StrictRJSFSchema = RJSFSchema, | ||
F extends FormContextType = any, | ||
>(): TemplatesType<T, S, F>["ButtonTemplates"] { | ||
return { | ||
SubmitButton: (props) => <Button {...props}>Submit</Button>, | ||
AddButton: (props) => ( | ||
/* a bit hacky to specify the style here */ | ||
<Button | ||
{...props} | ||
size="small" | ||
variant="muted" | ||
style={{ float: "right", marginRight: "1.2rem" }} | ||
> | ||
<Icon name="add" /> | ||
</Button> | ||
), | ||
CopyButton: (props) => ( | ||
<Button {...props} leftAdornment="+"> | ||
Add | ||
</Button> | ||
), | ||
MoveDownButton: (props) => ( | ||
<Button {...props} size="small" variant="muted"> | ||
<Icon name="arrow down" /> | ||
</Button> | ||
), | ||
MoveUpButton: (props) => ( | ||
<Button {...props} size="small" variant="muted"> | ||
<Icon name="arrow up" /> | ||
</Button> | ||
), | ||
RemoveButton: (props) => ( | ||
<Button {...props} size="small" variant="muted"> | ||
<Icon name="delete" /> | ||
</Button> | ||
), | ||
}; | ||
} | ||
|
||
export default buttonTemplates; |
Oops, something went wrong.