@transferwise/components 0.0.0-experimental-60cb1a1 → 0.0.0-experimental-69a95e1

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.
Files changed (76) hide show
  1. package/build/avatarLayout/AvatarLayout.js +1 -2
  2. package/build/avatarLayout/AvatarLayout.js.map +1 -1
  3. package/build/avatarLayout/AvatarLayout.mjs +1 -2
  4. package/build/avatarLayout/AvatarLayout.mjs.map +1 -1
  5. package/build/button/Button.js +2 -1
  6. package/build/button/Button.js.map +1 -1
  7. package/build/button/Button.mjs +2 -1
  8. package/build/button/Button.mjs.map +1 -1
  9. package/build/index.js +0 -2
  10. package/build/index.js.map +1 -1
  11. package/build/index.mjs +0 -1
  12. package/build/index.mjs.map +1 -1
  13. package/build/main.css +4 -2
  14. package/build/primitives/PrimitiveAnchor/src/PrimitiveAnchor.js +1 -1
  15. package/build/primitives/PrimitiveAnchor/src/PrimitiveAnchor.js.map +1 -1
  16. package/build/primitives/PrimitiveAnchor/src/PrimitiveAnchor.mjs +1 -1
  17. package/build/primitives/PrimitiveAnchor/src/PrimitiveAnchor.mjs.map +1 -1
  18. package/build/primitives/PrimitiveButton/src/PrimitiveButton.js +2 -1
  19. package/build/primitives/PrimitiveButton/src/PrimitiveButton.js.map +1 -1
  20. package/build/primitives/PrimitiveButton/src/PrimitiveButton.mjs +2 -1
  21. package/build/primitives/PrimitiveButton/src/PrimitiveButton.mjs.map +1 -1
  22. package/build/styles/avatarLayout/AvatarLayout.css +1 -2
  23. package/build/styles/button/Button.css +3 -0
  24. package/build/styles/main.css +4 -2
  25. package/build/types/avatarLayout/AvatarLayout.d.ts.map +1 -1
  26. package/build/types/button/Button.d.ts.map +1 -1
  27. package/build/types/index.d.ts +0 -2
  28. package/build/types/index.d.ts.map +1 -1
  29. package/build/types/primitives/PrimitiveButton/src/PrimitiveButton.d.ts.map +1 -1
  30. package/build/types/uploadInput/uploadButton/getAllowedFileTypes.d.ts.map +1 -1
  31. package/build/uploadInput/uploadButton/getAllowedFileTypes.js +3 -23
  32. package/build/uploadInput/uploadButton/getAllowedFileTypes.js.map +1 -1
  33. package/build/uploadInput/uploadButton/getAllowedFileTypes.mjs +3 -23
  34. package/build/uploadInput/uploadButton/getAllowedFileTypes.mjs.map +1 -1
  35. package/package.json +5 -5
  36. package/src/avatarLayout/AvatarLayout.css +1 -2
  37. package/src/avatarLayout/AvatarLayout.less +1 -1
  38. package/src/avatarLayout/AvatarLayout.tsx +0 -1
  39. package/src/button/Button.css +3 -0
  40. package/src/button/Button.less +7 -1
  41. package/src/button/Button.spec.tsx +103 -0
  42. package/src/button/Button.tsx +2 -1
  43. package/src/button/Button.vars.less +2 -3
  44. package/src/flowNavigation/__snapshots__/FlowNavigation.spec.js.snap +0 -1
  45. package/src/index.ts +0 -12
  46. package/src/main.css +4 -2
  47. package/src/primitives/PrimitiveAnchor/src/PrimitiveAnchor.tsx +1 -1
  48. package/src/primitives/PrimitiveButton/src/PrimitiveButton.tsx +3 -4
  49. package/src/primitives/PrimitiveButton/test/PrimitiveButton.spec.tsx +15 -9
  50. package/src/uploadInput/UploadInput.tests.story.tsx +5 -5
  51. package/src/uploadInput/uploadButton/getAllowedFileTypes.spec.ts +0 -12
  52. package/src/uploadInput/uploadButton/getAllowedFileTypes.ts +7 -33
  53. package/build/table/Table.js +0 -166
  54. package/build/table/Table.js.map +0 -1
  55. package/build/table/Table.messages.js +0 -24
  56. package/build/table/Table.messages.js.map +0 -1
  57. package/build/table/Table.messages.mjs +0 -22
  58. package/build/table/Table.messages.mjs.map +0 -1
  59. package/build/table/Table.mjs +0 -164
  60. package/build/table/Table.mjs.map +0 -1
  61. package/build/table/TableCell.js +0 -86
  62. package/build/table/TableCell.js.map +0 -1
  63. package/build/table/TableCell.mjs +0 -84
  64. package/build/table/TableCell.mjs.map +0 -1
  65. package/build/table/TableHeader.js +0 -57
  66. package/build/table/TableHeader.js.map +0 -1
  67. package/build/table/TableHeader.mjs +0 -55
  68. package/build/table/TableHeader.mjs.map +0 -1
  69. package/build/table/TableRow.js +0 -85
  70. package/build/table/TableRow.js.map +0 -1
  71. package/build/table/TableRow.mjs +0 -83
  72. package/build/table/TableRow.mjs.map +0 -1
  73. package/build/table/TableStatusText.js +0 -54
  74. package/build/table/TableStatusText.js.map +0 -1
  75. package/build/table/TableStatusText.mjs +0 -52
  76. package/build/table/TableStatusText.mjs.map +0 -1
