@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.
@@ -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, hint, error, className, children }: FieldProps) => import("react").JSX.Element;
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":"AAaA,MAAM,MAAM,UAAU,GAAG;IACvB,6IAA6I;IAC7I,EAAE,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACnB,KAAK,EAAE,KAAK,CAAC,SAAS,CAAC;IACvB,IAAI,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IACvB,KAAK,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IACxB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;CAC5B,CAAC;AAEF,eAAO,MAAM,KAAK,oDAAqD,UAAU,gCA8ChF,CAAC"}
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":"AAEA,OAAO,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAElC,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AAEtC,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,+BAYlB"}
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-24e63f3",
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": "^14.9.6",
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 WithErrorMessage = () => {
22
+ export const WithStatusMessages = () => {
21
23
  const [value, setValue] = useState<string | undefined>('This is some text');
22
24
  return (
23
- <Field label="Phone number" error="This is a required field">
24
- <Input value={value} onChange={({ target }) => setValue(target.value)} />
25
- </Field>
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" hint="This is a helpful message">
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 label="Phone number" hint="Please include country code" error={error}>
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 }) => {
@@ -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 = ({ id, label, hint, error, className, children }: FieldProps) => {
25
- const hasError = Boolean(error);
26
- const hasHint = Boolean(hint) && !hasError;
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={hasError || hasHint ? descriptionId : undefined}>
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': hasHint,
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
- {hasHint && (
55
- <InlineAlert type={Sentiment.NEUTRAL} id={descriptionId}>
56
- {hint}
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>Where possible consumers should use Field instead of doing this manually.</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="error">{message}</InlineAlert>
80
+ <InlineAlert type="negative">{message}</InlineAlert>
77
81
  </div>
78
- <div className="form-group has-positive">
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 { AlertCircle as AlertCircleIcon } from '@transferwise/icons';
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 danger = type === 'negative' || type === 'error';
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('alert alert-detach', `alert-${danger ? 'danger' : type}`, className)}
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
- {danger && <AlertCircleIcon />}
50
+ {getStatusIcon(type as Sentiment)}
28
51
  <div>{children}</div>
29
52
  </div>
30
53
  );
@@ -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-1 m-b-0', className)}
15
+ className={classNames('control-label d-flex flex-column gap-y-xs m-b-0', className)}
16
16
  >
17
17
  {children}
18
18
  </label>