superdesk-ui-framework 3.1.12 → 3.1.13
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/app/styles/_helpers.scss +17 -0
- package/app/styles/_toggle-box.scss +45 -28
- package/app/styles/form-elements/_inputs.scss +14 -0
- package/app/styles/grids/_grid-layout.scss +3 -0
- package/app-typescript/components/DatePicker.tsx +6 -0
- package/app-typescript/components/Layouts/LayoutContainer.tsx +7 -1
- package/app-typescript/components/Layouts/PageLayout.tsx +2 -1
- package/app-typescript/components/TimePickerV2.tsx +222 -0
- package/app-typescript/components/ToggleBox/CustomHeaderToggleBox.tsx +6 -1
- package/app-typescript/components/ToggleBox/SimpleToggleBox.tsx +10 -20
- package/app-typescript/components/ToggleBox/index.tsx +3 -1
- package/app-typescript/components/TreeMenu.tsx +8 -5
- package/app-typescript/components/TreeSelect/TreeSelect.tsx +13 -12
- package/app-typescript/components/TreeSelect/TreeSelectItem.tsx +11 -1
- package/app-typescript/index.ts +1 -0
- package/dist/components/TimePicker.tsx +43 -1
- package/dist/components/Togglebox.tsx +19 -4
- package/dist/components/TreeMenu.tsx +2 -0
- package/dist/components/utilities/TextUtilities.tsx +39 -0
- package/dist/design-patterns/ThreePaneLayoutPattern.tsx +1 -1
- package/dist/examples.bundle.js +2184 -1924
- package/dist/superdesk-ui.bundle.css +72 -20
- package/dist/superdesk-ui.bundle.js +1815 -1604
- package/dist/vendor.bundle.js +16 -16
- package/examples/pages/components/TimePicker.tsx +43 -1
- package/examples/pages/components/Togglebox.tsx +19 -4
- package/examples/pages/components/TreeMenu.tsx +2 -0
- package/examples/pages/components/utilities/TextUtilities.tsx +39 -0
- package/examples/pages/design-patterns/ThreePaneLayoutPattern.tsx +1 -1
- package/package.json +1 -1
- package/react/components/DatePicker.d.ts +3 -0
- package/react/components/DatePicker.js +2 -2
- package/react/components/Layouts/LayoutContainer.d.ts +1 -0
- package/react/components/Layouts/LayoutContainer.js +8 -1
- package/react/components/Layouts/PageLayout.d.ts +1 -0
- package/react/components/Layouts/PageLayout.js +1 -1
- package/react/components/TimePickerV2.d.ts +28 -0
- package/react/components/TimePickerV2.js +189 -0
- package/react/components/ToggleBox/CustomHeaderToggleBox.d.ts +1 -0
- package/react/components/ToggleBox/CustomHeaderToggleBox.js +6 -3
- package/react/components/ToggleBox/SimpleToggleBox.js +8 -6
- package/react/components/ToggleBox/index.d.ts +2 -1
- package/react/components/TreeMenu.js +7 -7
- package/react/components/TreeSelect/TreeSelect.js +9 -11
- package/react/components/TreeSelect/TreeSelectItem.d.ts +1 -0
- package/react/components/TreeSelect/TreeSelectItem.js +7 -4
- package/react/index.d.ts +1 -0
- package/react/index.js +5 -3
package/app/styles/_helpers.scss
CHANGED
@@ -1721,6 +1721,23 @@ h6 {
|
|
1721
1721
|
word-break: break-all;
|
1722
1722
|
}
|
1723
1723
|
|
1724
|
+
// LINE HIGHT
|
1725
|
+
.line-height-1 {
|
1726
|
+
line-height: 1;
|
1727
|
+
}
|
1728
|
+
.line-height-xs {
|
1729
|
+
line-height: 1.1;
|
1730
|
+
}
|
1731
|
+
.line-height-sm {
|
1732
|
+
line-height: 1.2;
|
1733
|
+
}
|
1734
|
+
.line-height-md {
|
1735
|
+
line-height: 1.4;
|
1736
|
+
}
|
1737
|
+
.line-height-lg {
|
1738
|
+
line-height: 1.5;
|
1739
|
+
}
|
1740
|
+
|
1724
1741
|
// LINE CLAMP
|
1725
1742
|
// limit the number of horizontal lines in an elemnt (e.g. <p>)
|
1726
1743
|
// it doesn't work if the element has set flex-grow: 1;
|
@@ -2,30 +2,31 @@
|
|
2
2
|
|
3
3
|
.toggle-box {
|
4
4
|
position: relative;
|
5
|
-
|
6
|
-
|
5
|
+
display: grid;
|
6
|
+
grid-template-columns: 1fr;
|
7
|
+
grid-template-rows: auto 1fr auto;
|
8
|
+
transition: grid-template-rows 0.2s ease;
|
7
9
|
&.hidden {
|
10
|
+
grid-template-rows: auto 0fr auto;
|
11
|
+
transition: grid-template-rows 0.2s ease;
|
8
12
|
.toggle-box__chevron {
|
9
13
|
i {
|
10
14
|
transform: rotate(0);
|
11
15
|
}
|
12
16
|
}
|
13
|
-
|
14
17
|
.toggle-box__chevron--circle {
|
15
18
|
background-color: var(--sd-colour-btn-bg-neutral);
|
16
|
-
|
17
19
|
i {
|
18
20
|
color: var(--color-text-light);
|
19
21
|
}
|
20
22
|
}
|
21
|
-
|
22
23
|
.toggle-box__content-wraper {
|
23
|
-
max-height: 0;
|
24
24
|
transition: all ease-out .5s;
|
25
25
|
}
|
26
|
-
|
27
|
-
|
28
|
-
|
26
|
+
}
|
27
|
+
&.open {
|
28
|
+
.toggle-box__content {
|
29
|
+
animation: fadeIn 0.3s ease-in 0s 1;
|
29
30
|
}
|
30
31
|
}
|
31
32
|
|
@@ -39,23 +40,35 @@
|
|
39
40
|
}
|
40
41
|
}
|
41
42
|
}
|
43
|
+
&.toggle-box--large-title {
|
44
|
+
.toggle-box__header,
|
45
|
+
a.toggle-box__header {
|
46
|
+
.toggle-box__label {
|
47
|
+
font-size: var(--text-size-medium);
|
48
|
+
color: var(--color-text);
|
49
|
+
text-transform: none;
|
50
|
+
font-weight: 500;
|
51
|
+
}
|
52
|
+
&:hover {
|
53
|
+
.toggle-box__label {
|
54
|
+
color: var(--sd-colour-interactive);
|
55
|
+
}
|
56
|
+
}
|
57
|
+
}
|
58
|
+
}
|
42
59
|
|
43
60
|
&.toggle-box--marg-b10 {
|
44
61
|
margin-block-end: 1rem;
|
45
62
|
}
|
46
|
-
|
47
63
|
&.toggle-box--margin-none {
|
48
64
|
margin-block-end: 0;
|
49
65
|
}
|
50
|
-
|
51
66
|
&.toggle-box--margin-small {
|
52
67
|
margin-block-end: $sd-base-increment * 2;
|
53
68
|
}
|
54
|
-
|
55
69
|
&.toggle-box--margin-normal {
|
56
70
|
margin-block-end: $sd-base-increment * 3;
|
57
71
|
}
|
58
|
-
|
59
72
|
&.toggle-box--margin-large {
|
60
73
|
margin-block-end: $sd-base-increment * 4;
|
61
74
|
}
|
@@ -73,12 +86,12 @@
|
|
73
86
|
|
74
87
|
.toggle-box__header,
|
75
88
|
a.toggle-box__header {
|
89
|
+
grid-row: 1 / 2;
|
76
90
|
display: flex;
|
77
91
|
cursor: pointer;
|
78
|
-
margin-block-end: 1.8rem;
|
79
92
|
align-items: center;
|
80
93
|
text-decoration: none !important;
|
81
|
-
|
94
|
+
align-self: flex-start;
|
82
95
|
.toggle-box__chevron {
|
83
96
|
i {
|
84
97
|
transition: all .3s;
|
@@ -87,10 +100,11 @@ a.toggle-box__header {
|
|
87
100
|
}
|
88
101
|
|
89
102
|
.toggle-box__label {
|
90
|
-
font-size:
|
91
|
-
padding: 0
|
92
|
-
color: var(--color-
|
103
|
+
font-size: var(--text-size-x-small);
|
104
|
+
padding: 0 var(--space--2) 0 var(--space--1);
|
105
|
+
color: var(--color-text-light);
|
93
106
|
text-transform: uppercase;
|
107
|
+
transition: color 0.2s ease;
|
94
108
|
}
|
95
109
|
|
96
110
|
.toggle-box__line {
|
@@ -101,7 +115,8 @@ a.toggle-box__header {
|
|
101
115
|
}
|
102
116
|
|
103
117
|
&:hover {
|
104
|
-
.toggle-box__label
|
118
|
+
.toggle-box__label,
|
119
|
+
{
|
105
120
|
color: var(--sd-colour-interactive);
|
106
121
|
text-decoration: none !important;
|
107
122
|
}
|
@@ -115,7 +130,6 @@ a.toggle-box__header {
|
|
115
130
|
.toggle-box__chevron {
|
116
131
|
box-shadow: 0 0 0 3px $sd-colour--focus-shadow;
|
117
132
|
}
|
118
|
-
|
119
133
|
.toggle-box__label {
|
120
134
|
color: var(--sd-colour-interactive);
|
121
135
|
}
|
@@ -127,30 +141,33 @@ a.toggle-box__header {
|
|
127
141
|
}
|
128
142
|
|
129
143
|
.toggle-box__content-wraper {
|
130
|
-
|
144
|
+
grid-row: 2 / 3;
|
145
|
+
transition: grid-template-rows 0.2s ease;
|
146
|
+
display: flex;
|
147
|
+
flex-direction: column;
|
148
|
+
justify-content: flex-start;
|
149
|
+
align-items: stretch;
|
150
|
+
overflow: hidden;
|
131
151
|
}
|
132
152
|
|
133
|
-
.toggle-box__content {
|
134
|
-
|
153
|
+
.toggle-box__content {
|
154
|
+
overflow-y: auto;
|
155
|
+
padding-block-start: 1.8rem;
|
156
|
+
flex:1;
|
135
157
|
}
|
136
158
|
|
137
159
|
// Buttons
|
138
160
|
.toggle-box__button {
|
139
161
|
color: $grayLight;
|
140
162
|
cursor: pointer;
|
141
|
-
|
142
163
|
i {
|
143
164
|
color: $grayLight;
|
144
165
|
margin-inline-end: 0.5rem;
|
145
166
|
vertical-align: text-bottom;
|
146
167
|
}
|
147
|
-
|
148
168
|
&:hover {
|
149
169
|
text-decoration: none;
|
150
170
|
color: $white;
|
151
171
|
i { color: $white; }
|
152
172
|
}
|
153
173
|
}
|
154
|
-
|
155
|
-
|
156
|
-
|
@@ -1365,3 +1365,17 @@
|
|
1365
1365
|
opacity: 0;
|
1366
1366
|
}
|
1367
1367
|
}
|
1368
|
+
|
1369
|
+
.sd__input__time-picker-v2 {
|
1370
|
+
display: flex;
|
1371
|
+
}
|
1372
|
+
|
1373
|
+
.input-wrapper__time-picker-v2 {
|
1374
|
+
display: flex;
|
1375
|
+
align-items: center;
|
1376
|
+
}
|
1377
|
+
|
1378
|
+
.time-picker-v2-suffix {
|
1379
|
+
padding: 0 8px;
|
1380
|
+
font-size: 1.6rem;
|
1381
|
+
}
|
@@ -700,6 +700,9 @@ $planningEditor-width: 53rem;
|
|
700
700
|
grid-template-columns: [slideInLeft] auto [mainContent] 1fr [slideInRight] auto [overlayContainer] 0;
|
701
701
|
grid-template-rows: [headerToolbar] auto [contentBlock] 1fr;
|
702
702
|
overflow: auto;
|
703
|
+
&.sd-main-content-grid--full-height {
|
704
|
+
height: 100%;
|
705
|
+
}
|
703
706
|
}
|
704
707
|
|
705
708
|
.sd-main-content-grid__header {
|
@@ -37,6 +37,9 @@ interface IDatePickerBase extends IInputWrapper {
|
|
37
37
|
interface IDatePicker extends IDatePickerBase {
|
38
38
|
value: Date | null;
|
39
39
|
onChange(valueNext: Date | null): void;
|
40
|
+
maxDate?: Date;
|
41
|
+
minDate?: Date;
|
42
|
+
showButtonBar?: boolean;
|
40
43
|
'data-test-id'?: string;
|
41
44
|
}
|
42
45
|
|
@@ -157,6 +160,7 @@ export class DatePicker extends React.PureComponent<IDatePicker, IState> {
|
|
157
160
|
tabindex={this.props.tabindex}
|
158
161
|
>
|
159
162
|
<Calendar
|
163
|
+
showButtonBar={this.props.showButtonBar}
|
160
164
|
inputId={this.htmlId}
|
161
165
|
ariaLabelledBy={this.htmlId + 'label'}
|
162
166
|
ref={(ref) => {
|
@@ -208,6 +212,8 @@ export class DatePicker extends React.PureComponent<IDatePicker, IState> {
|
|
208
212
|
)}
|
209
213
|
appendTo={document.body} // making it work inside `overflow:hidden`
|
210
214
|
disabled={this.props.disabled}
|
215
|
+
minDate={this.props.minDate}
|
216
|
+
maxDate={this.props.maxDate}
|
211
217
|
onBlur={(event) => {
|
212
218
|
// @ts-ignore: Object is possibly 'null'.
|
213
219
|
if (!event?.target.value) {
|
@@ -1,13 +1,19 @@
|
|
1
1
|
import * as React from 'react';
|
2
|
+
import classNames from 'classnames';
|
2
3
|
|
3
4
|
interface IProps {
|
4
5
|
children?: React.ReactNode;
|
6
|
+
fullHeight?: boolean;
|
5
7
|
}
|
6
8
|
|
7
9
|
export class LayoutContainer extends React.PureComponent<IProps> {
|
8
10
|
render() {
|
11
|
+
const classes = classNames('sd-content-wrapper__main-content-area sd-main-content-grid comfort', {
|
12
|
+
'sd-main-content-grid--full-height': this.props.fullHeight,
|
13
|
+
},
|
14
|
+
);
|
9
15
|
return (
|
10
|
-
<div className=
|
16
|
+
<div className={classes}>
|
11
17
|
{this.props.children}
|
12
18
|
</div>
|
13
19
|
);
|
@@ -19,12 +19,13 @@ interface IProps {
|
|
19
19
|
rightPanelOpen?: boolean;
|
20
20
|
leftPanel?: React.ReactNode;
|
21
21
|
leftPanelOpen?: boolean;
|
22
|
+
fullHeight?: boolean; // For cases where the parent container is not display: grid;
|
22
23
|
}
|
23
24
|
|
24
25
|
export class PageLayout extends React.PureComponent<IProps> {
|
25
26
|
render() {
|
26
27
|
return (
|
27
|
-
<LayoutContainer>
|
28
|
+
<LayoutContainer fullHeight={this.props.fullHeight}>
|
28
29
|
{this.props.header && (
|
29
30
|
<HeaderPanel>
|
30
31
|
{this.props.header}
|
@@ -0,0 +1,222 @@
|
|
1
|
+
import * as React from 'react';
|
2
|
+
import { InputWrapper } from './Form';
|
3
|
+
import {IInputWrapper} from './Form/InputWrapper';
|
4
|
+
import {padStart, range} from 'lodash';
|
5
|
+
|
6
|
+
interface IProps extends IInputWrapper {
|
7
|
+
value: string; // ISO 8601, 13:59:01
|
8
|
+
allowSeconds?: boolean;
|
9
|
+
disabledOptions: {
|
10
|
+
hours?: Array<number>;
|
11
|
+
minutes?: Array<number>;
|
12
|
+
seconds?: Array<number>;
|
13
|
+
};
|
14
|
+
'data-test-id'?: string;
|
15
|
+
onChange(valueNext: string): void;
|
16
|
+
}
|
17
|
+
|
18
|
+
type ITimeUnit = 'hours' | 'minutes' | 'seconds';
|
19
|
+
|
20
|
+
export class TimePickerV2 extends React.PureComponent<IProps> {
|
21
|
+
private is12HourFormat: boolean;
|
22
|
+
|
23
|
+
constructor(props: IProps) {
|
24
|
+
super(props);
|
25
|
+
|
26
|
+
this.handleTimeChange = this.handleTimeChange.bind(this);
|
27
|
+
this.getCorrectedTime = this.getCorrectedTime.bind(this);
|
28
|
+
this.getOptionsForTimeUnit = this.getOptionsForTimeUnit.bind(this);
|
29
|
+
this.padValue = this.padValue.bind(this);
|
30
|
+
|
31
|
+
const hour = new Date().toLocaleTimeString([], { hour: 'numeric' });
|
32
|
+
this.is12HourFormat = hour.includes('AM') || hour.includes('PM');
|
33
|
+
}
|
34
|
+
|
35
|
+
/**
|
36
|
+
* in case initial time is not valid according to disabled options, we return first valid option
|
37
|
+
*/
|
38
|
+
private getCorrectedTime(timeUnit: ITimeUnit, timeStringArray: Array<string>): string {
|
39
|
+
const dividedValue = this.props.value.split(':');
|
40
|
+
const value = (() => {
|
41
|
+
if (timeUnit === 'hours') {
|
42
|
+
return dividedValue[0];
|
43
|
+
} else if (timeUnit === 'minutes') {
|
44
|
+
return dividedValue[1];
|
45
|
+
}
|
46
|
+
|
47
|
+
return dividedValue[2];
|
48
|
+
})();
|
49
|
+
|
50
|
+
if (!(this.props.disabledOptions[timeUnit] ?? []).includes(parseInt(value, 10)) && value != null) {
|
51
|
+
return value;
|
52
|
+
}
|
53
|
+
|
54
|
+
return timeStringArray[0];
|
55
|
+
}
|
56
|
+
|
57
|
+
private getOptionsForTimeUnit(timeUnit: ITimeUnit): Array<string> {
|
58
|
+
let format12HourArr = range(1, 13);
|
59
|
+
format12HourArr.unshift(format12HourArr.pop() as number);
|
60
|
+
|
61
|
+
const timeUnitArray = (() => {
|
62
|
+
if (timeUnit === 'hours') {
|
63
|
+
if (this.is12HourFormat) {
|
64
|
+
return format12HourArr;
|
65
|
+
} else {
|
66
|
+
return range(24);
|
67
|
+
}
|
68
|
+
} else {
|
69
|
+
return range(60);
|
70
|
+
}
|
71
|
+
})();
|
72
|
+
|
73
|
+
return timeUnitArray
|
74
|
+
.filter((item) => !(this.props.disabledOptions[timeUnit] ?? []).includes(item))
|
75
|
+
.map((value) => padStart(value.toString(), 2, '0'));
|
76
|
+
}
|
77
|
+
|
78
|
+
private handleTimeChange(index: number, newValue: string) {
|
79
|
+
let current = this.props.value.split(':');
|
80
|
+
|
81
|
+
const updated12HourValue = (() => {
|
82
|
+
if (parseInt(current[0], 10) >= 12) {
|
83
|
+
if (newValue === '12') {
|
84
|
+
return newValue;
|
85
|
+
} else {
|
86
|
+
return (parseInt(newValue, 10) + 12).toString();
|
87
|
+
}
|
88
|
+
} else {
|
89
|
+
if (newValue === '12') {
|
90
|
+
return '00';
|
91
|
+
} else {
|
92
|
+
return newValue;
|
93
|
+
}
|
94
|
+
}
|
95
|
+
})();
|
96
|
+
|
97
|
+
current[index] = this.is12HourFormat ? updated12HourValue : newValue;
|
98
|
+
|
99
|
+
this.props.onChange(current.join(':'));
|
100
|
+
}
|
101
|
+
|
102
|
+
componentDidMount(): void {
|
103
|
+
const correctedTime = [
|
104
|
+
this.getCorrectedTime('hours', this.getOptionsForTimeUnit('hours')),
|
105
|
+
':',
|
106
|
+
this.getCorrectedTime('minutes', this.getOptionsForTimeUnit('minutes')),
|
107
|
+
this.props.allowSeconds
|
108
|
+
? `:${this.getCorrectedTime('seconds', this.getOptionsForTimeUnit('seconds'))}`
|
109
|
+
: '',
|
110
|
+
].join('');
|
111
|
+
|
112
|
+
if (this.props.value !== correctedTime) {
|
113
|
+
this.props.onChange(correctedTime);
|
114
|
+
}
|
115
|
+
}
|
116
|
+
|
117
|
+
padValue(value: number) {
|
118
|
+
return padStart((value).toString(), 2, '0');
|
119
|
+
}
|
120
|
+
|
121
|
+
updatedTimeUnit() {
|
122
|
+
const timeUnitValuesArray = this.props.value.split(':');
|
123
|
+
|
124
|
+
/**
|
125
|
+
* updating the initial value from props
|
126
|
+
*/
|
127
|
+
if (this.is12HourFormat) {
|
128
|
+
if (parseInt(timeUnitValuesArray[0], 10) > 12) {
|
129
|
+
timeUnitValuesArray[0] = this.padValue(parseInt(timeUnitValuesArray[0], 10) - 12);
|
130
|
+
}
|
131
|
+
}
|
132
|
+
|
133
|
+
return timeUnitValuesArray;
|
134
|
+
}
|
135
|
+
|
136
|
+
render() {
|
137
|
+
const timeUnitValuesArray = this.updatedTimeUnit();
|
138
|
+
|
139
|
+
return (
|
140
|
+
<InputWrapper
|
141
|
+
label={this.props.label}
|
142
|
+
error={this.props.error}
|
143
|
+
invalid={this.props.error != null}
|
144
|
+
required={this.props.required}
|
145
|
+
disabled={this.props.disabled}
|
146
|
+
info={this.props.info}
|
147
|
+
inlineLabel={this.props.inlineLabel}
|
148
|
+
labelHidden={this.props.labelHidden}
|
149
|
+
tabindex={this.props.tabindex}
|
150
|
+
>
|
151
|
+
<div className='sd__input__time-picker-v2' data-test-id={this.props['data-test-id']}>
|
152
|
+
<div className='input-wrapper__time-picker-v2'>
|
153
|
+
<select
|
154
|
+
className='sd-input__select'
|
155
|
+
value={timeUnitValuesArray[0]}
|
156
|
+
onChange={({target}) => {
|
157
|
+
this.handleTimeChange(0, target.value);
|
158
|
+
}}
|
159
|
+
>
|
160
|
+
{this.getOptionsForTimeUnit('hours').map((hour) => (
|
161
|
+
<option value={hour} label={hour} key={hour} />
|
162
|
+
))}
|
163
|
+
</select>
|
164
|
+
<span className='time-picker-v2-suffix'>:</span>
|
165
|
+
</div>
|
166
|
+
<div className='input-wrapper__time-picker-v2'>
|
167
|
+
<select
|
168
|
+
className='sd-input__select'
|
169
|
+
value={timeUnitValuesArray[1]}
|
170
|
+
onChange={({target}) => {
|
171
|
+
this.handleTimeChange(1, target.value);
|
172
|
+
}}
|
173
|
+
>
|
174
|
+
{this.getOptionsForTimeUnit('minutes').map((minute) => (
|
175
|
+
<option value={minute} label={minute} key={minute} />
|
176
|
+
))}
|
177
|
+
</select>
|
178
|
+
{this.props.allowSeconds && (<span className='time-picker-v2-suffix'>:</span>)}
|
179
|
+
</div>
|
180
|
+
{this.props.allowSeconds && (
|
181
|
+
<div className='input-wrapper__time-picker-v2'>
|
182
|
+
<select
|
183
|
+
className='sd-input__select'
|
184
|
+
value={timeUnitValuesArray[2]}
|
185
|
+
onChange={({target}) => {
|
186
|
+
this.handleTimeChange(2, target.value);
|
187
|
+
}}
|
188
|
+
>
|
189
|
+
{this.getOptionsForTimeUnit('seconds').map((second) => (
|
190
|
+
<option value={second} label={second} key={second} />
|
191
|
+
))}
|
192
|
+
</select>
|
193
|
+
</div>
|
194
|
+
)}
|
195
|
+
{this.is12HourFormat && (
|
196
|
+
<div className='input-wrapper__time-picker-v2'>
|
197
|
+
<span className='time-picker-v2-suffix' />
|
198
|
+
<select
|
199
|
+
className='sd-input__select'
|
200
|
+
value={(parseInt(this.props.value.split(':')[0], 10) >= 12) ? 'PM' : 'AM'}
|
201
|
+
onChange={({target}) => {
|
202
|
+
let splitValue = this.props.value.split(':');
|
203
|
+
|
204
|
+
if (target.value === 'PM') {
|
205
|
+
splitValue[0] = this.padValue(parseInt(splitValue[0], 10) + 12);
|
206
|
+
} else {
|
207
|
+
splitValue[0] = this.padValue(parseInt(splitValue[0], 10) - 12);
|
208
|
+
}
|
209
|
+
|
210
|
+
this.props.onChange(splitValue.join(':'));
|
211
|
+
}}
|
212
|
+
>
|
213
|
+
<option value='AM' label='AM' />
|
214
|
+
<option value='PM' label='PM' />
|
215
|
+
</select>
|
216
|
+
</div>
|
217
|
+
)}
|
218
|
+
</div>
|
219
|
+
</InputWrapper>
|
220
|
+
);
|
221
|
+
}
|
222
|
+
}
|
@@ -1,5 +1,6 @@
|
|
1
1
|
import * as React from 'react';
|
2
2
|
import classNames from 'classnames';
|
3
|
+
import nextId from "react-id-generator";
|
3
4
|
import {IPropsCustomHeader} from "../ToggleBox/index";
|
4
5
|
|
5
6
|
interface IState {
|
@@ -7,6 +8,7 @@ interface IState {
|
|
7
8
|
}
|
8
9
|
|
9
10
|
export class CustomHeaderToggleBox extends React.PureComponent<IPropsCustomHeader, IState> {
|
11
|
+
htmlId = nextId('togglebox-');
|
10
12
|
constructor(props: IPropsCustomHeader) {
|
11
13
|
super(props);
|
12
14
|
this.state = {
|
@@ -24,10 +26,12 @@ export class CustomHeaderToggleBox extends React.PureComponent<IPropsCustomHeade
|
|
24
26
|
let classes = classNames('sd-shadow--z1 new-collapse-box', {
|
25
27
|
'new-collapse-box--open': this.state.isOpen,
|
26
28
|
});
|
29
|
+
const { isOpen } = this.state;
|
27
30
|
|
28
31
|
return (
|
29
32
|
<div
|
30
33
|
className={classes}
|
34
|
+
aria-expanded={isOpen}
|
31
35
|
data-test-id='toggle-box'
|
32
36
|
>
|
33
37
|
<div className='new-collapse-box__header'>
|
@@ -38,6 +42,7 @@ export class CustomHeaderToggleBox extends React.PureComponent<IPropsCustomHeade
|
|
38
42
|
<button
|
39
43
|
className='new-collapse-box__divider'
|
40
44
|
onClick={this.toggle}
|
45
|
+
aria-controls={this.htmlId}
|
41
46
|
>
|
42
47
|
<span className='label label--translucent new-collapse-box__divider-label'>
|
43
48
|
{this.props.toggleButtonLabel}
|
@@ -46,7 +51,7 @@ export class CustomHeaderToggleBox extends React.PureComponent<IPropsCustomHeade
|
|
46
51
|
</div>
|
47
52
|
|
48
53
|
<div className='new-collapse-box__content'>
|
49
|
-
<div className='new-collapse-box__content-inner p-2 pt-0-5'>
|
54
|
+
<div id={this.htmlId} aria-hidden={!isOpen} className='new-collapse-box__content-inner p-2 pt-0-5'>
|
50
55
|
{this.props.children}
|
51
56
|
</div>
|
52
57
|
</div>
|
@@ -14,7 +14,7 @@ interface IState {
|
|
14
14
|
*/
|
15
15
|
|
16
16
|
export class SimpleToggleBox extends React.PureComponent<IPropsSimple, IState> {
|
17
|
-
htmlId = nextId();
|
17
|
+
htmlId = nextId('togglebox-');
|
18
18
|
constructor(props: IPropsSimple) {
|
19
19
|
super(props);
|
20
20
|
this.state = {
|
@@ -45,10 +45,13 @@ export class SimpleToggleBox extends React.PureComponent<IPropsSimple, IState> {
|
|
45
45
|
render() {
|
46
46
|
let classes = classNames('toggle-box', {
|
47
47
|
'toggle-box--margin-normal': this.props.margin === undefined,
|
48
|
+
'toggle-box--large-title': this.props.largeTitle,
|
49
|
+
'toggle-box--circle': this.props.circledChevron,
|
48
50
|
[`toggle-box--margin-${this.props.margin}`]: this.props.margin,
|
49
51
|
'hidden': !this.state.isOpen,
|
52
|
+
'open': this.state.isOpen,
|
50
53
|
}, this.props.className);
|
51
|
-
const { title,
|
54
|
+
const { title, children, badge } = this.props;
|
52
55
|
const { isOpen } = this.state;
|
53
56
|
|
54
57
|
return (
|
@@ -61,7 +64,8 @@ export class SimpleToggleBox extends React.PureComponent<IPropsSimple, IState> {
|
|
61
64
|
role="button"
|
62
65
|
tabIndex={0}
|
63
66
|
onKeyDown={this.handleKeyDown}
|
64
|
-
|
67
|
+
aria-expanded={isOpen}
|
68
|
+
aria-controls={this.htmlId}
|
65
69
|
>
|
66
70
|
<div className="toggle-box__chevron">
|
67
71
|
<i className="icon-chevron-right-thin" />
|
@@ -75,23 +79,9 @@ export class SimpleToggleBox extends React.PureComponent<IPropsSimple, IState> {
|
|
75
79
|
{badge ? badge : null}
|
76
80
|
</a>
|
77
81
|
<div className="toggle-box__content-wraper">
|
78
|
-
{
|
79
|
-
|
80
|
-
|
81
|
-
</div>
|
82
|
-
)}
|
83
|
-
|
84
|
-
{hideUsingCSS && (
|
85
|
-
<div
|
86
|
-
className={classNames(
|
87
|
-
'toggle-box__content',
|
88
|
-
{ 'toggle-box__content--hidden': !isOpen },
|
89
|
-
)}
|
90
|
-
aria-describedby={`togglebox-${this.htmlId}`}
|
91
|
-
>
|
92
|
-
{children}
|
93
|
-
</div>
|
94
|
-
)}
|
82
|
+
<div id={this.htmlId} className="toggle-box__content" aria-hidden={!isOpen}>
|
83
|
+
{children}
|
84
|
+
</div>
|
95
85
|
</div>
|
96
86
|
</div>
|
97
87
|
);
|
@@ -7,8 +7,10 @@ export interface IPropsSimple {
|
|
7
7
|
title: string;
|
8
8
|
badge?: JSX.Element;
|
9
9
|
children: React.ReactNode;
|
10
|
-
|
10
|
+
circledChevron?: boolean;
|
11
11
|
initiallyOpen?: boolean; // defaults to false
|
12
|
+
largeTitle?: boolean;
|
13
|
+
|
12
14
|
className?: string;
|
13
15
|
margin?: 'none' | 'small' | 'normal' | 'large';
|
14
16
|
onOpen?(): void;
|
@@ -285,11 +285,9 @@ export class TreeMenu<T> extends React.Component<IProps<T>, IState<T>> {
|
|
285
285
|
|
286
286
|
const item = this.state.buttonTree.pop();
|
287
287
|
|
288
|
-
|
289
|
-
|
290
|
-
|
291
|
-
});
|
292
|
-
}
|
288
|
+
this.setState({
|
289
|
+
buttonValue: item ?? null,
|
290
|
+
});
|
293
291
|
}
|
294
292
|
|
295
293
|
recursion(arr: Array<ITreeMenuNode<T>>) {
|
@@ -414,6 +412,7 @@ export class TreeMenu<T> extends React.Component<IProps<T>, IState<T>> {
|
|
414
412
|
<ul
|
415
413
|
ref={this.ref}
|
416
414
|
className="suggestion-list suggestion-list--multi-select"
|
415
|
+
role='tree'
|
417
416
|
>
|
418
417
|
{this.state.options.map((option, i: React.Key | undefined) => (
|
419
418
|
<TreeSelectItem
|
@@ -425,6 +424,10 @@ export class TreeMenu<T> extends React.Component<IProps<T>, IState<T>> {
|
|
425
424
|
}}
|
426
425
|
disabledItem={disabledItem(option)}
|
427
426
|
getBorderColor={this.props.getBorderColor}
|
427
|
+
parentCategory={this.state.buttonValue == null
|
428
|
+
? undefined
|
429
|
+
: this.props.getLabel(this.state.buttonValue.value)
|
430
|
+
}
|
428
431
|
getBackgroundColor={this.props.getBackgroundColor}
|
429
432
|
getId={this.props.getId}
|
430
433
|
optionTemplate={this.props.optionTemplate}
|