@@ -1,28 +1,8 @@
1
1
  'use strict';
2
2
 
3
- const parseFileType = fileType => {
4
- if (fileType?.includes('.')) {
5
- return fileType.replace('.', '').toUpperCase();
6
- }
7
- const mimeType = fileType?.split('/');
8
- if (mimeType?.length > 1) {
9
- let parsedType = mimeType[1];
10
- if (parsedType.toLocaleLowerCase() === 'jpeg') {
11
- parsedType = 'jpg, '.concat(parsedType).toUpperCase();
12
- }
13
- return parsedType.toUpperCase();
14
- }
15
- return fileType;
16
- };
17
- const getAllowedFileTypes = fileTypes => fileTypes.map(fileType => {
18
- const splittedFileTypes = fileType?.split(',');
19
- if (splittedFileTypes?.length > 1) {
20
- // If `fileType` contains `format` and `mime` types, remove mime types, proceed only with format types
21
- return splittedFileTypes.filter(splittedFileType => !splittedFileType?.includes('/')).map(splittedFileType => parseFileType(splittedFileType)).join(', ');
22
- }
23
- // If `fileType` contains only `format` or `mime` type, parse the type
24
- return parseFileType(fileType);
25
- });
3
+ const getAllowedFileTypes = fileTypes => fileTypes.map(fileTypeDefinition => fileTypeDefinition.split(',').filter(extension => !extension.includes('/')) // Filter out mime types
4
+ .map(extension => extension.replace('.', '').toUpperCase()) // Remove dot and convert extensions to uppercase to be displayed in the instructions
5
+ .join(', '));
26
6
 
27
7
  module.exports = getAllowedFileTypes;
28
8
  //# sourceMappingURL=getAllowedFileTypes.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"getAllowedFileTypes.js","sources":["../../../src/uploadInput/uploadButton/getAllowedFileTypes.ts"],"sourcesContent":["import { FileType } from '../../common';\n\nconst parseFileType = (fileType: string): string => {\n if (fileType?.includes('.')) {\n return fileType.replace('.', '').toUpperCase();\n }\n\n const mimeType = fileType?.split('/');\n if (mimeType?.length > 1) {\n let parsedType = mimeType[1];\n\n if (parsedType.toLocaleLowerCase() === 'jpeg') {\n parsedType = 'jpg, '.concat(parsedType).toUpperCase();\n }\n\n return parsedType.toUpperCase();\n }\n\n return fileType;\n};\n\nconst getAllowedFileTypes = (fileTypes: readonly FileType[] | readonly string[]): string[] =>\n fileTypes.map((fileType: string) => {\n const splittedFileTypes = fileType?.split(',');\n\n if (splittedFileTypes?.length > 1) {\n // If `fileType` contains `format` and `mime` types, remove mime types, proceed only with format types\n return splittedFileTypes\n .filter((splittedFileType: string) => !splittedFileType?.includes('/'))\n .map((splittedFileType: string) => parseFileType(splittedFileType))\n .join(', ');\n }\n\n // If `fileType` contains only `format` or `mime` type, parse the type\n return parseFileType(fileType);\n });\n\nexport default getAllowedFileTypes;\n"],"names":["parseFileType","fileType","includes","replace","toUpperCase","mimeType","split","length","parsedType","toLocaleLowerCase","concat","getAllowedFileTypes","fileTypes","map","splittedFileTypes","filter","splittedFileType","join"],"mappings":";;AAEA,MAAMA,aAAa,GAAIC,QAAgB,IAAY;AACjD,EAAA,IAAIA,QAAQ,EAAEC,QAAQ,CAAC,GAAG,CAAC,EAAE;IAC3B,OAAOD,QAAQ,CAACE,OAAO,CAAC,GAAG,EAAE,EAAE,CAAC,CAACC,WAAW,EAAE,CAAA;AAChD,GAAA;AAEA,EAAA,MAAMC,QAAQ,GAAGJ,QAAQ,EAAEK,KAAK,CAAC,GAAG,CAAC,CAAA;AACrC,EAAA,IAAID,QAAQ,EAAEE,MAAM,GAAG,CAAC,EAAE;AACxB,IAAA,IAAIC,UAAU,GAAGH,QAAQ,CAAC,CAAC,CAAC,CAAA;AAE5B,IAAA,IAAIG,UAAU,CAACC,iBAAiB,EAAE,KAAK,MAAM,EAAE;MAC7CD,UAAU,GAAG,OAAO,CAACE,MAAM,CAACF,UAAU,CAAC,CAACJ,WAAW,EAAE,CAAA;AACvD,KAAA;AAEA,IAAA,OAAOI,UAAU,CAACJ,WAAW,EAAE,CAAA;AACjC,GAAA;AAEA,EAAA,OAAOH,QAAQ,CAAA;AACjB,CAAC,CAAA;AAEKU,MAAAA,mBAAmB,GAAIC,SAAkD,IAC7EA,SAAS,CAACC,GAAG,CAAEZ,QAAgB,IAAI;AACjC,EAAA,MAAMa,iBAAiB,GAAGb,QAAQ,EAAEK,KAAK,CAAC,GAAG,CAAC,CAAA;AAE9C,EAAA,IAAIQ,iBAAiB,EAAEP,MAAM,GAAG,CAAC,EAAE;AACjC;AACA,IAAA,OAAOO,iBAAiB,CACrBC,MAAM,CAAEC,gBAAwB,IAAK,CAACA,gBAAgB,EAAEd,QAAQ,CAAC,GAAG,CAAC,CAAC,CACtEW,GAAG,CAAEG,gBAAwB,IAAKhB,aAAa,CAACgB,gBAAgB,CAAC,CAAC,CAClEC,IAAI,CAAC,IAAI,CAAC,CAAA;AACf,GAAA;AAEA;EACA,OAAOjB,aAAa,CAACC,QAAQ,CAAC,CAAA;AAChC,CAAC;;;;"}
