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 9 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
17 changes: 6 additions & 11 deletions src/controls/BooleanControl.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
import { ControlProps, isDescriptionHidden } from "@jsonforms/core"
import { Form } from "antd"
import { Checkbox } from "../antd/Checkbox"
import { QuestionCircleOutlined } from "@ant-design/icons"
import { tooltipStringToAntdLabelTooltip } from "./utils"
import { withJsonFormsControlProps } from "@jsonforms/react"

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

const showTooltip =
!showDescription && !isDescriptionHidden(visible, description, true, true)
const tooltip =
showTooltip && description
? tooltipStringToAntdLabelTooltip(description)
: undefined
return (
<Form.Item
id={id}
name={path}
initialValue={data ?? schema.default}
{...{
...(showTooltip
? {
tooltip: {
title: description,
icon: <QuestionCircleOutlined />,
},
}
: {}),
}}
tooltip={tooltip}
>
<Checkbox
id={`${id}-input`}
Expand Down
8 changes: 8 additions & 0 deletions src/controls/NumericControl.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ import type { ControlProps, RendererProps } from "@jsonforms/core"
import { Col, Form } from "antd"
import type { Rule } from "antd/es/form"
import { InputNumber } from "../antd/InputNumber"
import type { NumericControlOptions } from "../ui-schema"
import { tooltipStringToAntdLabelTooltip } from "./utils"
import { withJsonFormsControlProps } from "@jsonforms/react"

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

const options: NumericControlOptions = props.uischema.options ?? {}
const tooltip = options.tooltip
? tooltipStringToAntdLabelTooltip(options.tooltip)
: undefined

return (
<Form.Item
label={props.label}
Expand All @@ -23,6 +30,7 @@ export const NumericControl = (props: ControlProps & RendererProps) => {
initialValue={initialValue}
rules={rules}
validateTrigger={["onBlur"]}
tooltip={tooltip}
>
<Col span={18}>{InputNumber({ ...props })}</Col>
</Form.Item>
Expand Down
8 changes: 8 additions & 0 deletions src/controls/NumericSliderControl.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ import { Col, Form, Row } from "antd"
import type { Rule } from "antd/es/form"
import { InputNumber } from "../antd/InputNumber"
import { Slider } from "../antd/Slider"
import type { NumericControlOptions } from "../ui-schema"
import { tooltipStringToAntdLabelTooltip } from "./utils"
import { withJsonFormsControlProps } from "@jsonforms/react"

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

const options: NumericControlOptions = props.uischema.options ?? {}
const tooltip = options.tooltip
? tooltipStringToAntdLabelTooltip(options.tooltip)
: undefined

return (
<Form.Item
label={props.label}
Expand All @@ -26,6 +33,7 @@ export const NumericSliderControl = (props: ControlProps & RendererProps) => {
initialValue={initialValue}
rules={rules}
validateTrigger={["onBlur"]}
tooltip={tooltip}
>
<Row>
<Col span={8}>{Slider({ ...props })}</Col>
Expand Down
15 changes: 12 additions & 3 deletions src/controls/PrimitiveArrayControl.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import { Form, Button, Col, Row } from "antd"
import React, { useEffect, useMemo } from "react"
import { ArrayControlOptions } from "../ui-schema"
import { usePreviousValue } from "../common/usePreviousValue"
import { tooltipStringToAntdLabelTooltip } from "./utils"

type ArrayControlProps = Omit<JSFArrayControlProps, "data"> & {
data?: unknown[]
Expand Down Expand Up @@ -68,11 +69,19 @@ 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 tooltip = options.tooltip
? tooltipStringToAntdLabelTooltip(options.tooltip)
: undefined

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

import type { TextControlOptions, TextControlType } from "../ui-schema"
import { tooltipStringToAntdLabelTooltip } from "./utils"
import { assertNever } from "../common/assert-never"
import { withJsonFormsControlProps } from "@jsonforms/react"
interface TextControlProps extends ControlProps {
Expand Down Expand Up @@ -42,6 +42,8 @@ export function TextControl({
(uischema.options as TextControlOptions) ?? {}
const textControlType: TextControlType = options.type ?? "singleline"
const tooltip = options.tooltip
? tooltipStringToAntdLabelTooltip(options.tooltip)
: undefined
const placeholderText = options.placeholderText
const form = Form.useFormInstance()
const rules: Rule[] = [
Expand All @@ -63,14 +65,7 @@ export function TextControl({
name={path}
rules={rules}
validateTrigger={["onBlur"]}
{...(tooltip
? {
tooltip: {
title: tooltip,
icon: <QuestionCircleOutlined />,
},
}
: {})}
tooltip={tooltip}
>
<TextControlInput
type={textControlType}
Expand Down
7 changes: 7 additions & 0 deletions src/controls/combinators/AnyOfControl.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ import { JsonFormsDispatch, withJsonFormsOneOfProps } from "@jsonforms/react"
import { Form, Space } from "antd"
import { useEffect, useState } from "react"
import { CombinatorSchemaSwitcher } from "./CombinatorSchemaSwitcher"
import { AnyOfControlOptions } from "../../ui-schema"
import { tooltipStringToAntdLabelTooltip } from "../utils"

export function AnyOfControl({
handleChange,
Expand Down Expand Up @@ -72,12 +74,17 @@ export function AnyOfControl({
])

const labelDescription = Helpers.createLabelDescriptionFrom(uischema, schema)
const options: AnyOfControlOptions = uischema.options ?? {}
const tooltip = options.tooltip
? tooltipStringToAntdLabelTooltip(options.tooltip)
: undefined

return (
<Space direction="vertical" style={{ width: "100%" }} size="middle">
<Form.Item
rules={[{ required, message: `${schema.title} is required` }]}
label={labelDescription.show ? labelDescription.text : ""}
tooltip={tooltip}
>
<CombinatorSchemaSwitcher
config={config as unknown}
Expand Down
14 changes: 12 additions & 2 deletions src/controls/combinators/OneOfControl.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@ import {
import { JsonFormsDispatch, withJsonFormsOneOfProps } from "@jsonforms/react"
import { Form, Space } from "antd"
import { useState } from "react"
import { ControlUISchema } from "../../ui-schema"
import { ControlUISchema, OneOfControlOptions } from "../../ui-schema"
import { tooltipStringToAntdLabelTooltip } from "../utils"
import { ControlLabel } from "../../common/ControlLabel"
import { CombinatorSchemaSwitcher } from "./CombinatorSchemaSwitcher"

Expand Down Expand Up @@ -35,8 +36,17 @@ export function OneOfControl({
uischemas,
)

const options: OneOfControlOptions = uischema.options ?? {}
const tooltip = options.tooltip
? tooltipStringToAntdLabelTooltip(options.tooltip)
: undefined

return (
<Form.Item required={required} label={uischema.label ? "" : schema.title}>
<Form.Item
required={required}
label={uischema.label ? "" : schema.title}
tooltip={tooltip}
>
<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
10 changes: 10 additions & 0 deletions src/controls/utils.ts → src/controls/utils.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
import { QuestionCircleOutlined } from "@ant-design/icons"
import { LabelTooltipType } from "antd/es/form/FormItemLabel"

export function decimalToPercentage(value?: number) {
if (value === undefined) return ""
const percentage = parseFloat((value * 100).toFixed(10)) // accounting for 10 digits after the decimal point
Expand All @@ -11,3 +14,10 @@
export const coerceToInteger = (value: number) => Math.round(value)

export const coerceToNumber = (value: number) => Number(value)

export const tooltipStringToAntdLabelTooltip = (
tooltip: string,
): LabelTooltipType => ({

Check warning on line 20 in src/controls/utils.tsx

View check run for this annotation

Codecov / codecov/patch

src/controls/utils.tsx#L20

Added line #L20 was not covered by tests
title: tooltip,
icon: <QuestionCircleOutlined />,
NathanFarmer marked this conversation as resolved.
Show resolved Hide resolved
})
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,
},
}
23 changes: 23 additions & 0 deletions src/stories/controls/OneOfControl.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,20 @@ const segmentedUISchema = {
],
} satisfies UISchema<typeof schema>

const tooltipUISchema = {
type: "VerticalLayout",
elements: [
{
type: "Control",
scope: "#/properties/deliveryOption",
options: {
optionType: "segmented",
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 +306,12 @@ export const OneOfArray: Story = {
},
},
}

export const OneOfTooltip: Story = {
parameters: { controls: { expanded: true } },
tags: ["autodocs"],
args: {
jsonSchema: schema,
uiSchema: tooltipUISchema,
},
}
20 changes: 20 additions & 0 deletions src/stories/controls/PrimitiveArrayControl.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { StorybookAntDJsonForm } from "../../common/StorybookAntDJsonForm"
import {
stringArrayControlJsonSchema,
arrayControlUISchema,
arrayControlTooltipUISchema,
} from "../../testSchemas/arraySchema"

const meta: Meta<typeof StorybookAntDJsonForm> = {
Expand Down Expand Up @@ -84,3 +85,22 @@ export const PrePopulatedArray: Story = {
data: { assets: [1, 2, 3] },
},
}

export const WithTooltip: Story = {
tags: ["autodocs"],
args: {
jsonSchema: {
type: "object",
properties: {
assets: {
type: "array",
items: {
type: "number",
},
},
},
} satisfies JSONSchema,
uiSchema: arrayControlTooltipUISchema,
data: { assets: [1, 2, 3] },
},
}
Loading
Loading