superdesk-ui-framework 2.4.19 → 2.4.20
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/_accessibility.scss +7 -3
- package/app/styles/_buttons.scss +52 -1
- package/app/styles/_spinner.scss +46 -0
- package/app-typescript/components/Button.tsx +7 -1
- package/app-typescript/components/Input.tsx +14 -4
- package/app-typescript/components/Spinner.tsx +33 -0
- package/app-typescript/components/TabCustom.tsx +89 -40
- package/app-typescript/components/TabList.tsx +43 -18
- package/app-typescript/index.ts +1 -1
- package/dist/examples.bundle.css +36 -1
- package/dist/examples.bundle.js +865 -625
- package/dist/react/Buttons.tsx +25 -0
- package/dist/react/Inputs.tsx +6 -3
- package/dist/react/Tabs.tsx +225 -72
- package/dist/superdesk-ui.bundle.css +74 -13
- package/dist/superdesk-ui.bundle.js +544 -396
- package/dist/vendor.bundle.js +13 -13
- package/examples/pages/react/Buttons.tsx +25 -0
- package/examples/pages/react/Inputs.tsx +6 -3
- package/examples/pages/react/Tabs.tsx +225 -72
- package/package.json +2 -2
- package/react/components/Button.d.ts +2 -0
- package/react/components/Button.js +4 -2
- package/react/components/Input.d.ts +2 -0
- package/react/components/Input.js +13 -4
- package/react/components/Spinner.d.ts +12 -0
- package/react/components/Spinner.js +70 -0
- package/react/components/TabCustom.d.ts +22 -12
- package/react/components/TabCustom.js +52 -23
- package/react/components/TabList.d.ts +11 -2
- package/react/components/TabList.js +32 -11
- package/react/index.d.ts +1 -1
- package/react/index.js +2 -2
@@ -3,8 +3,12 @@
|
|
3
3
|
top: 0;
|
4
4
|
z-index: -1;
|
5
5
|
pointer-events: none;
|
6
|
-
opacity: 0;
|
7
|
-
height:
|
8
|
-
width:
|
6
|
+
opacity: 0 !important;
|
7
|
+
height: 0;
|
8
|
+
width: 0;
|
9
|
+
min-width: 0;
|
9
10
|
overflow: hidden;
|
11
|
+
font-size: 0.01px !important;
|
12
|
+
padding: 0 !important;
|
13
|
+
margin: 0 !important;
|
10
14
|
}
|
package/app/styles/_buttons.scss
CHANGED
@@ -53,7 +53,7 @@ $button-sizes: (
|
|
53
53
|
|
54
54
|
/// opacity for a disabled button.
|
55
55
|
/// @type List
|
56
|
-
$button-opacity-disabled: 0.
|
56
|
+
$button-opacity-disabled: 0.6 !default;
|
57
57
|
|
58
58
|
/// Background color lightness on hover for buttons.
|
59
59
|
/// @type Number
|
@@ -99,6 +99,7 @@ $icn-button-focus-box-shadow: 0 0 0 2px rgba(94, 169, 200, 0.30);
|
|
99
99
|
text-align: center;
|
100
100
|
text-decoration: none;
|
101
101
|
cursor: pointer;
|
102
|
+
gap: 0.6rem;
|
102
103
|
}
|
103
104
|
|
104
105
|
/// Expands a button to make it full-width.
|
@@ -477,6 +478,19 @@ $icn-button-focus-box-shadow: 0 0 0 2px rgba(94, 169, 200, 0.30);
|
|
477
478
|
}
|
478
479
|
}
|
479
480
|
}
|
481
|
+
|
482
|
+
&.btn--primary,
|
483
|
+
&.btn--success,
|
484
|
+
&.btn--warning,
|
485
|
+
&.btn--alert,
|
486
|
+
&.btn--highlight,
|
487
|
+
&.btn--sd-green,
|
488
|
+
&.btn--secondary {
|
489
|
+
color: var(--sd-btn-txt);
|
490
|
+
.sd-spinner__path {
|
491
|
+
stroke: var(--sd-btn-txt);
|
492
|
+
}
|
493
|
+
}
|
480
494
|
}
|
481
495
|
|
482
496
|
// Hollow UI dark
|
@@ -489,6 +503,19 @@ $icn-button-focus-box-shadow: 0 0 0 2px rgba(94, 169, 200, 0.30);
|
|
489
503
|
@include button-hollow-style($color);
|
490
504
|
}
|
491
505
|
}
|
506
|
+
|
507
|
+
&.btn--primary,
|
508
|
+
&.btn--success,
|
509
|
+
&.btn--warning,
|
510
|
+
&.btn--alert,
|
511
|
+
&.btn--highlight,
|
512
|
+
&.btn--sd-green,
|
513
|
+
&.btn--secondary {
|
514
|
+
color: var(--sd-btn-color);
|
515
|
+
.sd-spinner__path {
|
516
|
+
stroke: var(--sd-btn-color);
|
517
|
+
}
|
518
|
+
}
|
492
519
|
|
493
520
|
// Hollow disabled UI dark
|
494
521
|
&.btn--disabled,
|
@@ -582,6 +609,16 @@ $icn-button-focus-box-shadow: 0 0 0 2px rgba(94, 169, 200, 0.30);
|
|
582
609
|
}
|
583
610
|
}
|
584
611
|
}
|
612
|
+
|
613
|
+
&--primary, &--success, &--warning, &--alert, &--highlight, &--sd-green, &--secondary {
|
614
|
+
color: $white;
|
615
|
+
[class^="icon-"], [class*=" icon-"] {
|
616
|
+
color: $white;
|
617
|
+
}
|
618
|
+
.sd-spinner__path {
|
619
|
+
stroke: $white;
|
620
|
+
}
|
621
|
+
}
|
585
622
|
}
|
586
623
|
|
587
624
|
// SD create button
|
@@ -1123,3 +1160,17 @@ $button-nav-color: currentColor;
|
|
1123
1160
|
position: absolute;
|
1124
1161
|
width: 1px;
|
1125
1162
|
}
|
1163
|
+
|
1164
|
+
.btn {
|
1165
|
+
&[data-loading="true"] {
|
1166
|
+
pointer-events: none;
|
1167
|
+
.sd-spinner {
|
1168
|
+
margin-inline-start: -0.3rem;
|
1169
|
+
}
|
1170
|
+
&.btn--icon-only {
|
1171
|
+
.sd-spinner {
|
1172
|
+
margin-inline-start: 0;
|
1173
|
+
}
|
1174
|
+
}
|
1175
|
+
}
|
1176
|
+
}
|
@@ -0,0 +1,46 @@
|
|
1
|
+
.sd-spinner {
|
2
|
+
animation: rotate 2s linear infinite;
|
3
|
+
z-index: 1;
|
4
|
+
&--mini {
|
5
|
+
width: 1.8rem;
|
6
|
+
height: 1.8rem;
|
7
|
+
}
|
8
|
+
&--small {
|
9
|
+
width: 2.4rem;
|
10
|
+
height: 2.4rem;
|
11
|
+
}
|
12
|
+
&--medium {
|
13
|
+
width: 3.2rem;
|
14
|
+
height: 3.2rem;
|
15
|
+
}
|
16
|
+
&--large {
|
17
|
+
width: 4.8rem;
|
18
|
+
height: 4.8rem;
|
19
|
+
}
|
20
|
+
}
|
21
|
+
.sd-spinner__path {
|
22
|
+
stroke: var(--color-text-light);
|
23
|
+
stroke-linecap: round;
|
24
|
+
animation: dash 1.5s ease-in-out infinite;
|
25
|
+
}
|
26
|
+
|
27
|
+
@keyframes rotate {
|
28
|
+
100% {
|
29
|
+
transform: rotate(360deg);
|
30
|
+
}
|
31
|
+
}
|
32
|
+
|
33
|
+
@keyframes dash {
|
34
|
+
0% {
|
35
|
+
stroke-dasharray: 1, 150;
|
36
|
+
stroke-dashoffset: 0;
|
37
|
+
}
|
38
|
+
50% {
|
39
|
+
stroke-dasharray: 90, 150;
|
40
|
+
stroke-dashoffset: -32;
|
41
|
+
}
|
42
|
+
100% {
|
43
|
+
stroke-dasharray: 90, 150;
|
44
|
+
stroke-dashoffset: -124;
|
45
|
+
}
|
46
|
+
}
|
@@ -1,6 +1,7 @@
|
|
1
1
|
import * as React from 'react';
|
2
2
|
import classNames from 'classnames';
|
3
3
|
import { Icon } from './Icon';
|
4
|
+
import { Spinner } from './Spinner';
|
4
5
|
|
5
6
|
interface IButtonBase {
|
6
7
|
id?: string;
|
@@ -20,6 +21,8 @@ interface IPropsButton extends IButtonBase {
|
|
20
21
|
expand?: boolean;
|
21
22
|
style?: 'filled' | 'hollow' | 'text-only'; // defaults to 'filled'
|
22
23
|
shape?: 'square' | 'round'; // defaults to 'square'
|
24
|
+
isLoading?: boolean;
|
25
|
+
loadingLabel?: string;
|
23
26
|
}
|
24
27
|
|
25
28
|
export class Button extends React.PureComponent<IPropsButton> {
|
@@ -40,10 +43,13 @@ export class Button extends React.PureComponent<IPropsButton> {
|
|
40
43
|
id={this.props.id}
|
41
44
|
className={classes}
|
42
45
|
tabIndex={0}
|
46
|
+
disabled={this.props.isLoading}
|
47
|
+
data-loading={this.props.isLoading}
|
43
48
|
onClick={this.props.disabled ? () => false : (event) => this.props.onClick(event)}
|
44
49
|
aria-label={this.props.iconOnly ? this.props.text : ''}
|
45
50
|
data-test-id={this.props['data-test-id']}>
|
46
|
-
{this.props.
|
51
|
+
{this.props.isLoading ? <Spinner size="mini" /> : null}
|
52
|
+
{this.props.icon && !this.props.isLoading ? <Icon name={this.props.icon} /> : null}
|
47
53
|
{this.props.iconOnly ? null : this.props.text}
|
48
54
|
</button>
|
49
55
|
);
|
@@ -35,15 +35,25 @@ export class Input extends React.Component<IProps, IState> {
|
|
35
35
|
|
36
36
|
htmlId = nextId();
|
37
37
|
|
38
|
-
|
39
|
-
this.setState({ value:
|
40
|
-
this.props.onChange(
|
38
|
+
handleData(value: string) {
|
39
|
+
this.setState({ value: value ?? '' });
|
40
|
+
this.props.onChange(value ?? '');
|
41
41
|
|
42
42
|
if (this.props.maxLength && !this.props.invalid) {
|
43
|
-
this.setState({ invalid:
|
43
|
+
this.setState({ invalid: value.length > this.props.maxLength });
|
44
44
|
}
|
45
45
|
}
|
46
46
|
|
47
|
+
handleChange(event: React.ChangeEvent<HTMLInputElement>) {
|
48
|
+
this.handleData(event.target.value);
|
49
|
+
}
|
50
|
+
|
51
|
+
componentDidUpdate(prevProps: IProps) {
|
52
|
+
if (this.props.value !== prevProps.value) {
|
53
|
+
this.handleData(this.props.value ?? '');
|
54
|
+
}
|
55
|
+
}
|
56
|
+
|
47
57
|
render() {
|
48
58
|
const classes = classNames('sd-input', {
|
49
59
|
'sd-input--inline-label': this.props.inlineLabel,
|
@@ -0,0 +1,33 @@
|
|
1
|
+
import * as React from 'react';
|
2
|
+
import classNames from 'classnames';
|
3
|
+
import './../../app/styles/_spinner.scss';
|
4
|
+
|
5
|
+
class LoadingOverlay extends React.PureComponent {
|
6
|
+
render() {
|
7
|
+
return (
|
8
|
+
<div className="sd-loading-overlay--plain">
|
9
|
+
{this.props.children}
|
10
|
+
</div>
|
11
|
+
);
|
12
|
+
}
|
13
|
+
}
|
14
|
+
|
15
|
+
interface IProps {
|
16
|
+
size?: 'mini' | 'small' | 'medium' | 'large'; // defaults to 'small'
|
17
|
+
}
|
18
|
+
|
19
|
+
class Spinner extends React.PureComponent<IProps> {
|
20
|
+
render() {
|
21
|
+
let classes = classNames('sd-spinner', {
|
22
|
+
'sd-spinner--small': this.props.size === undefined,
|
23
|
+
[`sd-spinner--${this.props.size}`]: this.props.size || this.props.size !== undefined,
|
24
|
+
});
|
25
|
+
return (
|
26
|
+
<svg role="progressbar" className={classes} viewBox="0 0 50 50">
|
27
|
+
<circle className="sd-spinner__path" cx="25" cy="25" r="20" fill="none" stroke-width="5"></circle>
|
28
|
+
</svg>
|
29
|
+
);
|
30
|
+
}
|
31
|
+
}
|
32
|
+
|
33
|
+
export { Spinner, LoadingOverlay };
|
@@ -1,84 +1,133 @@
|
|
1
1
|
import * as React from 'react';
|
2
2
|
import classNames from 'classnames';
|
3
|
+
|
3
4
|
interface ITabs {
|
4
5
|
size?: 'normal' | 'large' | 'small'; // defaults to 'normal'
|
5
6
|
theme?: 'light' | 'dark'; // defaults to 'light'
|
6
7
|
ariaLabel?: string;
|
7
8
|
children: Array<any>;
|
8
|
-
onClick(
|
9
|
+
onClick(id: string): void;
|
10
|
+
tabs?: Array<{label: string, id: string}>;
|
11
|
+
activePanel: string;
|
9
12
|
}
|
10
13
|
|
11
14
|
interface ITabLabel {
|
12
|
-
label
|
13
|
-
|
15
|
+
label?: string;
|
16
|
+
id: string;
|
17
|
+
children: Array<any>;
|
14
18
|
}
|
15
19
|
|
16
20
|
interface ITabContent {
|
17
21
|
theme?: 'light' | 'dark'; // defaults to 'light'
|
18
|
-
children: any
|
19
|
-
activePanel:
|
22
|
+
children: Array<any>;
|
23
|
+
activePanel: string;
|
24
|
+
tabs?: Array<{content: React.ReactNode | string, id: string}>;
|
20
25
|
}
|
21
26
|
|
22
27
|
interface ITabPanel {
|
23
|
-
|
24
|
-
children: any
|
28
|
+
id: string;
|
29
|
+
children: Array<any>;
|
25
30
|
}
|
26
31
|
|
27
|
-
export const
|
28
|
-
return (
|
29
|
-
<span>{label}</span>
|
30
|
-
);
|
31
|
-
};
|
32
|
-
|
33
|
-
export const Tabs = ({ size, theme, ariaLabel, children, onClick }: ITabs) => {
|
32
|
+
export const TabNav = ({ size, theme, ariaLabel, children, onClick, tabs, activePanel }: ITabs) => {
|
34
33
|
const [index, setIndex] = React.useState(0);
|
35
34
|
|
36
|
-
function
|
37
|
-
|
38
|
-
|
35
|
+
function goTo(id: string) {
|
36
|
+
if (tabs) {
|
37
|
+
const refLabel = tabs?.find((item) => item.id === id);
|
38
|
+
|
39
|
+
if (refLabel) {
|
40
|
+
setIndex(tabs.indexOf(refLabel));
|
41
|
+
}
|
42
|
+
} else {
|
43
|
+
const refLabel = children.find((item) => item.props.id === id);
|
44
|
+
setIndex(children.indexOf(refLabel));
|
45
|
+
}
|
39
46
|
}
|
40
47
|
|
41
|
-
|
42
|
-
|
43
|
-
};
|
48
|
+
React.useEffect(() => {
|
49
|
+
goTo(activePanel ? activePanel : (tabs ? tabs[0].id : children[0].props.id));
|
50
|
+
}, []);
|
51
|
+
|
52
|
+
function handleSelected(id: string) {
|
53
|
+
goTo(id);
|
54
|
+
onClick(id);
|
55
|
+
}
|
44
56
|
|
45
57
|
let classes = classNames('sd-nav-tabs', {
|
46
58
|
[`sd-nav-tabs--${size}`]: size && size !== undefined,
|
47
59
|
'sd-nav-tabs--ui-dark': theme === 'dark',
|
48
60
|
});
|
49
|
-
|
61
|
+
return (
|
50
62
|
<div className={classes} role='tablist' aria-label={ariaLabel ? ariaLabel : 'tabs'}>
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
63
|
+
{tabs ?
|
64
|
+
tabs.map((item, i) =>
|
65
|
+
<button
|
66
|
+
id={`tab-${item.id}`}
|
67
|
+
key={i}
|
68
|
+
aria-controls={'tabpanel-' + item.id}
|
69
|
+
className={'sd-nav-tabs__tab' + (index === i ? ' sd-nav-tabs__tab--active' : '')}
|
70
|
+
onClick={() => handleSelected(item.id)}
|
71
|
+
role='tab'
|
72
|
+
aria-selected={index === i ? 'true' : 'false'} >
|
73
|
+
{item.label}
|
74
|
+
</button>)
|
75
|
+
:
|
76
|
+
children.map((item, i) =>
|
77
|
+
<button
|
78
|
+
id={`tab-${item.props.id}`}
|
79
|
+
key={i}
|
80
|
+
aria-controls={'tabpanel-' + item.props.id}
|
81
|
+
className={'sd-nav-tabs__tab' + (index === i ? ' sd-nav-tabs__tab--active' : '')}
|
82
|
+
onClick={() => handleSelected(item.props.id)}
|
83
|
+
role='tab'
|
84
|
+
aria-selected={index === i ? 'true' : 'false'} >
|
85
|
+
{item}
|
86
|
+
</button>)
|
87
|
+
}
|
62
88
|
</div>
|
63
89
|
);
|
64
90
|
};
|
65
91
|
|
66
|
-
export const TabContent = ({ theme, children, activePanel }: ITabContent) => {
|
92
|
+
export const TabContent = ({ theme, children, activePanel, tabs }: ITabContent) => {
|
93
|
+
if (!activePanel && tabs) {
|
94
|
+
activePanel = tabs[0].id;
|
95
|
+
} else if (!activePanel && children) {
|
96
|
+
activePanel = children[0].props.id;
|
97
|
+
}
|
98
|
+
|
67
99
|
return (
|
68
100
|
<div className={'sd-nav-tabs__content' +
|
69
101
|
(theme === 'dark' ? ' sd-nav-tabs__content--ui-dark' : '')}>
|
70
|
-
|
71
|
-
panel
|
72
|
-
|
73
|
-
{panel}
|
74
|
-
|
102
|
+
{tabs ?
|
103
|
+
tabs.map((panel: any, i: number) =>
|
104
|
+
panel.id === activePanel ?
|
105
|
+
<div className='sd-nav-tabs__pane' role='tabpanel' aria-labelledby={`tab-${panel.id}`} key={i}>
|
106
|
+
{panel.content}
|
107
|
+
</div> : null)
|
108
|
+
:
|
109
|
+
children.map((panel: any, i: number) =>
|
110
|
+
panel.props.id === activePanel ?
|
111
|
+
<div className='sd-nav-tabs__pane'
|
112
|
+
role='tabpanel'
|
113
|
+
aria-labelledby={`tab-${panel.props.id}`}
|
114
|
+
key={i}>
|
115
|
+
{panel}
|
116
|
+
</div> : null)
|
117
|
+
}
|
75
118
|
</div>
|
76
119
|
);
|
77
120
|
};
|
78
121
|
|
79
|
-
export const
|
122
|
+
export const TabItem = ({ children }: ITabLabel) => {
|
123
|
+
return (
|
124
|
+
<span>{children}</span>
|
125
|
+
);
|
126
|
+
};
|
127
|
+
|
128
|
+
export const TabPanel = ({ children, id }: ITabPanel) => {
|
80
129
|
return (
|
81
|
-
<React.Fragment key={
|
130
|
+
<React.Fragment key={id}>
|
82
131
|
{children}
|
83
132
|
</React.Fragment>
|
84
133
|
);
|
@@ -5,6 +5,8 @@ interface ITabList {
|
|
5
5
|
size?: 'normal' | 'large' | 'small'; // defaults to 'normal'
|
6
6
|
theme?: 'light' | 'dark'; // defaults to 'light'
|
7
7
|
children: Array<any>;
|
8
|
+
selected?: string;
|
9
|
+
tabs?: Array<{label: string, content: React.ReactNode | string, id?: string}>;
|
8
10
|
}
|
9
11
|
|
10
12
|
interface IState {
|
@@ -12,7 +14,8 @@ interface IState {
|
|
12
14
|
}
|
13
15
|
|
14
16
|
interface ITab {
|
15
|
-
|
17
|
+
id?: string;
|
18
|
+
label?: string;
|
16
19
|
}
|
17
20
|
|
18
21
|
class Tab extends React.PureComponent<ITab> {
|
@@ -35,17 +38,45 @@ class TabList extends React.PureComponent<ITabList, IState> {
|
|
35
38
|
this.goTo = this.goTo.bind(this);
|
36
39
|
}
|
37
40
|
|
41
|
+
componentDidMount() {
|
42
|
+
if (this.props.selected) {
|
43
|
+
this.goTo(this.props.selected ?? '');
|
44
|
+
}
|
45
|
+
}
|
46
|
+
|
38
47
|
private handleChange(index: number) {
|
39
48
|
this.setState({
|
40
49
|
index: index,
|
41
50
|
});
|
42
51
|
}
|
43
52
|
|
44
|
-
public goTo(
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
53
|
+
public goTo(index: string) {
|
54
|
+
if (this.props.tabs) {
|
55
|
+
const refLabel = this.props.tabs?.find((item) => item.id === index);
|
56
|
+
this.setState({
|
57
|
+
index: refLabel ? this.props.tabs?.indexOf(refLabel) : 0,
|
58
|
+
});
|
59
|
+
} else {
|
60
|
+
const refLabel = this.props.children.find((item) => item.props.id === index);
|
61
|
+
this.setState({
|
62
|
+
index: this.props.children.indexOf(refLabel),
|
63
|
+
});
|
64
|
+
}
|
65
|
+
}
|
66
|
+
|
67
|
+
private navBar(arr: any) {
|
68
|
+
return arr.map((item: any, index: any) => {
|
69
|
+
let label = this.props.tabs ? item.label : item.props.label;
|
70
|
+
return <button
|
71
|
+
id={`TabList-${index}`}
|
72
|
+
key={index}
|
73
|
+
onClick={() => this.handleChange(index)}
|
74
|
+
role='tab'
|
75
|
+
aria-selected={this.state.index === index ? 'true' : 'false'}
|
76
|
+
className={'sd-nav-tabs__tab' + (this.state.index === index ? ' sd-nav-tabs__tab--active' : '')}>
|
77
|
+
<span>{label}</span>
|
78
|
+
</button>;
|
79
|
+
});
|
49
80
|
}
|
50
81
|
|
51
82
|
render() {
|
@@ -53,23 +84,17 @@ class TabList extends React.PureComponent<ITabList, IState> {
|
|
53
84
|
[`sd-nav-tabs--${this.props.size}`]: this.props.size && this.props.size !== undefined,
|
54
85
|
'sd-nav-tabs--ui-dark': this.props.theme === 'dark',
|
55
86
|
});
|
56
|
-
|
57
87
|
return (
|
58
88
|
<React.Fragment>
|
59
89
|
<div className={classes} role='tablist'>
|
60
|
-
{this.props.
|
61
|
-
<button
|
62
|
-
key={index}
|
63
|
-
onClick={() => this.handleChange(index)}
|
64
|
-
role='tab'
|
65
|
-
aria-selected={this.state.index === index ? 'true' : 'false'}
|
66
|
-
className={'sd-nav-tabs__tab' + (this.state.index === index ? ' sd-nav-tabs__tab--active' : '')}>
|
67
|
-
<span>{item.props.label}</span>
|
68
|
-
</button>)}
|
90
|
+
{this.props.tabs ? this.navBar(this.props.tabs) : this.navBar(this.props.children)}
|
69
91
|
</div>
|
70
|
-
<div
|
92
|
+
<div aria-labelledby={`TabList-${this.state.index}`}
|
93
|
+
role='tabpanel' className={'sd-nav-tabs__content' +
|
71
94
|
(this.props.theme === 'dark' ? ' sd-nav-tabs__content--ui-dark' : '')}>
|
72
|
-
{this.props.
|
95
|
+
{this.props.tabs
|
96
|
+
? <Tab id={this.props.tabs[this.state.index].id}>{this.props.tabs[this.state.index].content}</Tab>
|
97
|
+
: this.props.children[this.state.index]}
|
73
98
|
</div>
|
74
99
|
</React.Fragment>
|
75
100
|
);
|
package/app-typescript/index.ts
CHANGED
@@ -47,7 +47,7 @@ export { DropdownLabel } from './components/DropdownFirst';
|
|
47
47
|
export { DropdownDivider } from './components/DropdownFirst';
|
48
48
|
export { Dropdown } from './components/Dropdown';
|
49
49
|
export { Tag } from './components/Tag';
|
50
|
-
export {
|
50
|
+
export { TabItem, TabPanel, TabContent, TabNav } from './components/TabCustom';
|
51
51
|
export { EmptyState } from './components/EmptyState';
|
52
52
|
export { Autocomplete } from './components/Autocomplete';
|
53
53
|
export { DonutChart } from './components/DonutChart';
|
package/dist/examples.bundle.css
CHANGED
@@ -1162,7 +1162,42 @@ pre[class*="language-"] {
|
|
1162
1162
|
.docs-page__section {
|
1163
1163
|
max-width: 80%;
|
1164
1164
|
}
|
1165
|
-
}
|
1165
|
+
}.sd-spinner {
|
1166
|
+
animation: rotate 2s linear infinite;
|
1167
|
+
z-index: 1; }
|
1168
|
+
.sd-spinner--mini {
|
1169
|
+
width: 1.8rem;
|
1170
|
+
height: 1.8rem; }
|
1171
|
+
.sd-spinner--small {
|
1172
|
+
width: 2.4rem;
|
1173
|
+
height: 2.4rem; }
|
1174
|
+
.sd-spinner--medium {
|
1175
|
+
width: 3.2rem;
|
1176
|
+
height: 3.2rem; }
|
1177
|
+
.sd-spinner--large {
|
1178
|
+
width: 4.8rem;
|
1179
|
+
height: 4.8rem; }
|
1180
|
+
|
1181
|
+
.sd-spinner__path {
|
1182
|
+
stroke: var(--color-text-light);
|
1183
|
+
stroke-linecap: round;
|
1184
|
+
animation: dash 1.5s ease-in-out infinite; }
|
1185
|
+
|
1186
|
+
@keyframes rotate {
|
1187
|
+
100% {
|
1188
|
+
transform: rotate(360deg); } }
|
1189
|
+
|
1190
|
+
@keyframes dash {
|
1191
|
+
0% {
|
1192
|
+
stroke-dasharray: 1, 150;
|
1193
|
+
stroke-dashoffset: 0; }
|
1194
|
+
50% {
|
1195
|
+
stroke-dasharray: 90, 150;
|
1196
|
+
stroke-dashoffset: -32; }
|
1197
|
+
100% {
|
1198
|
+
stroke-dasharray: 90, 150;
|
1199
|
+
stroke-dashoffset: -124; } }
|
1200
|
+
@charset "UTF-8";
|
1166
1201
|
:root {
|
1167
1202
|
--sd-slugline-color: #005b7f; }
|
1168
1203
|
|