diff --git a/packages/components/CHANGELOG.md b/packages/components/CHANGELOG.md index c224663..0fa4633 100644 --- a/packages/components/CHANGELOG.md +++ b/packages/components/CHANGELOG.md @@ -1,5 +1,11 @@ # Change Log +## 2.5.1 (2024-06-12) + +### Features + +- Make Expanded state of Collapsable Sections controlled in Form (#45) + ## 2.4.0 (2024-05-31) ### Features diff --git a/packages/components/package.json b/packages/components/package.json index 14c32d6..a498117 100644 --- a/packages/components/package.json +++ b/packages/components/package.json @@ -86,5 +86,5 @@ "typecheck": "tsc --emitDeclarationOnly false --noEmit" }, "types": "dist/index.d.ts", - "version": "2.4.0" + "version": "2.5.1" } diff --git a/packages/components/src/components/Form/Form.test.tsx b/packages/components/src/components/Form/Form.test.tsx index a52de3a..6458a64 100644 --- a/packages/components/src/components/Form/Form.test.tsx +++ b/packages/components/src/components/Form/Form.test.tsx @@ -561,6 +561,9 @@ describe('Form', () => { getComponent<{ group1: { field: string; + subGroup1: { + field: string; + }; }; group2: { field: string; @@ -574,10 +577,22 @@ describe('Form', () => { label: '', }, (builder) => - builder.addInput({ - path: 'field', - defaultValue: '', - }) + builder + .addInput({ + path: 'field', + defaultValue: '', + }) + .addGroup( + { + path: 'subGroup1', + label: '', + }, + (builder) => + builder.addInput({ + path: 'field', + defaultValue: '', + }) + ) ) .addGroup( { @@ -600,6 +615,13 @@ describe('Form', () => { expect(selectors.sectionContent(false, 'group1')).toBeInTheDocument(); expect(selectors.fieldInput(false, 'group1.field')).toBeInTheDocument(); + /** + * Check subGroup 1 + */ + expect(selectors.sectionHeader(false, 'group1.subGroup1')).toBeInTheDocument(); + expect(selectors.sectionContent(false, 'group1.subGroup1')).toBeInTheDocument(); + expect(selectors.fieldInput(false, 'group1.subGroup1.field')).toBeInTheDocument(); + /** * Check group 2 */ @@ -625,6 +647,9 @@ describe('Form', () => { getComponent<{ group1: { field: string; + subGroup1: { + field: string; + }; }; group2: { field: string; @@ -638,10 +663,22 @@ describe('Form', () => { label: '', }, (builder) => - builder.addInput({ - path: 'field', - defaultValue: '', - }) + builder + .addInput({ + path: 'field', + defaultValue: '', + }) + .addGroup( + { + path: 'subGroup1', + label: '', + }, + (builder) => + builder.addInput({ + path: 'field', + defaultValue: '', + }) + ) ) .addGroup( { @@ -656,6 +693,7 @@ describe('Form', () => { ), expanded: { group1: false, + 'group1.subGroup1': false, }, onToggleExpanded, }) @@ -677,9 +715,37 @@ describe('Form', () => { * Expand group 1 */ fireEvent.click(selectors.sectionHeader(false, 'group1')); - expect(onToggleExpanded).toHaveBeenCalledWith({ - group1: true, - }); + expect(onToggleExpanded).toHaveBeenCalledWith( + { + group1: true, + 'group1.subGroup1': false, + }, + { path: 'group1', expanded: true } + ); + + /** + * Check if subGroup1 is collapsed + */ + expect(selectors.sectionHeader(false, 'group1.subGroup1')).toBeInTheDocument(); + expect(selectors.sectionContent(true, 'group1.subGroup1')).not.toBeInTheDocument(); + + /** + * Expand subGroup 1 + */ + fireEvent.click(selectors.sectionHeader(false, 'group1.subGroup1')); + expect(onToggleExpanded).toHaveBeenCalledWith( + { + group1: false, + 'group1.subGroup1': true, + }, + { path: 'group1.subGroup1', expanded: true } + ); + + /** + * Check if subGroup1 is expanded + */ + expect(selectors.sectionHeader(false, 'group1.subGroup1')).toBeInTheDocument(); + expect(selectors.sectionContent(false, 'group1.subGroup1')).toBeInTheDocument(); }); it('Should hide field', () => { diff --git a/packages/components/src/components/Form/Form.tsx b/packages/components/src/components/Form/Form.tsx index bbc9afe..9999bbb 100644 --- a/packages/components/src/components/Form/Form.tsx +++ b/packages/components/src/components/Form/Form.tsx @@ -1,6 +1,5 @@ import { dateTime, dateTimeFormat } from '@grafana/data'; import { - CollapsableSection, ColorPicker, DateTimePicker, Field, @@ -15,6 +14,7 @@ import React from 'react'; import { TEST_IDS } from '../../constants'; import { FormFieldType, RenderFormField } from '../../types'; +import { CollapsableSection } from '../CollapsableSection'; import { NumberInput } from '../NumberInput'; import { RangeSlider } from '../RangeSlider'; import { Slider } from '../Slider'; @@ -46,7 +46,7 @@ interface Props { /** * On Toggle Expanded */ - onToggleExpanded?: (expanded: Record) => void; + onToggleExpanded?: (expanded: Record, event: { path: string; expanded: boolean }) => void; /** * Fields @@ -139,12 +139,15 @@ export const Form = ({ headerDataTestId={TEST_IDS.form.sectionHeader(field.fullPath)} contentDataTestId={TEST_IDS.form.sectionContent(field.fullPath)} contentClassName={styles.section} - isOpen={expanded[field.path] ?? true} + isOpen={expanded[field.fullPath] ?? true} onToggle={(isOpen) => - onToggleExpanded({ - ...expanded, - [field.path]: isOpen, - }) + onToggleExpanded( + { + ...expanded, + [field.fullPath]: isOpen, + }, + { path: field.fullPath, expanded: isOpen } + ) } > {groupFieldsInRows(field.group).map((fields, index) =>