1
+ {"version":3,"file":"getAllowedFileTypes.js","sources":["../../../src/uploadInput/uploadButton/getAllowedFileTypes.ts"],"sourcesContent":["import { FileType } from '../../common';\n\nconst getAllowedFileTypes = (fileTypes: readonly FileType[] | readonly string[]): string[] =>\n fileTypes.map((fileTypeDefinition: string) =>\n fileTypeDefinition\n .split(',')\n .filter((extension) => !extension.includes('/')) // Filter out mime types\n .map((extension) => extension.replace('.', '').toUpperCase()) // Remove dot and convert extensions to uppercase to be displayed in the instructions\n .join(', '),\n );\n\nexport default getAllowedFileTypes;\n"],"names":["getAllowedFileTypes","fileTypes","map","fileTypeDefinition","split","filter","extension","includes","replace","toUpperCase","join"],"mappings":";;AAEA,MAAMA,mBAAmB,GAAIC,SAAkD,IAC7EA,SAAS,CAACC,GAAG,CAAEC,kBAA0B,IACvCA,kBAAkB,CACfC,KAAK,CAAC,GAAG,CAAC,CACVC,MAAM,CAAEC,SAAS,IAAK,CAACA,SAAS,CAACC,QAAQ,CAAC,GAAG,CAAC,CAAC;AAAC,CAChDL,GAAG,CAAEI,SAAS,IAAKA,SAAS,CAACE,OAAO,CAAC,GAAG,EAAE,EAAE,CAAC,CAACC,WAAW,EAAE,CAAC;AAAC,CAC7DC,IAAI,CAAC,IAAI,CAAC;;;;"}
@@ -1,26 +1,6 @@
1
- const parseFileType = fileType => {
2
- if (fileType?.includes('.')) {
3
- return fileType.replace('.', '').toUpperCase();
4
- }
5
- const mimeType = fileType?.split('/');
6
- if (mimeType?.length > 1) {
7
- let parsedType = mimeType[1];
8
- if (parsedType.toLocaleLowerCase() === 'jpeg') {
9
- parsedType = 'jpg, '.concat(parsedType).toUpperCase();
10
- }
11
- return parsedType.toUpperCase();
12
- }
13
- return fileType;
14
- };
15
- const getAllowedFileTypes = fileTypes => fileTypes.map(fileType => {
16
- const splittedFileTypes = fileType?.split(',');
17
- if (splittedFileTypes?.length > 1) {
18
- // If `fileType` contains `format` and `mime` types, remove mime types, proceed only with format types
19
- return splittedFileTypes.filter(splittedFileType => !splittedFileType?.includes('/')).map(splittedFileType => parseFileType(splittedFileType)).join(', ');
20
- }
21
- // If `fileType` contains only `format` or `mime` type, parse the type
22
- return parseFileType(fileType);
23
- });
1
+ const getAllowedFileTypes = fileTypes => fileTypes.map(fileTypeDefinition => fileTypeDefinition.split(',').filter(extension => !extension.includes('/')) // Filter out mime types
2
+ .map(extension => extension.replace('.', '').toUpperCase()) // Remove dot and convert extensions to uppercase to be displayed in the instructions
3
+ .join(', '));
24
4
 
25
5
  export { getAllowedFileTypes as default };
