genesys-react-components 0.1.6-devengage-1377-autofocus.120 → 0.1.8-devengage-1376.128

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 (37) hide show
  1. package/README.md +4 -0
  2. package/build/index.d.ts +1 -2
  3. package/build/index.js +6 -6
  4. package/build/index.js.map +1 -1
  5. package/package.json +7 -5
  6. package/src/alertblock/AlertBlock.scss +108 -0
  7. package/src/alertblock/AlertBlock.tsx +80 -0
  8. package/src/copybutton/CopyButton.scss +8 -0
  9. package/src/copybutton/CopyButton.tsx +42 -0
  10. package/src/dxaccordion/DxAccordion.scss +41 -0
  11. package/src/dxaccordion/DxAccordion.tsx +49 -0
  12. package/src/dxaccordion/DxAccordionGroup.scss +3 -0
  13. package/src/dxaccordion/DxAccordionGroup.tsx +12 -0
  14. package/src/dxbutton/DxButton.scss +79 -0
  15. package/src/dxbutton/DxButton.tsx +31 -0
  16. package/src/dxitemgroup/DxCheckbox.scss +145 -0
  17. package/src/dxitemgroup/DxCheckbox.tsx +46 -0
  18. package/src/dxitemgroup/DxItemGroup.scss +6 -0
  19. package/src/dxitemgroup/DxItemGroup.tsx +133 -0
  20. package/src/dxitemgroup/dropdown.scss +53 -0
  21. package/src/dxitemgroup/multiselect.scss +74 -0
  22. package/src/dxitemgroup/radiobutton.scss +2 -0
  23. package/src/dxlabel/DxLabel.scss +31 -0
  24. package/src/dxlabel/DxLabel.tsx +39 -0
  25. package/src/dxtabbedcontent/DxTabPanel.scss +0 -0
  26. package/src/dxtabbedcontent/DxTabPanel.tsx +8 -0
  27. package/src/dxtabbedcontent/DxTabbedContent.scss +45 -0
  28. package/src/dxtabbedcontent/DxTabbedContent.tsx +28 -0
  29. package/src/dxtextbox/DxTextbox.scss +107 -0
  30. package/src/dxtextbox/DxTextbox.tsx +159 -0
  31. package/src/dxtoggle/DxToggle.scss +76 -0
  32. package/src/dxtoggle/DxToggle.tsx +51 -0
  33. package/src/index.ts +141 -0
  34. package/src/loadingplaceholder/LoadingPlaceholder.scss +58 -0
  35. package/src/loadingplaceholder/LoadingPlaceholder.tsx +17 -0
  36. package/src/tooltip/Tooltip.scss +108 -0
  37. package/src/tooltip/Tooltip.tsx +46 -0
