@kaizen/components 1.73.12 → 1.74.0
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/dist/cjs/Filter/FilterMultiSelect/subcomponents/MultiSelectOption/MultiSelectOption.cjs +18 -3
- package/dist/cjs/Filter/FilterMultiSelect/subcomponents/SelectionControlButton/ClearButton/ClearButton.cjs +11 -1
- package/dist/cjs/Filter/FilterMultiSelect/subcomponents/SelectionControlButton/SelectAllButton/SelectAllButton.cjs +7 -1
- package/dist/cjs/TimeField/TimeField.cjs +2 -1
- package/dist/cjs/TimeField/subcomponents/TimeSegment/TimeSegment.cjs +4 -2
- package/dist/cjs/TimeField/subcomponents/TimeSegment/TimeSegment.module.scss.cjs +1 -0
- package/dist/esm/Filter/FilterMultiSelect/subcomponents/MultiSelectOption/MultiSelectOption.mjs +18 -3
- package/dist/esm/Filter/FilterMultiSelect/subcomponents/SelectionControlButton/ClearButton/ClearButton.mjs +11 -1
- package/dist/esm/Filter/FilterMultiSelect/subcomponents/SelectionControlButton/SelectAllButton/SelectAllButton.mjs +7 -1
- package/dist/esm/TimeField/TimeField.mjs +2 -1
- package/dist/esm/TimeField/subcomponents/TimeSegment/TimeSegment.mjs +4 -2
- package/dist/esm/TimeField/subcomponents/TimeSegment/TimeSegment.module.scss.mjs +1 -0
- package/dist/styles.css +4 -1
- package/dist/types/Badge/Badge.d.ts +3 -4
- package/dist/types/TimeField/subcomponents/TimeSegment/TimeSegment.d.ts +2 -1
- package/locales/en.json +12 -0
- package/package.json +1 -1
- package/src/Badge/Badge.tsx +9 -4
- package/src/Filter/FilterMultiSelect/subcomponents/MultiSelectOption/MultiSelectOption.spec.tsx +3 -3
- package/src/Filter/FilterMultiSelect/subcomponents/MultiSelectOption/MultiSelectOption.tsx +16 -2
- package/src/Filter/FilterMultiSelect/subcomponents/SelectionControlButton/ClearButton/ClearButton.tsx +11 -1
- package/src/Filter/FilterMultiSelect/subcomponents/SelectionControlButton/SelectAllButton/SelectAllButton.tsx +8 -1
- package/src/TimeField/TimeField.tsx +11 -3
- package/src/TimeField/subcomponents/TimeSegment/TimeSegment.module.scss +4 -1
- package/src/TimeField/subcomponents/TimeSegment/TimeSegment.tsx +7 -1
- package/src/__next__/Tooltip/_docs/Tooltip.spec.stories.tsx +4 -1
package/dist/cjs/Filter/FilterMultiSelect/subcomponents/MultiSelectOption/MultiSelectOption.cjs
CHANGED
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
var tslib = require('tslib');
|
|
4
4
|
var React = require('react');
|
|
5
|
+
var i18nReactIntl = require('@cultureamp/i18n-react-intl');
|
|
5
6
|
var focus = require('@react-aria/focus');
|
|
6
7
|
var listbox = require('@react-aria/listbox');
|
|
7
8
|
var utils = require('@react-aria/utils');
|
|
@@ -38,6 +39,7 @@ var MultiSelectOption = function (_a) {
|
|
|
38
39
|
isFocusVisible = _f.isFocusVisible,
|
|
39
40
|
focusProps = _f.focusProps;
|
|
40
41
|
var countElementId = React.useId();
|
|
42
|
+
var formatNumber = i18nReactIntl.useIntl().formatNumber;
|
|
41
43
|
return React__default.default.createElement("li", tslib.__assign({}, utils.mergeProps(optionProps, focusProps), {
|
|
42
44
|
ref: ref,
|
|
43
45
|
className: classnames__default.default(MultiSelectOption_module.option, classNameOverride, isSelected && MultiSelectOption_module.isSelected, isFocusVisible && MultiSelectOption_module.isFocusVisible, isDisabled && MultiSelectOption_module.isDisabled),
|
|
@@ -51,9 +53,22 @@ var MultiSelectOption = function (_a) {
|
|
|
51
53
|
})), item.rendered, ((_d = item.value) === null || _d === void 0 ? void 0 : _d.count) && React__default.default.createElement("span", {
|
|
52
54
|
id: countElementId,
|
|
53
55
|
className: MultiSelectOption_module.badgeContainer
|
|
54
|
-
}, React__default.default.createElement(
|
|
55
|
-
|
|
56
|
-
|
|
56
|
+
}, React__default.default.createElement(i18nReactIntl.FormattedMessage, {
|
|
57
|
+
defaultMessage: "<Badge>{count}</Badge><VisuallyHidden> available</VisuallyHidden>",
|
|
58
|
+
id: "filterMultiSelectMultiSelectOption.available",
|
|
59
|
+
description: "Number of filter items available",
|
|
60
|
+
values: {
|
|
61
|
+
count: formatNumber(parseInt(item.value.count)),
|
|
62
|
+
Badge: function (children) {
|
|
63
|
+
return React__default.default.createElement(Badge.Badge, {
|
|
64
|
+
classNameOverride: MultiSelectOption_module.badge
|
|
65
|
+
}, children);
|
|
66
|
+
},
|
|
67
|
+
VisuallyHidden: function (children) {
|
|
68
|
+
return React__default.default.createElement(VisuallyHidden.VisuallyHidden, null, children);
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
})));
|
|
57
72
|
};
|
|
58
73
|
MultiSelectOption.displayName = 'FilterMultiSelect.Option';
|
|
59
74
|
exports.MultiSelectOption = MultiSelectOption;
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
3
|
var React = require('react');
|
|
4
|
+
var i18nReactIntl = require('@cultureamp/i18n-react-intl');
|
|
4
5
|
var classnames = require('classnames');
|
|
5
6
|
var VisuallyHidden = require('../../../../../VisuallyHidden/VisuallyHidden.cjs');
|
|
6
7
|
require('../../../context/MenuTriggerProvider/MenuTriggerProvider.cjs');
|
|
@@ -31,7 +32,16 @@ var ClearButton = function () {
|
|
|
31
32
|
}));
|
|
32
33
|
}
|
|
33
34
|
}
|
|
34
|
-
},
|
|
35
|
+
}, React__default.default.createElement(i18nReactIntl.FormattedMessage, {
|
|
36
|
+
defaultMessage: "Clear<VisuallyHidden> selections</VisuallyHidden>",
|
|
37
|
+
id: "filterMultiSelectClearButton.label",
|
|
38
|
+
description: "Clear button label for filter multi-select",
|
|
39
|
+
values: {
|
|
40
|
+
VisuallyHidden: function (children) {
|
|
41
|
+
return React__default.default.createElement(VisuallyHidden.VisuallyHidden, null, children);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
}));
|
|
35
45
|
};
|
|
36
46
|
ClearButton.displayName = 'FilterMultiSelect.ClearButton';
|
|
37
47
|
exports.ClearButton = ClearButton;
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
var tslib = require('tslib');
|
|
4
4
|
var React = require('react');
|
|
5
|
+
var i18nReactIntl = require('@cultureamp/i18n-react-intl');
|
|
5
6
|
var classnames = require('classnames');
|
|
6
7
|
require('../../../context/MenuTriggerProvider/MenuTriggerProvider.cjs');
|
|
7
8
|
var SelectionProvider = require('../../../context/SelectionProvider/SelectionProvider.cjs');
|
|
@@ -20,6 +21,7 @@ var SelectAllButton = function () {
|
|
|
20
21
|
var filteredOptions = Array.from(selectionState.collection.getKeys()).filter(function (key) {
|
|
21
22
|
return !disabledOptions.includes(key);
|
|
22
23
|
});
|
|
24
|
+
var formatMessage = i18nReactIntl.useIntl().formatMessage;
|
|
23
25
|
return React__default.default.createElement("button", {
|
|
24
26
|
type: "button",
|
|
25
27
|
className: classnames__default.default(SelectionControlButton_module.button, selectionState.selectionManager.isSelectAll && SelectionControlButton_module.isDisabled),
|
|
@@ -27,7 +29,11 @@ var SelectAllButton = function () {
|
|
|
27
29
|
onClick: function () {
|
|
28
30
|
return !selectionState.selectionManager.isSelectAll && selectionState.selectionManager.setSelectedKeys(tslib.__spreadArray(tslib.__spreadArray([], selectedOptions, true), filteredOptions, true));
|
|
29
31
|
}
|
|
30
|
-
},
|
|
32
|
+
}, formatMessage({
|
|
33
|
+
defaultMessage: 'Select all',
|
|
34
|
+
id: 'filterMultiSelectSelectAllButton.label',
|
|
35
|
+
description: 'Select all button in filter multi select'
|
|
36
|
+
}));
|
|
31
37
|
};
|
|
32
38
|
SelectAllButton.displayName = 'FilterMultiSelect.SelectAllButton';
|
|
33
39
|
exports.SelectAllButton = SelectAllButton;
|
|
@@ -84,7 +84,8 @@ var TimeFieldComponent = function (_a) {
|
|
|
84
84
|
return React__default.default.createElement(TimeSegment.TimeSegment, {
|
|
85
85
|
key: i,
|
|
86
86
|
segment: segment,
|
|
87
|
-
state: state
|
|
87
|
+
state: state,
|
|
88
|
+
hasPadding: ![8294, 8297].includes(segment.text.charCodeAt(0))
|
|
88
89
|
});
|
|
89
90
|
}), React__default.default.createElement("div", {
|
|
90
91
|
className: TimeField_module.focusRing
|
|
@@ -15,7 +15,9 @@ var React__default = /*#__PURE__*/_interopDefault(React);
|
|
|
15
15
|
var classnames__default = /*#__PURE__*/_interopDefault(classnames);
|
|
16
16
|
var TimeSegment = function (_a) {
|
|
17
17
|
var segment = _a.segment,
|
|
18
|
-
state = _a.state
|
|
18
|
+
state = _a.state,
|
|
19
|
+
_b = _a.hasPadding,
|
|
20
|
+
hasPadding = _b === void 0 ? true : _b;
|
|
19
21
|
var ref = React__default.default.useRef(null);
|
|
20
22
|
var segmentProps = datepicker.useDateSegment(segment, state, ref).segmentProps;
|
|
21
23
|
// Chrome has a bug where `contenteditable` elements receive focus from external clicks.
|
|
@@ -26,7 +28,7 @@ var TimeSegment = function (_a) {
|
|
|
26
28
|
className: TimeSegment_module.timeSegmentWrapper
|
|
27
29
|
}, "\u200B", React__default.default.createElement("span", tslib.__assign({}, segmentProps, {
|
|
28
30
|
ref: ref,
|
|
29
|
-
className: classnames__default.default(TimeSegment_module.timeSegment, segment.type === 'literal' && TimeSegment_module.literal, segment.isPlaceholder && TimeSegment_module.placeholder, segment.type === 'dayPeriod' && TimeSegment_module.dayPeriod)
|
|
31
|
+
className: classnames__default.default(TimeSegment_module.timeSegment, segment.type === 'literal' && TimeSegment_module.literal, segment.isPlaceholder && TimeSegment_module.placeholder, segment.type === 'dayPeriod' && TimeSegment_module.dayPeriod, hasPadding && TimeSegment_module.hasPadding)
|
|
30
32
|
}), generateSegmentDisplayText.generateSegmentDisplayText(segment)), "\u200B");
|
|
31
33
|
};
|
|
32
34
|
TimeSegment.displayName = 'TimeSegment';
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
var styles = {
|
|
4
4
|
"timeSegmentWrapper": "TimeSegment-module_timeSegmentWrapper__WYD6y",
|
|
5
5
|
"timeSegment": "TimeSegment-module_timeSegment__eXb0c",
|
|
6
|
+
"hasPadding": "TimeSegment-module_hasPadding__9oYW3",
|
|
6
7
|
"placeholder": "TimeSegment-module_placeholder__j1-gK",
|
|
7
8
|
"literal": "TimeSegment-module_literal__mOkqz",
|
|
8
9
|
"dayPeriod": "TimeSegment-module_dayPeriod__fzT5I"
|
package/dist/esm/Filter/FilterMultiSelect/subcomponents/MultiSelectOption/MultiSelectOption.mjs
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { __assign } from 'tslib';
|
|
2
2
|
import React, { useId } from 'react';
|
|
3
|
+
import { useIntl, FormattedMessage } from '@cultureamp/i18n-react-intl';
|
|
3
4
|
import { useFocusRing } from '@react-aria/focus';
|
|
4
5
|
import { useOption } from '@react-aria/listbox';
|
|
5
6
|
import { mergeProps } from '@react-aria/utils';
|
|
@@ -30,6 +31,7 @@ const MultiSelectOption = /*#__PURE__*/function () {
|
|
|
30
31
|
isFocusVisible = _f.isFocusVisible,
|
|
31
32
|
focusProps = _f.focusProps;
|
|
32
33
|
var countElementId = useId();
|
|
34
|
+
var formatNumber = useIntl().formatNumber;
|
|
33
35
|
return /*#__PURE__*/React.createElement("li", __assign({}, mergeProps(optionProps, focusProps), {
|
|
34
36
|
ref: ref,
|
|
35
37
|
className: classnames(styles.option, classNameOverride, isSelected && styles.isSelected, isFocusVisible && styles.isFocusVisible, isDisabled && styles.isDisabled),
|
|
@@ -43,9 +45,22 @@ const MultiSelectOption = /*#__PURE__*/function () {
|
|
|
43
45
|
})), item.rendered, ((_d = item.value) === null || _d === void 0 ? void 0 : _d.count) && (/*#__PURE__*/React.createElement("span", {
|
|
44
46
|
id: countElementId,
|
|
45
47
|
className: styles.badgeContainer
|
|
46
|
-
}, /*#__PURE__*/React.createElement(
|
|
47
|
-
|
|
48
|
-
|
|
48
|
+
}, /*#__PURE__*/React.createElement(FormattedMessage, {
|
|
49
|
+
defaultMessage: "<Badge>{count}</Badge><VisuallyHidden> available</VisuallyHidden>",
|
|
50
|
+
id: "filterMultiSelectMultiSelectOption.available",
|
|
51
|
+
description: "Number of filter items available",
|
|
52
|
+
values: {
|
|
53
|
+
count: formatNumber(parseInt(item.value.count)),
|
|
54
|
+
Badge: function (children) {
|
|
55
|
+
return /*#__PURE__*/React.createElement(Badge, {
|
|
56
|
+
classNameOverride: styles.badge
|
|
57
|
+
}, children);
|
|
58
|
+
},
|
|
59
|
+
VisuallyHidden: function (children) {
|
|
60
|
+
return /*#__PURE__*/React.createElement(VisuallyHidden, null, children);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
}))));
|
|
49
64
|
};
|
|
50
65
|
MultiSelectOption.displayName = 'FilterMultiSelect.Option';
|
|
51
66
|
return MultiSelectOption;
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
+
import { FormattedMessage } from '@cultureamp/i18n-react-intl';
|
|
2
3
|
import classnames from 'classnames';
|
|
3
4
|
import { VisuallyHidden } from '../../../../../VisuallyHidden/VisuallyHidden.mjs';
|
|
4
5
|
import '../../../context/MenuTriggerProvider/MenuTriggerProvider.mjs';
|
|
@@ -23,7 +24,16 @@ const ClearButton = /*#__PURE__*/function () {
|
|
|
23
24
|
}));
|
|
24
25
|
}
|
|
25
26
|
}
|
|
26
|
-
},
|
|
27
|
+
}, /*#__PURE__*/React.createElement(FormattedMessage, {
|
|
28
|
+
defaultMessage: "Clear<VisuallyHidden> selections</VisuallyHidden>",
|
|
29
|
+
id: "filterMultiSelectClearButton.label",
|
|
30
|
+
description: "Clear button label for filter multi-select",
|
|
31
|
+
values: {
|
|
32
|
+
VisuallyHidden: function (children) {
|
|
33
|
+
return /*#__PURE__*/React.createElement(VisuallyHidden, null, children);
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
}));
|
|
27
37
|
};
|
|
28
38
|
ClearButton.displayName = 'FilterMultiSelect.ClearButton';
|
|
29
39
|
return ClearButton;
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { __spreadArray } from 'tslib';
|
|
2
2
|
import React from 'react';
|
|
3
|
+
import { useIntl } from '@cultureamp/i18n-react-intl';
|
|
3
4
|
import classnames from 'classnames';
|
|
4
5
|
import '../../../context/MenuTriggerProvider/MenuTriggerProvider.mjs';
|
|
5
6
|
import { useSelectionContext } from '../../../context/SelectionProvider/SelectionProvider.mjs';
|
|
@@ -12,6 +13,7 @@ const SelectAllButton = /*#__PURE__*/function () {
|
|
|
12
13
|
var filteredOptions = Array.from(selectionState.collection.getKeys()).filter(function (key) {
|
|
13
14
|
return !disabledOptions.includes(key);
|
|
14
15
|
});
|
|
16
|
+
var formatMessage = useIntl().formatMessage;
|
|
15
17
|
return /*#__PURE__*/React.createElement("button", {
|
|
16
18
|
type: "button",
|
|
17
19
|
className: classnames(styles.button, selectionState.selectionManager.isSelectAll && styles.isDisabled),
|
|
@@ -19,7 +21,11 @@ const SelectAllButton = /*#__PURE__*/function () {
|
|
|
19
21
|
onClick: function () {
|
|
20
22
|
return !selectionState.selectionManager.isSelectAll && selectionState.selectionManager.setSelectedKeys(__spreadArray(__spreadArray([], selectedOptions, true), filteredOptions, true));
|
|
21
23
|
}
|
|
22
|
-
},
|
|
24
|
+
}, formatMessage({
|
|
25
|
+
defaultMessage: 'Select all',
|
|
26
|
+
id: 'filterMultiSelectSelectAllButton.label',
|
|
27
|
+
description: 'Select all button in filter multi select'
|
|
28
|
+
}));
|
|
23
29
|
};
|
|
24
30
|
SelectAllButton.displayName = 'FilterMultiSelect.SelectAllButton';
|
|
25
31
|
return SelectAllButton;
|
|
@@ -79,7 +79,8 @@ const TimeFieldComponent = /*#__PURE__*/function () {
|
|
|
79
79
|
return /*#__PURE__*/React.createElement(TimeSegment, {
|
|
80
80
|
key: i,
|
|
81
81
|
segment: segment,
|
|
82
|
-
state: state
|
|
82
|
+
state: state,
|
|
83
|
+
hasPadding: ![8294, 8297].includes(segment.text.charCodeAt(0))
|
|
83
84
|
});
|
|
84
85
|
}), /*#__PURE__*/React.createElement("div", {
|
|
85
86
|
className: styles.focusRing
|
|
@@ -7,7 +7,9 @@ import styles from './TimeSegment.module.scss.mjs';
|
|
|
7
7
|
const TimeSegment = /*#__PURE__*/function () {
|
|
8
8
|
const TimeSegment = function (_a) {
|
|
9
9
|
var segment = _a.segment,
|
|
10
|
-
state = _a.state
|
|
10
|
+
state = _a.state,
|
|
11
|
+
_b = _a.hasPadding,
|
|
12
|
+
hasPadding = _b === void 0 ? true : _b;
|
|
11
13
|
var ref = React.useRef(null);
|
|
12
14
|
var segmentProps = useDateSegment(segment, state, ref).segmentProps;
|
|
13
15
|
// Chrome has a bug where `contenteditable` elements receive focus from external clicks.
|
|
@@ -18,7 +20,7 @@ const TimeSegment = /*#__PURE__*/function () {
|
|
|
18
20
|
className: styles.timeSegmentWrapper
|
|
19
21
|
}, "\u200B", /*#__PURE__*/React.createElement("span", __assign({}, segmentProps, {
|
|
20
22
|
ref: ref,
|
|
21
|
-
className: classnames(styles.timeSegment, segment.type === 'literal' && styles.literal, segment.isPlaceholder && styles.placeholder, segment.type === 'dayPeriod' && styles.dayPeriod)
|
|
23
|
+
className: classnames(styles.timeSegment, segment.type === 'literal' && styles.literal, segment.isPlaceholder && styles.placeholder, segment.type === 'dayPeriod' && styles.dayPeriod, hasPadding && styles.hasPadding)
|
|
22
24
|
}), generateSegmentDisplayText(segment)), "\u200B");
|
|
23
25
|
};
|
|
24
26
|
TimeSegment.displayName = 'TimeSegment';
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
var styles = {
|
|
2
2
|
"timeSegmentWrapper": "TimeSegment-module_timeSegmentWrapper__WYD6y",
|
|
3
3
|
"timeSegment": "TimeSegment-module_timeSegment__eXb0c",
|
|
4
|
+
"hasPadding": "TimeSegment-module_hasPadding__9oYW3",
|
|
4
5
|
"placeholder": "TimeSegment-module_placeholder__j1-gK",
|
|
5
6
|
"literal": "TimeSegment-module_literal__mOkqz",
|
|
6
7
|
"dayPeriod": "TimeSegment-module_dayPeriod__fzT5I"
|
package/dist/styles.css
CHANGED
|
@@ -10408,7 +10408,6 @@ input[type=range].InputRange-module_ratingScaleRange__gI-rs::-ms-thumb:not(:disa
|
|
|
10408
10408
|
|
|
10409
10409
|
.TimeSegment-module_timeSegment__eXb0c {
|
|
10410
10410
|
display: block;
|
|
10411
|
-
padding: 0 4px;
|
|
10412
10411
|
text-align: end;
|
|
10413
10412
|
background-color: var(--color-gray-300, #eaeaec);
|
|
10414
10413
|
border-radius: 3px;
|
|
@@ -10423,6 +10422,10 @@ input[type=range].InputRange-module_ratingScaleRange__gI-rs::-ms-thumb:not(:disa
|
|
|
10423
10422
|
outline: none;
|
|
10424
10423
|
}
|
|
10425
10424
|
|
|
10425
|
+
.TimeSegment-module_hasPadding__9oYW3 {
|
|
10426
|
+
padding: 0 4px;
|
|
10427
|
+
}
|
|
10428
|
+
|
|
10426
10429
|
.TimeSegment-module_placeholder__j1-gK {
|
|
10427
10430
|
color: rgba(var(--color-purple-800-rgb, 47, 36, 56), 0.7);
|
|
10428
10431
|
}
|
|
@@ -1,7 +1,6 @@
|
|
|
1
|
-
import { type HTMLAttributes } from 'react';
|
|
1
|
+
import { type HTMLAttributes, type PropsWithChildren } from 'react';
|
|
2
2
|
import { type OverrideClassName } from "../types/OverrideClassName";
|
|
3
|
-
type BadgeCommonProps = {
|
|
4
|
-
children?: string;
|
|
3
|
+
type BadgeCommonProps = PropsWithChildren<{
|
|
5
4
|
/**
|
|
6
5
|
* The "dark" variant is no longer in the UI kit
|
|
7
6
|
*/
|
|
@@ -14,7 +13,7 @@ type BadgeCommonProps = {
|
|
|
14
13
|
* Supports "small" and "large" sizes - defaults to "small"
|
|
15
14
|
*/
|
|
16
15
|
size?: 'small' | 'large';
|
|
17
|
-
} & OverrideClassName<HTMLAttributes<HTMLSpanElement>>;
|
|
16
|
+
}> & OverrideClassName<HTMLAttributes<HTMLSpanElement>>;
|
|
18
17
|
type DotProps = Omit<BadgeCommonProps, 'variant'> & {
|
|
19
18
|
children?: never;
|
|
20
19
|
variant: 'dot';
|
|
@@ -2,8 +2,9 @@ import { type DateFieldState, type DateSegment } from '@react-stately/datepicker
|
|
|
2
2
|
export type TimeSegmentProps = {
|
|
3
3
|
segment: DateSegment;
|
|
4
4
|
state: DateFieldState;
|
|
5
|
+
hasPadding?: boolean;
|
|
5
6
|
};
|
|
6
7
|
export declare const TimeSegment: {
|
|
7
|
-
({ segment, state }: TimeSegmentProps): JSX.Element;
|
|
8
|
+
({ segment, state, hasPadding, }: TimeSegmentProps): JSX.Element;
|
|
8
9
|
displayName: string;
|
|
9
10
|
};
|
package/locales/en.json
CHANGED
|
@@ -62,6 +62,14 @@
|
|
|
62
62
|
"description": "Label for the 'date to' field",
|
|
63
63
|
"message": "Date to"
|
|
64
64
|
},
|
|
65
|
+
"filterMultiSelectClearButton.label": {
|
|
66
|
+
"description": "Clear button label for filter multi-select",
|
|
67
|
+
"message": "Clear<VisuallyHidden> selections</VisuallyHidden>"
|
|
68
|
+
},
|
|
69
|
+
"filterMultiSelectMultiSelectOption.available": {
|
|
70
|
+
"description": "Number of filter items available",
|
|
71
|
+
"message": "<Badge>{count}</Badge><VisuallyHidden> available</VisuallyHidden>"
|
|
72
|
+
},
|
|
65
73
|
"filterMultiSelectSearchInput.label": {
|
|
66
74
|
"description": "Label for the search input",
|
|
67
75
|
"message": "Filter options by search query"
|
|
@@ -70,6 +78,10 @@
|
|
|
70
78
|
"description": "Placeholder for the search input",
|
|
71
79
|
"message": "Search…"
|
|
72
80
|
},
|
|
81
|
+
"filterMultiSelectSelectAllButton.label": {
|
|
82
|
+
"description": "Select all button in filter multi select",
|
|
83
|
+
"message": "Select all"
|
|
84
|
+
},
|
|
73
85
|
"inputSearch.clear": {
|
|
74
86
|
"description": "Label for the clear search button",
|
|
75
87
|
"message": "Clear search"
|
package/package.json
CHANGED
package/src/Badge/Badge.tsx
CHANGED
|
@@ -1,10 +1,14 @@
|
|
|
1
|
-
import React, {
|
|
1
|
+
import React, {
|
|
2
|
+
useLayoutEffect,
|
|
3
|
+
useState,
|
|
4
|
+
type HTMLAttributes,
|
|
5
|
+
type PropsWithChildren,
|
|
6
|
+
} from 'react'
|
|
2
7
|
import classnames from 'classnames'
|
|
3
8
|
import { type OverrideClassName } from '~components/types/OverrideClassName'
|
|
4
9
|
import styles from './Badge.module.css'
|
|
5
10
|
|
|
6
|
-
type BadgeCommonProps = {
|
|
7
|
-
children?: string
|
|
11
|
+
type BadgeCommonProps = PropsWithChildren<{
|
|
8
12
|
/**
|
|
9
13
|
* The "dark" variant is no longer in the UI kit
|
|
10
14
|
*/
|
|
@@ -17,7 +21,8 @@ type BadgeCommonProps = {
|
|
|
17
21
|
* Supports "small" and "large" sizes - defaults to "small"
|
|
18
22
|
*/
|
|
19
23
|
size?: 'small' | 'large'
|
|
20
|
-
} &
|
|
24
|
+
}> &
|
|
25
|
+
OverrideClassName<HTMLAttributes<HTMLSpanElement>>
|
|
21
26
|
|
|
22
27
|
type DotProps = Omit<BadgeCommonProps, 'variant'> & {
|
|
23
28
|
children?: never
|
package/src/Filter/FilterMultiSelect/subcomponents/MultiSelectOption/MultiSelectOption.spec.tsx
CHANGED
|
@@ -82,20 +82,20 @@ describe('<MultiSelectOptionWrapper /> - Visual content', () => {
|
|
|
82
82
|
<MultiSelectOptionWrapper
|
|
83
83
|
item={{
|
|
84
84
|
...itemMock,
|
|
85
|
-
value: { ...itemMock.value, count: '
|
|
85
|
+
value: { ...itemMock.value, count: '14' },
|
|
86
86
|
}}
|
|
87
87
|
/>,
|
|
88
88
|
)
|
|
89
89
|
})
|
|
90
90
|
|
|
91
91
|
it('shows the count in the badge', () => {
|
|
92
|
-
const badge = screen.getByText('
|
|
92
|
+
const badge = screen.getByText('14')
|
|
93
93
|
expect(badge).toBeInTheDocument()
|
|
94
94
|
})
|
|
95
95
|
|
|
96
96
|
it('has aria-description to describe the count are available for this option', () => {
|
|
97
97
|
const option = screen.getByLabelText('label-mock')
|
|
98
|
-
expect(option).toHaveAccessibleDescription('
|
|
98
|
+
expect(option).toHaveAccessibleDescription('14 available')
|
|
99
99
|
})
|
|
100
100
|
})
|
|
101
101
|
})
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import React, { useId } from 'react'
|
|
2
|
+
import { FormattedMessage, useIntl } from '@cultureamp/i18n-react-intl'
|
|
2
3
|
import { useFocusRing } from '@react-aria/focus'
|
|
3
4
|
import { useOption } from '@react-aria/listbox'
|
|
4
5
|
import { mergeProps } from '@react-aria/utils'
|
|
@@ -28,6 +29,7 @@ export const MultiSelectOption = ({
|
|
|
28
29
|
// focus ring for accessibility
|
|
29
30
|
const { isFocusVisible, focusProps } = useFocusRing()
|
|
30
31
|
const countElementId = useId()
|
|
32
|
+
const { formatNumber } = useIntl()
|
|
31
33
|
|
|
32
34
|
return (
|
|
33
35
|
<li
|
|
@@ -50,8 +52,20 @@ export const MultiSelectOption = ({
|
|
|
50
52
|
{item.rendered}
|
|
51
53
|
{item.value?.count && (
|
|
52
54
|
<span id={countElementId} className={styles.badgeContainer}>
|
|
53
|
-
<
|
|
54
|
-
|
|
55
|
+
<FormattedMessage
|
|
56
|
+
defaultMessage="<Badge>{count}</Badge><VisuallyHidden> available</VisuallyHidden>"
|
|
57
|
+
id="filterMultiSelectMultiSelectOption.available"
|
|
58
|
+
description="Number of filter items available"
|
|
59
|
+
values={{
|
|
60
|
+
count: formatNumber(parseInt(item.value.count)),
|
|
61
|
+
Badge: (children: React.ReactNode) => (
|
|
62
|
+
<Badge classNameOverride={styles.badge}>{children}</Badge>
|
|
63
|
+
),
|
|
64
|
+
VisuallyHidden: (children: React.ReactNode) => (
|
|
65
|
+
<VisuallyHidden>{children}</VisuallyHidden>
|
|
66
|
+
),
|
|
67
|
+
}}
|
|
68
|
+
/>
|
|
55
69
|
</span>
|
|
56
70
|
)}
|
|
57
71
|
</li>
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import React from 'react'
|
|
2
|
+
import { FormattedMessage } from '@cultureamp/i18n-react-intl'
|
|
2
3
|
import classnames from 'classnames'
|
|
3
4
|
import { VisuallyHidden } from '~components/VisuallyHidden'
|
|
4
5
|
import { useSelectionContext } from '../../../context'
|
|
@@ -28,7 +29,16 @@ export const ClearButton = (): JSX.Element => {
|
|
|
28
29
|
// TODO: add announcement here to inform selection cleared
|
|
29
30
|
}
|
|
30
31
|
>
|
|
31
|
-
|
|
32
|
+
<FormattedMessage
|
|
33
|
+
defaultMessage="Clear<VisuallyHidden> selections</VisuallyHidden>"
|
|
34
|
+
id="filterMultiSelectClearButton.label"
|
|
35
|
+
description="Clear button label for filter multi-select"
|
|
36
|
+
values={{
|
|
37
|
+
VisuallyHidden: (children: React.ReactNode) => (
|
|
38
|
+
<VisuallyHidden>{children}</VisuallyHidden>
|
|
39
|
+
),
|
|
40
|
+
}}
|
|
41
|
+
/>
|
|
32
42
|
</button>
|
|
33
43
|
)
|
|
34
44
|
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import React from 'react'
|
|
2
|
+
import { useIntl } from '@cultureamp/i18n-react-intl'
|
|
2
3
|
import classnames from 'classnames'
|
|
3
4
|
import { useSelectionContext } from '../../../context'
|
|
4
5
|
import styles from '../SelectionControlButton.module.scss'
|
|
@@ -11,6 +12,8 @@ export const SelectAllButton = (): JSX.Element => {
|
|
|
11
12
|
(key) => !disabledOptions.includes(key),
|
|
12
13
|
)
|
|
13
14
|
|
|
15
|
+
const { formatMessage } = useIntl()
|
|
16
|
+
|
|
14
17
|
return (
|
|
15
18
|
<button
|
|
16
19
|
type="button"
|
|
@@ -26,7 +29,11 @@ export const SelectAllButton = (): JSX.Element => {
|
|
|
26
29
|
// TODO: add announcement here to inform all selected
|
|
27
30
|
}
|
|
28
31
|
>
|
|
29
|
-
|
|
32
|
+
{formatMessage({
|
|
33
|
+
defaultMessage: 'Select all',
|
|
34
|
+
id: 'filterMultiSelectSelectAllButton.label',
|
|
35
|
+
description: 'Select all button in filter multi select',
|
|
36
|
+
})}
|
|
30
37
|
</button>
|
|
31
38
|
)
|
|
32
39
|
}
|
|
@@ -108,9 +108,17 @@ const TimeFieldComponent = ({
|
|
|
108
108
|
state.validationState === 'invalid' && styles.error,
|
|
109
109
|
)}
|
|
110
110
|
>
|
|
111
|
-
{state.segments.map((segment, i) =>
|
|
112
|
-
|
|
113
|
-
|
|
111
|
+
{state.segments.map((segment, i) => {
|
|
112
|
+
return (
|
|
113
|
+
<TimeSegment
|
|
114
|
+
key={i}
|
|
115
|
+
segment={segment}
|
|
116
|
+
state={state}
|
|
117
|
+
hasPadding={![8294, 8297].includes(segment.text.charCodeAt(0))}
|
|
118
|
+
// ^react-aria includes these characters to ensure correct RTL behaviour, but we want to avoid these adding random spacing
|
|
119
|
+
/>
|
|
120
|
+
)
|
|
121
|
+
})}
|
|
114
122
|
<div className={styles.focusRing} />
|
|
115
123
|
</div>
|
|
116
124
|
</div>
|
|
@@ -10,7 +10,6 @@
|
|
|
10
10
|
|
|
11
11
|
.timeSegment {
|
|
12
12
|
display: block;
|
|
13
|
-
padding: 0 4px;
|
|
14
13
|
text-align: end;
|
|
15
14
|
background-color: $color-gray-300;
|
|
16
15
|
border-radius: 3px;
|
|
@@ -27,6 +26,10 @@
|
|
|
27
26
|
}
|
|
28
27
|
}
|
|
29
28
|
|
|
29
|
+
.hasPadding {
|
|
30
|
+
padding: 0 4px;
|
|
31
|
+
}
|
|
32
|
+
|
|
30
33
|
.placeholder {
|
|
31
34
|
color: rgba($color-purple-800-rgb, 0.7);
|
|
32
35
|
}
|
|
@@ -8,9 +8,14 @@ import styles from './TimeSegment.module.scss'
|
|
|
8
8
|
export type TimeSegmentProps = {
|
|
9
9
|
segment: DateSegment
|
|
10
10
|
state: DateFieldState
|
|
11
|
+
hasPadding?: boolean
|
|
11
12
|
}
|
|
12
13
|
|
|
13
|
-
export const TimeSegment = ({
|
|
14
|
+
export const TimeSegment = ({
|
|
15
|
+
segment,
|
|
16
|
+
state,
|
|
17
|
+
hasPadding = true,
|
|
18
|
+
}: TimeSegmentProps): JSX.Element => {
|
|
14
19
|
const ref = React.useRef<HTMLDivElement>(null)
|
|
15
20
|
const { segmentProps } = useDateSegment(segment, state, ref)
|
|
16
21
|
|
|
@@ -29,6 +34,7 @@ export const TimeSegment = ({ segment, state }: TimeSegmentProps): JSX.Element =
|
|
|
29
34
|
segment.type === 'literal' && styles.literal,
|
|
30
35
|
segment.isPlaceholder && styles.placeholder,
|
|
31
36
|
segment.type === 'dayPeriod' && styles.dayPeriod,
|
|
37
|
+
hasPadding && styles.hasPadding,
|
|
32
38
|
)}
|
|
33
39
|
>
|
|
34
40
|
{generateSegmentDisplayText(segment)}
|
|
@@ -62,8 +62,11 @@ export const OnButton: Story = {
|
|
|
62
62
|
|
|
63
63
|
await step('Escape closes', async () => {
|
|
64
64
|
await userEvent.tab() // focus
|
|
65
|
+
await waitFor(() => expect(canvas.getByRole('tooltip')).toBeVisible())
|
|
65
66
|
await userEvent.keyboard('{Escape}')
|
|
66
|
-
await waitFor(() => expect(canvas.queryByRole('tooltip')).toBeNull()
|
|
67
|
+
await waitFor(() => expect(canvas.queryByRole('tooltip')).toBeNull(), {
|
|
68
|
+
timeout: 5000,
|
|
69
|
+
})
|
|
67
70
|
await userEvent.tab() // unfocus
|
|
68
71
|
})
|
|
69
72
|
},
|