26
6
  //# sourceMappingURL=getAllowedFileTypes.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"getAllowedFileTypes.mjs","sources":["../../../src/uploadInput/uploadButton/getAllowedFileTypes.ts"],"sourcesContent":["import { FileType } from '../../common';\n\nconst parseFileType = (fileType: string): string => {\n if (fileType?.includes('.')) {\n return fileType.replace('.', '').toUpperCase();\n }\n\n const mimeType = fileType?.split('/');\n if (mimeType?.length > 1) {\n let parsedType = mimeType[1];\n\n if (parsedType.toLocaleLowerCase() === 'jpeg') {\n parsedType = 'jpg, '.concat(parsedType).toUpperCase();\n }\n\n return parsedType.toUpperCase();\n }\n\n return fileType;\n};\n\nconst getAllowedFileTypes = (fileTypes: readonly FileType[] | readonly string[]): string[] =>\n fileTypes.map((fileType: string) => {\n const splittedFileTypes = fileType?.split(',');\n\n if (splittedFileTypes?.length > 1) {\n // If `fileType` contains `format` and `mime` types, remove mime types, proceed only with format types\n return splittedFileTypes\n .filter((splittedFileType: string) => !splittedFileType?.includes('/'))\n .map((splittedFileType: string) => parseFileType(splittedFileType))\n .join(', ');\n }\n\n // If `fileType` contains only `format` or `mime` type, parse the type\n return parseFileType(fileType);\n });\n\nexport default getAllowedFileTypes;\n"],"names":["parseFileType","fileType","includes","replace","toUpperCase","mimeType","split","length","parsedType","toLocaleLowerCase","concat","getAllowedFileTypes","fileTypes","map","splittedFileTypes","filter","splittedFileType","join"],"mappings":"AAEA,MAAMA,aAAa,GAAIC,QAAgB,IAAY;AACjD,EAAA,IAAIA,QAAQ,EAAEC,QAAQ,CAAC,GAAG,CAAC,EAAE;IAC3B,OAAOD,QAAQ,CAACE,OAAO,CAAC,GAAG,EAAE,EAAE,CAAC,CAACC,WAAW,EAAE,CAAA;AAChD,GAAA;AAEA,EAAA,MAAMC,QAAQ,GAAGJ,QAAQ,EAAEK,KAAK,CAAC,GAAG,CAAC,CAAA;AACrC,EAAA,IAAID,QAAQ,EAAEE,MAAM,GAAG,CAAC,EAAE;AACxB,IAAA,IAAIC,UAAU,GAAGH,QAAQ,CAAC,CAAC,CAAC,CAAA;AAE5B,IAAA,IAAIG,UAAU,CAACC,iBAAiB,EAAE,KAAK,MAAM,EAAE;MAC7CD,UAAU,GAAG,OAAO,CAACE,MAAM,CAACF,UAAU,CAAC,CAACJ,WAAW,EAAE,CAAA;AACvD,KAAA;AAEA,IAAA,OAAOI,UAAU,CAACJ,WAAW,EAAE,CAAA;AACjC,GAAA;AAEA,EAAA,OAAOH,QAAQ,CAAA;AACjB,CAAC,CAAA;AAEKU,MAAAA,mBAAmB,GAAIC,SAAkD,IAC7EA,SAAS,CAACC,GAAG,CAAEZ,QAAgB,IAAI;AACjC,EAAA,MAAMa,iBAAiB,GAAGb,QAAQ,EAAEK,KAAK,CAAC,GAAG,CAAC,CAAA;AAE9C,EAAA,IAAIQ,iBAAiB,EAAEP,MAAM,GAAG,CAAC,EAAE;AACjC;AACA,IAAA,OAAOO,iBAAiB,CACrBC,MAAM,CAAEC,gBAAwB,IAAK,CAACA,gBAAgB,EAAEd,QAAQ,CAAC,GAAG,CAAC,CAAC,CACtEW,GAAG,CAAEG,gBAAwB,IAAKhB,aAAa,CAACgB,gBAAgB,CAAC,CAAC,CAClEC,IAAI,CAAC,IAAI,CAAC,CAAA;AACf,GAAA;AAEA;EACA,OAAOjB,aAAa,CAACC,QAAQ,CAAC,CAAA;AAChC,CAAC;;;;"}
