Skip to content

Commit b38d108

Browse files
committed
feat: add support for hidden field in schema that hides properties based on prop value
1 parent 13753b5 commit b38d108

File tree

10 files changed

+96
-38
lines changed

10 files changed

+96
-38
lines changed

src/Common/RJSF/Form.tsx

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@
1414
* limitations under the License.
1515
*/
1616

17-
import React from 'react'
1817
import RJSF from '@rjsf/core'
1918
import RJSFValidator from '@rjsf/validator-ajv8'
2019

src/Common/RJSF/rjsfForm.scss

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,14 @@
3939
// This is added as the array field itself has a margin bottom
4040
margin: 0;
4141
}
42+
43+
& legend {
44+
display: none;
45+
}
46+
47+
&:has(+ div) {
48+
margin-bottom: 8px;
49+
}
4250
}
4351

4452
&__additional-fields,
@@ -53,15 +61,15 @@
5361
&:has(> .remove-btn__container)::after {
5462
border-radius: 4px;
5563
transform: translate(-50%, -50%);
56-
top: 50%;
57-
left: 50%;
64+
top: 50%;
65+
left: 50%;
5866
background: transparent;
5967
z-index: -1;
6068
position: absolute;
6169
/* NOTE: this overlay is exactly 6px wider & taller on all sides
62-
* therefore the 12px (6 + 6) on height & width */
63-
height: calc(100% + 12px);
64-
width: calc(100% + 12px);
70+
* therefore the 8px (4 + 4) on height & width */
71+
height: calc(100% + 8px);
72+
width: calc(100% + 8px);
6573
content: '';
6674
transition: all 100ms ease-out;
6775
}

src/Common/RJSF/templates/ArrayFieldItemTemplate.tsx

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,12 +14,10 @@
1414
* limitations under the License.
1515
*/
1616

17-
import React, { CSSProperties } from 'react'
1817
import { ArrayFieldTemplateItemType } from '@rjsf/utils'
1918

