From 9a3d1a6ad6f9a73b8b2ce32b4ffabce39778bea9 Mon Sep 17 00:00:00 2001 From: david0xd Date: Wed, 22 Jan 2025 13:23:24 +0100 Subject: [PATCH] Add disabled states to all input components --- .../browserify-plugin/snap.manifest.json | 2 +- .../packages/browserify/snap.manifest.json | 2 +- .../src/jsx/components/form/Checkbox.test.tsx | 11 +++- .../src/jsx/components/form/Checkbox.ts | 3 ++ .../src/jsx/components/form/Dropdown.ts | 3 ++ .../jsx/components/form/FileInput.test.tsx | 13 +++++ .../src/jsx/components/form/FileInput.ts | 3 ++ .../src/jsx/components/form/Input.test.tsx | 54 +++++++++++++++++++ .../src/jsx/components/form/Input.ts | 2 + .../src/jsx/components/form/Radio.test.tsx | 18 +++++++ .../src/jsx/components/form/Radio.ts | 3 ++ .../jsx/components/form/RadioGroup.test.tsx | 36 +++++++++++++ .../src/jsx/components/form/RadioGroup.ts | 3 ++ .../src/jsx/components/form/Selector.test.tsx | 41 ++++++++++++++ .../src/jsx/components/form/Selector.ts | 3 ++ .../components/form/SelectorOption.test.tsx | 25 +++++++++ .../src/jsx/components/form/SelectorOption.ts | 3 ++ .../snaps-sdk/src/jsx/validation.test.tsx | 25 +++++++++ packages/snaps-sdk/src/jsx/validation.ts | 8 +++ 19 files changed, 254 insertions(+), 4 deletions(-) diff --git a/packages/examples/packages/browserify-plugin/snap.manifest.json b/packages/examples/packages/browserify-plugin/snap.manifest.json index 0d829905dc..ca259b5265 100644 --- a/packages/examples/packages/browserify-plugin/snap.manifest.json +++ b/packages/examples/packages/browserify-plugin/snap.manifest.json @@ -7,7 +7,7 @@ "url": "https://github.com/MetaMask/snaps.git" }, "source": { - "shasum": "ssGPi4fxyZSvKOMXbVdOa/vnTx0qrq6WZWCUV91dLqo=", + "shasum": "OGd9oaCS1/I80grXQCFf5900ZUH2hpmnyklFTSpTh34=", "location": { "npm": { "filePath": "dist/bundle.js", diff --git a/packages/examples/packages/browserify/snap.manifest.json b/packages/examples/packages/browserify/snap.manifest.json index 1376a8e7eb..c9bd9332b2 100644 --- a/packages/examples/packages/browserify/snap.manifest.json +++ b/packages/examples/packages/browserify/snap.manifest.json @@ -7,7 +7,7 @@ "url": "https://github.com/MetaMask/snaps.git" }, "source": { - "shasum": "+342Ghzfo9UpTxJgqIPOieHvqRTnf4h00s8r0DpbozY=", + "shasum": "EG/2i55Y2f9IV97KMkFS1rgetcZsKrhbTlgoJ07M0zs=", "location": { "npm": { "filePath": "dist/bundle.js", diff --git a/packages/snaps-sdk/src/jsx/components/form/Checkbox.test.tsx b/packages/snaps-sdk/src/jsx/components/form/Checkbox.test.tsx index 7ac2a7557a..1bb3ece167 100644 --- a/packages/snaps-sdk/src/jsx/components/form/Checkbox.test.tsx +++ b/packages/snaps-sdk/src/jsx/components/form/Checkbox.test.tsx @@ -14,9 +14,15 @@ describe('Checkbox', () => { }); }); - it('renders a checkbox with a variant and a label', () => { + it('renders a disabled checkbox with a variant and a label', () => { const result = ( - + ); expect(result).toStrictEqual({ @@ -26,6 +32,7 @@ describe('Checkbox', () => { checked: true, variant: 'toggle', label: 'Foo', + disabled: true, }, key: null, }); diff --git a/packages/snaps-sdk/src/jsx/components/form/Checkbox.ts b/packages/snaps-sdk/src/jsx/components/form/Checkbox.ts index ad2dd799fc..108e5e0685 100644 --- a/packages/snaps-sdk/src/jsx/components/form/Checkbox.ts +++ b/packages/snaps-sdk/src/jsx/components/form/Checkbox.ts @@ -8,12 +8,14 @@ import { createSnapComponent } from '../../component'; * @property checked - Whether the checkbox is checked or not. * @property label - An optional label for the checkbox. * @property variant - An optional variant for the checkbox. + * @property disabled - Whether the Checkbox is disabled. */ export type CheckboxProps = { name: string; checked?: boolean | undefined; label?: string | undefined; variant?: 'default' | 'toggle' | undefined; + disabled?: boolean | undefined; }; const TYPE = 'Checkbox'; @@ -27,6 +29,7 @@ const TYPE = 'Checkbox'; * @param props.checked - Whether the checkbox is checked or not. * @param props.label - An optional label for the checkbox. * @param props.variant - An optional variant for the checkbox. + * @param props.disabled - Whether the Checkbox is disabled. * @returns A checkbox element. * @example * diff --git a/packages/snaps-sdk/src/jsx/components/form/Dropdown.ts b/packages/snaps-sdk/src/jsx/components/form/Dropdown.ts index f0c476fb2b..d153b4325d 100644 --- a/packages/snaps-sdk/src/jsx/components/form/Dropdown.ts +++ b/packages/snaps-sdk/src/jsx/components/form/Dropdown.ts @@ -9,11 +9,13 @@ import type { OptionElement } from './Option'; * state in the form data. * @property value - The selected value of the dropdown. * @property children - The children of the dropdown. + * @property disabled - Whether the Dropdown is disabled. */ export type DropdownProps = { name: string; value?: string | undefined; children: SnapsChildren; + disabled?: boolean | undefined; }; const TYPE = 'Dropdown'; @@ -26,6 +28,7 @@ const TYPE = 'Dropdown'; * state in the form data. * @param props.value - The selected value of the dropdown. * @param props.children - The children of the dropdown. + * @param props.disabled - Whether the Dropdown is disabled. * @returns A dropdown element. * @example * diff --git a/packages/snaps-sdk/src/jsx/components/form/FileInput.test.tsx b/packages/snaps-sdk/src/jsx/components/form/FileInput.test.tsx index 77ea8a4542..8e64905129 100644 --- a/packages/snaps-sdk/src/jsx/components/form/FileInput.test.tsx +++ b/packages/snaps-sdk/src/jsx/components/form/FileInput.test.tsx @@ -26,4 +26,17 @@ describe('FileInput', () => { key: null, }); }); + + it('renders disabled file input', () => { + const result = ; + + expect(result).toStrictEqual({ + type: 'FileInput', + props: { + name: 'foo', + disabled: true, + }, + key: null, + }); + }); }); diff --git a/packages/snaps-sdk/src/jsx/components/form/FileInput.ts b/packages/snaps-sdk/src/jsx/components/form/FileInput.ts index 7a009ae689..56bc6b9b95 100644 --- a/packages/snaps-sdk/src/jsx/components/form/FileInput.ts +++ b/packages/snaps-sdk/src/jsx/components/form/FileInput.ts @@ -10,11 +10,13 @@ import { createSnapComponent } from '../../component'; * specified, the file input field accepts all file types. * @property compact - Whether the file input field is compact. Default is * `false`. + * @property disabled - whether the file input is disabled. */ export type FileInputProps = { name: string; accept?: string[] | undefined; compact?: boolean | undefined; + disabled?: boolean | undefined; }; const TYPE = 'FileInput'; @@ -33,6 +35,7 @@ const TYPE = 'FileInput'; * valid values, see the [MDN documentation](https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes/accept). * @param props.compact - Whether the file input field is compact. Default is * `false`. + * @param props.disabled - Whether the file input is disabled. * @returns A file input element. * @example * diff --git a/packages/snaps-sdk/src/jsx/components/form/Input.test.tsx b/packages/snaps-sdk/src/jsx/components/form/Input.test.tsx index f446081a89..1696e8447e 100644 --- a/packages/snaps-sdk/src/jsx/components/form/Input.test.tsx +++ b/packages/snaps-sdk/src/jsx/components/form/Input.test.tsx @@ -42,4 +42,58 @@ describe('Input', () => { key: null, }); }); + + it('renders a disabled text input', () => { + const result = ; + + expect(result).toStrictEqual({ + type: 'Input', + props: { + name: 'foo', + type: 'text', + disabled: true, + }, + key: null, + }); + }); + + it('renders a disabled number input', () => { + const result = ( + + ); + + expect(result).toStrictEqual({ + type: 'Input', + props: { + name: 'foo', + type: 'number', + min: 0, + max: 10, + step: 1, + disabled: true, + }, + key: null, + }); + }); + + it('renders a disabled password input', () => { + const result = ; + + expect(result).toStrictEqual({ + type: 'Input', + props: { + name: 'foo', + type: 'password', + disabled: true, + }, + key: null, + }); + }); }); diff --git a/packages/snaps-sdk/src/jsx/components/form/Input.ts b/packages/snaps-sdk/src/jsx/components/form/Input.ts index 814bac24f5..6897019687 100644 --- a/packages/snaps-sdk/src/jsx/components/form/Input.ts +++ b/packages/snaps-sdk/src/jsx/components/form/Input.ts @@ -6,6 +6,7 @@ export type GenericInputProps = { name: string; value?: string | undefined; placeholder?: string | undefined; + disabled?: boolean | undefined; }; export type TextInputProps = { type: 'text' } & GenericInputProps; @@ -57,6 +58,7 @@ const TYPE = 'Input'; * Only applicable to the type `number` input. * @param props.step - The step value of the input field. * Only applicable to the type `number` input. + * @param props.disabled - Whether the input is disabled. * @returns An input element. * @example * diff --git a/packages/snaps-sdk/src/jsx/components/form/Radio.test.tsx b/packages/snaps-sdk/src/jsx/components/form/Radio.test.tsx index 3c4f441296..5f51eb2f4e 100644 --- a/packages/snaps-sdk/src/jsx/components/form/Radio.test.tsx +++ b/packages/snaps-sdk/src/jsx/components/form/Radio.test.tsx @@ -13,4 +13,22 @@ describe('Radio', () => { key: null, }); }); + + it('renders a disabled radio option', () => { + const result = ( + + Foo + + ); + + expect(result).toStrictEqual({ + type: 'Radio', + props: { + value: 'foo', + disabled: true, + children: 'Foo', + }, + key: null, + }); + }); }); diff --git a/packages/snaps-sdk/src/jsx/components/form/Radio.ts b/packages/snaps-sdk/src/jsx/components/form/Radio.ts index d01200d3b3..43b8f2ab70 100644 --- a/packages/snaps-sdk/src/jsx/components/form/Radio.ts +++ b/packages/snaps-sdk/src/jsx/components/form/Radio.ts @@ -6,10 +6,12 @@ import { createSnapComponent } from '../../component'; * @property value - The value of the radio option. This is used to populate the * state in the form data. * @property children - The text to display. + * @property disabled - Whether the Radio is disabled. */ type RadioProps = { value: string; children: string; + disabled?: boolean | undefined; }; const TYPE = 'Radio'; @@ -22,6 +24,7 @@ const TYPE = 'Radio'; * @param props.value - The value of the radio option. This is used to populate the * state in the form data. * @param props.children - The text to display. + * @param props.disabled - Whether the Radio is disabled. * @returns A radio element. * @example * diff --git a/packages/snaps-sdk/src/jsx/components/form/RadioGroup.test.tsx b/packages/snaps-sdk/src/jsx/components/form/RadioGroup.test.tsx index f9874a44f1..5770570490 100644 --- a/packages/snaps-sdk/src/jsx/components/form/RadioGroup.test.tsx +++ b/packages/snaps-sdk/src/jsx/components/form/RadioGroup.test.tsx @@ -45,4 +45,40 @@ describe('RadioGroup', () => { key: null, }); }); + + it('renders a disabled Radio group', () => { + const result = ( + + Option A + Option B + + ); + + expect(result).toStrictEqual({ + type: 'RadioGroup', + props: { + name: 'radio-choice', + disabled: true, + children: [ + { + type: 'Radio', + key: null, + props: { + value: 'A', + children: 'Option A', + }, + }, + { + type: 'Radio', + key: null, + props: { + value: 'B', + children: 'Option B', + }, + }, + ], + }, + key: null, + }); + }); }); diff --git a/packages/snaps-sdk/src/jsx/components/form/RadioGroup.ts b/packages/snaps-sdk/src/jsx/components/form/RadioGroup.ts index b23ef09100..755c826d1a 100644 --- a/packages/snaps-sdk/src/jsx/components/form/RadioGroup.ts +++ b/packages/snaps-sdk/src/jsx/components/form/RadioGroup.ts @@ -9,12 +9,15 @@ const TYPE = 'RadioGroup'; * * @property name - The name of the dropdown. This is used to identify the * state in the form data. + * @property value - The value of the radio group element. * @property children - Radio options in form of elements. + * @property disabled - Whether the RadioGroup is disabled. */ type RadioGroupProps = { name: string; value?: string | undefined; children: SnapsChildren; + disabled?: boolean | undefined; }; /** diff --git a/packages/snaps-sdk/src/jsx/components/form/Selector.test.tsx b/packages/snaps-sdk/src/jsx/components/form/Selector.test.tsx index 843025d3d0..127c4c217c 100644 --- a/packages/snaps-sdk/src/jsx/components/form/Selector.test.tsx +++ b/packages/snaps-sdk/src/jsx/components/form/Selector.test.tsx @@ -100,4 +100,45 @@ describe('Selector', () => { key: null, }); }); + + it('renders a disabled selector', () => { + const result = ( + + + + + + ); + + expect(result).toStrictEqual({ + type: 'Selector', + props: { + name: 'selector', + value: 'foo', + title: 'Choose an option', + disabled: true, + children: { + type: 'SelectorOption', + props: { + value: 'foo', + children: { + type: 'Card', + props: { + title: 'Foo', + value: '$1', + }, + key: null, + }, + }, + key: null, + }, + }, + key: null, + }); + }); }); diff --git a/packages/snaps-sdk/src/jsx/components/form/Selector.ts b/packages/snaps-sdk/src/jsx/components/form/Selector.ts index 67e8adb9c8..f35792d68c 100644 --- a/packages/snaps-sdk/src/jsx/components/form/Selector.ts +++ b/packages/snaps-sdk/src/jsx/components/form/Selector.ts @@ -10,12 +10,14 @@ import type { SelectorOptionElement } from './SelectorOption'; * @property title - The title of the selector. This is displayed in the UI. * @property value - The selected value of the selector. * @property children - The children of the selector. + * @property disabled - Whether the Selector is disabled. */ export type SelectorProps = { name: string; title: string; value?: string | undefined; children: SnapsChildren; + disabled?: boolean | undefined; }; const TYPE = 'Selector'; @@ -29,6 +31,7 @@ const TYPE = 'Selector'; * @param props.title - The title of the selector field. This is displayed in the UI. * @param props.value - The selected value of the selector. * @param props.children - The children of the selector. + * @property disabled - Whether the Selector is disabled. * @returns A selector element. * @example * diff --git a/packages/snaps-sdk/src/jsx/components/form/SelectorOption.test.tsx b/packages/snaps-sdk/src/jsx/components/form/SelectorOption.test.tsx index 65dd9aeb0a..7ea5451270 100644 --- a/packages/snaps-sdk/src/jsx/components/form/SelectorOption.test.tsx +++ b/packages/snaps-sdk/src/jsx/components/form/SelectorOption.test.tsx @@ -25,4 +25,29 @@ describe('Option', () => { key: null, }); }); + + it('renders a disabled selector option', () => { + const result = ( + + + + ); + + expect(result).toStrictEqual({ + type: 'SelectorOption', + props: { + value: 'foo', + disabled: true, + children: { + type: 'Card', + props: { + title: 'Foo', + value: 'Bar', + }, + key: null, + }, + }, + key: null, + }); + }); }); diff --git a/packages/snaps-sdk/src/jsx/components/form/SelectorOption.ts b/packages/snaps-sdk/src/jsx/components/form/SelectorOption.ts index 67734f5716..00c847c01c 100644 --- a/packages/snaps-sdk/src/jsx/components/form/SelectorOption.ts +++ b/packages/snaps-sdk/src/jsx/components/form/SelectorOption.ts @@ -7,10 +7,12 @@ import type { CardElement } from '../Card'; * @property value - The value of the selector option. This is used to populate the * state in the form data. * @property children - The component to display. + * @property disabled - Whether the selector option is disabled. */ export type SelectorOptionProps = { value: string; children: CardElement; + disabled?: boolean; }; const TYPE = 'SelectorOption'; @@ -23,6 +25,7 @@ const TYPE = 'SelectorOption'; * @param props.value - The value of the selector option. This is used to populate the * state in the form data. * @param props.children - The component to display. + * @param props.disabled - Whether the selector option is disabled. * @returns A selector option element. * @example * diff --git a/packages/snaps-sdk/src/jsx/validation.test.tsx b/packages/snaps-sdk/src/jsx/validation.test.tsx index c656ac598f..ba679aae53 100644 --- a/packages/snaps-sdk/src/jsx/validation.test.tsx +++ b/packages/snaps-sdk/src/jsx/validation.test.tsx @@ -208,8 +208,11 @@ describe('ButtonStruct', () => { describe('InputStruct', () => { it.each([ , + , , + , , + , , , , @@ -809,6 +812,7 @@ describe('CheckboxStruct', () => { , , , + , ])('validates a dropdown element', (value) => { expect(is(value, CheckboxStruct)).toBe(true); }); @@ -897,6 +901,10 @@ describe('DropdownStruct', () => { , + + + + , ])('validates a dropdown element', (value) => { expect(is(value, DropdownStruct)).toBe(true); }); @@ -928,6 +936,12 @@ describe('RadioGroupStruct', () => { Option 1 Option 2 , + + Option 1 + + Option 2 + + , ])('validates a radio group element', (value) => { expect(is(value, RadioGroupStruct)).toBe(true); }); @@ -958,6 +972,7 @@ describe('FileInputStruct', () => { , , , + , ])('validates a file input element', (value) => { expect(is(value, FileInputStruct)).toBe(true); }); @@ -999,6 +1014,16 @@ describe('SelectorStruct', () => { , + + + + + , + + + + + , ])('validates a selector element', (value) => { expect(is(value, SelectorStruct)).toBe(true); }); diff --git a/packages/snaps-sdk/src/jsx/validation.ts b/packages/snaps-sdk/src/jsx/validation.ts index 5b6c03a5e1..3d290c3e27 100644 --- a/packages/snaps-sdk/src/jsx/validation.ts +++ b/packages/snaps-sdk/src/jsx/validation.ts @@ -263,6 +263,7 @@ export const CheckboxStruct: Describe = element('Checkbox', { checked: optional(boolean()), label: optional(string()), variant: optional(nullUnion([literal('default'), literal('toggle')])), + disabled: optional(boolean()), }); /** @@ -272,6 +273,7 @@ export const GenericInputPropsStruct = object({ name: string(), value: optional(string()), placeholder: optional(string()), + disabled: optional(boolean()), }); /** @@ -344,6 +346,7 @@ export const DropdownStruct: Describe = element('Dropdown', { name: string(), value: optional(string()), children: children([OptionStruct]), + disabled: optional(boolean()), }); /** @@ -380,6 +383,7 @@ export const SelectorOptionStruct: Describe = element( { value: string(), children: CardStruct, + disabled: optional(boolean()), }, ); @@ -391,6 +395,7 @@ export const SelectorStruct: Describe = element('Selector', { title: string(), value: optional(string()), children: children([SelectorOptionStruct]), + disabled: optional(boolean()), }); /** @@ -399,6 +404,7 @@ export const SelectorStruct: Describe = element('Selector', { export const RadioStruct: Describe = element('Radio', { value: string(), children: string(), + disabled: optional(boolean()), }); /** @@ -410,6 +416,7 @@ export const RadioGroupStruct: Describe = element( name: string(), value: optional(string()), children: children([RadioStruct]), + disabled: optional(boolean()), }, ); @@ -422,6 +429,7 @@ export const FileInputStruct: Describe = element( name: string(), accept: nullUnion([optional(array(string()))]), compact: optional(boolean()), + disabled: optional(boolean()), }, );