1
+ {"version":3,"file":"getAllowedFileTypes.mjs","sources":["../../../src/uploadInput/uploadButton/getAllowedFileTypes.ts"],"sourcesContent":["import { FileType } from '../../common';\n\nconst getAllowedFileTypes = (fileTypes: readonly FileType[] | readonly string[]): string[] =>\n fileTypes.map((fileTypeDefinition: string) =>\n fileTypeDefinition\n .split(',')\n .filter((extension) => !extension.includes('/')) // Filter out mime types\n .map((extension) => extension.replace('.', '').toUpperCase()) // Remove dot and convert extensions to uppercase to be displayed in the instructions\n .join(', '),\n );\n\nexport default getAllowedFileTypes;\n"],"names":["getAllowedFileTypes","fileTypes","map","fileTypeDefinition","split","filter","extension","includes","replace","toUpperCase","join"],"mappings":"AAEA,MAAMA,mBAAmB,GAAIC,SAAkD,IAC7EA,SAAS,CAACC,GAAG,CAAEC,kBAA0B,IACvCA,kBAAkB,CACfC,KAAK,CAAC,GAAG,CAAC,CACVC,MAAM,CAAEC,SAAS,IAAK,CAACA,SAAS,CAACC,QAAQ,CAAC,GAAG,CAAC,CAAC;AAAC,CAChDL,GAAG,CAAEI,SAAS,IAAKA,SAAS,CAACE,OAAO,CAAC,GAAG,EAAE,EAAE,CAAC,CAACC,WAAW,EAAE,CAAC;AAAC,CAC7DC,IAAI,CAAC,IAAI,CAAC;;;;"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@transferwise/components",
3
- "version": "0.0.0-experimental-60cb1a1",
3
+ "version": "0.0.0-experimental-69a95e1",
4
4
  "description": "Neptune React components",
5
5
  "license": "Apache-2.0",
6
6
  "repository": {
@@ -91,13 +91,13 @@
91
91
  "rollup": "^4.18.1",
92
92
  "rollup-preserve-directives": "^1.1.1",
93
93
  "storybook": "^8.2.2",
94
- "@transferwise/less-config": "3.1.0",
95
- "@transferwise/neptune-css": "0.0.0-experimental-60cb1a1",
96
- "@wise/components-theming": "1.6.1"
94
+ "@transferwise/neptune-css": "0.0.0-experimental-69a95e1",
95
+ "@wise/components-theming": "1.6.1",
96
+ "@transferwise/less-config": "3.1.0"
97
97
  },
98
98
  "peerDependencies": {
99
99
  "@transferwise/icons": "^3.13.1",
100
- "@transferwise/neptune-css": "0.0.0-experimental-60cb1a1",
100
+ "@transferwise/neptune-css": "0.0.0-experimental-69a95e1",
101
101
  "@wise/art": "^2.16",
102
102
  "@wise/components-theming": "^1.0.0",
103
103
  "react": ">=18",
@@ -24,8 +24,7 @@
24
24
  margin-right: calc(var(--np-avatar-layout-size) - var(--np-avatar-size) * 2);
25
25
  }
26
26
  .np-avatar-layout-horizontal {
27
- width: calc(var(--np-avatar-size) * var(--np-avatar-avatars-count) - (var(--np-avatar-offset) * (var(--np-avatar-avatars-count) - 1)));
28
- width: calc(var(--np-avatar-size) * var(--np-avatar-avatars-count) - calc(var(--np-avatar-offset) * calc(var(--np-avatar-avatars-count) - 1)));
27
+ width: calc(var(--np-avatar-size) * 2 - var(--np-avatar-offset));
29
28
  height: var(--np-avatar-layout-size);
30
29
  }
31
30
  .np-avatar-layout-horizontal-mask {
@@ -35,7 +35,7 @@
35
35
  }
36
36
 
37
37
  &-horizontal {
38
- width: calc(var(--np-avatar-size) * var(--np-avatar-avatars-count) - calc(var(--np-avatar-offset) * calc(var(--np-avatar-avatars-count) - 1)));
38
+ width: calc(var(--np-avatar-size) * 2 - var(--np-avatar-offset));
39
39
  height: var(--np-avatar-layout-size);
40
40
 
41
41
  &-mask {
@@ -40,7 +40,6 @@ export default function AvatarLayout({
40
40
  '--np-avatar-layout-size': `${size}px`,
41
41
  '--np-avatar-size': `${avatarSize}px`,
42
42
  '--np-avatar-offset': `${isDiagonal ? DIAGONAL_LAYOUT_STYLE_CONFIG[size].offset : HORIZONTAL_LAYOUT_OFFSET[size]}px`,
43
- '--np-avatar-avatars-count': avatars.length,
44
43
  }}
45
44
  {...restProps}
46
45
  >
@@ -68,10 +68,13 @@
68
68
  }
69
69
  .wds-Button.wds-Button--disabled,
70
70
  .wds-Button:disabled {
71
+ filter: none;
71
72
  mix-blend-mode: luminosity;
72
73
  opacity: 0.45;
73
74
  cursor: not-allowed;
74
75
  }
76
+ .wds-Button.wds-Button--disabled,
77
+ .wds-Button:disabled,
75
78
  .wds-Button.wds-Button--disabled:hover,
76
79
  .wds-Button:disabled:hover,
77
80
  .wds-Button.wds-Button--disabled:active,
@@ -30,10 +30,16 @@
30
30
 
31
31
  &.wds-Button--disabled,
32
32
  &:disabled {
33
+ // The declarations below are necessary as design specs for
34
+ // the button's disabled state have changed. This is to be
35
+ // further investigated at a later stage.
36
+ // @see https://transferwise.atlassian.net/browse/DS-7386
37
+ filter: none;
33
38
  mix-blend-mode: luminosity;
34
39
  opacity: 0.45;
35
40
  cursor: not-allowed;
36
41
 
42
+ &,
37
43
  &:hover,
38
44
  &:active {
39
45
  background-color: var(--Button-background);
@@ -122,7 +128,7 @@
122
128
 
123
129
 
124
130
 
125
- // Width mofidiers
131
+ // Width modifiers
126
132
  &--block {
127
133
  width: 100%;
128
134
  }
@@ -67,6 +67,109 @@ describe('Button', () => {
67
67
  );
68
68
  expect(screen.getByRole('link', { name })).toHaveAttribute('href', href);
69
69
  });
70
+
71
+ describe('disabled mode', () => {
72
+ describe('button', () => {
73
+ it('should not be disabled by default', () => {
74
+ render(<Button v2>{name}</Button>);
75
+ const button = screen.getByRole('button');
76
+ expect(button).toBeEnabled();
77
+ expect(button).not.toHaveAttribute('aria-disabled');
78
+ });
79
+
80
+ it('should respect disabled mode and set it only via the `disabled` attribute', () => {
81
+ render(
82
+ <Button v2 disabled>
83
+ {name}
84
+ </Button>,
85
+ );
86
+ const button = screen.getByRole('button');
87
+ expect(button).toBeDisabled();
88
+ expect(button).not.toHaveAttribute('aria-disabled');
89
+ });
90
+ });
91
+
92
+ describe('anchor', () => {
93
+ it('should not be disabled by default', () => {
94
+ render(
95
+ <Button v2 href="wise.com">
96
+ {name}
97
+ </Button>,
98
+ );
99
+ const button = screen.getByRole('link');
100
+ expect(button).toBeEnabled();
101
+ expect(button).not.toHaveAttribute('aria-disabled');
102
+ });
103
+
104
+ it('should respect disabled mode', () => {
105
+ render(
106
+ <Button v2 href="wise.com" disabled>
107
+ {name}
108
+ </Button>,
109
+ );
110
+ const button = screen.getByRole('link');
111
+ expect(button).toHaveAttribute('aria-disabled');
112
+ expect(button).toBeEnabled();
113
+ expect(button).not.toHaveAttribute('href');
114
+ });
115
+ });
116
+ });
117
+
118
+ describe('loading mode', () => {
119
+ describe('button', () => {
120
+ it('should not be loading by default', () => {
121
+ render(<Button v2>{name}</Button>);
122
+ const button = screen.getByRole('button');
123
+ expect(button).toBeEnabled();
124
+ expect(button).not.toHaveAttribute('aria-busy');
125
+ });
126
+
127
+ it('should respect loading mode', () => {
128
+ render(
129
+ <Button v2 loading>
130
+ {name}
131
+ </Button>,
132
+ );
133
+ const button = screen.getByRole('button');
134
+ expect(button).toHaveAttribute('aria-busy');
135
+ // the `disabled` attribute is not set to keep the button
136
+ // focusable but aria attribute is defined to make it
137
+ // announced properly by the assistive tech
138
+ expect(button).toBeEnabled();
139
+ expect(button).toHaveAttribute('aria-disabled');
140
+ });
141
+ });
142
+
143
+ describe('anchor', () => {
144
+ it('should not be loading by default', () => {
145
+ render(
146
+ <Button v2 href="wise.com">
147
+ {name}
148
+ </Button>,
149
+ );
150
+ const button = screen.getByRole('link');
151
+ expect(button).toBeEnabled();
152
+ expect(button).not.toHaveAttribute('aria-busy');
153
+ expect(button).not.toHaveAttribute('aria-disabled');
154
+ });
155
+
156
+ it('should respect loading mode', () => {
157
+ render(
158
+ <Button v2 loading href="wise.com">
159
+ {name}
160
+ </Button>,
161
+ );
162
+ const button = screen.getByRole('link');
163
+ expect(button).toHaveAttribute('aria-busy');
164
+ // the `disabled` attribute is not set to keep the button
165
+ // focusable but aria attribute is defined to make it
166
+ // announced properly by the assistive tech
167
+ expect(button).toBeEnabled();
168
+ expect(button).toHaveAttribute('aria-disabled');
169
+ expect(button).not.toHaveAttribute('href');
170
+ });
171
+ });
172
+ });
70
173
  });
71
174
  });
