Skip to content

Commit

Permalink
Fix type issue with Field children (#2715)
Browse files Browse the repository at this point in the history
This fixes an issue when using a conditional in a `Field` children.
  • Loading branch information
GuillaumeRx authored Sep 12, 2024
1 parent dfaea71 commit dee5632
Show file tree
Hide file tree
Showing 6 changed files with 74 additions and 21 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
"url": "https://github.com/MetaMask/snaps.git"
},
"source": {
"shasum": "/Q9cCxwaArV8k2VM4puQEsbni/bpNbcPEUi1s+XOL/U=",
"shasum": "N8UDq+EKKrGSUr/xn+g8Fn0ebj34zd+6Urgv1S7pzuM=",
"location": {
"npm": {
"filePath": "dist/bundle.js",
Expand Down
2 changes: 1 addition & 1 deletion packages/examples/packages/browserify/snap.manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
"url": "https://github.com/MetaMask/snaps.git"
},
"source": {
"shasum": "+fLeOqcKGPU0z+W2NcYDN9RwCl1ft1avMUe5fG1SUX0=",
"shasum": "j2B/JJ/tTdTWMJo+c5S8vZpnt4pRk9Xp3MhYBmDaz1s=",
"location": {
"npm": {
"filePath": "dist/bundle.js",
Expand Down
5 changes: 5 additions & 0 deletions packages/snaps-sdk/src/jsx/component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,11 @@ export type Nestable<Type> = Type | Nestable<Type>[];
*/
export type SnapsChildren<Type> = Nestable<Type | boolean | null>;

/**
* A type type that can be a generic JSX element, a boolean, or null.
*/
export type GenericSnapChildren = GenericSnapElement | boolean | null;

/**
* A JSX node, which can be an element, a string, null, or an array of nodes.
*/
Expand Down
26 changes: 26 additions & 0 deletions packages/snaps-sdk/src/jsx/components/form/Field.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -322,4 +322,30 @@ describe('Field', () => {
},
});
});

it('renders a field with a conditional', () => {
const result = (
<Field>
<Input name="foo" />
{false && <Button type="submit">Submit</Button>}
</Field>
);

expect(result).toStrictEqual({
type: 'Field',
key: null,
props: {
children: [
{
type: 'Input',
key: null,
props: {
name: 'foo',
},
},
false,
],
},
});
});
});
8 changes: 4 additions & 4 deletions packages/snaps-sdk/src/jsx/components/form/Field.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import type { GenericSnapElement } from '../../component';
import type { GenericSnapChildren } from '../../component';
import { createSnapComponent } from '../../component';
import type { CheckboxElement } from './Checkbox';
import type { DropdownElement } from './Dropdown';
Expand All @@ -18,9 +18,9 @@ export type FieldProps = {
label?: string | undefined;
error?: string | undefined;
children:
| [InputElement, GenericSnapElement]
| [GenericSnapElement, InputElement]
| [GenericSnapElement, InputElement, GenericSnapElement]
| [InputElement, GenericSnapChildren]
| [GenericSnapChildren, InputElement]
| [GenericSnapChildren, InputElement, GenericSnapChildren]
| DropdownElement
| RadioGroupElement
| FileInputElement
Expand Down
52 changes: 37 additions & 15 deletions packages/snaps-sdk/src/jsx/validation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ import {
} from '../internals';
import type { EmptyObject } from '../types';
import type {
GenericSnapChildren,
GenericSnapElement,
JsonObject,
Key,
Expand Down Expand Up @@ -153,6 +154,27 @@ function children<Head extends AnyStruct, Tail extends AnyStruct[]>(
>;
}

/**
* A helper function for creating a struct which allows a single child of a specific
* type, as well as `null` and `boolean`.
*
* @param struct - The struct to allow as a single child.
* @returns The struct for the children.
*/
function singleChild<Type extends AnyStruct>(
struct: Type,
): Struct<Infer<Type> | boolean | null, null> {
return nullable(
selectiveUnion((value) => {
if (typeof value === 'boolean') {
return boolean();
}

return struct;
}),
) as unknown as Struct<Infer<Type> | boolean | null, null>;
}

/**
* A helper function for creating a struct for a JSX element.
*
Expand Down Expand Up @@ -312,30 +334,30 @@ export const FileInputStruct: Describe<FileInputElement> = element(
/**
* A subset of JSX elements that represent the tuple Box + Input of the Field children.
*/
// eslint-disable-next-line @typescript-eslint/no-use-before-define
const BOX_INPUT_LEFT = [lazy(() => BoxChildStruct), InputStruct] as [
typeof BoxChildStruct,
typeof InputStruct,
];
const BOX_INPUT_LEFT = [
// eslint-disable-next-line @typescript-eslint/no-use-before-define
singleChild(lazy(() => BoxChildStruct)),
InputStruct,
] as [typeof BoxChildStruct, typeof InputStruct];

/**
* A subset of JSX elements that represent the tuple Input + Box of the Field children.
*/
// eslint-disable-next-line @typescript-eslint/no-use-before-define
const BOX_INPUT_RIGHT = [InputStruct, lazy(() => BoxChildStruct)] as [
typeof InputStruct,
typeof BoxChildStruct,
];
const BOX_INPUT_RIGHT = [
InputStruct,
// eslint-disable-next-line @typescript-eslint/no-use-before-define
singleChild(lazy(() => BoxChildStruct)),
] as [typeof InputStruct, typeof BoxChildStruct];

/**
* A subset of JSX elements that represent the tuple Box + Input + Box of the Field children.
*/
const BOX_INPUT_BOTH = [
// eslint-disable-next-line @typescript-eslint/no-use-before-define
lazy(() => BoxChildStruct),
singleChild(lazy(() => BoxChildStruct)),
InputStruct,
// eslint-disable-next-line @typescript-eslint/no-use-before-define
lazy(() => BoxChildStruct),
singleChild(lazy(() => BoxChildStruct)),
] as [typeof BoxChildStruct, typeof InputStruct, typeof BoxChildStruct];

/**
Expand Down Expand Up @@ -377,9 +399,9 @@ const FieldChildStruct = nullUnion([
tuple(BOX_INPUT_BOTH),
...FIELD_CHILDREN_ARRAY,
]) as unknown as Struct<
| [InputElement, GenericSnapElement]
| [GenericSnapElement, InputElement]
| [GenericSnapElement, InputElement, GenericSnapElement]
| [InputElement, GenericSnapChildren]
| [GenericSnapChildren, InputElement]
| [GenericSnapChildren, InputElement, GenericSnapChildren]
| DropdownElement
| RadioGroupElement
| FileInputElement
Expand Down

0 comments on commit dee5632

Please sign in to comment.