2019
export const ArrayFieldItemTemplate = ({
2120
children,
22-
className,
2321
disabled,
2422
hasToolbar,
2523
hasRemove,
@@ -32,7 +30,7 @@ export const ArrayFieldItemTemplate = ({
3230
const { RemoveButton } = registry.templates.ButtonTemplates
3331

3432
return (
35-
<div className="dc__position-rel display-grid rjsf-form-template__array-field-item flex-align-center mb-12">
33+
<div className="dc__position-rel display-grid rjsf-form-template__array-field-item flex-align-center">
3634
{children}
3735
<div className="dc__position-abs remove-btn__container" style={{ right: "-28px", top: "9px" }}>
3836
{hasToolbar && hasRemove && (

src/Common/RJSF/templates/ButtonTemplates/AddButton.tsx

Lines changed: 10 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,9 @@
1414
* limitations under the License.
1515
*/
1616

17-
import React, { useEffect, useState, useRef } from 'react'
1817
import { IconButtonProps } from '@rjsf/utils'
1918

20-
import { ConditionalWrap } from '../../../Helper'
21-
import { getTippyWrapperWithContent } from '../../utils'
19+
import Tippy from '../../../Tippy'
2220
import { ADD_BUTTON_WIDTH } from '../../constants'
2321
import { ReactComponent as PlusIcon } from '../../../../Assets/Icon/ic-add.svg'
2422

@@ -30,26 +28,27 @@ export const AddButton = ({
3028
uiSchema,
3129
...props
3230
}: IconButtonProps & Partial<Record<'label', string>>) => {
33-
const [showTippy, setShowTippy] = useState(false)
34-
const buttonRef = useRef<HTMLButtonElement>(null)
3531
const content = `Add ${label}`
3632

37-
useEffect(() => setShowTippy(buttonRef.current?.offsetWidth >= ADD_BUTTON_WIDTH.MAX_WIDTH_VALUE), [buttonRef.current])
38-
3933
return (
4034
<div className="flexbox flex-justify-start">
41-
<ConditionalWrap condition={showTippy} wrap={getTippyWrapperWithContent(content)}>
35+
<Tippy
36+
className="default-tt dc__word-break"
37+
arrow={false}
38+
placement="right"
39+
content={content}
40+
truncateWidth={ADD_BUTTON_WIDTH.MAX_WIDTH_VALUE}
41+
>
4242
<button
43-
ref={buttonRef}
4443
{...props}
4544
type="button"
4645
className={`dc__outline-none-imp p-0 dc__transparent flex dc__gap-4 cursor ${ADD_BUTTON_WIDTH.MAX_WIDTH_CLASSNAME}`}
4746
title="Add"
4847
>
4948
<PlusIcon className="icon-dim-16 fcb-5" />
50-
<span className="cb-5 fs-13 lh-20 dc__truncate">{content}</span>
49+
<span className="cb-5 fs-13 lh-24 dc__truncate">{content}</span>
5150
</button>
52-
</ConditionalWrap>
51+
</Tippy>
5352
</div>
5453
)
5554
}

src/Common/RJSF/templates/Field.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,8 @@ export const Field = (props: FieldTemplateProps) => {
4949
return hidden ? (
5050
<div className="hidden">{children}</div>
5151
) : (
52-
<div className={`${classNames} mb-12`}>
52+
// NOTE: need to override the margins of default rjsf css
53+
<div className={`${classNames} mb-0`}>
5354
{showTitle && (
5455
<TitleField
5556
id={id}

src/Common/RJSF/templates/ObjectFieldTemplate.tsx

Lines changed: 20 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -14,17 +14,12 @@
1414
* limitations under the License.
1515
*/
1616

17-
import React from 'react'
18-
import {
19-
ObjectFieldTemplatePropertyType,
20-
ObjectFieldTemplateProps,
21-
canExpand,
22-
getUiOptions,
23-
titleId,
24-
} from '@rjsf/utils'
17+
import { ObjectFieldTemplateProps, canExpand, titleId } from '@rjsf/utils'
2518
import { FieldRowWithLabel } from '../common/FieldRow'
2619
import { TitleField } from './TitleField'
2720
import { AddButton } from './ButtonTemplates'
21+
import { JSONPath } from 'jsonpath-plus'
22+
import { RJSFFormSchema } from '../types'
2823

2924
const Field = ({
3025
disabled,
@@ -38,7 +33,7 @@ const Field = ({
3833
schema,
3934
title,
4035
uiSchema,
41-
}: ObjectFieldTemplateProps) => {
36+
}: ObjectFieldTemplateProps<any, RJSFFormSchema, any>) => {
4237
const hasAdditionalProperties = !!schema.additionalProperties
4338

4439
const ActionButton = canExpand(schema, uiSchema, formData) && (
@@ -52,7 +47,19 @@ const Field = ({
5247
/>
5348
)
5449

55-
const Properties = properties.map((prop: ObjectFieldTemplatePropertyType) => prop.content)
50+
const Properties = properties
51+
.filter((prop) => {
52+
const hiddenSchemaProp = schema.properties?.[prop.name]?.hidden
53+
if (!hiddenSchemaProp) {
54+
return true
55+
}
56+
const isHidden =
57+
hiddenSchemaProp.condition === JSONPath({ path: hiddenSchemaProp.match, json: formData })[0]
58+
// NOTE: if should be hidden then filter it out i.e return false
59+
return !isHidden
60+
})
61+
.sort((prop) => (schema.properties?.[prop.name]?.type === 'boolean' ? -1 : 1))
62+
.map((prop) => prop.content)
5663

5764
if (hasAdditionalProperties) {
5865
if (properties.length) {
@@ -85,9 +92,8 @@ const Field = ({
8592
)
8693
}
8794

88-
export const ObjectFieldTemplate = (props: ObjectFieldTemplateProps) => {
95+
export const ObjectFieldTemplate = (props: ObjectFieldTemplateProps<any, RJSFFormSchema, any>) => {
8996
const { idSchema, registry, required, schema, title, uiSchema, description } = props
90-
const options = getUiOptions(uiSchema)
9197
const hasAdditionalProperties = !!schema.additionalProperties
9298
const showTitle = title && !hasAdditionalProperties
9399

@@ -106,11 +112,11 @@ export const ObjectFieldTemplate = (props: ObjectFieldTemplateProps) => {
106112
)}
107113
{/* Not adding the border and padding for non-objects and root schema */}
108114
<div
109-
className={
115+
className={`${
110116
schema.properties && !hasAdditionalProperties && idSchema.$id !== 'root'
111117
? 'dc__border-left pl-12'
112118
: ''
113-
}
119+
} flexbox-col dc__gap-8`}
114120
>
115121
<Field {...props} />
116122
</div>

src/Common/RJSF/types.ts

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,5 +16,18 @@
1616

1717
import { ComponentProps } from 'react'
1818
import RJSFForm from '@rjsf/core'
19+
import { StrictRJSFSchema } from '@rjsf/utils'
1920

2021
export type FormProps = Omit<ComponentProps<typeof RJSFForm>, 'validator'>
22+
23+
interface Hidden {
24+
condition: boolean
25+
match: string
26+
}
27+
28+
export interface RJSFFormSchema extends StrictRJSFSchema {
29+
properties: {
30+
[key: string]: RJSFFormSchema
31+
}
32+
hidden: Hidden
33+
}

src/Common/RJSF/utils.tsx

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
*/
1616

1717
import { TranslatableString, englishStringTranslator } from '@rjsf/utils'
18-
import Tippy from '@tippyjs/react'
18+
import Tippy from '../Tippy'
1919

2020
/**
2121
* Override for the TranslatableString from RJSF
@@ -138,8 +138,16 @@ export const getInferredTypeFromValueType = (value) => {
138138
}
139139

140140
export const getTippyWrapperWithContent =
141-
(content, placement?: React.ComponentProps<typeof Tippy>['placement']) => (children) => (
142-
<Tippy className="default-tt dc__word-break" arrow={false} placement={placement || 'right'} content={content}>
141+
(content, placement?: React.ComponentProps<typeof Tippy>['placement'], truncateWidth = 0) =>
142+
(children) => (
143+
<Tippy
144+
className="default-tt"
145+
maxWidth={300}
146+
arrow={false}
147+
placement={placement || 'right'}
148+
content={content}
149+
truncateWidth={truncateWidth}
150+
>
143151
{children}
144152
</Tippy>
145153
)

src/Common/Tippy.tsx

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
import { useEffect, useRef, useState } from 'react'
2+
import TippyJS, { TippyProps as TippyJSProps } from '@tippyjs/react'
3+
4+
// TODO: we should generalize this Tippy to work without sending in this truncateWidth
5+
const Tippy = ({ truncateWidth = 0, children, ...rest }: TippyJSProps & Record<'truncateWidth', number>) => {
6+
// NOTE: if showOnTruncate is off then always showTippy
7+
const [showTippy, setShowTippy] = useState(!!truncateWidth)
8+
const ref = useRef(null)
9+
10+
useEffect(() => {
11+
if (truncateWidth) {
12+
setShowTippy(ref.current?.offsetWidth >= truncateWidth)
13+
}
14+
}, [ref.current?.offsetWidth])
15+
16+
return !showTippy ? (
17+
children
18+
) : (
19+
<TippyJS {...rest}>
20+
<span ref={ref}>{children}</span>
21+
</TippyJS>
22+
)
23+
}
24+
25+
export default Tippy

src/Common/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,3 +72,4 @@ export * from './GenericDescription'
7272
export * from './SegmentedBarChart'
7373
export * from './CodeEditor'
7474
export * from './AppStatus'
75+
export { default as Tippy } from './Tippy'

0 commit comments

Comments
 (0)