72
175
 
@@ -87,7 +87,8 @@ const Button = forwardRef<HTMLButtonElement | HTMLAnchorElement, NewButtonProps>
87
87
  {...(props as any)}
88
88
  href={href}
89
89
  className={classNames}
90
- disabled={disabled}
90
+ disabled={disabled || loading}
91
+ aria-busy={loading || undefined}
91
92
  >
92
93
  {content}
93
94
  </PrimitiveAnchor>
@@ -39,10 +39,9 @@
39
39
  --Button-secondary-negative-background-hover: var(--color-sentiment-negative-secondary-hover);
40
40
  --Button-secondary-negative-background-active: var(--color-sentiment-negative-secondary-active);
41
41
  --Button-secondary-negative-color: var(--color-sentiment-negative-primary);
42
- }
43
42
 
44
- .np-theme-personal--bright-green {
45
- .wds-Button {
43
+
44
+ .np-theme-personal--bright-green & {
46
45
  --color-contrast: #FFFFFF;
47
46
  --Button-secondary-color: var(--color-interactive-control);
48
47
  --Button-secondary-negative-color: var(--color-contrast);
@@ -9,7 +9,6 @@ exports[`FlowNavigation on mobile renders as expected 1`] = `
9
9
  class="np-flow-header d-flex flex-wrap align-items-center justify-content-between flex__item--12 np-flow-navigation__content p-x-3 np-flow-navigation--xs-max"
10
10
  >
11
11
  <button
12
- aria-disabled="false"
13
12
  aria-label="back to previous step"
14
13
  aria-live="off"
15
14
  class="np-circle d-flex align-items-center justify-content-center np-icon-button np-icon-button-tertiary-default"
package/src/index.ts CHANGED
@@ -96,17 +96,6 @@ export type { UploadProps } from './upload';
96
96
  export type { UploadError, UploadResponse, UploadedFile } from './uploadInput/types';
97
97
  export type { WithIdProps } from './withId';
98
98
  export type { IconButtonProps } from './iconButton';
99
- export type {
100
- TableProps,
101
- TableRowType,
102
- TableRowClickableType,
103
- TableHeaderType,
104
- TableCellLeading,
105
- TableCellText,
106
- TableCellCurrency,
107
- TableCellStatus,
108
- TableCellType,
109
- } from './table';
110
99
 
111
100
  /**
112
101
  * Components
@@ -207,7 +196,6 @@ export { default as Tooltip } from './tooltip';
207
196
  export { default as Typeahead } from './typeahead';
208
197
  export { default as Upload } from './upload';
209
198
  export { default as UploadInput } from './uploadInput';
210
- export { default as Table } from './table';
211
199
 
212
200
  /**
213
201
  * Hooks
package/src/main.css CHANGED
@@ -531,8 +531,7 @@ div.critical-comms .critical-comms-body {
531
531
  margin-right: calc(var(--np-avatar-layout-size) - var(--np-avatar-size) * 2);
532
532
  }
533
533
  .np-avatar-layout-horizontal {
534
- width: calc(var(--np-avatar-size) * var(--np-avatar-avatars-count) - (var(--np-avatar-offset) * (var(--np-avatar-avatars-count) - 1)));
535
- width: calc(var(--np-avatar-size) * var(--np-avatar-avatars-count) - calc(var(--np-avatar-offset) * calc(var(--np-avatar-avatars-count) - 1)));
534
+ width: calc(var(--np-avatar-size) * 2 - var(--np-avatar-offset));
536
535
  height: var(--np-avatar-layout-size);
537
536
  }
538
537
  .np-avatar-layout-horizontal-mask {
@@ -787,10 +786,13 @@ div.critical-comms .critical-comms-body {
787
786
  }
788
787
  .wds-Button.wds-Button--disabled,
789
788
  .wds-Button:disabled {
789
+ filter: none;
790
790
  mix-blend-mode: luminosity;
791
791
  opacity: 0.45;
792
792
  cursor: not-allowed;
793
793
  }
794
+ .wds-Button.wds-Button--disabled,
795
+ .wds-Button:disabled,
794
796
  .wds-Button.wds-Button--disabled:hover,
795
797
  .wds-Button:disabled:hover,
796
798
  .wds-Button.wds-Button--disabled:active,
@@ -90,7 +90,7 @@ const PrimitiveAnchor = forwardRef<HTMLAnchorElement, PrimitiveAnchorProps>(
90
90
  * https://www.scottohara.me/blog/2021/05/28/disabled-links.html
91
91
  */
92
92
  const anchorProps = {
93
- 'aria-disabled': disabled,
93
+ 'aria-disabled': disabled || undefined,
94
94
  className: anchorClasses,
95
95
  'data-testid': testId,
96
96
  href: disabled ? undefined : href,
@@ -95,10 +95,9 @@ const PrimitiveButton = forwardRef<HTMLButtonElement, PrimitiveButtonProps>(
95
95
  * by assistive technologies, set to 'polite' during loading.
96
96
  */
97
97
  const buttonProps = {
98
- 'aria-disabled': disabled || loading,
99
- 'aria-label': loading
100
- ? intl.formatMessage(messages.loadingAriaLabel as MessageDescriptor)
101
- : props['aria-label'],
98
+ 'aria-disabled': loading || undefined,
99
+ 'aria-busy': loading || undefined,
100
+ 'aria-label': loading ? intl.formatMessage(messages.loadingAriaLabel) : props['aria-label'],
102
101
  'aria-live': (loading ? 'polite' : 'off') as 'polite' | 'off' | 'assertive' | undefined,
103
102
  className: classNames,
104
103
  'data-testid': testId,
@@ -1,7 +1,7 @@
1
1
  import { screen } from '@testing-library/react';
2
- import PrimitiveButton from '../src';
3
- import messages from '../../../i18n/commonMessages/Button.messages';
4
2
  import { render } from '../../../test-utils';
3
+ import PrimitiveButton from '../src';
4
+ import allMessages from '../../../i18n';
5
5
 
6
6
  describe('Button', () => {
7
7
  const defaultProps = {
@@ -11,7 +11,7 @@ describe('Button', () => {
11
11
  const renderButton = (
12
12
  props?: Partial<typeof defaultProps>,
13
13
  locale = 'en',
14
- localeMessages = messages,
14
+ localeMessages = allMessages.en,
15
15
  ) => {
16
16
  return render(
17
17
  <PrimitiveButton {...defaultProps} {...props} />,
@@ -50,6 +50,17 @@ describe('Button', () => {
50
50
  expect(button).toBeDisabled();
51
51
  });
52
52
 
53
+ it('disables and announces the button as busy in loading mode', () => {
54
+ const props = {
55
+ ...defaultProps,
56
+ loading: true,
57
+ };
58
+
59
+ renderButton(props);
60
+
61
+ expect(screen.getByRole('button', { busy: true })).toHaveAttribute('aria-disabled', 'true');
62
+ });
63
+
53
64
  it('sets data-testid attribute', () => {
54
65
  const props = {
55
66
  ...defaultProps,
@@ -98,12 +109,7 @@ describe('Button', () => {
98
109
  loading: true,
99
110
  };
100
111
 
101
- const spanishMessages = {
102
- ...messages,
103
- 'neptune.Button.loadingAriaLabel': 'cargando',
104
- };
105
-
106
- renderButton(props, 'es', spanishMessages);
112
+ renderButton(props, 'es', allMessages.es);
107
113
 
108
114
  const button = screen.getByRole('button');
109
115
  expect(button).toHaveAttribute('aria-label', 'cargando');
@@ -4,7 +4,7 @@ import { Meta, StoryObj } from '@storybook/react';
4
4
  import { Status } from '../common';
5
5
  import UploadInput, { UploadInputProps } from './UploadInput';
6
6
  import { UploadedFile, UploadResponse } from './types';
7
- import { userEvent } from '@storybook/test';
7
+ import { userEvent, within } from '@storybook/test';
8
8
 
9
9
  const meta: Meta<typeof UploadInput> = {
10
10
  title: 'Forms/UploadInput/Tests',
@@ -65,8 +65,8 @@ const createDelayedPromise = async ({
65
65
  });
66
66
 
67
67
  const props = {
68
- onUploadFile: async () => createDelayedPromise(),
69
- onDeleteFile: async () => createDelayedPromise(),
68
+ onUploadFile: async (formData: FormData) => createDelayedPromise(),
69
+ onDeleteFile: async (id: string | number) => createDelayedPromise(),
70
70
  };
71
71
 
72
72
  export const UploadInputWithDescriptionFromProps: Story = {
@@ -268,7 +268,7 @@ export const DeletingTop: Story = {
268
268
  files: [files[0], files[1], files[2]],
269
269
  multiple: true,
270
270
  },
271
- play: async () => {
271
+ play: async ({ canvasElement }) => {
272
272
  await userEvent.tab();
273
273
  await triggerModalAndConfirm();
274
274
  await triggerModalAndConfirm({ isLink: false });
@@ -282,7 +282,7 @@ export const DeletingBottom: Story = {
282
282
  files: [files[0], files[1], files[2]],
283
283
  multiple: true,
284
284
  },
285
- play: async () => {
285
+ play: async ({ canvasElement }) => {
286
286
  await userEvent.tab();
287
287
  await userEvent.tab();
288
288
  await userEvent.tab();
@@ -38,16 +38,4 @@ describe('getAllowedFileTypes', () => {
38
38
  expect(allowedFileTypes).toStrictEqual(['*']);
39
39
  });
40
40
  });
41
-
42
- describe('using only mime types', () => {
43
- const mimeTypes = ['application/json', 'image/jpeg'];
44
-
45
- beforeAll(() => {
46
- allowedFileTypes = getAllowedFileTypes(mimeTypes);
47
- });
48
-
49
- it('returns the original mime types', () => {
50
- expect(allowedFileTypes).toStrictEqual(['JSON', 'JPG, JPEG']);
51
- });
52
- });
53
41
  });
@@ -1,38 +1,12 @@
1
1
  import { FileType } from '../../common';
2
2
 
3
- const parseFileType = (fileType: string): string => {
4
- if (fileType?.includes('.')) {
5
- return fileType.replace('.', '').toUpperCase();
6
- }
7
-
8
- const mimeType = fileType?.split('/');
9
- if (mimeType?.length > 1) {
10
- let parsedType = mimeType[1];
11
-
12
- if (parsedType.toLocaleLowerCase() === 'jpeg') {
13
- parsedType = 'jpg, '.concat(parsedType).toUpperCase();
14
- }
15
-
16
- return parsedType.toUpperCase();
17
- }
18
-
19
- return fileType;
20
- };
21
-
22
3
  const getAllowedFileTypes = (fileTypes: readonly FileType[] | readonly string[]): string[] =>
23
- fileTypes.map((fileType: string) => {
24
- const splittedFileTypes = fileType?.split(',');
25
-
26
- if (splittedFileTypes?.length > 1) {
27
- // If `fileType` contains `format` and `mime` types, remove mime types, proceed only with format types
28
- return splittedFileTypes
29
- .filter((splittedFileType: string) => !splittedFileType?.includes('/'))
30
- .map((splittedFileType: string) => parseFileType(splittedFileType))
31
- .join(', ');
32
- }
33
-
34
- // If `fileType` contains only `format` or `mime` type, parse the type
35
- return parseFileType(fileType);
36
- });
4
+ fileTypes.map((fileTypeDefinition: string) =>
5
+ fileTypeDefinition
6
+ .split(',')
7
+ .filter((extension) => !extension.includes('/')) // Filter out mime types
8
+ .map((extension) => extension.replace('.', '').toUpperCase()) // Remove dot and convert extensions to uppercase to be displayed in the instructions
9
+ .join(', '),
10
+ );
37
11
 
38
12
  export default getAllowedFileTypes;