@@ -0,0 +1,39 @@
1
+ import { GenesysDevIcon, GenesysDevIcons } from 'genesys-dev-icons';
2
+ import React from 'react';
3
+
4
+ import './DxLabel.scss';
5
+
6
+ interface IProps {
7
+ label?: string;
8
+ description?: string;
9
+ useFieldset?: boolean;
10
+ className?: string;
11
+ children: React.ReactNode;
12
+ }
13
+
14
+ export default function DxLabel(props: IProps) {
15
+ const hasLabel = props.label && props.label !== '';
16
+
17
+ const description = props.description ? (
18
+ <div className='input-description'>
19
+ <GenesysDevIcon icon={GenesysDevIcons.AppInfoSolid} />
20
+ <span>{props.description}</span>
21
+ </div>
22
+ ) : undefined;
23
+
24
+ const contents = (
25
+ <React.Fragment>
26
+ {' '}
27
+ {hasLabel ? <span className='label-text'>{props.label}</span> : undefined}
28
+ {props.children}
29
+ {description}
30
+ </React.Fragment>
31
+ );
32
+
33
+ const className = `dx-label${props.className ? ' ' + props.className : ''}`;
34
+
35
+ if (props.useFieldset) {
36
+ return <fieldset className={className}>{contents}</fieldset>;
37
+ }
38
+ return <label className={className}>{contents}</label>;
39
+ }
File without changes
@@ -0,0 +1,8 @@
1
+ import React from 'react';
2
+ import { DxTabPanelProps } from '..';
3
+
4
+ import './DxTabPanel.scss';
5
+
6
+ export default function DxTabPanel(props: DxTabPanelProps) {
7
+ return <div className={`dx-tab-panel${props.className ? ' ' + props.className : ''}`}>{props.children}</div>;
8
+ }
@@ -0,0 +1,45 @@
1
+ .dx-tabbed-content {
2
+ margin: 40px 0;
3
+
4
+ .tab-titles {
5
+ border-bottom: 1px solid #bfd4e4;
6
+ font-weight: normal;
7
+ font-size: 14px;
8
+ line-height: 20px;
9
+
10
+ .tab-title {
11
+ display: inline-block;
12
+ padding: 5px 20px;
13
+ border-bottom: 1px solid transparent;
14
+ cursor: pointer;
15
+
16
+ &:hover {
17
+ border-color: #bfd4e4;
18
+ }
19
+
20
+ &.active {
21
+ border-bottom-color: #597393;
22
+ font-weight: bold;
23
+ }
24
+
25
+ // Make markdown-parsed paragraphs look normal
26
+ & p {
27
+ margin: 0;
28
+ display: inline;
29
+ }
30
+ }
31
+ }
32
+
33
+ .tab-content {
34
+ padding: 13px 20px 20px 20px;
35
+ border-bottom: 1px solid #bfd4e4;
36
+
37
+ // Clear excess margins from content, we provide the padding
38
+ & > *:first-child {
39
+ margin-top: 0;
40
+ }
41
+ & > *:last-child {
42
+ margin-bottom: 0;
43
+ }
44
+ }
45
+ }
@@ -0,0 +1,28 @@
1
+ import React, { useState } from 'react';
2
+ import { DxTabbedContentProps } from '..';
3
+
4
+ import './DxTabbedContent.scss';
5
+
6
+ export default function DxTabbedContent(props: DxTabbedContentProps) {
7
+ const [activeTab, setActiveTab] = useState(props.initialTabId || 0);
8
+ const [titles] = useState<React.ReactNode[]>(
9
+ // Scrape titles from child elements
10
+ React.Children.toArray(props.children).map((child: any) => {
11
+ if (!child || !child.props || !child.props.title) return 'Unknown title';
12
+ return child.props.title;
13
+ })
14
+ );
15
+
16
+ return (
17
+ <div className={`dx-tabbed-content${props.className ? ' ' + props.className : ''}`}>
18
+ <div className='tab-titles'>
19
+ {titles.map((title, i) => (
20
+ <span key={i} className={`tab-title${i === activeTab ? ' active' : ''}`} onClick={() => setActiveTab(i)}>
21
+ {title}
22
+ </span>
23
+ ))}
24
+ </div>
25
+ <div className='tab-content'>{React.Children.toArray(props.children)[activeTab]}</div>
26
+ </div>
27
+ );
28
+ }
@@ -0,0 +1,107 @@
1
+ .dx-textbox {
2
+ display: flex;
3
+ flex-flow: row nowrap;
4
+ justify-content: space-between;
5
+ align-items: center;
6
+ gap: 10px;
7
+ border: 1px solid #c6cbd1;
8
+ border-radius: 2px;
9
+ margin: 0;
10
+ padding: 0 10px;
11
+ height: 32px;
12
+ background-color: #ffffff;
13
+
14
+ &.with-label {
15
+ margin-top: 0;
16
+ }
17
+
18
+ &:focus-within {
19
+ outline: #aac9ff solid 2px;
20
+ }
21
+
22
+ .icon {
23
+ display: block;
24
+ flex: none;
25
+ color: #75757a;
26
+
27
+ &.input-icon {
28
+ font-size: 14px;
29
+ line-height: 0;
30
+ }
31
+
32
+ &.clear-icon {
33
+ font-size: 11px;
34
+ line-height: 0;
35
+ cursor: pointer;
36
+ padding: 4px;
37
+ margin-right: -4px;
38
+ }
39
+ }
40
+
41
+ .dx-input {
42
+ flex-grow: 1;
43
+ border: 0;
44
+ background: transparent;
45
+ box-sizing: border-box;
46
+ height: 32px;
47
+ width: 100%;
48
+ padding: 0;
49
+ margin: 0;
50
+ font-family: Roboto;
51
+ font-style: normal;
52
+ font-weight: normal;
53
+ font-size: 14px;
54
+ line-height: 16px;
55
+ color: #272d2d;
56
+
57
+ &:focus-visible {
58
+ outline: 0;
59
+ }
60
+
61
+ &::placeholder {
62
+ font-style: normal;
63
+ font-weight: 300;
64
+ font-size: 14px;
65
+ line-height: 16px;
66
+ color: #757576;
67
+ }
68
+ }
69
+
70
+ &.disabled {
71
+ background-color: #e6ebec;
72
+ border-color: #e8eaed;
73
+ cursor: not-allowed;
74
+
75
+ input {
76
+ cursor: not-allowed;
77
+ color: #75757a;
78
+ }
79
+
80
+ .icon,
81
+ input::placeholder {
82
+ color: #ffffff;
83
+ }
84
+ }
85
+ }
86
+
87
+ .dx-textarea {
88
+ padding: 10px;
89
+ border: 1px solid #c6cbd1;
90
+ border-radius: 2px;
91
+ width: 100%;
92
+ font-family: 'Roboto', sans-serif;
93
+ box-sizing: border-box;
94
+
95
+ &:focus-within {
96
+ outline: #aac9ff solid 2px;
97
+ }
98
+
99
+ &::placeholder {
100
+ font-family: 'Roboto', sans-serif;
101
+ font-style: normal;
102
+ font-weight: 300;
103
+ font-size: 14px;
104
+ line-height: 16px;
105
+ color: #757576;
106
+ }
107
+ }
@@ -0,0 +1,159 @@
1
+ import { GenesysDevIcon, GenesysDevIcons } from 'genesys-dev-icons';
2
+ import React, { useEffect, useRef, useState } from 'react';
3
+ import DxLabel from '../dxlabel/DxLabel';
4
+ import { DxTextboxProps } from '..';
5
+
6
+ import './DxTextbox.scss';
7
+
8
+ export default function DxTextbox(props: DxTextboxProps) {
9
+ const [debounceMs, setDebounceMs] = useState(props.changeDebounceMs || 300);
10
+ const [value, setValue] = useState(props.initialValue || props.value || '');
11
+ const [isFocused, setIsFocused] = useState(false);
12
+ const [escapePressed, setEscapePressed] = useState(Date.now());
13
+ const [step, setStep] = useState<string | number | undefined>(undefined);
14
+ let [timer, setTimer] = useState(undefined as unknown as ReturnType<typeof setTimeout>);
15
+
16
+ // Constructor
17
+ useEffect(() => {
18
+ // Register global key bindings
19
+ document.addEventListener('keydown', globalKeyBindings, false);
20
+
21
+ return () => {
22
+ document.removeEventListener('keydown', globalKeyBindings, false);
23
+ };
24
+ }, []);
25
+
26
+ // Value prop updated
27
+ useEffect(() => {
28
+ // Ignore value changed if initial value was set; they're mutually exclusive
29
+ if (!props.initialValue) {
30
+ setValue(props.value || '');
31
+ }
32
+ }, [props.value]);
33
+
34
+ // Escape pressed
35
+ useEffect(() => {
36
+ if (!isFocused) return;
37
+ setValue('');
38
+ inputRef.current?.blur();
39
+ // eslint-disable-next-line react-hooks/exhaustive-deps
40
+ }, [escapePressed]);
41
+
42
+ // Value changed
43
+ useEffect(() => {
44
+ if (props.inputType === 'decimal') {
45
+ // Normalize step setting
46
+ if (!isNaN(parseFloat(value))) {
47
+ const match = /\.(.+)/.exec(value);
48
+ console.log(match);
49
+ if (match) {
50
+ const s = `0.${Array.apply(null, Array(match[1].length - 1))
51
+ .map(() => '0')
52
+ .join('')}1`;
53
+ console.log(s);
54
+ setStep(s);
55
+ }
56
+ }
57
+ } else if (props.inputType === 'integer') {
58
+ // Overwrite value as integer to forcibly truncate floating point numbers
59
+ setValue(parseInt(value).toString());
60
+ }
61
+
62
+ // Debounce onChange notification
63
+ if (!props.onChange) return;
64
+ clearTimeout(timer);
65
+ setTimer(setTimeout(() => (props.onChange ? props.onChange(value) : undefined), debounceMs));
66
+ // eslint-disable-next-line react-hooks/exhaustive-deps
67
+ }, [value]);
68
+
69
+ // Update state from props
70
+ useEffect(() => {
71
+ setDebounceMs(props.changeDebounceMs || 300);
72
+ }, [props.changeDebounceMs]);
73
+
74
+ // Normalize inputRef
75
+ let inputRef; // = useRef<HTMLInputElement>(null);
76
+ if (props.inputRef) inputRef = props.inputRef;
77
+ else if (props.inputType === 'textarea') inputRef = useRef<HTMLTextAreaElement>(null);
78
+ else inputRef = useRef<HTMLInputElement>(null);
79
+
80
+ const hasLabel = props.label && props.label !== '';
81
+
82
+ // Global key bindings
83
+ function globalKeyBindings(event: KeyboardEvent) {
84
+ // Escape - cancel search
85
+ if (event.key === 'Escape') {
86
+ event.stopPropagation();
87
+ event.preventDefault();
88
+ setEscapePressed(Date.now());
89
+ return;
90
+ }
91
+ }
92
+
93
+ // Normalize input type
94
+ let inputType: React.HTMLInputTypeAttribute | undefined = props.inputType;
95
+ if (inputType === 'integer' || inputType === 'decimal') inputType = 'number';
96
+
97
+ let component;
98
+ switch (inputType) {
99
+ case 'textarea': {
100
+ component = (
101
+ <textarea
102
+ className="dx-textarea"
103
+ placeholder={props.placeholder}
104
+ ref={inputRef}
105
+ value={value}
106
+ onChange={(e) => setValue(e.target.value)}
107
+ onFocus={() => {
108
+ setIsFocused(true);
109
+ if (props.onFocus) props.onFocus();
110
+ }}
111
+ onBlur={() => {
112
+ setIsFocused(false);
113
+ if (props.onBlur) props.onBlur();
114
+ }}
115
+ disabled={props.disabled === true}
116
+ autoFocus={props.autoFocus}
117
+ />
118
+ );
119
+ break;
120
+ }
121
+ // TODO: special handling for other inputType values
122
+ default: {
123
+ component = (
124
+ <div className={`dx-textbox${hasLabel ? ' with-label' : ''}${props.disabled ? ' disabled' : ''}`}>
125
+ {props.icon ? <GenesysDevIcon icon={props.icon} className="input-icon" /> : undefined}
126
+ <input
127
+ className="dx-input"
128
+ type={inputType}
129
+ step={step}
130
+ value={value}
131
+ placeholder={props.placeholder}
132
+ onChange={(e) => setValue(e.target.value)}
133
+ ref={inputRef}
134
+ onFocus={() => {
135
+ setIsFocused(true);
136
+ if (props.onFocus) props.onFocus();
137
+ }}
138
+ onBlur={() => {
139
+ setIsFocused(false);
140
+ if (props.onBlur) props.onBlur();
141
+ }}
142
+ disabled={props.disabled === true}
143
+ autoFocus={props.autoFocus}
144
+ />
145
+ {props.clearButton && (value || isFocused) && !props.disabled ? (
146
+ <GenesysDevIcon icon={GenesysDevIcons.AppTimes} className="clear-icon" onClick={() => setValue('')} />
147
+ ) : undefined}
148
+ </div>
149
+ );
150
+ }
151
+ }
152
+
153
+ // Render
154
+ return (
155
+ <DxLabel label={props.label} description={props.description} className={props.className}>
156
+ {component}
157
+ </DxLabel>
158
+ );
159
+ }
@@ -0,0 +1,76 @@
1
+ .dx-toggle-container {
2
+ display: inline-block;
3
+ .dx-toggle {
4
+ background: #f5f8fb;
5
+ border: 1px solid #c6cbd1;
6
+ border-radius: 6px;
7
+ height: 26px;
8
+ // width: 72px;
9
+ padding: 0px 4px;
10
+ display: flex;
11
+ flex-flow: row nowrap;
12
+ justify-content: space-between;
13
+ align-items: center;
14
+ gap: 2px;
15
+ cursor: pointer;
16
+
17
+ &:hover {
18
+ .slider {
19
+ border-color: #aac9ff;
20
+ }
21
+ }
22
+
23
+ .icon {
24
+ font-size: 10px;
25
+ line-height: 0;
26
+ margin: 0 5px;
27
+ color: #c4c4c4;
28
+ }
29
+
30
+ .clear-placeholder {
31
+ width: 19px;
32
+ padding: 0 1px 0 0;
33
+ margin: 0;
34
+ display: block;
35
+ }
36
+
37
+ .slider {
38
+ height: 22px;
39
+ width: 22px;
40
+ border-radius: 22px;
41
+ background-color: #419bb2;
42
+ box-shadow: 0px 1px 2px rgba(0, 0, 0, 0.25);
43
+ display: flex;
44
+ align-items: center;
45
+ justify-content: center;
46
+ border: 1px solid transparent;
47
+
48
+ .icon {
49
+ font-size: 10px;
50
+ line-height: 0;
51
+ color: #ffffff;
52
+ padding: 0;
53
+ margin: 0;
54
+ }
55
+ }
56
+ }
57
+
58
+ &.disabled {
59
+ .dx-toggle {
60
+ border-color: #e8eaed;
61
+ color: #ffffff;
62
+ cursor: not-allowed;
63
+
64
+ &:hover {
65
+ .slider {
66
+ border-color: transparent;
67
+ }
68
+ }
69
+
70
+ .slider {
71
+ color: #8a9a9e;
72
+ background-color: #e0e6e8;
73
+ }
74
+ }
75
+ }
76
+ }
@@ -0,0 +1,51 @@
1
+ import React, { useEffect, useState } from 'react';
2
+ import { GenesysDevIcon, GenesysDevIcons } from 'genesys-dev-icons';
3
+ import { BooleanChangedCallback, DxToggleProps } from '..';
4
+
5
+ import './DxToggle.scss';
6
+ import DxLabel from '../dxlabel/DxLabel';
7
+
8
+ export default function DxToggle(props: DxToggleProps) {
9
+ let initialValue: boolean | undefined = props.value !== undefined ? props.value : props.initialValue;
10
+ if (!props.isTriState) initialValue = initialValue || false;
11
+
12
+ const [value, setValue] = useState<boolean | undefined>(initialValue);
13
+
14
+ const trueIcon = props.trueIcon || GenesysDevIcons.AppCheck;
15
+ const falseIcon = props.falseIcon || GenesysDevIcons.AppTimes;
16
+
17
+ useEffect(() => {
18
+ if (props.initialValue || props.value === value || (!props.isTriState && props.value === undefined)) return;
19
+ setValue(props.value);
20
+ }, [props.value]);
21
+
22
+ useEffect(() => {
23
+ if (props.onChange) props.onChange(value);
24
+ // eslint-disable-next-line react-hooks/exhaustive-deps
25
+ }, [value]);
26
+
27
+ const toggleValue = () => {
28
+ if (props.disabled) return;
29
+ if (props.isTriState) {
30
+ if (value === undefined) setValue(true);
31
+ else if (value === true) setValue(false);
32
+ else setValue(undefined);
33
+ } else {
34
+ setValue(!value);
35
+ }
36
+ };
37
+
38
+ return (
39
+ <DxLabel label={props.label} description={props.description} className={props.className}>
40
+ <div className={`dx-toggle-container${props.disabled ? ' disabled' : ''}`}>
41
+ <div className='dx-toggle' onClick={toggleValue}>
42
+ {value !== false ? <GenesysDevIcon icon={falseIcon} /> : undefined}
43
+ {value === true && props.isTriState ? <div className='clear-placeholder'>&nbsp;</div> : undefined}
44
+ <div className='slider'>{value !== undefined ? <GenesysDevIcon icon={value ? trueIcon : falseIcon} /> : undefined}</div>
45
+ {value === false && props.isTriState ? <div className='clear-placeholder'>&nbsp;</div> : undefined}
46
+ {value !== true ? <GenesysDevIcon icon={trueIcon} /> : undefined}
47
+ </div>
48
+ </div>
49
+ </DxLabel>
50
+ );
51
+ }
package/src/index.ts ADDED
@@ -0,0 +1,141 @@
1
+ import { GenesysDevIcons } from 'genesys-dev-icons';
2
+ import DxAccordion from './dxaccordion/DxAccordion';
3
+ import DxAccordionGroup from './dxaccordion/DxAccordionGroup';
4
+ import DxButton from './dxbutton/DxButton';
5
+ import DxItemGroup from './dxitemgroup/DxItemGroup';
6
+ import DxCheckbox from './dxitemgroup/DxCheckbox';
7
+ import DxLabel from './dxlabel/DxLabel';
8
+ import DxTabbedContent from './dxtabbedcontent/DxTabbedContent';
9
+ import DxTabPanel from './dxtabbedcontent/DxTabPanel';
10
+ import DxTextbox from './dxtextbox/DxTextbox';
11
+ import DxToggle from './dxtoggle/DxToggle';
12
+ import AlertBlock from './alertblock/AlertBlock';
13
+ import LoadingPlaceholder from './loadingplaceholder/LoadingPlaceholder';
14
+ import Tooltip from './tooltip/Tooltip';
15
+ import CopyButton from './copybutton/CopyButton';
16
+
17
+ export {
18
+ DxAccordion,
19
+ DxAccordionGroup,
20
+ DxButton,
21
+ DxItemGroup,
22
+ DxCheckbox,
23
+ DxLabel,
24
+ DxTabbedContent,
25
+ DxTabPanel,
26
+ DxTextbox,
27
+ DxToggle,
28
+ Tooltip,
29
+ CopyButton,
30
+ LoadingPlaceholder,
31
+ AlertBlock,
32
+ };
33
+
34
+ export interface StringChangedCallback {
35
+ (value: string): void;
36
+ }
37
+
38
+ export interface BooleanChangedCallback {
39
+ (value?: boolean): void;
40
+ }
41
+
42
+ export interface CheckedChangedCallback {
43
+ (checked: boolean): void;
44
+ }
45
+
46
+ export interface VoidEventCallback {
47
+ (): void;
48
+ }
49
+
50
+ // Item in a DxItemGroup
51
+ export interface DxItemGroupItem {
52
+ label: string;
53
+ value: string;
54
+ disabled?: boolean;
55
+ isSelected?: boolean;
56
+ }
57
+
58
+ // Item value of a DxItemGroupItem in a DxItemGroup
59
+ export interface DxItemGroupItemValue {
60
+ item: DxItemGroupItem;
61
+ isSelected: boolean;
62
+ }
63
+
64
+ export interface ItemChangedCallback {
65
+ (item: DxItemGroupItem, isSelected: boolean): void;
66
+ }
67
+
68
+ export interface ItemGroupChangedCallback {
69
+ (items: DxItemGroupItemValue[]): void;
70
+ }
71
+
72
+ export interface DxToggleProps {
73
+ isTriState?: boolean;
74
+ initialValue?: boolean;
75
+ value?: boolean;
76
+ label?: string;
77
+ description?: string;
78
+ trueIcon?: GenesysDevIcons;
79
+ falseIcon?: GenesysDevIcons;
80
+ disabled?: boolean;
81
+ onChange?: BooleanChangedCallback;
82
+ className?: string;
83
+ }
84
+
85
+ export type DxTextboxType = 'text' | 'textarea' | 'password' | 'email' | 'date' | 'datetime-local' | 'time' | 'integer' | 'decimal';
86
+
87
+ export interface DxTextboxProps {
88
+ initialValue?: string;
89
+ value?: string;
90
+ inputType?: DxTextboxType;
91
+ label?: string;
92
+ description?: string;
93
+ placeholder?: string;
94
+ icon?: GenesysDevIcons;
95
+ clearButton?: boolean;
96
+ onChange?: StringChangedCallback;
97
+ changeDebounceMs?: number;
98
+ inputRef?: React.RefObject<HTMLInputElement>;
99
+ onFocus?: VoidEventCallback;
100
+ onBlur?: VoidEventCallback;
101
+ disabled?: boolean;
102
+ className?: string;
103
+ autoFocus?: boolean;
104
+ }
105
+
106
+ export interface DxAccordionProps {
107
+ title: React.ReactNode;
108
+ children: React.ReactNode;
109
+ showOpen?: boolean;
110
+ className?: string;
111
+ expandTrigger?: any;
112
+ showOpenTrigger?: any;
113
+ containerId?: string;
114
+ headingIcon?: any;
115
+ headingColor?: string;
116
+ }
117
+
118
+ export interface DxItemGroupProps {
119
+ title?: string;
120
+ description?: string;
121
+ format: DxItemGroupFormat;
122
+ items: DxItemGroupItem[];
123
+ disabled?: boolean;
124
+ className?: string;
125
+ onItemChanged?: ItemChangedCallback;
126
+ onItemsChanged?: ItemGroupChangedCallback;
127
+ }
128
+
129
+ export type DxItemGroupFormat = 'checkbox' | 'radio' | 'dropdown' | 'multiselect';
130
+
131
+ export interface DxTabbedContentProps {
132
+ children: React.ReactNode;
133
+ initialTabId?: number;
134
+ className?: string;
135
+ }
136
+
137
+ export interface DxTabPanelProps {
138
+ title: React.ReactNode;
139
+ children: React.ReactNode;
140
+ className?: string;
141
+ }