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 16 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
24 changes: 12 additions & 12 deletions src/controls/BooleanControl.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
/* eslint-disable @typescript-eslint/no-unsafe-assignment */
import { ControlProps, isDescriptionHidden } from "@jsonforms/core"
import {
ControlElement,
ControlProps,
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"

export function BooleanControl({
Expand Down Expand Up @@ -39,21 +43,17 @@ export function BooleanControl({

const showTooltip =
!showDescription && !isDescriptionHidden(visible, description, true, true)
const uiSchema = uischema as ControlUISchema<typeof uischema> & ControlElement
NathanFarmer marked this conversation as resolved.
Show resolved Hide resolved
const formItemProps = 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
12 changes: 11 additions & 1 deletion src/controls/NumericControl.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,12 @@
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) => {
Expand All @@ -14,6 +19,10 @@ export const NumericControl = (props: ControlProps & RendererProps) => {
{ required: props.required, message: `${props.label} is required` },
]

const uiSchema = props.uischema as ControlUISchema<typeof props.uischema> &
ControlElement
const formItemProps = uiSchema.formItemProps ?? {}

return (
<Form.Item
label={props.label}
Expand All @@ -23,6 +32,7 @@ export const NumericControl = (props: ControlProps & RendererProps) => {
initialValue={initialValue}
rules={rules}
validateTrigger={["onBlur"]}
{...formItemProps}
>
<Col span={18}>{InputNumber({ ...props })}</Col>
</Form.Item>
Expand Down
12 changes: 11 additions & 1 deletion src/controls/NumericSliderControl.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,13 @@
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) => {
Expand All @@ -17,6 +22,10 @@ export const NumericSliderControl = (props: ControlProps & RendererProps) => {
{ required: props.required, message: `${props.label} is required` },
]

const uiSchema = props.uischema as ControlUISchema<typeof props.uischema> &
ControlElement
const formItemProps = uiSchema.formItemProps ?? {}

return (
<Form.Item
label={props.label}
Expand All @@ -26,6 +35,7 @@ export const NumericSliderControl = (props: ControlProps & RendererProps) => {
initialValue={initialValue}
rules={rules}
validateTrigger={["onBlur"]}
{...formItemProps}
>
<Row>
<Col span={8}>{Slider({ ...props })}</Col>
Expand Down
16 changes: 12 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,7 +12,7 @@ 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"> & {
Expand Down Expand Up @@ -68,11 +69,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 uiSchema = uischema as ControlUISchema<typeof uischema> & ControlElement
const options: ArrayControlOptions = uiSchema.options ?? {}
const formItemProps = 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: 7 additions & 13 deletions src/controls/TextControl.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
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 {
Expand All @@ -26,6 +25,7 @@ export function TextControl({
id,
uischema,
}: TextControlProps) {
const uiSchema = uischema as ControlUISchema<typeof uischema> & ControlElement
const setInitialValue = useCallback(
(value: unknown) => {
if (typeof value !== "number") return value
Expand All @@ -37,8 +37,9 @@ export function TextControl({
)
const ariaLabel = label || schema.description
const options: TextControlOptions =
(uischema.options as TextControlOptions) ?? {}
const tooltip = options.tooltip
(uiSchema.options as TextControlOptions) ?? {}
const formItemProps = 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 +61,7 @@ export function TextControl({
name={path}
rules={rules}
validateTrigger={["onBlur"]}
{...(tooltip
? {
tooltip: {
title: tooltip,
icon: <QuestionCircleOutlined />,
},
}
: {})}
tooltip={tooltip}
>
<TextControlInput
aria-label={ariaLabel}
Expand Down
8 changes: 7 additions & 1 deletion src/controls/combinators/AnyOfControl.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ 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 {
ControlElement,
CombinatorRendererProps,
createCombinatorRenderInfos,
createDefaultValue,
Expand All @@ -12,6 +13,7 @@ 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"

export function AnyOfControl({
Expand Down Expand Up @@ -73,18 +75,22 @@ export function AnyOfControl({

const labelDescription = Helpers.createLabelDescriptionFrom(uischema, schema)

const uiSchema = uischema as ControlUISchema<typeof uischema> & ControlElement
const formItemProps = 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}
renderInfos={combinatorRenderInfos}
selectedIndex={selectedIndex}
setSelectedIndex={setSelectedIndex}
uischema={uischema}
uischema={uiSchema}
path={path}
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
data={data}
Expand Down
16 changes: 12 additions & 4 deletions src/controls/combinators/OneOfControl.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import {
ControlElement,
CombinatorRendererProps,
createCombinatorRenderInfos,
JsonSchema,
Expand Down Expand Up @@ -35,13 +36,20 @@ export function OneOfControl({
uischemas,
)

const uiSchema = uischema as ControlUISchema<typeof uischema> & ControlElement
const formItemProps = 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"
{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
<ControlLabel
uischema={uischema as ControlUISchema<unknown>}
uischema={uiSchema as ControlUISchema<unknown>}
schema={schema}
/>
) : null}
Expand All @@ -50,7 +58,7 @@ export function OneOfControl({
renderInfos={oneOfRenderInfos}
selectedIndex={selectedIndex}
setSelectedIndex={setSelectedIndex}
uischema={uischema}
uischema={uiSchema}
path={path}
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
data={data}
Expand Down
File renamed without changes.
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,
},
}
10 changes: 10 additions & 0 deletions src/stories/controls/NumericSliderControl.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ import { StorybookAntDJsonForm } from "../../common/StorybookAntDJsonForm"
import {
numericSliderBasisPointsSchema,
numericSliderVerticalUISchema,
numericSliderTooltipUISchema,
numericSliderKelvinSchema,
numericSliderTemperatureSchema,
numericSliderTemperatureUISchema,
numericSliderFinalGradeSchema,
Expand Down Expand Up @@ -60,3 +62,11 @@ export const OptionalUSDWithDefault: Story = {
uiSchema: numericSliderUSDUISchema,
},
}

export const WithTooltip: Story = {
tags: ["autodocs"],
args: {
jsonSchema: numericSliderKelvinSchema,
uiSchema: numericSliderTooltipUISchema,
},
}
9 changes: 9 additions & 0 deletions src/stories/controls/ObjectControl.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { StorybookAntDJsonForm } from "../../common/StorybookAntDJsonForm"
import {
objectSchema,
objectUISchemaWithName,
objectUISchemaWithTooltip,
objectUISchemaWithNameAndLastName,
objectUISchemaWithRule,
} from "../../testSchemas/objectSchema"
Expand Down Expand Up @@ -56,3 +57,11 @@ export const ObjectWithRuleHidingLastNameIfNameIsJohn: Story = {
uiSchema: objectUISchemaWithRule,
},
}

export const ObjectWithTooltip: Story = {
tags: ["autodocs"],
args: {
jsonSchema: objectSchema,
uiSchema: objectUISchemaWithTooltip,
},
}
25 changes: 25 additions & 0 deletions src/stories/controls/OneOfControl.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,22 @@ const segmentedUISchema = {
],
} satisfies UISchema<typeof schema>

const tooltipUISchema = {
type: "VerticalLayout",
elements: [
{
type: "Control",
scope: "#/properties/deliveryOption",
options: {
optionType: "segmented",
},
formItemProps: {
tooltip: "We charge a $3 delivery fee",
},
},
],
} satisfies UISchema<typeof schema>

export const Segmented: Story = {
parameters: { controls: { expanded: true } },
tags: ["autodocs"],
Expand Down Expand Up @@ -292,3 +308,12 @@ export const OneOfArray: Story = {
},
},
}

export const OneOfTooltip: Story = {
parameters: { controls: { expanded: true } },
tags: ["autodocs"],
args: {
jsonSchema: schema,
uiSchema: tooltipUISchema,
},
}
Loading
Loading