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

feat: Add formItemProps to UI schemas #80

Merged
merged 27 commits into from
May 20, 2024
Merged
Show file tree
Hide file tree
Changes from 23 commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
391ea0b
Add tooltip option to NumericControl
NathanFarmer May 15, 2024
de4f297
Add tooltip option to NumericSliderControl
NathanFarmer May 15, 2024
4572fd0
Add tooltip util method
NathanFarmer May 15, 2024
262be1e
Add tooltip option to PrimitiveArrayControl
NathanFarmer May 15, 2024
6a8f3b8
Add stories for ObjectControl and tooltip
NathanFarmer May 15, 2024
e711f4d
Add tooltip option to OneOfControl
NathanFarmer May 15, 2024
0c926c3
Add story for TextControl
NathanFarmer May 15, 2024
39b4ab8
Add tooltip option to AnyOfControl
NathanFarmer May 15, 2024
6180ca0
Add tooltip option to BooleanControl
NathanFarmer May 15, 2024
f9570ba
Use formItemProps instead of options
NathanFarmer May 20, 2024
616cc18
Spread formItemProps instead of passing tooltip directly
NathanFarmer May 20, 2024
4d31e85
Fix uischema types in controls
NathanFarmer May 20, 2024
08ab7d7
Merge branch 'main' into f/ph-1294/tooltip-in-all-ui-schemas
NathanFarmer May 20, 2024
bec09aa
Typing errors
NathanFarmer May 20, 2024
d069048
Merge branch 'f/ph-1294/tooltip-in-all-ui-schemas' of github.com:grea…
NathanFarmer May 20, 2024
54be81e
Typing errors
NathanFarmer May 20, 2024
5b5f29b
Narrow typing
NathanFarmer May 20, 2024
79a55a5
Format
NathanFarmer May 20, 2024
0701163
Cleanup
NathanFarmer May 20, 2024
a6c1f76
Cleanup
NathanFarmer May 20, 2024
d377b30
Improve typing
NathanFarmer May 20, 2024
805b98d
Missed one
NathanFarmer May 20, 2024
92a8ae2
Format
NathanFarmer May 20, 2024
1d7f2bc
Use Omit in types
NathanFarmer May 20, 2024
abd744c
Improve naming conventions
NathanFarmer May 20, 2024
fac3611
Fix BooleanControl special case
NathanFarmer May 20, 2024
66e6d5a
Format
NathanFarmer May 20, 2024
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
28 changes: 16 additions & 12 deletions src/controls/BooleanControl.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,18 @@
/* eslint-disable @typescript-eslint/no-unsafe-assignment */
import { ControlProps, isDescriptionHidden } from "@jsonforms/core"
import {
ControlElement,
ControlProps as JSFControlProps,
isDescriptionHidden,
} from "@jsonforms/core"
import { Form } from "antd"
import { Checkbox } from "../antd/Checkbox"
import { QuestionCircleOutlined } from "@ant-design/icons"
import { ControlUISchema } from "../ui-schema"
import { withJsonFormsControlProps } from "@jsonforms/react"

type ControlProps = JSFControlProps & {
uischema: ControlUISchema<unknown> | ControlElement
NathanFarmer marked this conversation as resolved.
Show resolved Hide resolved
}

