Skip to content

Commit 21c44ee

Browse files
authored
Merge pull request #39 from input-output-hk/feat/uncontrolled-input
feat: add UncontrolledPasswordBox
2 parents 56477c4 + 640f70c commit 21c44ee

File tree

4 files changed

+140
-1
lines changed

4 files changed

+140
-1
lines changed

src/design-system/index.ts

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,13 @@ export { ToastBar } from './toast-bar';
2424
export * from './tooltip';
2525
export { Message } from './message';
2626
export { Metadata, MetadataLink } from './metadata';
27-
export { PasswordBox } from './password-box';
27+
export { PasswordBox, UncontrolledPasswordBox } from './password-box';
28+
export type {
29+
UncontrolledPasswordBoxProps,
30+
PasswordBoxProps,
31+
OnPasswordChange,
32+
Password,
33+
} from './password-box';
2834
export { TextLink } from './text-link';
2935
export * as ProfileDropdown from './profile-dropdown';
3036
export type { AccountData } from './profile-dropdown';
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,8 @@
11
export { PasswordBox } from './password-box.component';
22
export type { PasswordBoxProps } from './password-box.component';
3+
export { UncontrolledPasswordBox } from './uncontrolled-password-box.component';
4+
export type { UncontrolledPasswordBoxProps } from './uncontrolled-password-box.component';
5+
export type {
6+
OnPasswordChange,
7+
Password,
8+
} from './uncontrolled-password-box-input.component';
Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
import React, { useState } from 'react';
2+
3+
import * as Form from '@radix-ui/react-form';
4+
import cn from 'classnames';
5+
6+
import { Flex } from '../flex';
7+
import { Text } from '../text';
8+
9+
import { PasswordInputButton } from './password-box-button.component';
10+
import * as cx from './password-box-input.css';
11+
12+
export type Password = {
13+
input: HTMLInputElement;
14+
// TODO: convert this to UInt8Array
15+
value: string;
16+
};
17+
18+
export type OnPasswordChange = (event: Readonly<Password>) => void;
19+
20+
export interface UncontrolledPasswordInputProps
21+
extends Omit<Form.FormControlProps, 'value' | 'onChange'> {
22+
required?: boolean;
23+
disabled?: boolean;
24+
id?: string;
25+
label: string;
26+
name?: string;
27+
errorMessage?: string;
28+
onChange: OnPasswordChange;
29+
defaultIsPasswordVisible?: boolean;
30+
containerClassName?: string;
31+
containerStyle?: React.CSSProperties;
32+
testId?: string;
33+
}
34+
35+
export const UncontrolledPasswordInput = ({
36+
required = false,
37+
disabled = false,
38+
id,
39+
label,
40+
name,
41+
errorMessage = '',
42+
containerClassName = '',
43+
onChange,
44+
defaultIsPasswordVisible = false,
45+
containerStyle,
46+
testId,
47+
}: Readonly<UncontrolledPasswordInputProps>): JSX.Element => {
48+
const [isPasswordVisible, setIsPasswordVisible] = useState(
49+
defaultIsPasswordVisible,
50+
);
51+
52+
const onChangeHandler: React.ChangeEventHandler<HTMLInputElement> = event =>
53+
onChange({ input: event.target, value: event.target.value });
54+
55+
return (
56+
<div className={cx.root}>
57+
<Form.Field
58+
name="field"
59+
className={cn(cx.container, {
60+
[cx.disabledContainer]: disabled,
61+
[containerClassName]: containerClassName,
62+
})}
63+
style={containerStyle}
64+
>
65+
<Flex justifyContent="space-between" alignItems="center">
66+
<Form.Control asChild>
67+
<input
68+
type={isPasswordVisible ? 'text' : 'password'}
69+
required={required}
70+
placeholder=""
71+
className={cn(cx.input, { [cx.largeDots]: !isPasswordVisible })}
72+
disabled={disabled}
73+
name={name}
74+
onChange={onChangeHandler}
75+
id={id}
76+
data-testid={testId}
77+
/>
78+
</Form.Control>
79+
<Form.Label
80+
className={cn(cx.label, { [cx.disabledLabel]: disabled })}
81+
>
82+
{label}
83+
</Form.Label>
84+
<PasswordInputButton
85+
testId={testId && `${testId}-toggle`}
86+
onClick={(event): void => {
87+
event.preventDefault();
88+
setIsPasswordVisible(!isPasswordVisible);
89+
}}
90+
disabled={disabled}
91+
isPasswordVisible={isPasswordVisible}
92+
/>
93+
</Flex>
94+
</Form.Field>
95+
{errorMessage && (
96+
<Text.Label color="error" className={cx.errorMessage}>
97+
{errorMessage}
98+
</Text.Label>
99+
)}
100+
</div>
101+
);
102+
};
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
import React from 'react';
2+
3+
import * as Form from '@radix-ui/react-form';
4+
5+
import { UncontrolledPasswordInput } from './uncontrolled-password-box-input.component';
6+
7+
import type { UncontrolledPasswordInputProps } from './uncontrolled-password-box-input.component';
8+
9+
export interface UncontrolledPasswordBoxProps
10+
extends UncontrolledPasswordInputProps {
11+
rootStyle?: React.CSSProperties;
12+
onSubmit: (event: Readonly<React.FormEvent>) => void;
13+
}
14+
15+
export const UncontrolledPasswordBox = ({
16+
rootStyle,
17+
onSubmit,
18+
...props
19+
}: Readonly<UncontrolledPasswordBoxProps>): JSX.Element => {
20+
return (
21+
<Form.Root style={rootStyle} onSubmit={onSubmit}>
22+
<UncontrolledPasswordInput {...props} />
23+
</Form.Root>
24+
);
25+
};

0 commit comments

Comments
 (0)