@dnb/eufemia 9.46.2 → 9.47.1

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 (113) hide show
  1. package/CHANGELOG.md +22 -0
  2. package/cjs/components/input-masked/InputMasked.js +13 -1
  3. package/cjs/components/input-masked/InputMaskedHooks.js +1 -1
  4. package/cjs/components/input-masked/InputMaskedUtils.js +3 -3
  5. package/cjs/components/table/TableContainer.d.ts +3 -3
  6. package/cjs/components/table/TableContainer.js +20 -1
  7. package/cjs/components/table/TableTh.js +2 -2
  8. package/cjs/components/table/style/_table-accordion.scss +52 -8
  9. package/cjs/components/table/style/_table-container.scss +20 -2
  10. package/cjs/components/table/style/_table-td.scss +35 -67
  11. package/cjs/components/table/style/_table-th.scss +41 -34
  12. package/cjs/components/table/style/_table.scss +12 -13
  13. package/cjs/components/table/style/dnb-table-mixins.css +0 -0
  14. package/cjs/components/table/style/dnb-table-mixins.min.css +0 -0
  15. package/cjs/components/table/style/dnb-table-mixins.scss +11 -0
  16. package/cjs/components/table/style/dnb-table.css +124 -137
  17. package/cjs/components/table/style/dnb-table.min.css +8 -7
  18. package/cjs/components/table/style/themes/dnb-table-theme-ui.css +7 -3
  19. package/cjs/components/table/style/themes/dnb-table-theme-ui.min.css +1 -1
  20. package/cjs/components/table/style/themes/dnb-table-theme-ui.scss +6 -12
  21. package/cjs/components/upload/Upload.js +0 -1
  22. package/cjs/components/upload/UploadFileInput.js +2 -10
  23. package/cjs/components/upload/UploadFileList.js +0 -1
  24. package/cjs/components/upload/UploadFileListCell.js +22 -23
  25. package/cjs/components/upload/UploadInfo.js +1 -9
  26. package/cjs/components/upload/UploadVerify.d.ts +3 -0
  27. package/cjs/components/upload/UploadVerify.js +27 -3
  28. package/cjs/shared/Eufemia.js +1 -1
  29. package/cjs/style/dnb-ui-components.css +124 -137
  30. package/cjs/style/dnb-ui-components.min.css +8 -7
  31. package/cjs/style/themes/theme-eiendom/dnb-theme-eiendom.css +7 -3
  32. package/cjs/style/themes/theme-eiendom/dnb-theme-eiendom.min.css +1 -1
  33. package/cjs/style/themes/theme-ui/dnb-theme-ui.css +7 -3
  34. package/cjs/style/themes/theme-ui/dnb-theme-ui.min.css +1 -1
  35. package/components/input-masked/InputMasked.js +13 -1
  36. package/components/input-masked/InputMaskedHooks.js +1 -1
  37. package/components/input-masked/InputMaskedUtils.js +3 -3
  38. package/components/table/TableContainer.d.ts +3 -3
  39. package/components/table/TableContainer.js +21 -1
  40. package/components/table/TableTh.js +2 -2
  41. package/components/table/style/_table-accordion.scss +52 -8
  42. package/components/table/style/_table-container.scss +20 -2
  43. package/components/table/style/_table-td.scss +35 -67
  44. package/components/table/style/_table-th.scss +41 -34
  45. package/components/table/style/_table.scss +12 -13
  46. package/components/table/style/dnb-table-mixins.css +0 -0
  47. package/components/table/style/dnb-table-mixins.min.css +0 -0
  48. package/components/table/style/dnb-table-mixins.scss +11 -0
  49. package/components/table/style/dnb-table.css +124 -137
  50. package/components/table/style/dnb-table.min.css +8 -7
  51. package/components/table/style/themes/dnb-table-theme-ui.css +7 -3
  52. package/components/table/style/themes/dnb-table-theme-ui.min.css +1 -1
  53. package/components/table/style/themes/dnb-table-theme-ui.scss +6 -12
  54. package/components/upload/Upload.js +0 -1
  55. package/components/upload/UploadFileInput.js +3 -10
  56. package/components/upload/UploadFileList.js +0 -1
  57. package/components/upload/UploadFileListCell.js +17 -19
  58. package/components/upload/UploadInfo.js +1 -9
  59. package/components/upload/UploadVerify.d.ts +3 -0
  60. package/components/upload/UploadVerify.js +18 -1
  61. package/es/components/input-masked/InputMasked.js +12 -1
  62. package/es/components/input-masked/InputMaskedHooks.js +1 -1
  63. package/es/components/input-masked/InputMaskedUtils.js +3 -3
  64. package/es/components/table/TableContainer.d.ts +3 -3
  65. package/es/components/table/TableContainer.js +21 -1
  66. package/es/components/table/TableTh.js +2 -2
  67. package/es/components/table/style/_table-accordion.scss +52 -8
  68. package/es/components/table/style/_table-container.scss +20 -2
  69. package/es/components/table/style/_table-td.scss +35 -67
  70. package/es/components/table/style/_table-th.scss +41 -34
  71. package/es/components/table/style/_table.scss +12 -13
  72. package/es/components/table/style/dnb-table-mixins.css +0 -0
  73. package/es/components/table/style/dnb-table-mixins.min.css +0 -0
  74. package/es/components/table/style/dnb-table-mixins.scss +11 -0
  75. package/es/components/table/style/dnb-table.css +124 -137
  76. package/es/components/table/style/dnb-table.min.css +8 -7
  77. package/es/components/table/style/themes/dnb-table-theme-ui.css +7 -3
  78. package/es/components/table/style/themes/dnb-table-theme-ui.min.css +1 -1
  79. package/es/components/table/style/themes/dnb-table-theme-ui.scss +6 -12
  80. package/es/components/upload/Upload.js +0 -1
  81. package/es/components/upload/UploadFileInput.js +3 -7
  82. package/es/components/upload/UploadFileList.js +0 -1
  83. package/es/components/upload/UploadFileListCell.js +14 -18
  84. package/es/components/upload/UploadInfo.js +1 -9
  85. package/es/components/upload/UploadVerify.d.ts +3 -0
  86. package/es/components/upload/UploadVerify.js +11 -1
  87. package/es/shared/Eufemia.js +1 -1
  88. package/es/style/dnb-ui-components.css +124 -137
  89. package/es/style/dnb-ui-components.min.css +8 -7
  90. package/es/style/themes/theme-eiendom/dnb-theme-eiendom.css +7 -3
  91. package/es/style/themes/theme-eiendom/dnb-theme-eiendom.min.css +1 -1
  92. package/es/style/themes/theme-ui/dnb-theme-ui.css +7 -3
  93. package/es/style/themes/theme-ui/dnb-theme-ui.min.css +1 -1
  94. package/esm/dnb-ui-basis.min.mjs +1 -1
  95. package/esm/dnb-ui-components.min.mjs +1 -1
  96. package/esm/dnb-ui-elements.min.mjs +2 -2
  97. package/esm/dnb-ui-extensions.min.mjs +1 -1
  98. package/esm/dnb-ui-lib.min.mjs +2 -2
  99. package/esm/dnb-ui-web-components.min.mjs +2 -2
  100. package/package.json +1 -1
  101. package/shared/Eufemia.js +1 -1
  102. package/style/dnb-ui-components.css +124 -137
  103. package/style/dnb-ui-components.min.css +8 -7
  104. package/style/themes/theme-eiendom/dnb-theme-eiendom.css +7 -3
  105. package/style/themes/theme-eiendom/dnb-theme-eiendom.min.css +1 -1
  106. package/style/themes/theme-ui/dnb-theme-ui.css +7 -3
  107. package/style/themes/theme-ui/dnb-theme-ui.min.css +1 -1
  108. package/umd/dnb-ui-basis.min.js +1 -1
  109. package/umd/dnb-ui-components.min.js +1 -1
  110. package/umd/dnb-ui-elements.min.js +2 -2
  111. package/umd/dnb-ui-extensions.min.js +1 -1
  112. package/umd/dnb-ui-lib.min.js +2 -2
  113. package/umd/dnb-ui-web-components.min.js +2 -2
