@transferwise/components 0.0.0-experimental-24e63f3 → 0.0.0-experimental-1d9df7f
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/build/index.js +35 -18
- package/build/index.js.map +1 -1
- package/build/index.mjs +36 -19
- package/build/index.mjs.map +1 -1
- package/build/types/field/Field.d.ts +6 -1
- package/build/types/field/Field.d.ts.map +1 -1
- package/build/types/inlineAlert/InlineAlert.d.ts.map +1 -1
- package/package.json +3 -3
- package/src/field/Field.story.tsx +20 -6
- package/src/field/Field.tsx +23 -13
- package/src/inlineAlert/InlineAlert.story.tsx +8 -4
- package/src/inlineAlert/InlineAlert.tsx +28 -5
- package/src/label/Label.tsx +1 -1
|
@@ -1,11 +1,16 @@
|
|
|
1
|
+
import { Sentiment } from '../common';
|
|
1
2
|
export type FieldProps = {
|
|
2
3
|
/** `null` disables auto-generating the `id` attribute, falling back to nesting-based label association over setting `htmlFor` explicitly. */
|
|
3
4
|
id?: string | null;
|
|
4
5
|
label: React.ReactNode;
|
|
6
|
+
/** @deprecated use `message` and `type={Sentiment.NEUTRAL}` prop instead */
|
|
5
7
|
hint?: React.ReactNode;
|
|
8
|
+
message?: React.ReactNode;
|
|
9
|
+
/** @deprecated use `message` and `type={Sentiment.NEGATIVE}` prop instead */
|
|
6
10
|
error?: React.ReactNode;
|
|
11
|
+
type?: `${Sentiment.NEGATIVE | Sentiment.NEUTRAL | Sentiment.POSITIVE | Sentiment.WARNING}`;
|
|
7
12
|
className?: string;
|
|
8
13
|
children?: React.ReactNode;
|
|
9
14
|
};
|
|
10
|
-
export declare const Field: ({ id, label,
|
|
15
|
+
export declare const Field: ({ id, label, message: propMessage, type: propType, className, children, ...props }: FieldProps) => import("react").JSX.Element;
|
|
11
16
|
//# sourceMappingURL=Field.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Field.d.ts","sourceRoot":"","sources":["../../../src/field/Field.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"Field.d.ts","sourceRoot":"","sources":["../../../src/field/Field.tsx"],"names":[],"mappings":"AAGA,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AAUtC,MAAM,MAAM,UAAU,GAAG;IACvB,6IAA6I;IAC7I,EAAE,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACnB,KAAK,EAAE,KAAK,CAAC,SAAS,CAAC;IACvB,4EAA4E;IAC5E,IAAI,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IACvB,OAAO,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAC1B,6EAA6E;IAC7E,KAAK,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IACxB,IAAI,CAAC,EAAE,GAAG,SAAS,CAAC,QAAQ,GAAG,SAAS,CAAC,OAAO,GAAG,SAAS,CAAC,QAAQ,GAAG,SAAS,CAAC,OAAO,EAAE,CAAC;IAC5F,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;CAC5B,CAAC;AAEF,eAAO,MAAM,KAAK,uFAQf,UAAU,gCA4CZ,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"InlineAlert.d.ts","sourceRoot":"","sources":["../../../src/inlineAlert/InlineAlert.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"InlineAlert.d.ts","sourceRoot":"","sources":["../../../src/inlineAlert/InlineAlert.tsx"],"names":[],"mappings":"AAKA,OAAO,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAElC,OAAO,EAAE,SAAS,EAAQ,MAAM,WAAW,CAAC;AAG5C,MAAM,WAAW,gBAAgB;IAC/B,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,IAAI,CAAC,EAAE,GAAG,SAAS,EAAE,CAAC;IACtB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,SAAS,CAAC;CACrB;AAED,MAAM,CAAC,OAAO,UAAU,WAAW,CAAC,EAClC,EAAE,EACF,IAAgB,EAChB,SAAS,EACT,QAAQ,GACT,EAAE,gBAAgB,+BA+BlB"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@transferwise/components",
|
|
3
|
-
"version": "0.0.0-experimental-
|
|
3
|
+
"version": "0.0.0-experimental-1d9df7f",
|
|
4
4
|
"description": "Neptune React components",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"repository": {
|
|
@@ -92,13 +92,13 @@
|
|
|
92
92
|
"react-intl": "^6.6.6",
|
|
93
93
|
"rollup": "^4.17.2",
|
|
94
94
|
"storybook": "^8.1.10",
|
|
95
|
-
"@transferwise/neptune-css": "14.10.0",
|
|
96
95
|
"@transferwise/less-config": "3.1.0",
|
|
96
|
+
"@transferwise/neptune-css": "0.0.0-experimental-1d9df7f",
|
|
97
97
|
"@wise/components-theming": "1.3.0"
|
|
98
98
|
},
|
|
99
99
|
"peerDependencies": {
|
|
100
100
|
"@transferwise/icons": "^3.7.0",
|
|
101
|
-
"@transferwise/neptune-css": "
|
|
101
|
+
"@transferwise/neptune-css": "0.0.0-experimental-1d9df7f",
|
|
102
102
|
"@wise/art": "^2.7.0",
|
|
103
103
|
"@wise/components-theming": "^1.0.0",
|
|
104
104
|
"react": ">=18",
|
|
@@ -2,10 +2,12 @@ import { useState } from 'react';
|
|
|
2
2
|
|
|
3
3
|
import { Input } from '../inputs/Input';
|
|
4
4
|
import { Field } from './Field';
|
|
5
|
+
import { Sentiment } from '../common';
|
|
5
6
|
|
|
6
7
|
export default {
|
|
7
8
|
component: Field,
|
|
8
9
|
title: 'Field',
|
|
10
|
+
tags: ['autodocs'],
|
|
9
11
|
};
|
|
10
12
|
|
|
11
13
|
export const Basic = () => {
|
|
@@ -17,19 +19,27 @@ export const Basic = () => {
|
|
|
17
19
|
);
|
|
18
20
|
};
|
|
19
21
|
|
|
20
|
-
export const
|
|
22
|
+
export const WithStatusMessages = () => {
|
|
21
23
|
const [value, setValue] = useState<string | undefined>('This is some text');
|
|
22
24
|
return (
|
|
23
|
-
<
|
|
24
|
-
<
|
|
25
|
-
|
|
25
|
+
<div>
|
|
26
|
+
<Field label="Phone number" type={Sentiment.POSITIVE} message="Positive message">
|
|
27
|
+
<Input value={value} onChange={({ target }) => setValue(target.value)} />
|
|
28
|
+
</Field>
|
|
29
|
+
<Field label="Phone number" type={Sentiment.WARNING} message="Warning message">
|
|
30
|
+
<Input value={value} onChange={({ target }) => setValue(target.value)} />
|
|
31
|
+
</Field>
|
|
32
|
+
<Field label="Phone number" type={Sentiment.NEGATIVE} message="This is a required field">
|
|
33
|
+
<Input value={value} onChange={({ target }) => setValue(target.value)} />
|
|
34
|
+
</Field>
|
|
35
|
+
</div>
|
|
26
36
|
);
|
|
27
37
|
};
|
|
28
38
|
|
|
29
39
|
export const WithHelp = () => {
|
|
30
40
|
const [value, setValue] = useState<string | undefined>('This is some text');
|
|
31
41
|
return (
|
|
32
|
-
<Field label="Phone number"
|
|
42
|
+
<Field label="Phone number" message="This is a helpful message">
|
|
33
43
|
<Input value={value} onChange={({ target }) => setValue(target.value)} />
|
|
34
44
|
</Field>
|
|
35
45
|
);
|
|
@@ -39,7 +49,11 @@ export const WithHelpAndErrorOnBlur = () => {
|
|
|
39
49
|
const [value, setValue] = useState<string | undefined>('This is some text');
|
|
40
50
|
const [error, setError] = useState<string | undefined>(undefined);
|
|
41
51
|
return (
|
|
42
|
-
<Field
|
|
52
|
+
<Field
|
|
53
|
+
label="Phone number"
|
|
54
|
+
type={error ? Sentiment.NEGATIVE : Sentiment.NEUTRAL}
|
|
55
|
+
message={error || 'Please include country code'}
|
|
56
|
+
>
|
|
43
57
|
<Input
|
|
44
58
|
value={value}
|
|
45
59
|
onChange={({ target }) => {
|
package/src/field/Field.tsx
CHANGED
|
@@ -15,15 +15,28 @@ export type FieldProps = {
|
|
|
15
15
|
/** `null` disables auto-generating the `id` attribute, falling back to nesting-based label association over setting `htmlFor` explicitly. */
|
|
16
16
|
id?: string | null;
|
|
17
17
|
label: React.ReactNode;
|
|
18
|
+
/** @deprecated use `message` and `type={Sentiment.NEUTRAL}` prop instead */
|
|
18
19
|
hint?: React.ReactNode;
|
|
20
|
+
message?: React.ReactNode;
|
|
21
|
+
/** @deprecated use `message` and `type={Sentiment.NEGATIVE}` prop instead */
|
|
19
22
|
error?: React.ReactNode;
|
|
23
|
+
type?: `${Sentiment.NEGATIVE | Sentiment.NEUTRAL | Sentiment.POSITIVE | Sentiment.WARNING}`;
|
|
20
24
|
className?: string;
|
|
21
25
|
children?: React.ReactNode;
|
|
22
26
|
};
|
|
23
27
|
|
|
24
|
-
export const Field = ({
|
|
25
|
-
|
|
26
|
-
|
|
28
|
+
export const Field = ({
|
|
29
|
+
id,
|
|
30
|
+
label,
|
|
31
|
+
message: propMessage,
|
|
32
|
+
type: propType,
|
|
33
|
+
className,
|
|
34
|
+
children,
|
|
35
|
+
...props
|
|
36
|
+
}: FieldProps) => {
|
|
37
|
+
const type = props.error ? Sentiment.NEGATIVE : propType;
|
|
38
|
+
const message = props.error || props.hint || propMessage;
|
|
39
|
+
const hasError = type === Sentiment.NEGATIVE;
|
|
27
40
|
|
|
28
41
|
const labelId = useId();
|
|
29
42
|
|
|
@@ -35,14 +48,16 @@ export const Field = ({ id, label, hint, error, className, children }: FieldProp
|
|
|
35
48
|
return (
|
|
36
49
|
<FieldLabelIdContextProvider value={labelId}>
|
|
37
50
|
<InputIdContextProvider value={inputId}>
|
|
38
|
-
<InputDescribedByProvider value={
|
|
51
|
+
<InputDescribedByProvider value={message ? descriptionId : undefined}>
|
|
39
52
|
<InputInvalidProvider value={hasError}>
|
|
40
53
|
<div
|
|
41
54
|
className={classNames(
|
|
42
55
|
'form-group d-block',
|
|
43
56
|
{
|
|
57
|
+
'has-success': type === Sentiment.POSITIVE,
|
|
58
|
+
'has-warning': type === Sentiment.WARNING,
|
|
44
59
|
'has-error': hasError,
|
|
45
|
-
'has-info':
|
|
60
|
+
'has-info': type === Sentiment.NEUTRAL,
|
|
46
61
|
},
|
|
47
62
|
className,
|
|
48
63
|
)}
|
|
@@ -51,14 +66,9 @@ export const Field = ({ id, label, hint, error, className, children }: FieldProp
|
|
|
51
66
|
{label}
|
|
52
67
|
{children}
|
|
53
68
|
</Label>
|
|
54
|
-
{
|
|
55
|
-
<InlineAlert type={
|
|
56
|
-
{
|
|
57
|
-
</InlineAlert>
|
|
58
|
-
)}
|
|
59
|
-
{hasError && (
|
|
60
|
-
<InlineAlert type={Sentiment.NEGATIVE} id={descriptionId}>
|
|
61
|
-
{error}
|
|
69
|
+
{message && (
|
|
70
|
+
<InlineAlert type={type} id={descriptionId}>
|
|
71
|
+
{message}
|
|
62
72
|
</InlineAlert>
|
|
63
73
|
)}
|
|
64
74
|
</div>
|
|
@@ -51,7 +51,7 @@ export const Basic = () => {
|
|
|
51
51
|
|
|
52
52
|
return (
|
|
53
53
|
<>
|
|
54
|
-
{/*eslint-disable-next-line react/no-adjacent-inline-elements */}
|
|
54
|
+
{/* eslint-disable-next-line react/no-adjacent-inline-elements */}
|
|
55
55
|
<p>
|
|
56
56
|
The styling for the input (the coloured border) and the visibility of the inline alert is
|
|
57
57
|
controlled through the use of <code>has-***</code> classes which are applied to the{' '}
|
|
@@ -60,7 +60,11 @@ export const Basic = () => {
|
|
|
60
60
|
element. The available classes are <code>has-error</code>, <code>has-info</code>,{' '}
|
|
61
61
|
<code>has-warning</code> and <code>has-success</code>.
|
|
62
62
|
</p>
|
|
63
|
-
<p>
|
|
63
|
+
<p>
|
|
64
|
+
Where possible consumers should use{' '}
|
|
65
|
+
<a href="https://storybook.wise.design/?path=/story/field--basic">Field</a> instead of doing
|
|
66
|
+
this manually.
|
|
67
|
+
</p>
|
|
64
68
|
<div className={`form-group ${typeClass}`}>
|
|
65
69
|
<label className="control-label" htmlFor="id0">
|
|
66
70
|
Toggleable
|
|
@@ -73,9 +77,9 @@ export const Basic = () => {
|
|
|
73
77
|
Negative
|
|
74
78
|
</label>
|
|
75
79
|
<Input id="id1" value="Neptune is cool" />
|
|
76
|
-
<InlineAlert type="
|
|
80
|
+
<InlineAlert type="negative">{message}</InlineAlert>
|
|
77
81
|
</div>
|
|
78
|
-
<div className="form-group has-
|
|
82
|
+
<div className="form-group has-success">
|
|
79
83
|
<label className="control-label" htmlFor="id2">
|
|
80
84
|
Positive
|
|
81
85
|
</label>
|
|
@@ -1,8 +1,12 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {
|
|
2
|
+
CheckCircleFill as CheckCircleIcon,
|
|
3
|
+
CrossCircleFill as CrossCircleIcon,
|
|
4
|
+
} from '@transferwise/icons';
|
|
2
5
|
import classNames from 'classnames';
|
|
3
6
|
import { ReactNode } from 'react';
|
|
4
7
|
|
|
5
|
-
import { Sentiment } from '../common';
|
|
8
|
+
import { Sentiment, Size } from '../common';
|
|
9
|
+
import StatusIcon from '../statusIcon';
|
|
6
10
|
|
|
7
11
|
export interface InlineAlertProps {
|
|
8
12
|
id?: string;
|
|
@@ -17,14 +21,33 @@ export default function InlineAlert({
|
|
|
17
21
|
className,
|
|
18
22
|
children,
|
|
19
23
|
}: InlineAlertProps) {
|
|
20
|
-
const
|
|
24
|
+
const getStatusIcon = (sentiment: Sentiment) => {
|
|
25
|
+
// TODO: When `Sentiment.SUCCESS` and `Sentiment.ERROR` will be completely removed from the codebase, we should rewrite this component to StatusIcon using only
|
|
26
|
+
switch (sentiment) {
|
|
27
|
+
case Sentiment.POSITIVE:
|
|
28
|
+
case Sentiment.SUCCESS:
|
|
29
|
+
return <CheckCircleIcon />;
|
|
30
|
+
case Sentiment.WARNING:
|
|
31
|
+
return <StatusIcon sentiment={sentiment} size={Size.SMALL} />;
|
|
32
|
+
case Sentiment.NEGATIVE:
|
|
33
|
+
case Sentiment.ERROR:
|
|
34
|
+
return <CrossCircleIcon />;
|
|
35
|
+
default:
|
|
36
|
+
return null;
|
|
37
|
+
}
|
|
38
|
+
};
|
|
39
|
+
|
|
21
40
|
return (
|
|
22
41
|
<div
|
|
23
42
|
role="alert"
|
|
24
43
|
id={id}
|
|
25
|
-
className={classNames(
|
|
44
|
+
className={classNames(
|
|
45
|
+
'alert alert-detach',
|
|
46
|
+
`alert-${[Sentiment.NEGATIVE, Sentiment.ERROR].includes(type as Sentiment) ? 'danger' : type}`,
|
|
47
|
+
className,
|
|
48
|
+
)}
|
|
26
49
|
>
|
|
27
|
-
{
|
|
50
|
+
{getStatusIcon(type as Sentiment)}
|
|
28
51
|
<div>{children}</div>
|
|
29
52
|
</div>
|
|
30
53
|
);
|
package/src/label/Label.tsx
CHANGED
|
@@ -12,7 +12,7 @@ export const Label = ({ id, htmlFor, className, children }: LabelProps) => {
|
|
|
12
12
|
<label
|
|
13
13
|
id={id}
|
|
14
14
|
htmlFor={htmlFor}
|
|
15
|
-
className={classNames('control-label d-flex flex-column gap-y-
|
|
15
|
+
className={classNames('control-label d-flex flex-column gap-y-xs m-b-0', className)}
|
|
16
16
|
>
|
|
17
17
|
{children}
|
|
18
18
|
</label>
|