Skip to content

Commit 21dac9d

Browse files
committed
add SettingCell component
1 parent ea4b4e4 commit 21dac9d

File tree

5 files changed

+138
-1
lines changed

5 files changed

+138
-1
lines changed
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
import { Input } from './form';
2+
import { SettingCell } from './SettingCell';
3+
4+
describe('SettingCell', () => {
5+
it('renders a setting cell', () => {
6+
const result = (
7+
<SettingCell title="Title" description="Description">
8+
<Input name="setting1" />
9+
</SettingCell>
10+
);
11+
12+
expect(result).toStrictEqual({
13+
type: 'SettingCell',
14+
key: null,
15+
props: {
16+
title: 'Title',
17+
description: 'Description',
18+
children: {
19+
type: 'Input',
20+
key: null,
21+
props: {
22+
name: 'setting1',
23+
},
24+
},
25+
},
26+
});
27+
});
28+
});
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
import {
2+
createSnapComponent,
3+
type GenericSnapElement,
4+
type SnapsChildren,
5+
} from '../component';
6+
7+
/**
8+
* The props of the {@link SettingCell} component.
9+
*
10+
* @property title - The title.
11+
* @property description - The description.
12+
* @property children - The children to show within the cell.
13+
*/
14+
export type SettingCellProps = {
15+
title: string;
16+
description: string;
17+
children: SnapsChildren<GenericSnapElement>;
18+
};
19+
20+
const TYPE = 'SettingCell';
21+
22+
/**
23+
* A setting cell component which can be used to display a setting control.
24+
*
25+
* @param props - The props of the component.
26+
* @param props.title - The title.
27+
* @param props.description - The description.
28+
* @param props.children - The children to show within the cell.
29+
* @returns A setting cell element.
30+
* @example
31+
* <SettingCell title="Title" description="Description">
32+
* <Input name="setting1" />
33+
* </SettingCell>
34+
*/
35+
export const SettingCell = createSnapComponent<SettingCellProps, typeof TYPE>(
36+
TYPE,
37+
);
38+
39+
/**
40+
* A setting cell element.
41+
*
42+
* @see SettingCell
43+
*/
44+
export type SettingCellElement = ReturnType<typeof SettingCell>;

packages/snaps-sdk/src/jsx/components/index.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import type { ImageElement } from './Image';
1414
import type { LinkElement } from './Link';
1515
import type { RowElement } from './Row';
1616
import type { SectionElement } from './Section';
17+
import type { SettingCellElement } from './SettingCell';
1718
import type { SpinnerElement } from './Spinner';
1819
import type { TextElement } from './Text';
1920
import type { TooltipElement } from './Tooltip';
@@ -39,6 +40,7 @@ export * from './Tooltip';
3940
export * from './Footer';
4041
export * from './Container';
4142
export * from './Section';
43+
export * from './SettingCell';
4244

4345
/**
4446
* A built-in JSX element, which can be used in a Snap user interface.
@@ -63,4 +65,5 @@ export type JSXElement =
6365
| SectionElement
6466
| SpinnerElement
6567
| TextElement
66-
| TooltipElement;
68+
| TooltipElement
69+
| SettingCellElement;

packages/snaps-sdk/src/jsx/validation.test.tsx

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ import {
3333
SelectorOption,
3434
Section,
3535
Avatar,
36+
SettingCell,
3637
} from './components';
3738
import {
3839
AddressStruct,
@@ -70,6 +71,7 @@ import {
7071
SelectorStruct,
7172
SectionStruct,
7273
AvatarStruct,
74+
SettingCellStruct,
7375
} from './validation';
7476

7577
describe('KeyStruct', () => {
@@ -1414,6 +1416,51 @@ describe('SectionStruct', () => {
14141416
});
14151417
});
14161418

1419+
describe('SettingCellStruct', () => {
1420+
it.each([
1421+
<SettingCell title="foo" description="bar">
1422+
<Input name="foo" />
1423+
</SettingCell>,
1424+
<SettingCell title="foo" description="bar">
1425+
<Box>
1426+
<Input name="foo" />
1427+
</Box>
1428+
</SettingCell>,
1429+
<SettingCell title="foo" description="bar">
1430+
<Form name="foobar">
1431+
<Input name="foo" />
1432+
</Form>
1433+
</SettingCell>,
1434+
])('validates a setting cell element', (value) => {
1435+
expect(is(value, SettingCellStruct)).toBe(true);
1436+
});
1437+
1438+
it.each([
1439+
'foo',
1440+
42,
1441+
null,
1442+
undefined,
1443+
{},
1444+
[],
1445+
// @ts-expect-error - Invalid props.
1446+
<SettingCell />,
1447+
// @ts-expect-error - Invalid props.
1448+
<SettingCell foo="bar">
1449+
<Input name="foo" />
1450+
</SettingCell>,
1451+
<Box>
1452+
<Input name="foo" />
1453+
</Box>,
1454+
<Row label="label">
1455+
<Image src="<svg />" alt="alt" />
1456+
</Row>,
1457+
// @ts-expect-error - Invalid props.
1458+
<SettingCell title="foo" description="bar"></SettingCell>,
1459+
])('does not validate "%p"', (value) => {
1460+
expect(is(value, SettingCellStruct)).toBe(false);
1461+
});
1462+
});
1463+
14171464
describe('isJSXElement', () => {
14181465
it.each([
14191466
<Text>foo</Text>,

packages/snaps-sdk/src/jsx/validation.ts

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,7 @@ import {
8484
type SelectorOptionElement,
8585
IconName,
8686
} from './components';
87+
import type { SettingCellElement } from './components/SettingCell';
8788

8889
/**
8990
* A struct for the {@link Key} type.
@@ -633,6 +634,18 @@ export const SectionStruct: Describe<SectionElement> = element('Section', {
633634
),
634635
});
635636

637+
/**
638+
* A struct for the {@link SettingCellElement} type.
639+
*/
640+
export const SettingCellStruct: Describe<SettingCellElement> = element(
641+
'SettingCell',
642+
{
643+
children: BoxChildrenStruct,
644+
title: string(),
645+
description: string(),
646+
},
647+
);
648+
636649
/**
637650
* A subset of JSX elements that are allowed as children of the Footer component.
638651
* This set should include a single button or a tuple of two buttons.
@@ -821,6 +834,7 @@ export const BoxChildStruct = typedUnion([
821834
SelectorStruct,
822835
SectionStruct,
823836
AvatarStruct,
837+
SettingCellStruct,
824838
]);
825839

826840
/**
@@ -886,6 +900,7 @@ export const JSXElementStruct: Describe<JSXElement> = typedUnion([
886900
SelectorOptionStruct,
887901
SectionStruct,
888902
AvatarStruct,
903+
SettingCellStruct,
889904
]);
890905

891906
/**

0 commit comments

Comments
 (0)