@@ -1,6 +1,5 @@
1
1
  var _UploadStatus;
2
2
 
3
- import "core-js/modules/es.array.join.js";
4
3
  import "core-js/modules/es.array.map.js";
5
4
  import "core-js/modules/es.array.from.js";
6
5
  import "core-js/modules/es.string.iterator.js";
@@ -10,7 +9,7 @@ import { folder as FolderIcon } from '../../icons';
10
9
  import { makeUniqueId } from '../../shared/component-helper';
11
10
  import { UploadContext } from './UploadContext';
12
11
  import UploadStatus from './UploadStatus';
13
- import { extendWithAbbreviation } from './UploadVerify';
12
+ import { getAcceptedFileTypes } from './UploadVerify';
14
13
 
15
14
  var UploadFileInput = function UploadFileInput() {
16
15
  var fileInput = useRef(null);
@@ -28,15 +27,10 @@ var UploadFileInput = function UploadFileInput() {
28
27
  };
29
28
 
30
29
  var sharedId = id || makeUniqueId();
31
- var accept = extendWithAbbreviation(acceptedFileTypes).map(function (type) {
32
- return ".".concat(type);
33
- }).join(',');
34
- return React.createElement("div", {
35
- "data-testid": "upload-file-input"
36
- }, React.createElement(Button, {
30
+ var accept = getAcceptedFileTypes(acceptedFileTypes);
31
+ return React.createElement("div", null, React.createElement(Button, {
37
32
  top: "medium",
38
33
  id: "".concat(sharedId, "-input"),
39
- "data-testid": "upload-file-input-button",
40
34
  className: "dnb-upload__file-input-button",
41
35
  icon: FolderIcon,
42
36
  icon_position: "left",
@@ -45,7 +39,6 @@ var UploadFileInput = function UploadFileInput() {
45
39
  onClick: openFileDialog
46
40
  }, buttonText), _UploadStatus || (_UploadStatus = React.createElement(UploadStatus, null)), React.createElement("input", {
47
41
  "aria-labelledby": "".concat(sharedId, "-input"),
48
- "data-testid": "upload-file-input-input",
49
42
  ref: fileInput,
50
43
  accept: accept,
51
44
  className: "dnb-upload__file-input",
@@ -25,7 +25,6 @@ function UploadFileList() {
25
25
  }
26
26
 
27
27
  return React.createElement("ul", {
28
- "data-testid": "upload-file-list",
29
28
  className: "dnb-upload__file-list",
30
29
  "aria-label": fileListAriaLabel
31
30
  }, files.map(function (uploadFile, index) {
@@ -2,15 +2,15 @@ import _slicedToArray from "@babel/runtime/helpers/esm/slicedToArray";
2
2
 
3
3
  var _ProgressIndicator, _Icon;
4
4
 
5
- import "core-js/modules/es.function.name.js";
6
- import "core-js/modules/es.regexp.exec.js";
7
- import "core-js/modules/es.string.split.js";
8
5
  import "core-js/modules/es.array.iterator.js";
9
6
  import "core-js/modules/es.object.to-string.js";
10
7
  import "core-js/modules/es.string.iterator.js";
11
8
  import "core-js/modules/web.dom-collections.iterator.js";
12
9
  import "core-js/modules/web.url.js";
13
10
  import "core-js/modules/web.url-search-params.js";
11
+ import "core-js/modules/es.regexp.exec.js";
12
+ import "core-js/modules/es.string.split.js";
13
+ import "core-js/modules/es.function.name.js";
14
14
  import React, { useRef } from 'react';
15
15
  import classnames from 'classnames';
16
16
  import Button from '../button/Button';
@@ -21,6 +21,7 @@ import P from '../../elements/P';
21
21
  import { trash as TrashIcon, exclamation_medium as ExclamationIcon, file_pdf_medium as pdf, file_xls_medium as xls, file_ppt_medium as ppt, file_csv_medium as csv, file_txt_medium as txt, file_xml_medium as xml, file_medium as file } from '../../icons';
22
22
  import { getPreviousSibling, warn } from '../../shared/component-helper';
23
23
  import useUpload from './useUpload';
24
+ import { getFileTypeFromExtension } from './UploadVerify';
24
25
  var images = {
25
26
  pdf: pdf,
26
27
  xls: xls,
@@ -32,7 +33,7 @@ var images = {
32
33
  };
33
34
 
34
35
  var UploadFileListCell = function UploadFileListCell(_ref) {
35
- var _div, _a, _FormStatus;
36
+ var _div, _P, _FormStatus;
36
37
 
37
38
  var id = _ref.id,
38
39
  uploadFile = _ref.uploadFile,
@@ -42,10 +43,9 @@ var UploadFileListCell = function UploadFileListCell(_ref) {
42
43
  var file = uploadFile.file,
43
44
  errorMessage = uploadFile.errorMessage,
44
45
  isLoading = uploadFile.isLoading;
45
- var name = file.name,
46
- type = file.type;
47
- var fileType = type.split('/')[1] || '';
48
46
  var hasWarning = errorMessage != null;
47
+ var fileType = getFileTypeFromExtension(file);
48
+ var humanFileType = fileType.toUpperCase();
49
49
  var imageUrl = URL.createObjectURL(file);
50
50
  var cellRef = useRef();
51
51
  var exists = useExistsHighlight(id, file);
@@ -66,7 +66,6 @@ var UploadFileListCell = function UploadFileListCell(_ref) {
66
66
  };
67
67
 
68
68
  return React.createElement("li", {
69
- "data-testid": "upload-file-list-cell",
70
69
  className: classnames('dnb-upload__file-cell', hasWarning && 'dnb-upload__file-cell--warning', exists && 'dnb-upload__file-cell--highlight'),
71
70
  ref: cellRef
72
71
  }, React.createElement("div", {
@@ -74,7 +73,6 @@ var UploadFileListCell = function UploadFileListCell(_ref) {
74
73
  }, React.createElement("div", {
75
74
  className: "dnb-upload__file-cell__content__left"
76
75
  }, getIcon(), getTitle()), React.createElement("div", null, React.createElement(Button, {
77
- "data-testid": "upload-delete-button",
78
76
  icon: TrashIcon,
79
77
  variant: "tertiary",
80
78
  onClick: onDeleteHandler,
@@ -83,9 +81,7 @@ var UploadFileListCell = function UploadFileListCell(_ref) {
83
81
 
84
82
  function getIcon() {
85
83
  if (isLoading) {
86
- return _ProgressIndicator || (_ProgressIndicator = React.createElement(ProgressIndicator, {
87
- "data-testid": "upload-progress-indicator"
88
- }));
84
+ return _ProgressIndicator || (_ProgressIndicator = React.createElement(ProgressIndicator, null));
89
85
  }
90
86
 
91
87
  if (hasWarning) return _Icon || (_Icon = React.createElement(Icon, {
@@ -93,7 +89,12 @@ var UploadFileListCell = function UploadFileListCell(_ref) {
93
89
  }));
94
90
  var iconFileType = fileType;
95
91
 
96
- if (!Object.prototype.hasOwnProperty.call(images, fileType)) {
92
+ if (!iconFileType) {
93
+ var mimeParts = file.type.split('/');
94
+ iconFileType = images[mimeParts[0]] || images[mimeParts[1]];
95
+ }
96
+
97
+ if (!Object.prototype.hasOwnProperty.call(images, iconFileType)) {
97
98
  iconFileType = 'file';
98
99
  }
99
100
 
@@ -107,23 +108,20 @@ var UploadFileListCell = function UploadFileListCell(_ref) {
107
108
  className: "dnb-upload__file-cell__text-container dnb-upload__file-cell__text-container--loading"
108
109
  }, loadingText)) : React.createElement("div", {
109
110
  className: "dnb-upload__file-cell__text-container"
110
- }, _a || (_a = React.createElement("a", {
111
- "data-testid": "upload-file-anchor",
111
+ }, React.createElement("a", {
112
112
  target: "_blank",
113
113
  href: imageUrl,
114
114
  className: "dnb-anchor dnb-upload__file-cell__title",
115
115
  rel: "noopener noreferrer"
116
- }, name)), React.createElement(P, {
117
- "data-testid": "upload-subtitle",
116
+ }, file.name), _P || (_P = React.createElement(P, {
118
117
  className: "dnb-upload__file-cell__subtitle",
119
118
  size: "x-small",
120
119
  top: "xx-small"
121
- }, fileType.toUpperCase()));
120
+ }, humanFileType)));
122
121
  }
123
122
 
124
123
  function getWarning() {
125
124
  return hasWarning ? _FormStatus || (_FormStatus = React.createElement(FormStatus, {
126
- "data-testid": "upload-warning",
127
125
  top: "small",
128
126
  text: errorMessage,
129
127
  stretch: true
@@ -25,10 +25,8 @@ var UploadInfo = function UploadInfo() {
25
25
  fileMaxSize = context.fileMaxSize;
26
26
  var prettyfiedAcceptedFileFormats = acceptedFileTypes.join(', ').toUpperCase();
27
27
  return React.createElement(React.Fragment, null, React.createElement(Lead, {
28
- "data-testid": "upload-title",
29
28
  space: "0"
30
29
  }, title), React.createElement(P, {
31
- "data-testid": "upload-text",
32
30
  top: "xx-small",
33
31
  className: "dnb-upload__text"
34
32
  }, text), React.createElement(Dl, {
@@ -36,13 +34,7 @@ var UploadInfo = function UploadInfo() {
36
34
  bottom: 0,
37
35
  direction: "horizontal",
38
36
  className: "dnb-upload__condition-list"
39
- }, React.createElement(Dl.Item, null, React.createElement(Dt, {
40
- "data-testid": "upload-accepted-formats"
41
- }, fileTypeDescription), React.createElement(Dd, null, prettyfiedAcceptedFileFormats)), React.createElement(Dl.Item, null, React.createElement(Dt, {
42
- "data-testid": "upload-file-size"
43
- }, fileSizeDescription), React.createElement(Dd, null, String(fileSizeContent).replace('%size', format(fileMaxSize).toString()))), filesAmountLimit < defaultProps.filesAmountLimit && React.createElement(Dl.Item, null, React.createElement(Dt, {
44
- "data-testid": "upload-file-amount-limit"
45
- }, fileAmountDescription), React.createElement(Dd, null, filesAmountLimit))));
37
+ }, prettyfiedAcceptedFileFormats && React.createElement(Dl.Item, null, React.createElement(Dt, null, fileTypeDescription), React.createElement(Dd, null, prettyfiedAcceptedFileFormats)), React.createElement(Dl.Item, null, React.createElement(Dt, null, fileSizeDescription), React.createElement(Dd, null, String(fileSizeContent).replace('%size', format(fileMaxSize).toString()))), filesAmountLimit < defaultProps.filesAmountLimit && React.createElement(Dl.Item, null, React.createElement(Dt, null, fileAmountDescription), React.createElement(Dd, null, filesAmountLimit))));
46
38
  };
47
39
 
48
40
  export default UploadInfo;
@@ -1,5 +1,8 @@
1
1
  import { UploadFile, UploadContextProps, UploadAcceptedFileTypes } from './types';
2
2
  export declare function verifyFiles(files: UploadFile[], context: Pick<UploadContextProps, 'errorUnsupportedFile' | 'errorLargeFile' | 'acceptedFileTypes' | 'fileMaxSize'>): UploadFile[];
3
+ export declare function getFileTypeFromExtension(file: File): string;
4
+ export declare function getAcceptedFileTypes(acceptedFileTypes: UploadAcceptedFileTypes): string;
5
+ export declare function hasPreferredMimeType(acceptedFileTypes: UploadAcceptedFileTypes, file: File): boolean;
3
6
  export declare function extendWithAbbreviation(acceptedFileTypes: UploadAcceptedFileTypes, abbreviations?: {
4
7
  jpg: string;
5
8
  }): string[];
@@ -7,6 +7,9 @@ import "core-js/modules/es.regexp.to-string.js";
7
7
  import "core-js/modules/es.array.includes.js";
8
8
  import "core-js/modules/es.string.includes.js";
9
9
  import "core-js/modules/es.array.map.js";
10
+ import "core-js/modules/es.function.name.js";
11
+ import "core-js/modules/es.array.join.js";
12
+ import "core-js/modules/es.string.split.js";
10
13
  import "core-js/modules/web.dom-collections.for-each.js";
11
14
  import "core-js/modules/es.object.entries.js";
12
15
  import { format } from '../number-format/NumberUtils';
@@ -26,8 +29,9 @@ export function verifyFiles(files, context) {
26
29
  return false;
27
30
  }
28
31
 
32
+ var fileType = hasPreferredMimeType(acceptedFileTypes, file) ? file.type : getFileTypeFromExtension(file) || file.type;
29
33
  var foundType = extendWithAbbreviation(acceptedFileTypes).some(function (type) {
30
- return file.type.includes(type);
34
+ return fileType.includes(type);
31
35
  });
32
36
  return !foundType ? errorUnsupportedFile : null;
33
37
  };
@@ -44,6 +48,19 @@ export function verifyFiles(files, context) {
44
48
  });
45
49
  return cleanedFiles;
46
50
  }
51
+ export function getFileTypeFromExtension(file) {
52
+ return file.name.includes('.') && file.name.replace(/.*\.([^.]+)$/, '$1') || null;
53
+ }
54
+ export function getAcceptedFileTypes(acceptedFileTypes) {
55
+ return extendWithAbbreviation(acceptedFileTypes).map(function (type) {
56
+ return type.includes('/') ? type : ".".concat(type);
57
+ }).join(',');
58
+ }
59
+ export function hasPreferredMimeType(acceptedFileTypes, file) {
60
+ return file.type.split('/')[1] && (!(acceptedFileTypes !== null && acceptedFileTypes !== void 0 && acceptedFileTypes.length) || (acceptedFileTypes === null || acceptedFileTypes === void 0 ? void 0 : acceptedFileTypes.some(function (type) {
61
+ return type.toLowerCase() === file.type.toLowerCase();
62
+ })));
63
+ }
47
64
  export function extendWithAbbreviation(acceptedFileTypes) {
48
65
  var abbreviations = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {
49
66
  jpg: 'jpeg'
@@ -15,6 +15,17 @@ import Input, { inputPropTypes } from '../input/Input';
15
15
  import Context from '../../shared/Context';
16
16
  const InputMasked = React.forwardRef((props, ref) => {
17
17
  const context = React.useContext(Context);
18
+
19
+ if (props !== null && props !== void 0 && props.mask) {
20
+ const alias = context === null || context === void 0 ? void 0 : context.InputMasked;
21
+
22
+ for (const key in alias) {
23
+ if (/^as[_A-Z]|number_mask|currency_mask/.test(key)) {
24
+ delete alias[key];
25
+ }
26
+ }
27
+ }
28
+
18
29
  const contextAndProps = React.useCallback(extendPropsWithContext(props, InputMasked.defaultProps, context === null || context === void 0 ? void 0 : context.InputMasked), [props, InputMasked.defaultProps, context === null || context === void 0 ? void 0 : context.InputMasked]);
19
30
  return React.createElement(InputMaskedContext.Provider, {
20
31
  value: {
@@ -55,7 +66,7 @@ process.env.NODE_ENV !== "production" ? InputMasked.propTypes = _objectSpread({
55
66
  on_submit_blur: PropTypes.func
56
67
  }, inputPropTypes) : void 0;
57
68
  InputMasked.defaultProps = _objectSpread(_objectSpread({}, Input.defaultProps), {}, {
58
- mask: [],
69
+ mask: null,
59
70
  number_mask: null,
60
71
  currency_mask: null,
61
72
  mask_options: null,
@@ -182,7 +182,7 @@ export const useInputElement = () => {
182
182
  inputRef: ref,
183
183
  inputElement: inputElementRef.current,
184
184
  pipe: pipe,
185
- mask: mask,
185
+ mask: mask || [],
186
186
  showMask: showMask,
187
187
  guide: showGuide,
188
188
  keepCharPositions: keepCharPositions,
@@ -63,8 +63,8 @@ export const correctNumberValue = ({
63
63
  value = value.replace('.', decimalSymbol);
64
64
 
65
65
  if (localValue !== null) {
66
- const localNumberValue = localValue.replace(/[^\d,.]/g, '');
67
- const numberValue = value.replace(/[^\d,.]/g, '');
66
+ const localNumberValue = localValue.replace(/[^\d,.-]/g, '');
67
+ const numberValue = value.replace(/[^\d,.-]/g, '');
68
68
  const endsWithDecimal = localNumberValue.endsWith(decimalSymbol);
69
69
  const endsWithZeroAndDecimal = localNumberValue.endsWith(`${decimalSymbol}0`);
70
70
 
@@ -78,7 +78,7 @@ export const correctNumberValue = ({
78
78
  value = localValue;
79
79
  }
80
80
 
81
- if (/^-|-0$/.test(localValue)) {
81
+ if (/^(-|-0)$/.test(localValue.replace(/[^\d-0]/g, ''))) {
82
82
  value = localValue;
83
83
  } else if (localNumberValue === '' && numberValue === '0') {
84
84
  value = '';
@@ -9,7 +9,7 @@ export declare type TableContainerProps = {
9
9
  React.ReactElement<TableContainerHeadProps>,
10
10
  React.ReactElement<TableContainerBodyProps>,
11
11
  React.ReactElement<TableContainerFootProps>
12
- ];
12
+ ] | React.ReactElement<TableContainerBodyProps>;
13
13
  };
14
14
  export declare type TableContainerAllProps = TableContainerProps & React.TableHTMLAttributes<HTMLTableRowElement> & SpacingProps;
15
15
  declare function TableContainer(props: TableContainerAllProps): JSX.Element;
@@ -30,13 +30,13 @@ export declare type TableContainerHeadProps = {
30
30
  /**
31
31
  * The content of the component.
32
32
  */
33
- children: React.ReactNode;
33
+ children?: React.ReactNode;
34
34
  };
35
35
  export declare function TableContainerHead(props: TableContainerHeadProps & React.HTMLAttributes<HTMLDivElement>): JSX.Element;
36
36
  export declare type TableContainerFootProps = {
37
37
  /**
38
38
  * The content of the component.
39
39
  */
40
- children: React.ReactNode;
40
+ children?: React.ReactNode;
41
41
  };
42
42
  export declare function TableContainerFoot(props: TableContainerFootProps & React.HTMLAttributes<HTMLDivElement>): JSX.Element;
@@ -1,5 +1,8 @@
1
1
  import _extends from "@babel/runtime/helpers/esm/extends";
2
2
  import _objectWithoutProperties from "@babel/runtime/helpers/esm/objectWithoutProperties";
3
+
4
+ var _TableContainer$Head, _TableContainer$Foot;
5
+
3
6
  const _excluded = ["children", "className"],
4
7
  _excluded2 = ["children", "className"],
5
8
  _excluded3 = ["children", "className"],
@@ -10,6 +13,8 @@ import TableScrollView from './TableScrollView';
10
13
  import { createSpacingClasses } from '../space/SpacingUtils';
11
14
  import { validateDOMAttributes } from '../../shared/component-helper';
12
15
  export default function TableContainer(props) {
16
+ var _content$, _content$2;
17
+
13
18
  const {
14
19
  children,
15
20
  className
@@ -19,9 +24,24 @@ export default function TableContainer(props) {
19
24
  const spacingClasses = createSpacingClasses(props);
20
25
  validateDOMAttributes(props, rest);
21
26
  const ScrollView = TableScrollView;
27
+ const isArray = Array.isArray(children);
28
+ const content = isArray ? children : [children];
29
+
30
+ if (((_content$ = content[0]) === null || _content$ === void 0 ? void 0 : _content$.type) !== TableContainer.Head) {
31
+ content.unshift(_TableContainer$Head || (_TableContainer$Head = React.createElement(TableContainer.Head, {
32
+ key: "head"
33
+ })));
34
+ }
35
+
36
+ if (((_content$2 = content[2]) === null || _content$2 === void 0 ? void 0 : _content$2.type) !== TableContainer.Foot) {
37
+ content.push(_TableContainer$Foot || (_TableContainer$Foot = React.createElement(TableContainer.Foot, {
38
+ key: "foot"
39
+ })));
40
+ }
41
+
22
42
  return React.createElement("section", _extends({
23
43
  className: classnames('dnb-table__container', className, spacingClasses)
24
- }, rest), React.createElement(ScrollView, null, children));
44
+ }, rest), React.createElement(ScrollView, null, content));
25
45
  }
26
46
  export function TableContainerBody(props) {
27
47
  const {
@@ -17,8 +17,8 @@ export default function Th(componentProps) {
17
17
  } = componentProps,
18
18
  props = _objectWithoutProperties(componentProps, _excluded);
19
19
 
20
- const role = props.scope === 'row' ? 'rowheader' : 'columnheader';
21
- const scope = props.scope === 'row' ? 'row' : 'col';
20
+ const role = props.scope === 'row' || props.scope === 'rowgroup' ? 'rowheader' : 'columnheader';
21
+ const scope = props.scope === 'row' ? 'row' : props.scope || 'col';
22
22
  const ariaSort = sortable ? reversed ? 'descending' : 'ascending' : undefined;
23
23
  return React.createElement("th", _extends({
24
24
  role: role,
@@ -72,13 +72,17 @@
72
72
  position: relative;
73
73
  z-index: 2;
74
74
  }
75
- &__tr--has-accordion-content:hover,
76
- &__tr--has-accordion-content:active,
77
- &__tr--has-accordion-content:focus,
78
75
  &__tr--has-accordion-content#{&}__tr--expanded,
79
76
  &__tr__accordion_content {
80
- // ensure borders are visible in certain states
81
- z-index: 3;
77
+ z-index: 3; // ensure borders are visible in certain states
78
+ }
79
+
80
+ &__tr--has-accordion-content {
81
+ &:hover,
82
+ &:active,
83
+ html[data-whatinput='keyboard'] &:focus {
84
+ z-index: 5; // over table outline border
85
+ }
82
86
  }
83
87
 
84
88
  &__tr--has-accordion-content#{&}__tr--expanded
@@ -129,6 +133,13 @@
129
133
  }
130
134
  }
131
135
 
136
+ &--outline
137
+ tbody
138
+ &__tr--has-accordion-content:not(#{&}__tr--expanded):not(:nth-last-child(2))
139
+ &__td::before {
140
+ bottom: -0.0625rem;
141
+ }
142
+
132
143
  &__tr--has-accordion-content#{&}__tr--expanded:not(&__tr--disabled):hover
133
144
  &__td {
134
145
  background-color: var(--color-white);
@@ -193,14 +204,16 @@
193
204
  @include IS_SAFARI_DESKTOP {
194
205
  &[hidden] {
195
206
  /**
196
- * By reverting the display from "none" to "block",
197
- * we trick VoiceOver to not make this row as the end of the table. We still need "hidden" to get the correct number of rows (childCount).
198
- */
207
+ * By reverting the display from "none" to "block",
208
+ * we trick VoiceOver to not make this row as the end of the table. We still need "hidden" to get the correct number of rows (childCount).
209
+ */
199
210
  display: block;
200
211
  }
201
212
  }
202
213
 
203
214
  td {
215
+ padding: 0 !important; // medium and small size sets padding – but we never want a padding on this td
216
+
204
217
  width: calc(100% - 3.5rem);
205
218
 
206
219
  .dnb-table__size--medium & {
@@ -279,9 +292,40 @@
279
292
  vertical-align: top;
280
293
  }
281
294
 
295
+ &--outline
296
+ tbody
297
+ &__tr#{&}__tr--has-accordion-content:not(#{&}__tr--expanded):nth-last-child(2)
298
+ &__td:first-of-type {
299
+ &,
300
+ &::before,
301
+ &::after {
302
+ border-radius: 0 0 0 0.5rem;
303
+ }
304
+ }
305
+ &--outline tbody &__tr:last-of-type &__td:last-of-type,
306
+ &--outline
307
+ tbody
308
+ &__tr#{&}__tr--has-accordion-content:not(#{&}__tr--expanded):nth-last-child(2)
309
+ &__td:last-of-type {
310
+ &,
311
+ &::before,
312
+ &::after {
313
+ border-radius: 0 0 0.5rem 0;
314
+ }
315
+ }
316
+ &--outline tbody &__tr#{&}__tr__accordion_content:last-of-type &__td {
317
+ &,
318
+ &::before,
319
+ &::after {
320
+ border-radius: 0 0 0.5rem 0.5rem;
321
+ }
322
+ }
323
+
324
+ // stylelint-disable-next-line
282
325
  &__tr--has-accordion-content:not(&__tr--disabled) {
283
326
  cursor: pointer;
284
327
  }
328
+
285
329
  // prevent selection while animating – useful when user double-clicks
286
330
  // TODO: Our SASS version does not support :has – so we may use this in future
287
331
  // &__tr--has-accordion-content:has(& + &__tr__accordion_content--animating) {
@@ -34,6 +34,22 @@
34
34
  &__size--large .dnb-table__th {
35
35
  padding-top: 1.5rem;
36
36
  }
37
+
38
+ position: relative; // because of bottom border
39
+ &::after {
40
+ @include tableBorder();
41
+ border-bottom: var(--border);
42
+ }
43
+
44
+ /* stylelint-disable */
45
+ & tbody:first-child,
46
+ & > :not(thead) + tbody {
47
+ .dnb-table__tr:first-of-type .dnb-table__th::after,
48
+ .dnb-table__tr:first-of-type .dnb-table__td::after {
49
+ border-top: none;
50
+ }
51
+ }
52
+ /* stylelint-enable */
37
53
  }
38
54
  }
39
55
 
@@ -41,7 +57,8 @@
41
57
  padding: 2rem 1rem 0;
42
58
 
43
59
  &--empty {
44
- padding: 0.5rem 0 0;
60
+ padding: 0;
61
+ min-height: 1.5rem;
45
62
  }
46
63
 
47
64
  .dnb-spacing & .dnb-h--large:not([class*='space__top']) {
@@ -53,7 +70,8 @@
53
70
  padding-bottom: 1.25rem; // because of 8px scrollbar
54
71
 
55
72
  &--empty {
56
- padding-bottom: 1.5rem;
73
+ padding: 0;
74
+ min-height: 1rem;
57
75
  }
58
76
  }
59
77
 
@@ -16,80 +16,18 @@
16
16
  border-bottom: none;
17
17
  }
18
18
  }
19
- &:not(#{&}--outline) tbody &__tr:last-of-type &__td::after,
20
- &:not(#{&}--outline) tbody &__tr &__td[rowspan]::after {
21
- bottom: -0.0625rem;
22
- border-bottom: var(--border);
23
- }
24
19
 
25
20
  // table outline
26
- &--outline tbody &__td {
27
- &:first-of-type::after,
28
- &:last-of-type::after {
29
- @include tableBorder();
30
- }
31
-
32
- &:first-of-type::after {
33
- border-left: var(--outline);
34
- }
35
- &:last-of-type::after {
36
- border-right: var(--outline);
37
- }
38
-
39
- /* stylelint-disable */
21
+ &--outline {
22
+ position: relative;
40
23
  &,
41
- &::before,
42
24
  &::after {
43
- transition: border-radius 400ms var(--easing-default);
25
+ border-radius: 0.5rem;
44
26
  }
45
- /* stylelint-enable */
46
- }
47
- &--outline tbody &__tr:last-of-type &__td {
48
27
  &::after {
49
28
  @include tableBorder();
50
-
51
- border-bottom: var(--outline);
52
- }
53
- }
54
- &--outline thead &__th:first-of-type {
55
- &,
56
- &::after {
57
- border-radius: 0.5rem 0 0 0;
58
- }
59
- }
60
- &--outline thead &__th:last-of-type {
61
- &,
62
- &::after {
63
- border-radius: 0 0.5rem 0 0;
64
- }
65
- }
66
- &--outline tbody &__tr:last-of-type &__td:first-of-type,
67
- &--outline
68
- tbody
69
- &__tr#{&}__tr--has-accordion-content:not(#{&}__tr--expanded):nth-last-child(2)
70
- &__td:first-of-type {
71
- &,
72
- &::before,
73
- &::after {
74
- border-radius: 0 0 0 0.5rem;
75
- }
76
- }
77
- &--outline tbody &__tr:last-of-type &__td:last-of-type,
78
- &--outline
79
- tbody
80
- &__tr#{&}__tr--has-accordion-content:not(#{&}__tr--expanded):nth-last-child(2)
81
- &__td:last-of-type {
82
- &,
83
- &::before,
84
- &::after {
85
- border-radius: 0 0 0.5rem 0;
86
- }
87
- }
88
- &--outline tbody &__tr#{&}__tr__accordion_content:last-of-type &__td {
89
- &,
90
- &::before,
91
- &::after {
92
- border-radius: 0 0 0.5rem 0.5rem;
29
+ z-index: 3;
30
+ border: var(--outline);
93
31
  }
94
32
  }
95
33
 
@@ -112,6 +50,36 @@
112
50
  }
113
51
  }
114
52
 
53
+ // no thead, should have th in body
54
+ /* stylelint-disable */
55
+ &--outline tbody:first-child &__tr:first-of-type &__th,
56
+ &--outline > :not(thead) + tbody &__tr:first-of-type &__th {
57
+ &::after {
58
+ border-top: var(--outline);
59
+ }
60
+ &:first-of-type,
61
+ &:first-of-type::after {
62
+ border-radius: 0.5rem 0 0 0;
63
+ }
64
+ }
65
+ &--outline > tbody:first-child &__tr:first-of-type &__td,
66
+ &--outline > :not(thead) + tbody &__tr:first-of-type &__td {
67
+ &::after {
68
+ border-top: var(--outline);
69
+ }
70
+ &:last-of-type,
71
+ &:last-of-type::after {
72
+ border-radius: 0 0.5rem 0 0;
73
+ }
74
+ }
75
+ &:not(&--outline)#{&}--border > tbody:first-child &__td:last-of-type,
76
+ &:not(&--outline)#{&}--border > :not(thead) + tbody &__td:last-of-type {
77
+ &::after {
78
+ border-right: var(--border);
79
+ }
80
+ }
81
+ /* stylelint-enable */
82
+
115
83
  // spacing
116
84
  &__td--no-spacing,
117
85
  td#{&}__td--no-spacing {