export function BooleanControl({
data,
visible,
Expand Down Expand Up @@ -39,21 +47,17 @@ export function BooleanControl({

const showTooltip =
!showDescription && !isDescriptionHidden(visible, description, true, true)
const formItemProps =
"formItemProps" in uischema ? uischema.formItemProps : {}
const tooltip = showTooltip && description ? description : undefined

return (
<Form.Item
id={id}
name={path}
initialValue={data ?? schema.default}
{...{
...(showTooltip
? {
tooltip: {
title: description,
icon: <QuestionCircleOutlined />,
},
}
: {}),
}}
tooltip={tooltip}
{...formItemProps}
>
<Checkbox
id={`${id}-input`}
Expand Down
18 changes: 16 additions & 2 deletions src/controls/NumericControl.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,20 @@
import type { ControlProps, RendererProps } from "@jsonforms/core"
import type {
ControlElement,
ControlProps,
RendererProps,
} from "@jsonforms/core"
import { Col, Form } from "antd"
import type { Rule } from "antd/es/form"
import { InputNumber } from "../antd/InputNumber"
import { ControlUISchema } from "../ui-schema"
import { withJsonFormsControlProps } from "@jsonforms/react"

export const NumericControl = (props: ControlProps & RendererProps) => {
type NumericControlProps = ControlProps &
RendererProps & {
uischema: ControlUISchema<unknown> | ControlElement
NathanFarmer marked this conversation as resolved.
Show resolved Hide resolved
}

export const NumericControl = (props: NumericControlProps) => {
if (!props.visible) return null

const initialValue =
Expand All @@ -14,6 +24,9 @@ export const NumericControl = (props: ControlProps & RendererProps) => {
{ required: props.required, message: `${props.label} is required` },
]

const formItemProps =
"formItemProps" in props.uischema ? props.uischema.formItemProps : {}

return (
<Form.Item
label={props.label}
Expand All @@ -23,6 +36,7 @@ export const NumericControl = (props: ControlProps & RendererProps) => {
initialValue={initialValue}
rules={rules}
validateTrigger={["onBlur"]}
{...formItemProps}
>
<Col span={18}>{InputNumber({ ...props })}</Col>
</Form.Item>
Expand Down
18 changes: 16 additions & 2 deletions src/controls/NumericSliderControl.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,21 @@
import type { ControlProps, RendererProps } from "@jsonforms/core"
import type {
ControlElement,
ControlProps,
RendererProps,
} from "@jsonforms/core"
import { Col, Form, Row } from "antd"
import type { Rule } from "antd/es/form"
import { InputNumber } from "../antd/InputNumber"
import { Slider } from "../antd/Slider"
import { ControlUISchema } from "../ui-schema"
import { withJsonFormsControlProps } from "@jsonforms/react"

export const NumericSliderControl = (props: ControlProps & RendererProps) => {
type NumericSliderControlProps = RendererProps &
ControlProps & {
uischema: ControlUISchema<unknown> | ControlElement
}

export const NumericSliderControl = (props: NumericSliderControlProps) => {
if (!props.visible) return null

const initialValue =
Expand All @@ -17,6 +27,9 @@ export const NumericSliderControl = (props: ControlProps & RendererProps) => {
{ required: props.required, message: `${props.label} is required` },
]

const formItemProps =
"formItemProps" in props.uischema ? props.uischema.formItemProps : {}

return (
<Form.Item
label={props.label}
Expand All @@ -26,6 +39,7 @@ export const NumericSliderControl = (props: ControlProps & RendererProps) => {
initialValue={initialValue}
rules={rules}
validateTrigger={["onBlur"]}
{...formItemProps}
>
<Row>
<Col span={8}>{Slider({ ...props })}</Col>
Expand Down
13 changes: 11 additions & 2 deletions src/controls/ObjectArrayControl.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import {
ControlElement,
Helpers,
ArrayLayoutProps,
ArrayLayoutProps as JSFArrayLayoutProps,
composePaths,
createDefaultValue,
findUISchema,
Expand All @@ -12,10 +13,14 @@ import {
import { Flex, Form, List, Button } from "antd"
import range from "lodash.range"
import { useEffect, useMemo } from "react"
import { ArrayControlOptions } from "../ui-schema"
import { ArrayControlOptions, ControlUISchema } from "../ui-schema"
import { usePreviousValue } from "../common/usePreviousValue"
import React from "react"

type ArrayLayoutProps = JSFArrayLayoutProps & {
uischema: ControlUISchema<unknown> | ControlElement
}

export function ObjectArrayControl({
data,
enabled,
Expand Down Expand Up @@ -58,6 +63,9 @@ export function ObjectArrayControl({
}
})

const formItemProps =
"formItemProps" in uischema ? uischema.formItemProps : {}

const labelDescription = Helpers.createLabelDescriptionFrom(uischema, schema)
const label = labelDescription.show ? labelDescription.text : ""

Expand Down Expand Up @@ -86,6 +94,7 @@ export function ObjectArrayControl({
required={required}
rules={[{ required: required, message: `${label} is required` }]}
validateTrigger={["onBlur"]}
{...formItemProps}
>
<>{label}</>
<List<unknown>
Expand Down
17 changes: 13 additions & 4 deletions src/controls/PrimitiveArrayControl.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import {
ControlElement,
Helpers,
composePaths,
createDefaultValue,
Expand All @@ -11,11 +12,12 @@ import {
} from "@jsonforms/react"
import { Form, Button, Col, Row } from "antd"
import React, { useEffect, useMemo } from "react"
import { ArrayControlOptions } from "../ui-schema"
import { ArrayControlOptions, ControlUISchema } from "../ui-schema"
import { usePreviousValue } from "../common/usePreviousValue"

type ArrayControlProps = Omit<JSFArrayControlProps, "data"> & {
data?: unknown[]
uischema: ControlUISchema<unknown> | ControlElement
}

export function PrimitiveArrayControl({
Expand Down Expand Up @@ -68,11 +70,18 @@ export function PrimitiveArrayControl({
const labelDescription = Helpers.createLabelDescriptionFrom(uischema, schema)
const label = labelDescription.text || props.label // nullish coalescing doesn't work here because labelDescription.text can be an empty string =(

const options: ArrayControlOptions =
(uischema.options as ArrayControlOptions) ?? {}
const options: ArrayControlOptions = uischema.options ?? {}
const formItemProps =
"formItemProps" in uischema ? uischema.formItemProps : {}

return (
<Form.Item id={id} name={path} label={label} required={required}>
<Form.Item
id={id}
name={path}
label={label}
required={required}
{...formItemProps}
>
<Form.List name={path} initialValue={data ?? [undefined]}>
{(fields, { add, remove }, { errors }) => (
<Row justify={"start"}>
Expand Down
20 changes: 8 additions & 12 deletions src/controls/TextControl.tsx
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
import type { ChangeEvent } from "react"
import { useCallback, useEffect } from "react"
import { Input, Form } from "antd"
import { QuestionCircleOutlined } from "@ant-design/icons"
import type { Rule } from "antd/es/form"
import type { ControlProps } from "@jsonforms/core"
import type { ControlElement, ControlProps } from "@jsonforms/core"

import type { TextControlOptions } from "../ui-schema"
import type { ControlUISchema, TextControlOptions } from "../ui-schema"
import { assertNever } from "../common/assert-never"
import { withJsonFormsControlProps } from "@jsonforms/react"
interface TextControlProps extends ControlProps {
data: string
handleChange(path: string, value: string): void
path: string
uischema: ControlUISchema<unknown> | ControlElement
}

export function TextControl({
Expand All @@ -38,7 +38,9 @@ export function TextControl({
const ariaLabel = label || schema.description
const options: TextControlOptions =
(uischema.options as TextControlOptions) ?? {}
const tooltip = options.tooltip
const formItemProps =
"formItemProps" in uischema ? uischema.formItemProps : {}
const tooltip = options.tooltip ? options.tooltip : formItemProps?.tooltip
const placeholderText = options.placeholderText
const form = Form.useFormInstance()
const rules: Rule[] = [
Expand All @@ -60,14 +62,8 @@ export function TextControl({
name={path}
rules={rules}
validateTrigger={["onBlur"]}
{...(tooltip
? {
tooltip: {
title: tooltip,
icon: <QuestionCircleOutlined />,
},
}
: {})}
tooltip={tooltip}
{...formItemProps}
>
<TextControlInput
aria-label={ariaLabel}
Expand Down
11 changes: 10 additions & 1 deletion src/controls/combinators/AnyOfControl.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@ AnyOfControl should be used when a form item would control other elements within
AnyOfRenderer does not have options to render the label as a title
*/
import {
CombinatorRendererProps,
ControlElement,
CombinatorRendererProps as JSFCombinatorRendererProps,
createCombinatorRenderInfos,
createDefaultValue,
Helpers,
Expand All @@ -12,8 +13,13 @@ import {
import { JsonFormsDispatch, withJsonFormsOneOfProps } from "@jsonforms/react"
import { Form, Space } from "antd"
import { useEffect, useState } from "react"
import { ControlUISchema } from "../../ui-schema"
import { CombinatorSchemaSwitcher } from "./CombinatorSchemaSwitcher"

type CombinatorRendererProps = JSFCombinatorRendererProps & {
uischema: ControlUISchema<unknown> | ControlElement
}

export function AnyOfControl({
handleChange,
data,
Expand Down Expand Up @@ -72,12 +78,15 @@ export function AnyOfControl({
])

const labelDescription = Helpers.createLabelDescriptionFrom(uischema, schema)
const formItemProps =
"formItemProps" in uischema ? uischema.formItemProps : {}

return (
<Space direction="vertical" style={{ width: "100%" }} size="middle">
<Form.Item
rules={[{ required, message: `${schema.title} is required` }]}
label={labelDescription.show ? labelDescription.text : ""}
{...formItemProps}
>
<CombinatorSchemaSwitcher
config={config as unknown}
Expand Down
16 changes: 14 additions & 2 deletions src/controls/combinators/OneOfControl.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import {
CombinatorRendererProps,
ControlElement,
CombinatorRendererProps as JSFCombinatorRendererProps,
createCombinatorRenderInfos,
JsonSchema,
} from "@jsonforms/core"
Expand All @@ -10,6 +11,10 @@ import { ControlUISchema } from "../../ui-schema"
import { ControlLabel } from "../../common/ControlLabel"
import { CombinatorSchemaSwitcher } from "./CombinatorSchemaSwitcher"

type CombinatorRendererProps = JSFCombinatorRendererProps & {
uischema: ControlUISchema<unknown> | ControlElement
}

export function OneOfControl({
handleChange,
data,
Expand All @@ -35,8 +40,15 @@ export function OneOfControl({
uischemas,
)

const formItemProps =
"formItemProps" in uischema ? uischema.formItemProps : {}

return (
<Form.Item required={required} label={uischema.label ? "" : schema.title}>
<Form.Item
required={required}
label={uischema.label ? "" : schema.title}
{...formItemProps}
>
<Space direction="vertical" style={{ width: "100%" }} size="middle">
{uischema.type === "Control" && uischema.label ? ( // I don't think it's possible for type to be other than "Control"
// but until we improve the UISchema types a bit, it's hard to be sure
Expand Down
11 changes: 11 additions & 0 deletions src/stories/controls/AnyOfControl.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import {
SplitterUISchemaRegistryEntry,
splitterAnyOfJsonSchema,
AnyOfWithDefaultsBaseUISchema,
AnyOfTooltipUISchema,
AnyOfWithDefaultsSchema,
AnyOfWithDefaultsUISchemaRegistryEntries,
} from "../../testSchemas/anyOfSchema"
Expand Down Expand Up @@ -138,3 +139,13 @@ export const WithDefaultValues: Story<typeof AnyOfWithDefaultsSchema> = {
},
argTypes: { jsonSchema: { control: "object" } },
}

export const Tooltip: Story<typeof AnyOfWithDefaultsSchema> = {
parameters: { controls: { expanded: true } },
tags: ["autodocs"],
args: {
jsonSchema: AnyOfWithDefaultsSchema,
uiSchemaRegistryEntries: AnyOfWithDefaultsUISchemaRegistryEntries,
uiSchema: AnyOfTooltipUISchema,
},
}
9 changes: 9 additions & 0 deletions src/stories/controls/NumericControl.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import {
numericWeightSchema,
numericSheepSchema,
numericVerticalUISchema,
numericTooltipUISchema,
numericPriceSchema,
numericUSDUISchema,
numericROISchema,
Expand Down Expand Up @@ -77,3 +78,11 @@ export const RequiredPercentage: Story = {
uiSchema: numericPercentageUISchema,
},
}

export const WithTooltip: Story = {
tags: ["autodocs"],
args: {
jsonSchema: numericSheepSchema,
uiSchema: numericTooltipUISchema,
},
}
Loading
Loading